how to pass data to variables in iframe - javascript

I am working on project which connects a local server and global server (servers cant communicate) server communicate to html files via socket io
I am very new to this concept
my scenario is
browser connects to local app
local server sends html page which has iframe in it and iframe's source is global server
global server sends html page
my browser is showing html page in the global server and my local server is also running
how can I pass data from local server to global server?
basically local server sends data to container html file and it passes data to the html file in iframe so that it can pass data to global server
maybe a method is called from container html to iframe html and sends data ? is it possible?
hope I made my point clear
please help

What i understood that you need to pass some kind of variable in iframe so you can append your iframe's "src" property with it in the form of querystring.
You can get this querystring value while reloading of iframe.
e.g.
<div class="my-frame-container" myurl="http://myserver.com" elementid="mycontainerframe"><iframe id="myiFrame" src="" allowtransparency="true" width="100%" height="100%" frameborder="0"></iframe></div>
someEvent(e.g.: click)
window.parent.postMessage(
{
event_id: 'reloadMyFrame',
},
"*"
);
and in the iframe js file you can add a event listener
var eventMethod = window.addEventListener ? "addEventListener" :
"attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" :
"message";
eventer(messageEvent, function (e) {
var eventId = e.data["event_id"];
if(eventId==="reloadMyFrame")
{
var container = $('.my-frame-container');
var frameSrc = container.attr('myurl');
$('#myiFrame').attr("src", url);
$('#myiFrame').reload();
}
}
}

The best way is using event bus javascript
//main doc
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
console.log("main",event);
// ...
}
window.document.getElementById("iframe").contentWindow.postMessage('test', *);
//iframe
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
console.log("iframe",event);
// ...
}
window.parent.postMessage('test', *);
be aware of CORS problematic
https://developer.mozilla.org/docs/Web/API/Window/postMessage
More complet exemple

post message works fine but instead of post message you can call methods inside frame like an instance
$('#myIFrame').on('load',()=>{
let q = document.getElementById("myIFrame").contentWindow
q.method() // a method inside iFrames js
})
and you can call method from inside iFrame to main like
window.top.method();
BUT it will get caught on Uncaught DOMException: Blocked a frame with origin () from accessing a cross-origin frame. if you disable-web-security it will work fine

Related

Using postMessage to extension background page

I'm trying to send a CryptoKey (generated by SubtleCrypto.generateKey()) object from a contentscript to the background page of a webextension.
When using chrome.runtime.sendMessage to send the object, it is lost, as CryptoKey is not stringifyable (see also this question). Using window.postMessage to transfer the key to another window does work, as this method uses structured cloning..
Is there something similar to postMessage to send data that is not stringifyable to the background page of a webextension?
Thanks to the comment by #wOxxOm I solved it by creating a web accessible resource with this code:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
chrome.extension.getBackgroundPage().postMessage(event.data, "*");
}
This is triggered by the contentscript like that:
let iframe = document.createElement('iframe');
iframe.setAttribute('src', chrome.extension.getURL('webaccessible/index.html'));
iframe.addEventListener("load", () => {
iframe.contentWindow.postMessage(data);
})
While data is an object that contains the CryptoKey.
This data is received in the background script just like you normally would receive such messages:
window.addEventListener('message',(event) => {
console.log(event);
});

Access an Iframe variable from parent window

I have a webpage at url https://parent.com and it has an iframe injected into it with source https://iframe.com. Iframe has a global variable defined called iframe_variable. I want to access the iframe_variable from parent document.
I know browsers don't allow cross origin communication and they provide a postMessage API to do it securely.
Constraint: I do not have access to any of parent or iframe code.
On Browser console, I somehow want to access iframe_variable
I have tried the following:
Get reference of iframe first.
var iframe = document.getElementsByTagName('iframe')[0]; // There is only one iframe on document
Create a listener for message event posted from parent window.
var iframeListener = function(e) {
console.log("Got message from parent");
e.source.postMessage(JSON.stringify({'IFRAME_VARIABLE': window.IFRAME_VARIABLE}));
}
Create a listener for parent window to accept 'message' posted from iframe.
parentListener = function(e) {
console.log('Got message from iframe');
var data = JSON.parse(e.data);
window.VARIABLE = data.IFRAME_VARIABLE;
}
Attach parent_listener to message event.
window.addEventListener('message', parentListener, false);
Now if i try to post a message to iframe from parent as follows:
iframe.contentWindow.postMessage('test message', '*')
It doesn't trigger 'iframeListener'. The reason is because it is not registered against the message event in iframe.
I don't think I can even do that from the browser console when I am on parent.com as any attempt to do iframe.contentWindow.addEventListener will result in an error as it will be an attempt to access a different domain.
Is there a workaround that? Is there anything that I am missing in my understanding and research.
P.S: I have not written the origin checks for simplicity. I know I must check for the origin a message is posted from. Not doing that leaves a huge security hole.

How to postmessage HTMLIFrameElement?

I'm having issue passing HTMLIFrameElement object from parent site to iframe (located on a different domain) using postMessage method.
This is my code that I already tried:
var frame = document.getElementById('myHTMLIFrameElement');
frame = JSON.parse(JSON.stringify(frame));
event.source.postMessage(frame, "*");
Unfortunately, JSON.parse/JSON.stringify does not seem to be the right way of handling HTMLIFrameElement object. Can you please advise how to pass through HTMLIFrameElement object correctly?
Parsing DOM elements as JSON does not do anything useful as far as I know.
Since postMessage() is part of the window object, you could try using the window object of the frame, which is found under the contentWindow property of the iframe.
So you could try something like:
var frame = document.getElementById('myHTMLIFrameElement');
frame.contentWindow.postMessage( "stuffYouWantToSendToTheIframe", '*' );
And then in the script inside the iframe:
window.addEventListener('message', function( event ) {
// handle message
});

Cross Domain communication from Child (iframe) to Parent not working

I have a component within AEM (Adobe Experience Manager - a cms) on a page and I want to include this page onto another page (from a different domain) using an iframe. So in the code for the component I am using window.postMessage() and I'm trying to listen to that event in the parent. I have tried communicating the other way, parent to iframe and it worked fine, but I need to communicate the other way. So the component is a search component and when you click on a search result I want to redirect but from the parent window so I'm trying to send the URL to redirect to and then handle the redirection within the parent's JS code.
The code looks like:
(From the parent - html)
<iframe
width="1080"
height="700"
id="theFrame"
src="http://localhost:4502/content/zebra1/global/en_us/hey.html#q=print"
frameborder="0">
</iframe>
(From the parent - js)
function receiveMessage(e)
{
var key = e.message ? "message" : "data";
var data = e[key];
var redirect = JSON.parse(data);
redirectUrl = (redirect.origin ? redirect.origin : '') + (redirect.url ?
redirect.url : '');
if (redirectUrl) {
window.location.href = redirectUrl;
}
}
window.addEventListener("message", receiveMessage, false);
(From the iframe/child - js)
goToSearchResults : function( event ){
var windowOrigin = location.origin;
if( arguments[0].length == 3){
var redirect = {
origin: windowOrigin,
url: arguments[0][1].url || ''
};
if(!$('#supportSearchWrap').data('iframe')) {
location.replace(redirect.url);
} else {
window.postMessage(JSON.stringify(redirect), windowOrigin);
}
}
logger.log( redirect.origin + redirect.url , this.model );
}
It's not working for me. Does anyone see what I'm doing wrong or a better way to do this?
window.postMessage - The window refers to the instance of the window object to which you're posting your message. In your case, it should be the parent of the iframe window.
You can get that reference inside the iframe using window.parent or simply parent.
Also, the targetOrigin property should match the targeted window properties. From MDN docs, it is as below.
targetOrigin
Specifies what the origin of otherWindow must be for the event to be dispatched, either as the literal string "*" (indicating no preference) or as a URI. If at the time the event is scheduled to be dispatched the scheme, hostname, or port of otherWindow's document does not match that provided in targetOrigin, the event will not be dispatched; only if all three match will the event be dispatched.

How can I handle errors in loading an iframe?

I have an <iframe> that other sites can include so their users can POST a form back to my site. I'd like to handle gracefully the cases where my site is down or my server can't serve the <iframe> contents (that is, a response timeout or a 4xx or 5xx error). I tried adding an onError to the <iframe> object, but that didn't seem to do anything:
showIFrame = function() {
var iframe = document.createElement('iframe');
iframe.id = 'myIFrame';
iframe.src = 'http://myserver.com/someURLThatFailsToLoad';
iframe.onError = iframe.onerror = myHandler;
document.body.appendChild(iframe);
};
myHandler = function(error) {
document.getElementById('myIFrame').style.display = 'none';
console.error('Error loading iframe contents: ' + error);
return true;
};
If my server returns a 404 I just get the contents of the not-found page in my <iframe>. In fact, that error handler isn't ever triggered. Is there a way to make this work?
(I'm currently testing in Chrome, but I'd like it to also work for FF and IE >= 7.)
To detect whether your server is down or not, you can include an empty script file from your own domain. When the server is down, the onerror event handler will fire:
var el = document.createElement('script');
el.onerror = errorFunction;
el.src = "somebogusscript.js?" + new Date().getTime();
document.body.appendChild(el);
Note: don't forget to add a random string to the src attribute to avoid the client using a cached version (which could stop a look at the server at all).
Perhaps you could try onErrorUpdate for the event handler? I couldn't see an onError handler for iFrames. If that doesn't work, you could try onLoad and then check the source of the iframe or the title of it for a 404 message.
Such as:
if (frameDoc.title == 'title the server sends for 404') {
Source:
http://bytes.com/topic/javascript/answers/166288-catch-404-when-using-iframe
iFrame Methods: http://www.java2s.com/Code/HTMLCSSReference/HTML-Tag-Reference/iframeJavaScriptMethods.htm
iFrame Properties: http://www.java2s.com/Code/HTMLCSSReference/HTML-Tag-Reference/iframeJavaScriptProperties.htm
One technique is to set a JavaScript timeout when you make the request. If your timeout fires before the iframe onload event, the content didn't load. You could then set iframe.src to about:blank, delete, or reuse the iframe.

Categories

Resources