18

This is a bit complicated, please bear with me. Website A has a iframe that contains website B and website B has a iframe that contain website C.

There is a button on website C, when clicked, I want to refresh url of website B. below is the javascript called to do the refresh of website B from website C, which is in an iframe

function url_update(id){
   var host = 'https://websiteb.com ';
   var myHost = host.split('/'); 
   if (id != "" && myHost != ""){
    try {
        if (id.substring(0,1) != '/'){
            id = '/' + id;
        }
        var dft_url = myHost[0] + '//' + myHost[2] + id;
        window.parent.location.href = dft_url;
    } catch(e){alert("Cannot go to the desired url location: " + dft_url);}
   } 
 }

but when the line "window.parent.location.href = dft_url;" gets executed, I received the following error:

 Unsafe JavaScript attempt to initiate navigation for frame with URL  
 'https://websiteB.com' from frame with URL
 'https://websiteC.com'. The frame attempting navigation is 
  neither same-origin with the target, nor is it the target's parent or    
  opener.

I don't understand why this happening and how to fix it. Any help will be appreciated.

I did some research, most claimed this is an origin problem, but if I take out website A, meaning only have website B with an iframe that contains website C, then the above code works. Even though they have different domains

Noob Coder
  • 349
  • 1
  • 3
  • 10
  • You might want to make `c` a page in `b` make it part of `b`... – brso05 Jul 07 '15 at 13:32
  • 2
    You won't be able to do that if the domains are different, look into HTML5 messaging api. https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage With this api you can accept messages from sites with different domains and run JS based on the message, e.g. change the url of the page that received the message. – user2879041 Jul 07 '15 at 13:32
  • @ brso05: I can't do that, I do no own website B, or A, I only have access to website C. This is why C is in a iframe embed into B. – Noob Coder Jul 07 '15 at 13:38
  • @user2879041: is there a way to check what the value of window.parent of website C, is it website A or website B? – Noob Coder Jul 09 '15 at 14:40
  • @JayChen do you mean like window.parent.location.href? not entirely too sure of what you mean by the value – user2879041 Jul 13 '15 at 13:41
  • I've experienced the same thing, tested in Chrome 44. What's interesting is that C is actually allowed to change the location of the top window doing window.top.location.href = "blahblah" even though Website A and C are cross domain. I don't understand why iframe C can navigate the top window, but not iframe B. – Tore Jul 30 '15 at 10:45
  • @Tore indeed an iframe may change url of the top most window, which is rather surprising (though you may block this behaviour by sandboxing the iframe). If C is on different domain than B and A, and `postMessage` is not an option, then surely C is not able to change B's location. – artur grzesiak Jul 30 '15 at 15:44

2 Answers2

17

You can find an explanation of this behavior in a comment of the Chromium source code. See here:

https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/frame/Frame.cpp&sq=package:chromium&rcl=1438193817&type=cs&l=202

Basically top-level windows have less restrictions regarding navigation than other windows. See restrictions for non top windows:

A document can navigate its decendant frames, or, more generally, a document can navigate a frame if the document is in the same origin as any of that frame's ancestors (in the frame hierarchy).

Where as for top window:

Specifically, a document can navigate a top-level frame if that frame opened the document or if the document is the same-origin with any of the top-level frame's opener's ancestors (in the frame hierarchy).

Reason for that is:

Top-level frames are easier to navigate than other frames because they display their URLs in the address bar (in most browsers).

So basically, for a non top window, it absolutely needs to be same origin to allow navigation, but for top windows, a frame that was opened by that window can navigate even if it's not same-origin. Which seems to be the problem you're facing, when B is top, the same origin doesn't apply, but when it's not top, then it applies.

According to this, I'm not sure there's a straightforward, or any at all, solution.

Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57
3

I know this old, but I came here because I have same issue. I solved mine using sandbox attribute in my iframe :

var iframe = document.createElement('iframe');
iframe.setAttribute("sandbox", "allow-scripts allow-top-navigation");
var html = '<body><script>window.top.location="https://redirectDomain.tld";</script></body>';
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
document.body.appendChild(iframe);

You can read more from sources :
Creating an iframe with given HTML dynamically
Frames and Windows

Dzulfikar Adib
  • 116
  • 1
  • 7