Access parent window from iframe (cross-domain) - javascript

I've encountered the task to access parent window from iFrame, if the window in iFrame was loaded from another domain. If I understand correctly, all modern browsers do now allow to do this. So I'm here to find the best solution.
I'm going to accomplish this next way:
I have an overlay with an iFrame within it. This will work instead of pop-ups to prevent pop-up blockers to block my content. The task is to reload the main page when the document in the iFrame finishes some work.
In a document, which will be loaded to an iFrame, I will add
<div id="is_closed" class="false"></div>
In a parent window I'll add function, which will be called every second and check if this div still has class name "false". When this will be changed to "true", I'll call some callbacks.
If you have any better solution, please share it with me. Will appreciate any help.
Edit: This is impossible because it's not only impossible to manipulate parent window from child window, but vice versa too. My idea was to manipulate child window from parent window. I was wrong.

If I were you I would check out window.postMessage. It may do what you want:
For reference see the following:
MDN - Window.postMessage
https://stackoverflow.com/a/3076648/296889 - see the Window.postMessage section

If I understand correctly, all modern browsers do now allow to do this. So I'm here to find the best solution.
This is your solution. What you're asking is not possible.
See related questions:
How to access parent Iframe from JavaScript
<iframe> javascript access parent DOM across domains?
Cross-domain access in iframe from child to parent
EDIT
As mentioned in the comments below, #JeremysAwesome's answer offers a method that would allow cross-domain requests under certain circumstances. See the SO question below for more information.
Ways to circumvent the same-origin policy

but you can change the src attribute of the iframe (adding a #hashtag for example) and listen to the onhashchange event in the child window. Given that you're in position to change both pages.

another way would be: setting the iframes src to a javascript: link 500-ish milliseconds after it loads. Example:
setTimeout(function() {
document.getElementsByTagName("iframe")[0].src = `javascript:
(function(){
setInterval(function() {
if (document.getElementById("is_closed").className.match(/true/g)) {
...//see #jeremysawesome on how to do window.postMessage
}
})()`
}, 500);
While #jeremysawesome 's answer did work, this will work on an embedded iframe no matter the host domain, this is great when working with websites hosted on domains such as blogspot.com that don't allow you to change this type of content easily...
Now obviously you'll still need to launch window.postMessage, more info on that can be found on #jeremysawesome 's answer

set a variable/item in sessionStorage and use it on both sides as you wish.
localStorage can do it for longer times.
security risk is someone uses and manipulates this to hijack your side. BUT if someone wants to do so - there will allways be a possibility.
Remember: Life finds a way... ;-)

Related

How can I prevent Iframe messing browser's history after interactions with it?

So in my case I use Iframes to attach Grafana to my page (which provides me beautiful and easy to use graphs).
It's possible to notice that Grafana's Iframes triggers a kind of refresh on my Angular page after each interaction of zoom in or zoom out (using mouse clicks) on the graph thus messing broswer's history. I don't see any changes on Iframe's src to justify this page refresh and it doesn't trigger anything apparently (doesn't trigger any onload, for example).
Is this a normal behavior? How can I prevent this?
I am using a scripted dashboard of Grafana version 6.2.2 along with Angular 6.1.
Hoping to help out, some things that I might try in your scenario:
A blank html page with only a grafana Iframe in it. See if it still refreshes the parent page. If not, then maybe the problem is with angular.
You said sandbox breaks the iframe? Maybe play around with different sandbox values. Like allow-scripts and see if it needs one of those values to work
https://www.w3schools.com/tags/att_iframe_sandbox.asp
Maybe try putting the grafana iframe in another iframe. I've never done this before, but maybe it will try to refresh the parent iframe instead of the parent page.
It could be helpful to post your angular html code to the question too. Might be some hints in there.
Without the effective implementation of the iframe is difficult to suggest the best way to act.
The simplest solution that comes in mind is iframe's sandbox attribute:
<iframe src="my_iframe.html" sandbox></iframe>
What's an iframe sandbox ?
The sandbox attribute enables an extra set of restrictions for the content in the iframe.
When the sandbox attribute is present, and it will:
treat the content as being from a unique origin
block form submission
block script execution
disable APIs
prevent links from targeting other browsing contexts
prevent content from using plugins (through , , , or other)
prevent the content to navigate its top-level browsing context
block automatically triggered features
The value of the sandbox attribute can either be just sandbox (then
all restrictions are applied), or a space-separated list of
pre-defined values that will REMOVE the particular restrictions.
Ref: https://www.w3schools.com/tags/att_iframe_sandbox.asp
You can overwrite the <iframe>'s pushState and replaceState functions:
iframe.contentWindow.history.pushState = new Proxy(iframe.contentWindow.history.pushState, {
apply: () => {},
});
iframe.contentWindow.history.replaceState = new Proxy(iframe.contentWindow.history.replaceState, {
apply: () => {},
});

iFrame alternative for getting cross-domain URL

I'm creating a web-based game. As a part of it, the player must go to the home page of a website, and follow a series of link until he reaches to the "destination page" in the minor time possible. Think of it as a sort of link treasure hunt.
In order to control the game, I created a page with a javascript timer on the top, and an iFrame showing the website to surf (which is not mine and I have no control over it).
However this has a huge fault: it is not possible to detect the current cross-domain URL of the iFrame, so my page cannot know when the user has arrived to the destination page and stop the game.
Is there any alternative way I could achieve this?
Is there any alternative way I could achieve this?
No, there is not.
The Same Origin Policy completely prevents you from accessing properties of any window object that displays content from another domain.
(If one was a subdomain of the other, then document.domain would help. But from your problem description it doesn’t sound like that was the case.)
And besides the technical issue: Generating traffic and clicks (that will skew their statistics/analytics) on a site that you don’t own, just for the purpose of being able to present your own game, would be rather unfair (aka a “dick move”.)
You can wait upto the contentWindow of the iFrame is resolved and you have a reference to the iFrame's window, after you changed the source pragmatically.
once you have that, you can add a onload handler on iFrame's <body> and inject some postMessage call inside that handler, so once the body is loaded of the iFrame's window it wil call postMessage from the onload handler of body and it will notify your outer window, of-course you have to add message listener in outer window using window.addEventListener("message", callback)

Setting the onload property of a child window

I have a parent opening a new window, and trying to detect when the child window has loaded. In Chrome, I've tried
open('http://www.google.com').onload = function() { alert(location.href); };
but that doesn't seem to work.
Why doesn't the above method work? Are there alternatives?
If you want to be absolutely certain that a page has loaded, you can use messaging.
If you are able to use HTML5, there is a new feature called web-messaging.
This works very well on cross domain sources.
If HTML5 is not an option, use JS instead. I used a simple jQuery plugin called: windowmsg. It has worked excellently for me. I'm really not sure about this working on a cross site environment, but I think it should.
Beware of the security issues that these kind of solutions offer.
The method as it is should work(and works for me), but not when opening a window with a document from a different domain.
For security-reasons the new window will not dispatch the load-event to a document from another domain.
Technically speaking the child window and parent window are two different instances of the browser. We call them as child window and parent window. They do not have access to each other.So its not possible to perform any action in one window on the click of HTML elements in second window.
So, I suggest that you should not open a new window if you need access. You can use fancybox or lightbox that is effectively a part of the same window and that, you have control.

Make links inside an iframe open in a new window

I'm trying to display an map inside an iframe that has a needle which on mouseover shows some information about a certain company, the thing is once you click the link the page opens up inside the iframe which ruins the experience, so i was wondering is it possible to make the links inside an iframe open up in a new window instead perhaps using jquery or something similiar?
the code i have atm is
http://www.jsfiddle.net/rkd59/1/
Edit: the very least capture a click within the iframe so i might resize the iframe
You will need some kind of open API to do this properly, and Eniro doesn't provide one according to this page (in Swedish).
I would recommend you to use the Google Maps API v3 instead. I've made an example on jsFiddle that looks similar to that of Eniro.
I'll gladly give you more help with this, so just ask away!
You can't (or it is extremely hard to ) make events inside the iframe affect the parent page. This is to prevent attacks from XSS, or cross site scripting. Having said that, if the site within the iframe is on your own domain and you want to set up some extremely tricky ajaxing and php session IDs, maybe you could make something work, but even then I'm not sure. And I don't know if this would be a security hole, maybe someone else can speak to that. It would perhaps look like:
main page sets up session ID and passes that to the iframe url via a get variable
the iframe takes click information and sends it to a Session variable via an ajaxing call to a script on the server.
The main page then reads (how?) the session cookie and makes changes based on it's value.
All in all, you may find that it may be much simpler and more secure to acheive what you want using a different method.
Due this map is loaded inside an iFrame, it's not possible to run any javascript event listeners on the links, neither is it possible to change the html.
Please try the following:
<script>
x=document.querySelectorAll("a");
for(i=0;i<x.length;i++)
{
x[i].setAttribute("target","_blank");
}
</script>
Thus all links open in new frame.
To make a link popup in a new window you would usually use target="_blank" as such:
Go to Yahoo
However this will only work if you can modify the code you're showing within the iFrame
There is a partial solution.
You can add an absolutely positioned DIV tag over the top of the IFRAME and capture clicks on this instead. See example here shaded in 20% alpha red.
http://www.jsfiddle.net/rkd59/6/
However, this means that the map works in "read-only mode" and while you can capture the click event you wont know what link the user has clicked on.

Webpage limitations when wrapped inside an IFrame?

I am developing a webpage which our customers want to insert on their websites by wrapping my page in an iframe (cross domain). I don't need to interact with the parent or know anything about whats outside the iframe.
I am using HTML, CSS, Javascript and Webservices.
Question: How am I limited inside an iframe compared to if my page was running outside the iframe?
You're not. Any JS linked within the iframe from your domain will act in the context of the iframe. Aside from being crammed into an unusual container it should work the same as it would if it was loaded independently.
If your needs should change however, there are ways to send signals between parent frame and iframe if both pages have JS written to cooperate. There's methods using the # in URLs which can be read by the parent and don't force page reloads and I believe they share the window.resize event which can be fired manually without actually resizing the window.
UPDATE: There are far better ways to communicate between cross-domain iframes now than there used to be. Naturally you'll still require cooperating JS on both ends but you can use window.postMessage rather than triggering messages via window.resize and data after a hash symbol in the URL. That was a cool trick though.
When creating links you should have in mind to maybe use the target-attribute of the a-tag if you want to create a link for the parent window. Otherwise the new page would be loaded into the iframe.

Categories

Resources