How to set focus to top frame within an iframe crossdomain. - javascript

I have an iframe in my web-page. So when Esc is pressed inside the iframe I need to set focus the top frame of document. The iframe is from an different domain.
Here Frame-B URL will be some abc.com and frame-A will be from xyz.com
So when an event is fired in Frame-B I need to focus Frame-A.
I can bind any number of events in Frame-A and Frame-B.
I have found a old way like this "An iframe in an iframe in an iframe". which am not interested in.
Any Idea how this can be done?

If you have some control over the outer frame (let's say it's your site, but still a different one than B), then there's a number of solutions to your problem. If you don't have any control over the outer frame, (because it is google.com for example) then there's nothing you can do. The browsers are designed to prevent it. See Jonas answer.
So what about if you can control the outer page? Any of the following would work:
Use postMessage. All you have to do is adding an very generic event listener in Frame-A. It's available in "all" browsers except IE7 and below.
Use a server as a middleman. Send a request from Frame-B to your server and let Frame-A access it from there. If you don't want to poll, you could use web sockets in Frame-A (or rather a good web socket lib, that fallbacks on other technologies if web sockets are not present).
Use the fragment identifier hack. You can read about that (and several other techniques) here: http://softwareas.com/cross-domain-communication-with-iframes

Related

Accessing and modifying iframe contents, postMessage vs jQuery.contents()

It's possible with
$('#iframe_id').contents().find('.stuff_to_modify).addClass('whatever');
But it's also possible using window.postMessage events, by sending a do_something message to a script from the iframe, which does the modifications when the message is received (adds that class).
I was wondering which is the way I should go, and what are the differences between these two methods (drawbacks, advantages).
The jQuery method seems nicer because I don't need to include any script in my iframe anymore
The major difference between window.postMessage and jQuery sample you gave is that, postMessage enables cross-origin communication.
Meaning, if a Parent page which hosts the iframe is from domain A, while the content of the iframe is from domain B, then postMessage allows you to communicate while the jQuery approach will result in the security error.
The link you provided is a java script wrapper to window.postMessage implementation of the browser and falls back to window location hash polling for browsers that do not support it. Other benefits are listed in your link itself.
So, if the two pages are from same origin, i.e served from same domain, then you can go the jQuery approach itself. If it is from two different origins, you may have to use the JS wrapper.

How can I prevent an iframe from accessing parent frame?

I've got a page with an iframe. The page and the source of the iframe are in different domains. Inside the iframe I'm using a rich text editor called CuteEditor (which has turned out to be not so cute). There are certain javascript functions in CuteEditor which try to access 'document' but the browser denies access since they're not in the same domain.
Here's the exact error:
Permission denied to access property 'document'
http://dd.byu.edu/plugins/cuteeditor_files/Scripts/Dialog/DialogHead.js
Line 1
Editing the javascript is out of the question because it's been minfied and obfuscated so all the variable names are cryptic.
Using a different editor is currently out of the question because this is a work project and this is the editor I've been told to use.
Is there a way to keep the iframe self-contained? So it does everything inside the iframe and doesn't try to break out to the parent frame?
If the child iframe is loaded from a different domain, then it will not be able to access the parent page or DOM.
However, there is a still a possible vulnerability to man-in-the-middle attack as follows. Suppose your page loads off http://yoursite.com and the iframe goes to http://badsite.org
first http://badsite.org redirects to http://yoursite.com/badpage
This is the step that requires a man-in-the-middle attack. The attacker must either be able to get between the user and yoursite.com, or control the answers to your DNS lookup. This is easier than it sounds -- anyone who has administrative control over a public WiFi access point could do it (think Starbucks, hotels, airports.) The goal is to serve the content of http://yoursite.com/badpage from the attacker's site, not your actual site.
The attacker can then serve whatever malicious code they like from the (fake) http://yoursite.org/badpage. Because this is in the same domain as the main page, it will have access to the parent DOM.
The HTML5 iframe sandbox attribute seems to be the way to avoid this. You can read the spec, but the best description might be here.
This seems to be supported on Chrome, IE10, FireFox, Safari.
The spec says that if the "allow-same-origin" attribute is not set, "the content is treated as being from a unique origin." This should prevent your child iframe from accessing any part of the parent's DOM, no matter what the browser thinks the URL is.
You shouldn't need to worry about that happening.
The only way iframes can talk cross-origin is with postMessage, and that's only possible if you're listening to that domain directly.
https://developer.mozilla.org/en/DOM/window.postMessage

Running a bookmarklet on an iFrame that is coming from a different domain

Is there any way to run a bookmarklet on an iFrame which is from a different domain?
For example, I have a page loaded from http://example.com, which has an iFrame whose source is set to http://example2.com. When I run the bookmarklet, it is always run on http://example.com, since that is the main page. I want to run it on the other iFrame though.
When I attempt to interact with the iFrame (e.g. by changing its source attribute to javascript:alert('test')), Chrome shows the following error:
Unsafe JavaScript attempt to access frame with URL http://example.com from frame with URL http://example2.com. Domains, protocols and ports must match.
I tried dragging and dropping the bookmarklet into the frame, but it says:
Failed to load resource
Is there any way for me to interact with an iFrame using a bookmarklet in Chrome?
There is a way to do cross-domain message-passing (not arbitrary code execution) using window.postMessage, yet all a frame A can do to frame B (when they are not of the same origin) is passing it a message hoping that B has a callback function listening for this message.
So here if you control exemple2.com (what's in the frame that don't get the bookmarklet), you can make the bookmarklet pass a message to the iframe and handle it in the iframe.
Else I don't think you have a solution here, except very complicated ones (like proxying).
Other links:
In-depth article about same origin policy and its implementations in browsers
A cross-browser, backward compatible postMessage attempt (as jQuery plugin)
iFrames have alot of security on them as do ajax calls.
Any attempt to use these in a cross-domain manner will result in a security error.
Imagine you were able to interact with other iFrames on different domains. You would be able to make an iFrame (like facebook login's page) that had width and height of 100% and add a function to execute on a submit event which would email you the username and pass before submitting.
So you're gonna have a lot of trouble accomplishing what you're trying to do. You basically can't mess with a page that you don't own. You can use firebug to edit it with the html tab though.
Hope that helps
One option if you are not in control of the page or the iframe is to load the iframe into a new window. The src attribute of the iframe is available to read by the parent JS, which can then open a new tab or window. The user can then click on the bookmarklet a second time to load it into this new page.

monitoring iframe content/status from the parent page

What methods are available to monitor the status of IFRAME page, I know there are security limits but I hope some small notification system is still possible.
My situation is that I have created a parent page that is located on customer's server, and this page has has iframe page located on my server (my domain). I need to somehow communicate a little between these two:
Can I make javascript to the parent page that can check if my iframe page has a specific string on it, or somehow make iframe page to notify the parent page?
Is there e.g. any possibility to make a timer that checks iframe content time to time?
I also accept answer how mydomain/client.page calls callback on customerdomain.intranet.com/parentpage.htm that has client on iframe
You need to use cross site JavaScript techniques to be able to do this. Here is an example.
Put another file into your server, call it helper.html, include it to your file served by customers server using an iframe. Set the src of the helper.html iframe with adding get parameters, ie. http:/myserver.com/helper.html?param1=a&param2=b, in the helper file use javascript to call method on parent's parent ( parent.parent.messageFromIframe(params) ). Which is the page on your server itself. Since helper and the container page are on the same domain it should work. The technique is popular, for instance Facebook was using it for their Javascript api.
I got information that this is possible by setting parent.location (from iframe) to have hash data like this "mydomain.com/mypage#mymessage"
By default, security restrictions in the browser will prevent access from/to the document in the iframe if it is in a different domain to the parent page. This is, of course, just as it should be.
I believe this would prevent even checking the current location of the iframe, but that's easily testable. If it's accessible, then you could poll the iframe for its location, and whenever the page in the iframe updates, have it append a random querystring parameter. Comparison of that parameter to the value from the previous poll would tell you if it's changed.
However, as I say, I suspect it's not possible.
Edit: This question suggests it is only possible for the initial src attribute: How do I get the current location of an iframe?

How to gracefully handle iframe breaker?

I understand that there is no way to kill the iframe breaker... However, I was wondering, is there a way to gracefully handling it.
So far, I managed to detect it before exiting, using <body onunload="function();">. I was wondering whether it is possible to prevent it from loading the iframe or force it to open in the new window, etc.
Cheers,
Mickey
In fact, you can actually do what you really want to do, which is bust the iframe buster. The technique lets you use onbeforeunload to switch the page back to yours, but indirectly, since the browsers are too smart to let you set the URL in onbeforeunload. So instead, onbeforeunload sets an indicator variable to mark that the URL has changed, and you periodically poll that variable using a setInterval routine established when your page loads. As long as you're polling fast enough to catch the variable change, you can jump in and change the page's URL yourself. The trick is to change it to a page that returns a 204, a special status which tells the browser to leave the current page alone.
That said, this is a cat-and-mouse game. Check out Jeff Attwood's StackOverflow question on this, where he asks how to bust the above technique. Web pages can bust the buster buster by beating the poll interval; basically, they set the URL to point to a tiny page, and one that has already been cached. As soon as the URL changes to that page, it will load faster than the poll routine can jump in and notice that the indicator variable has changed.
It's not easy to prevent loading the frame in the first place. If you really wanted, you could have your server download the page and parse the Javascript to see if the iframe-busting technique is present. However, short of emulating a browser, you can only rely on basic pattern-matching and it would be easy for a page to bypass that. (e.g. use top["l"+"ocation"] instead of top.location).
A smarter technique would be to track which URLs were redirecting using Ajax requests back to the server. (e.g. if the iframe is still there after it has loaded, send an Ajax request back to your server). You can't 100% guarantee the accuracy of those requests, since they come from the browser, but you can at least use them to build up a manual blacklist.
You also can't force the iframe to break out into another window.
You can use the sandbox attribute introduced in HTML5 to prevent the iframe buster. Just don't include allow-top-navigation in the whitelist:
<iframe sandbox="allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts"
src="foo.html"></iframe>
Are you talking about an embedded iframe setting top.location? There's no way to prevent that as far as I know.
If you're worried about the contents of an iframe doing something you don't want, you could consider sanitizing the contents of that frame and hosting it yourself. Obviously this is very tricky, but it's pretty much the only true solution. See Caja for a project that does this. This limits what you can actually host of course (if the code you're hosting uses XHR you're outta luck, for instance).

Categories