Communication between two iframes from the same domain with postMessage - html

I have two iframes from the same domain, which are hosted in document from another domain. The problem is these iframes cannot communicate with each other through postMessage. I cant even access the DOM of iframe1 from iframe2 even though they belong to same domain. Is there any solution ????
I used following options to refer the required iframe.
parent.frame[x]
I tried following lines to access DOM of iframes
parent.frame[x].contentWindow returns null,
parent.frame[x].document.getElementsByTagName("body") returns null
Update:
I guess my question is not clear enough. There is no problem with postMessage api, the actual problem is browser creates a custom frameset around the iframe document, in my case!
So parent.frame[x] won't point to the iframe window, instead it points to the custom frameset inside the iframe window.
Following question explains the problem well.
Prevent browser from loading a custom frameset in an iframe's document

If you want cross-window same-domain communication, you can set it up via localStorage. When you add an item to localStorage, you get window "storage" event in all other windows / iframes / tabs of the same domain.
So, you basically localStorage.setItem('name', 'value') in one iframe while you listen to window.addEventListener('storage', (event) => {/* handle message */}) and you get the message.

Take a look at the following description of the postMessage function and how it could be used. So in frame1 you call the postMessage method and in frame2 you subscribe for notifications. Obviously the browser you are using must support this API.
There's also a very nice jQuery plugin which wraps this API and simplifies its usage. It also works in browsers that do not support the postMessage method by using the hash portion of the url.

Related

How do we get iframes to allow state changes to reflect in our components?

I'm building a component that uses an <iframe> to display another component. This component connects to an NGXS state which needs to reflect changes made to the state. After a lot of failures and testing I discovered the component will always only load the default settings of the state. I created a <button> to toggle a boolean and added an *ngIf to the <iframe> so I can force it to reload manually after trying things like this.Frame.(contentDocument || contentWindow).location.reload(true); didn't make any difference.
I created a stablitz app to demonstrate this issue however I think stackblitz blocks the use of <iframe>s in their platform so you might need to copy it into a local project to tinker with it. It's a simple app that shows the state outside of the <iframe> as well as inside with a button that toggles the <iframe> on and off so you can see how only the default values load after you update the value I have available for demonstration purposes. I'm not getting any type of errors and the issue isn't a matter of something being wrong with the code so I don't know what more to show that isn't in the stackblitz.
Does anybody know why and how <iframe>s do this and if there's a way around it? The only thing I can think to try is make a NestJS app to see if putting the data outside the app and making an API request from the component inside the <iframe> will be allowed, however I don't know why this issue is occurring to in turn know if that too won't be rejected for that same reason. How this can be handled?
The document running in an iframe is isolated from its host. They do not share memory- Angular does not provide a way to synchronize state between a host and an iframe on the page out of the box. The example is actually booting two Angular apps (one inside the frame and one outside). If you are using an iframe for security and isolation purposes, you'll need to devise a way to pass state between the host and the child via postMessage (and be aware that you are running two copies of your application). If this isn't for security/isolation, simply do not use an iframe to contain the child component.

Avoid cookies pop up window inside iframe?

I have an iframe that displays live prices of stock market. My problem is that when i load my page, this iframe shows a pop up window for cookies policy.
Is there anyway to avoid this window completely (or select "accept" in background) so that this iframe will directly show stock prices?
I found some information about sandbox option but could not go deeper with that
My website is the following and the iframe is on the down-left
https://grbusinessforum.com/
("Αποδέχομαι" is the button of "Accept cookies")
Thanks
Sandboxing the iframe can prevent all JS from running inside it, but that would probably break the page in other ways.
There's nothing you can do from outside the frame.
You'd need to change the page inside the frame instead. You could add a query string to the URL that it uses to disable the tracking cookies by default, or use postMessage to send a message into the frame that code there uses to remove the cookie prompt.
Of course, this will need the cooperation of the people who control the site you are displaying in the frame … but if they are happy for you to show their content on your page that shouldn't be too much of a problem, should it?

Evaluate javascript on every dynamically loaded nested iFrames using Puppeteer

Before I start describing my problem I just want to give a heads-up that all the pages, iFrames etc. are hosted locally on my PC. And that I have used page.setBypassCSP(true) to temporarily disable any origin based restrictions.
Here we go, I have a webpage which embeds an iFrame and that iFrame may embed another one (and the list can go on...). Some of the deeper iFrames may be appended to the body of it's parent via Javascript e.g. document.body.appendChild inside a setTimeout(..., 3000) which kind of simulates a dynamic iframe load. I want to know what is the best way to evaluate a script source on all of these iFrames. I tried using page.on('framenavigated', ...) but this only works for the page's immediate child frame(s).
I tried recursively iterating through all the frames in the page using page.frames() but that only works for iFrames that are available at the time when the DOMContentLoaded event is fired.
I'm looking for a way to listen to all the framenavigated events fired by all the nested iFrames even for the ones that loaded dynamically at any point of time, after the page is loaded. Any pointers would be greatly appreciated.
UPDATE:
I have tried listening to events using page.on('frameattached', ...) and page.on('framedetached', ...) but that also doesn't let me list all iFrames.

Object Tag and IE9

I've come across an interesting problem with IE9 and object tags.
In the simplest form for a client I am hosting a website (ASP .NET Web Forms site) within an object tag from a page in a separate website, for reasons that are ridiculous and mind blowing, the html looks like the following:
<object id="so" data="https://so.com/so" scrolling="auto" frameborder="0">
</object>
In Chrome and Firefox when I click a link in the html inside the object tag, the browser tab has a loading icon (as per a normal page event) giving the user feedback that an event has occurred. In IE 9 this does not occur so the user doesn't know that clicking the link has fired any events.
I've looked at the onbeforeunload event of the object tag with no success, for instance:
<object id="so" data="https://so.com/so" scrolling="auto" frameborder="0" onBeforeOnLoad="javascript: onDocumentUnLoad();">
</object>
Using the above method the onbeforeunload function is not called.
I also tried using a ajax load via jQuery into a div but handling out of context css and js references and post-backs become unmanageable and also adding click events to every button or href affected performance and functionality.
I was was wondering if there's another approach to give the user feedback or a simple workaround.
I've found a solution that works.
In the parent page create an handler for a custom event. In this case "unloadingChild":
//using jQuery 1.4.2
$("body").bind("unloadingChild", function(){
console.log("child unloaded");
});
In the child hosted page trigger the custom event via the body unload event:
//body element unload
$(window).unload(bodyUnload());
function bodyUnload(){
//trigger the parent unloadingChild event
parent.$("body").trigger("unloadingChild");
}
I don't know if it's the best way but it seems like a good way. That certainly works for this scenario.
It doesn't solve the object unload but it gets around the problem.
This will only work for two websites with the same origin. Otherwise you will get an error similar to "Permission denied to access property '$'"

Any way to read elements from another website in an iframe?

I'm playing around with some stuff and trying to discern if when using a cross-domain iframe(post_message) if I can read the elements: div-tag p-tag etc of site within the iframe? I haven't seen any other posts on this, so hopefully someone can provide some insight.
postMessage allows you to communicate with a cooperating iframe. To use it, one window must send a message with postMessage and the other window must have an event listener listening for the message and it must process that message and do whatever you want done with it.
So, it is possible to use postMessage to retrieve content from an iframe, even a cross-origin iframe, but it requires that there be code in the iframe that can receive the message, understand what is being asked of it and do postMessage back to the original frame with the information that was requested.
So, this means that if you control both the window and iframe javascript, you can do what you ask, but if you don't control one of the two and they don't already have the right javascript code in them to fetch the data you want, then you can't get the job done with postMessage. All it does is deliver messages. The code to process those messages must be put there by the owner of that particular web page.