...but I do control part of the javascript inside the second domain (which integrates the iframe).
So, what I need is some workaround my problem. We have example2.com (this one holds the iframe) and example.com (this one is the original, within the iframe). Inside the iframe the user clicks a button that executes parent.redirectUser() and although I have that function defined in example2.com it fails to execute because it points the function as forbidden to access from within the iframe. Considering I can control the javascript in example2.com, is there any other way to workaround this situation? Thank you very much for your help...
Yes, you can do it.
You can use messages technique,
send message from child(example2.com):
parent.postMessage("Ok", "example.com");
in parent(example.com) you must add the following code:
//add eventlistener for message event
if (window.addEventListener) {
window.addEventListener("message", listener);
} else {
// IE8
window.attachEvent("onmessage", listener);
}
function listener(event) {
//check the message trust or not?
if (event.data == "Ok") {
//from parent you can call function, but function must be placed in global scope
redirectUser();
}
}
Related
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.
I am attempting to run a script in a webpage, that should be executed in an <iframe>. Right now I can call a function that is set within the <iframe>.. I'm just having issues running a script to the <iframe>'s context.
Here's how I run a function set in the <iframe>
$('#iframe').get(0).contentWindow.performSearch();
Now instead of calling the preformSearch function, I wish to run a script - for this example, this is the script...
console.log('worked!');
My actual script is a big one, so I won't put it here - for the sake of this question.
So, is there any way to run that script through the <iframe>'s context? For example, my first guess would be/was..
$('#iframe').get(0).contentWindow.function(){
console.log('worked!');
}
I've never messed with running functions through something like an <iframe> before though, so I'm stumped.
Thanks for any help in advance!
NOTE I am using NW.js (Node-Webkit) to remove all <iframe> restrictions.
NOTE v2 The preformSearch() function was just a reforence on how I call functions in the frame.
You could try and use the messaging mechanizm
which means that on the parent frame you could send the message with
var win =$("#iframe").contentWindow;
win.postMessage({ messageType: "predefinedMessage", features: data }, '*');
and than in the iframe you could get the message
function FrameCommunicator(attachManager) {
var mfilesFrame;
function _actOnMessage(data) {
if (data.messageType === "predefinedMessage") {
//perform here what you need
}
}
window.addEventListener("message", function (e) {
var data = e.data;
mfilesFrame = e.source;
_actOnMessage(data);
}, false);
}
now the thing is that the iframe and the parent fram can have the same code if they reference to the remotely.
Another way would be just to send the content of the message as JS and run it with eval , but that is risky , bad practice and lotsa other things :)
I'm trying to get postMessage() to work to communicate between an iframe and my main website. However using the exact syntax given in the example code on MDN, I am being presented with a nice Undefined is not a function error. I've tried several things, such as initializing the iframe inside Javascript and appending it to my page, but that left me with the same error. Same for have seperate selectors to select my iframe.
I have the following Javascript code:
<script type="text/javascript">
$(document).ready(function() {
$('.editor').postMessage("A", "domain here");
});
function receiveMessage(event)
{
if (event.origin !== "domain here")
return;
// Do something
}
window.addEventListener("message", receiveMessage, false);
</script>
The script above tries to send a message to my iframe on the page, which looks like:
<iframe src="domain here/frameListener.html" class="editor"></iframe>
It then has a function receiveMessage to catch any messages being send as a response to the main webpage. Last but not least, I've tried the answers given in this question: But that did not fix my problem. It is therefore not a duplicate.
How can I get rid of this error message?
postMessage is not a jQuery function so you need to get the actual window DOM element and call it on that:
$('.editor').get(0).contentWindow.postMessage("A", "domain here");
Furthermore, you need to access the contentWindow property of the iframe. Here is an excerpt from the MDN docs:
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
A reference to another window; such a reference may be
obtained, for example, using the contentWindow property of an iframe
element, the object returned by window.open, or by named or numeric
index on window.frames.
Javascript:
inFrame = true;
try {
if(window.top == self) {
inFrame = false;
}
} catch (err){}
try {
if(window.parent.location == self.location){
inFrame = false;
}
} catch (err){}
This is a piece of javascript code I use to detect whether my library is inside an iframe.
1 out of 100% of requests report that my library is inside an iframe which I think is not possible.
Is there a possibility that this code to fail [report true on false or vice versa]?
From access log [I log every such iframe requests]
I found that it happens in all modern browsers [ie 6-9, chrome, ff, safari] from user agent string.
I couldn't make any sense out of referrer because they are same as my publisher site.
In some cases I found for same referrer, same url requested & same client ip my library had been once inside an iframe & not in other. This made me doubt the above code.
Will there be any difference while window or document is being loaded in the properties [self, location, top, parent] I use to check? Because my script loads and executes synchronously mostly before the document is ready or window is completely loaded and that does the iniframe test to proceed further.
this is how I get the is in frame result and it works for me inFrame = window.top != window
If all you're trying to do is detect when your code is in a frame of any kind, all you need is this:
if (window.top !== window) {
// you are embedded in a frame
}
or to set your variable inFrame like this:
inFrame = (window.top !== window);
or in function form:
function isInFrame() {
return (window.top !== window);
}
As long as you aren't accessing properties on the window.top object, you shouldn't need exception handlers to protect from cross domain parents. In a cross-origin situation, you can access window.top, but you cannot access properties such as window.top.location.href.
As for your other questions:
Is there a possibility that this code to fail [report true on false or vice versa]?
The first part of your code looks OK though the exception handler is not required. The second part of your code will throw an exception every time in modern browsers when the window and parent frame are different origins.
Will there be any difference while window or document is being loaded
in the properties [self, location, top, parent] I use to check?
Because my script loads and executes synchronously mostly before the
document is ready or window is completely loaded and that does the
iniframe test to proceed further.
At the point your window is loading, it is safe to make this check. Both window and window.top will be valid at that point even if neither has completed loading yet. So, there should not be any issues with inFrame detection that require you to wait for anything to complete loading.
You know most modern browsers allow you to "View Frame" right? As in, view the frame content without the parent. That's an entirely plausable answer for 3. (I do it all the time).
A plausible cause of 1 and 2 is that self is not really defined in javascript therefore may not always be equal to window. You should therefore be checking window or better yet window.self not self like Özgür suggests.
I have a iframe (in my domain), that iframe has a file iframe.js.
My parent document has a file parent.js.
I need to call a function that is in parent.js, from a function that is in iframe.js.
I tried doing window.parent.myfunction() this function is in the parent.js file.
But, it didn't work. Only when I put the function on the parent page (I mean in the HTML), then it worked.
Any idea how to get this to work?
Try just parent.myfunction(). Also be 100% sure that the parent.js is included in your parent document.
I know this is an old question, but in case the accepted answer doesn't work (it didn't work for me) you could do this inside parent.js
window.myfunction = function () {
alert("I was called from a child iframe");
}
Now from the iframe you can call myfunction() like you initially wanted
window.parent.myfunction();
Window.postMessage() method safely enables cross-origin communication.
If you have access to parent page then any data can be passed as well as any parent method can be called directly from Iframe.
Parent page:
if (window.addEventListener) {
window.addEventListener("message", onMessage, false);
} else if (window.attachEvent) {
window.attachEvent("onmessage", onMessage, false);
}
function onMessage(event) {
// Check sender origin to be trusted
if (event.origin !== "http://example.com") return;
var data = event.data;
if (typeof(window[data.func]) == "function") {
window[data.func].call(null, data.message);
}
}
// Function to be called from iframe
function parentFuncName(message) {
alert(message);
}
Iframe code:
window.parent.postMessage({
'func': 'parentFuncName',
'message': 'Message text from iframe.'
}, "*");
References:
Cross-document messaging (https://html.spec.whatwg.org/multipage/comms.html#web-messaging)
Window.postMessage method (https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)
Can I Use (http://caniuse.com/#search=postMessage)