From 4248bd9ff26da5cf1a5c5df5a5e40784c814ef4a Mon Sep 17 00:00:00 2001 From: sashafir Date: Thu, 1 Mar 2018 21:15:26 -0800 Subject: [PATCH] release 0.0.4, window.location and document.location simulation --- README.md | 7 +++-- demo/index.html | 16 +++++++++-- demo/page-purple.html | 9 +++++- demo/page-violet.html | 7 +++++ demo/page.css | 2 ++ demo/page.js | 17 ++++++++++-- embed-page.html | 64 +++++++++++++++++++++++-------------------- security.md | 19 +++++++++++++ 8 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 demo/page.css create mode 100644 security.md diff --git a/README.md b/README.md index 7bba96d..ce26cc2 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ WebComponent acting as IFRAME. [![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/EPA-WG/embed-page) +## Security +* General browser and application [security improvements overview](security.md). + The scope insulation for DOM and CSS is done by WebComponet shadow dom, API for JS are insulated by closure for global objects with wrappers limiting the dom access root to component content. Similar approach will be applied for url, storage, cookies, etc. @@ -18,8 +21,8 @@ The content could be set either by **src** attribute or by Polymer {{data}} bind ``` ## To see in action -See the live basic [DEMO](https://raw-dot-custom-elements.appspot.com/EPA-WG/embed-page/v0.0.3/embed-page/demo/index.html) -, or check the [demo page on webcomponents.org](https://www.webcomponents.org/element/EPA-WG/embed-page/demo/demo/index.html) +See the live basic [DEMO](https://raw-dot-custom-elements.appspot.com/EPA-WG/embed-page/v0.0.4/embed-page/demo/index.html) +, check the [demo page on webcomponents.org](https://www.webcomponents.org/element/EPA-WG/embed-page/demo/demo/index.html) , or locally run ```bash $ polymer serve --open diff --git a/demo/index.html b/demo/index.html index 6fe36a2..d4e6a44 100644 --- a/demo/index.html +++ b/demo/index.html @@ -29,7 +29,8 @@ - + +

Extra line to show the DOM resizing when switching the pages within <embed-page /> component.

diff --git a/demo/page-violet.html b/demo/page-violet.html index 83007ad..574ae9e 100644 --- a/demo/page-violet.html +++ b/demo/page-violet.html @@ -22,6 +22,13 @@

Violet header

+
+
+ + + diff --git a/demo/page.css b/demo/page.css new file mode 100644 index 0000000..aadab7c --- /dev/null +++ b/demo/page.css @@ -0,0 +1,2 @@ +.win-location, +.doc-location{width: 100%;} \ No newline at end of file diff --git a/demo/page.js b/demo/page.js index ed9234c..b12c942 100644 --- a/demo/page.js +++ b/demo/page.js @@ -1,9 +1,20 @@ -let cb = document.getElementById("external"); -cb.checked=true; +document.getElementById("external").checked=true; [...document.getElementsByTagName('button')].forEach( b => b.onclick = ()=>ToggleCb(b) ); function ToggleCb( b ) { let a = document.getElementsByClassName( b.getAttribute('for') ); for( let x of a ) x.checked = !x.checked; -} \ No newline at end of file +} +const $ = css => document.querySelector(css) +, winLocation = $('.win-location') +, docLocation = $('.doc-location'); + + +winLocation.value = window.location; +docLocation.value = document.location; +document.querySelector('.win-location~*[value=get]').onclick = x => winLocation.value = window.location; +document.querySelector('.doc-location~*[value=get]').onclick = x => docLocation.value = document.location; +document.querySelector('.win-location~*[value=set]').onclick = x => window.location = winLocation.value ; +document.querySelector('.doc-location~*[value=set]').onclick = x => document.location = docLocation.value ; + diff --git a/embed-page.html b/embed-page.html index 81f3150..80b49ee 100644 --- a/embed-page.html +++ b/embed-page.html @@ -19,6 +19,31 @@ , FRAME_BLANK = "about:blank"; let GBL_InstancesCount = 0; + class EpaLocationHolder + { + constructor( app, a ) + { + this.getLocation = x=> a; + this.setLocation = v=> app.src = v; + } + get location( ){ return this.getLocation() } + set location(v){ return this.setLocation( v ) } + } + class EpaDocument extends EpaLocationHolder + { + constructor( app, f, a ) + { + super( app, a ); + Object.assign( this, + { getElementById : x=> $( '#'+x, f )[0] + , getElementsByTagName : x=> $( x, f ) + , getElementsByClassName : x=> f.getElementsByClassName( x ) + , createElement : x=> doc.createElement(x) + , querySelectorAll : x=> f.querySelectorAll(x) + , querySelector : x=> f.querySelector(x) + }) + } + } /** * `embed-page` * embeds page in iframe fashion but using shadow dom for CSS and dom insulation and closure for JS jailing. @@ -29,6 +54,7 @@ */ class EmbedPage extends Polymer.Element { + static get is() { return 'embed-page' } static get properties() @@ -66,17 +92,15 @@ onBeforeFetch(){ addClass ( this.$f,'loading') } onAfterFetch (){ removeClass( this.$f,'loading') } + get context() - { const f = this.$.framed; - return { window : win - , document : { getElementById: id => $( '#'+id, f )[0] - , getElementsByTagName: x => $( x, f ) - , getElementsByClassName: x => f.getElementsByClassName( x ) - , createElement : x=> doc.createElement(x) - , querySelectorAll: x=> f.querySelectorAll(x) - , querySelector : x=> f.querySelector(x) - , location: { protocol : doc.location.protocol } - } + { const f = this.$.framed + , a = doc.createElement('a'); + a.href = this.src; + a.toString = function(){ return this.href } + + return { window : new EpaLocationHolder(this,a) + , document : new EpaDocument(this,f,a) , head : doc.head , body : doc.body } @@ -128,15 +152,6 @@ } const scriptsSelector = 'script:not([type]),script[type="application/javascript"],script[type="text/javascript"]'; - //ajax('https://www.cahousefinder.com/wp-includes/js/jquery/jquery.js?ver=1.11.0','GET').then( - // x=>{ - // debugger; - // }, - // err=>{ - // debugger; - // } - //); - //if ('serviceWorker' in navigator) // //navigator.serviceWorker.register('https://cdn.xml4jquery.com/ajax/poc/sw.js' // not allowed as page has different origin // navigator.serviceWorker.register('sw.js' @@ -148,16 +163,7 @@ // log("Error", err); // }); - //fetch( 'https://www.cahousefinder.com/wp-includes/js/jquery/jquery.js?ver=1.11.0', { mode: 'no-cors' } ) - //.then( r => r.text() ) - //.then( - // x=>{ - // debugger; - // }, - // err=>{ - // debugger; - // } - //); + win.customElements.define( EmbedPage.is, EmbedPage ); diff --git a/security.md b/security.md new file mode 100644 index 0000000..6a59c8d --- /dev/null +++ b/security.md @@ -0,0 +1,19 @@ +# EPA browser and application security improvement overview + +Current standards stack provides a little for 3rd party UI integration into web page. +In order to allocate some space in page for 3rd party app content host page either +* should suffer from IFRAME limitations or +* compromise own security by injecting 3rd party JS into page. + +\ has given a flexibility of embedded DOM and IFRAME kind of browsing +context insulation. + +Unlike direct injection of 3rd party script EPA executes JS in host page with +insulation layer preventing access to document, window and major APIs. + +\ at this stage yet a proof of concept for +[Embeddable Progressive Application](https://github.com/EPA-WG/EPA-concept) and potentially +the polyfill for standard-to-be implemented natively by browser with all security concerns addressed. + + + \ No newline at end of file