Cross-window Communication
The Same Origin policy restricts the windows access to one another. That means, if a user has opened two pages: the first one from daivd-brown.com and the second one - gmail.com, then they couldn't want a script from daivd-brown.com for reading a mail from gmail.com. The purpose of such a policy is to protect users from information theft.
Describing the Same Origin¶
Two URLs are considered to have the same origin when their protocol, domain, and port are the same.
Here are examples of same-origin URLs:
- http://oursite.com
- http://oursite.com/
- http://oursite.com/my/page.html
Now, let’s see examples of URLs that don’t have the same origin:
- http://site.org
- http://www.site.com
- https://site.com
- http://site.com:8080
According to the Same Origin policy:
- In case of having a reference to another window ( for example, a popup created with or a window inside <iframe>, and the window is from the same origin, then complete access to that window is provided.
- In another way, in case of coming from another origin, then the content of the window can’t be accessed. Only the location can be an exception: it can be modified. But, the location can’t be read.
iFrame
The <iframe> tag can host an independent embedded window that has its window and document objects. They can be accessed with the following properties:- iframe.contentWindow for accessing the window within the <iframe>.
- iframe.contentDocument for getting the document within <iframe>. It’s a shorthand for iframe.contentWindow.document.
While accessing something inside the embedded window, the browser inspects whether the iframe has the same origin. Otherwise, access will be denied. In the example below, you can see an attempt to read and write to <iframe> from another origin:
<!DOCTYPE html>
<html>
<head></head>
<body>
<iframe id="iframe" src="https://example.com"></iframe>
<script>
iframe.onload = function() {
// get the reference to the inner window
let iframeWindow = iframe.contentWindow; // OK
try {
//but not to the document inside it
let doc = iframe.contentDocument; // ERROR
} catch(err) {
alert(err); // Security Error, another origin
}
// also we cannot READ the page URL in the iframe
try {
// Cannot read URL from Location object
let href = iframe.contentWindow.location.href; // ERROR
} catch(err) {
alert(err); // Security Error
}
//can be WRITE to a location (and therefore load something else in the iframe)
iframe.contentWindow.location = '/'; // OK
iframe.onload = null; // clear the handler so that it does not start after changing the location
};
</script>
</body>
</html>
But this code will lead to errors in all circumstances except:
- Receiving the reference to the inner window iframe.contentWindow .
- While writing to the location .
Differently, when the <iframe> has the same origin, anything can be done with it, like here:
<!DOCTYPE html>
<html>
<head></head>
<body>
<!-- iframe from the same site -->
<iframe id="iframe" src="/"></iframe>
<script>
iframe.onload = function() {
// just do anything
iframe.contentDocument.body.prepend("Welcome to Web");
};
</script>
</body>
</html>
Windows on Subdomains: document.domain¶
So, by default two URLs that have different domains have different origins. But, when windows have the same second-level domain, it is possible to make the browser ignore the difference.
The following code should be run to make it work:
document.domain = 'oursite.com';
Iframe: wrong document pitfall¶
If the frame is from the same origin with a possibility of accessing its document, then there exists a pitfall. It is an essential thing to know but doesn’t relate to cross-origin requests.
So, doing something with the document at once will be lost:
<!DOCTYPE html>
<html>
<head></head>
<body>
<iframe id="iframe" src="/" ></iframe>
<script>
let oldDocs = iframe.contentDocument;
iframe.onload = function() {
let newDocs = iframe.contentDocument;
// the loaded document is different from the original
alert(oldDocs == newDocs); // false
};
</script>
</body>
</html>
That’s the wrong document. Setting any event handlers on it will be ignored. The right document is where iframe.onload occurs. However, it occurs only when the total iframe with all the resources is loaded.
With setInterval the moment can be caught earlier, like here:
<!DOCTYPE html>
<html>
<head></head>
<body>
<iframe id="iframe" src="/" ></iframe>
<script>
let oldDocs = iframe.contentDocument;
// every 100 ms we check if the document is new
let timer = setInterval(() => {
let newDocs = iframe.contentDocument;
if (newDocs == oldDocs) return;
alert("New document is here");
clearInterval(timer); // cancel setInterval, no longer needed
}, 500);
</script>
</body>
</html>
Window.frames¶
There is an alternative option of getting a window object for <iframe>.
You can get it from the named collection window.frames :
- By number window.frames[0] .
- By name window.frames.iframeName.
Let’s take a look at an example:
<!DOCTYPE html>
<html>
<head></head>
<body>
<iframe id="iframe" src="/" style="height:100px" name="win"></iframe>
<script>
alert(iframe.contentWindow == frames[0]); // true
alert(iframe.contentWindow == frames.win); // true
</script>
</body>
</html>
Cross-window Messaging¶
Windows can talk to each other no matter what origin they have, with the help of the postMessage interface.
0 Comments
CAN FEEDBACK
Emoji