An answer to "Foolproof way to detect if iframe is cross domain" describes a method to test if an iframe on a page points to a same-domain or cross-domain page, working around different browsers' interpretations of the cross-domain policy and avoiding error messages that would interrupt a user or stop javascript.
I'm looking to do the equivalent of this but from the child page inside the iframe testing whether it is inside a cross-domain iframe or not.
It's possible to access (same domain) info about the parent with the parent
global e.g. parent.document.location
, but is there a reliable way to do this cross-browser without crashing into errors when it detects that the parent is cross-domain?
For handy testing, here's a jsbin inside a jsfiddle that crashes into an error when trying to test if parent.location.host
is accessible. Is there a reliable way to get something usable like false
telling us that this is a cross-domain parent, instead of an error?
Is there a try...catch
variant which will be robust cross-browser? Or maybe some clever trick using a return value from parent.postMessage()
? (although the parent page cannot be edited)
Use case: imagine embedable content that is to be embedded on pages on its own site, and by third parties. If the page is on a same-domain iframe, we hide branding and links back to the original site because the user is already here. If they access the page from a 3rd party iframe or load the page directly, we show the branding and credits so they can see the source of the content.
To clarify, I know about the same-domain policy and I don't care what the cross browser domain is, I'm just looking to write a simple but reliable if
condition like if( crossDomainParent() ){ /* do something */}
First check if you are IFramed.
window.self !== window.top
If you are IFramed, then your referrer is your parent frame url.
document.referrer
From this url you should be able to detect if you want to branch your code.
Real cross-browser solution for posterity:
function isCrossOriginFrame() {
try {
return (!window.top.location.hostname);
} catch (e) {
return true;
}
}
console.log(isCrossOriginFrame());
Tested on a decent swath of desktop and mobile browsers.
https://jsfiddle.net/arzd4btc/3/
use x-frame header this will prevent to load your site to frame/iframe . there are various options read here
With your current restrictions, there's no way to achieve this using the DOM API. Any evaluation with a window that belongs to another domain will spew out an error.
However, a "hack" would be to send an XHR from your child window to load a known page in your domain. If this XHR completes successfully, then you know that both windows are the same domain.
However, this will log an error message to the console.
Try this (in iframe)
<script type="text/javascript">
var detectOrigin = (window.location.ancestorOrigins === undefined ?
/example.com/.test(document.domain) /* firefox */ :
/example.com/.test(window.location.ancestorOrigins[0])); /* webkit */
if (detectOrigin === true) {console.log(detectOrigin)}; /* `true` example.com origin */
if (detectOrigin === false) {console.log(detectOrigin)}; /* `false` !example.com origin */
</script>
If I see your use case:
I would check it server side (who called your site), using $_SERVER['REMOTE_ADDR']
, and if it is your IP than you can hide branding and links backs.
If the use case is about to prevent framing your site you can use X-Frame-Options: deny
.
Other guess:
Elements inside a document have a ownerDocument
property, maybe that can help detecting what you want.
I attempted to use referer to determine cross-domain, but I discovered it was unreliable on many sites. Maybe someone will find this useful.
function IsCrossDomainFrame() {
if( parent === window ) return false; //not a frame
var parentLocation = new URL(document.referer);//the referer of an iframe is the parent
return (parentLocation.protocol !== location.protocol ||
parentLocation.hostname !== location.hostname ||
parentLocation.port !== location.port);
}
Protocol, hostname, and port determine cross-domain.
For nested iframes : a recursive way to know if iframe (where this code is executed) is cross domain or not :
function crosDomIfrm(win, data) {
data = (typeof data === 'undefined')?{ref:win.document.location,isCD:false}:data;
try {
if( win.document.referrer != '' ){
data.isCD = parseURL(data.ref) != parseURL(win.document.referrer);
}
} catch(e){}
if ( (win.self !== win.parent) && !data.isCD ) { //I'm in iframe
data = crosDomIfrm( win.parent, data );
}
return {ref:data.ref,isCD:data.isCD};
},
function parseURL(url) {
var a=document.createElement('a');
a.href=url;
return a.hostname;
}