Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run code in context of frame window

I'd like to run some javascript in the context of an iframe's window. Right now the only way I can think to do that is to inject a script tag:

myIframe = document.createElement('iframe');
myIframe.setAttribute('name', 'xyz123');
document.body.appendChild(myIframe);

myIframe.contentWindow.document.write(`
    <script>
        console.log('The current window name is:', window.name);
    </script>
`);

Note: this is a same-domain iframe, without a src, so I have full access to the contentWindow.

It's important for my use case that the code runs with the correct globals; window, document etc should all be scoped to the iframe itself.

Is there any other way I can do this? The above works, but the script needs to run on different domains all with different CSP rules, which means adding support for nonces/hashes etc.

Is it possible to do something like:

myIframe.contentWindow.run(function() {
    console.log('The current window name is:' window.name);
});

I've tried myIframe.contentWindow.setTimeout but that still seems to run the code in the context of the parent window.

like image 684
bluepnume Avatar asked Sep 01 '17 04:09

bluepnume


2 Answers

You can actually create that run function, and then apply a callback function to this which of course will be the iframe context. Then you can access iframe elements by using this:

myIframe.contentWindow.run = function(fn) {
    fn.apply(this);
};

myIframe.contentWindow.run(function() {
    console.log('(run) The current window name is:', this.window.name);
});

Console output

(run) The current window name is: xyz123

You can check my example here: http://zikro.gr/dbg/html/con-frame/

EDIT

If you want to just use window rather than this.window, then you can create a parameter to the inline function with he name window, and then just pass this.window to that function like this:

myIframe.contentWindow.run = function(fn) {
    fn.call(this, this.window);
};

myIframe.contentWindow.run(function(window) {
    console.log('(run) The current window name is:', window.name);
});

And it still works as expected.

like image 146
Christos Lytras Avatar answered Nov 20 '22 19:11

Christos Lytras


Maybe split the javascript to part run from main window (let's call it main.js) and from iframe (let's call it iframe.js). Then in iframe's src place link to iframe.js or iframe.html which loads js file (I'm not sure if you can include javascript straight from src attribute).

If you load js into the iframe, use solution at Calling a function inside an iframe from outside the iframe.

like image 2
Marcin Szwarc Avatar answered Nov 20 '22 19:11

Marcin Szwarc