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.
Related
After reading this compendium of methods here Ways to circumvent the same-origin policy it's apparent that any workaround requires modification of the target iframe code to get communications across domains.
Unfortunately on this project I'm working on I may only modify the parent page's code, the iframe is provided from another source and is untouchable by us. Are there any methods that don't require modifications to the iframe code?
The only solution then is to fetch the iframe content from your server, either through a proxy or through specific code, and serve it yourself so that the browser only sees one origin.
But be aware that this usually breaks the rules or contract of normal use of the site providing the iframe. If they didn't include CORS headers to allow inclusion and access, there's probably a reason.
No, there cant be such a method, that would kill the security.
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
How can an IFRAME with URL https://domain/ access the DOM of the parent frame which has URL http://domain/ (HTTPS calls HTTP)?
Both frames will cooperate. The domain is the same in both frames, just the protocol is different. Setting document.domain is not allowed as that would allow for XSS attacks coming from other untrusted frames.
As an alternative to accessing the DOM it would be enough to send a message (containing a single integer). Notice, that the postMessage API only works in IE8+. I need IE6+.
Is easyXDM an option. It supports postMessage for browsers with support, and falls back to other mechanisms for older browsers. Some of the mechanisms are a bit hacky but they work.
But why do you want to have a secure iframe on an insecure page?
I have a web app in http://domain1/app1/called.html, and I want to embed that application inside http://domain2/app2/caller.html with an iframe (or a popup, it's the same)
the user should be able to interact with called.html, until they press a certain button, in that case I need to tell caller.html that the user selected an item from called.html
I tried implementing it with javascript.
in called.html I encode the data in json, and then I execute a "called_callback" javascript function in caller.html, passing the json as a parameter.
if called.html was called with a popup, I issue window.opener.called_callback( jsonData ), if it's an iframe I just issue parent.called_callback( jsonData )
having caller.html and called.html in the same domain everything works fine, but from different domains I get the following errors:
permission denied (on IE6)
and
Unsafe JavaScript attempt to access frame with URL [..]/caller.html from frame with URL [...]called.html. Domains, protocols and ports must match. (on google chrome)
Is it possible to overcome this limitation?
What other way of achieving it can you think of???
I guess caller.html could implement a web service, and I could send the result calling it, but the page caller.html would have to poll in order to detect any change...
So how can one application communicate with another one in a different domain to signal an event???
You can use JSONP to call resources from one domain to another.
You can use window.name as ~2Mb text transfer between cross domain frames for older browser.
Or for modern browser you can use window.postMessage to communicate string data between the 2 frames.
But you need some cooperation from the domains for these techniques to work.
You should look into using JSONP. It is fully supported in jQuery if you are using that particular framework. It allows you to use JSON across domains.
Thanks to both answer I found the following:
http://benalman.com/code/projects/jquery-postmessage/docs/files/jquery-ba-postmessage-js.html
http://benalman.com/projects/jquery-postmessage-plugin/
jQuery postMessage enables simple and
easy window.postMessage communication
in browsers that support it (FF3,
Safari 4, IE8), while falling back to
a document.location.hash communication
method for all other browsers (IE6,
IE7, Opera).
With the addition of the
window.postMessage method, JavaScript
finally has a fantastic means for
cross-domain frame communication.
Unfortunately, this method isn’t
supported in all browsers. One example
where this plugin is useful is when a
child Iframe needs to tell its parent
that its contents have resized.
I'll have a look at it...
here's a very complete document that analizes the different approaches...
http://softwareas.com/cross-domain-communication-with-iframes
another solution to have a look at
http://easyxdm.net/
with a sample
http://easyxdm.net/wp/2010/03/17/setting-up-your-first-socket/
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.