# Cross-window communication The "Same Origin" (same site) policy limits access of windows and frame to each other. The idea is that if we have two windows open: one from `john-smith.com`, and another one is `gmail.com`, then we wouldn't want a script from `john-smith.com` to read our mail. [cut] ## Same Origin [#same-origin] Two URLs are said to have the "same origin" if they have the same protocol, domain and port. These URLs all share the same origin: - `http://site.com` - `http://site.com/` - `http://site.com/my/page.html` 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`) 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. 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 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`, 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: ```js document.domain = 'site.com'; ``` Then they can interact without limitations. That's only possible for pages with the same second-level domain. ```` ## Accessing an iframe contents An ` ``` The code above shows errors for any operations except: - Getting the reference to the inner window `iframe.contentWindow` - Changing its `location`. ```smart header="`iframe.onload` vs `iframe.contentWindow.onload`" The `iframe.onload` event is actually the same as `iframe.contentWindow.onload`. It triggers when the embedded window fully loads with all resources. ...But `iframe.onload` is always available, while `iframe.contentWindow.onload` needs the same origin. ``` And now an example with the same origin. We can do anything with the embedded window: ```html run ``` ### 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! Here, look: ```html run ``` 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` of the embedded document? 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 ``` Let me know in comments if you know a better solution here. ## window.frames An alternative way to get a window object for ` ``` An iframe may have other iframes inside. The corresponding `window` objects form a hierarchy. Navigation links are: - `window.frames` -- the collection of "children" windows (for nested frames). - `window.parent` -- the reference to the "parent" (outer) window. - `window.top` -- the reference to the topmost parent window. For instance: ```js run window.frames[0].parent === window; // true ``` We can use the `top` property to check if the current document is open inside a frame or not: ```js run if (window == top) { // current window == window.top? alert('The script is in the topmost window, not in a frame'); } else { alert('The script runs in a frame!'); } ``` ## The sandbox attribute The `sandbox` attribute allows to forbid certain actions inside an `