diff --git a/4-frames-and-windows/03-cross-window-communication/article.md b/4-frames-and-windows/03-cross-window-communication/article.md index 3c502b77..15394969 100644 --- a/4-frames-and-windows/03-cross-window-communication/article.md +++ b/4-frames-and-windows/03-cross-window-communication/article.md @@ -10,28 +10,30 @@ The idea is that if we have two windows open: one from `john-smith.com`, and ano Two URLs are said to have the "same origin" if they have the same protocol, domain and port. -These URLs have the same origin: +These URLs all share the same origin: - `http://site.com` - `http://site.com/` - `http://site.com/my/page.html` -These ones are not: +These ones do not: -- `http://www.site.com` (another domain: `www.` matters) -- `http://site.org` (another domain: `.org` matters) -- `https://site.com` (another protocol: `https`) -- `http://site.com:8080` (another port: `8080`) +- http://www.site.com (another domain: `www.` matters) +- http://site.org (another domain: `.org` matters) +- https://site.com (another protocol: `https`) +- http://site.com:8080 (another port: `8080`) If we have a reference to another window (a popup or iframe), and that window comes from the same origin, then we can do everything with it. -Otherwise, we can only change its location. Please note: not *read*, but modify it, redirect it to another place. That's possible, because such action does not reveal any data. Also such windows windows may exchange messages. Soon about that later. +If it comes from another origin, then we can only change its location. Please note: not *read* the location, but *modify* it, redirect it to another place. That's safe, because the URL may contain sensitive parameters, so reading it from another origin is prohibited, but changing is not. + +Also such windows windows may exchange messages. Soon about that later. ````warn header="Exclusion: subdomains may be same-origin" There's an important exclusion in the same-origin policy. -If windows share the same second-level domain, for instance `john.site.com`, `peter.site.com` and `site.com`, and assign to `document.domain` their common second-level domain `site.com`, then limitations are removed. +If windows share the same second-level domain, for instance `john.site.com`, `peter.site.com` and `site.com`, we can use JavaScript to assign to `document.domain` their common second-level domain `site.com`. Then these windows are treated as having the same origin. In other words, all such documents (including the one from `site.com`) should have the code: @@ -40,49 +42,51 @@ document.domain = 'site.com'; ``` Then they can interact without limitations. + +That's only possible for pages with the same second-level domain. ```` -## Managing iframes +## Accessing an iframe contents -An ` ``` @@ -98,7 +102,7 @@ The `iframe.onload` event is actually the same as `iframe.contentWindow.onload`. ...But `iframe.onload` is always available, while `iframe.contentWindow.onload` needs the same origin. ``` -And here's an example with the same origin: +And now an example with the same origin. We can do anything with the embedded window: ```html run @@ -111,7 +115,7 @@ And here's an example with the same origin: ``` -### Wait until the iframe loads +### Please wait until the iframe loads When an iframe is created, it immediately has a document. But that document is different from the one that finally loads into it! @@ -126,6 +130,7 @@ Here, look: iframe.onload = function() { let newDoc = iframe.contentDocument; *!* + // the loaded document is not the same as initial! alert(oldDoc == newDoc); // false */!* }; @@ -134,9 +139,9 @@ Here, look: That's actually a well-known pitfall for novice developers. We shouldn't work with the document immediately, because that's the *wrong document*. If we set any event handlers on it, they will be ignored. -...But the `onload` event triggers when the whole iframe with all resources is loaded. What if we want to act sooner, on `DOMContentLoaded`? +...But the `onload` event triggers when the whole iframe with all resources is loaded. What if we want to act sooner, on `DOMContentLoaded` of the embedded document? -We can try to catch the moment when a new document appears, and then setup necessary handlers, like this: +That's not possible if the iframe comes from another origin. But for the same origin we can try to catch the moment when a new document appears, and then setup necessary handlers, like this: ```html run @@ -148,19 +153,19 @@ We can try to catch the moment when a new document appears, and then setup neces let timer = setInterval(() => { if (iframe.contentDocument == oldDoc) return; - // yeah, now set handlers and do whatever we want - clearInterval(timer); - + // new document, let's set handlers iframe.contentDocument.addEventListener('DOMContentLoaded', () => { iframe.contentDocument.body.prepend('Hello, world!'); }); + + clearInterval(timer); // cancel setInterval, don't need it any more }, 100); ``` Let me know in comments if you know a better solution here. -### window.frames +## window.frames An alternative way to get a window object for `