Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome extension: send postMessage from iframe to parent window [duplicate]

I'm doing a plugin to do some transformations to the interface. I keep getting unsafe javascript attempt to access frame with url.... Domains, protocols and ports must match (typical cross site issue)

But being an extension it should have access to the iframe's content http://code.google.com/chrome/extensions/content_scripts.html ...

Doesn anyone know how to access it's contents so they can be capturable?

like image 661
fmsf Avatar asked Jul 04 '12 08:07

fmsf


People also ask

Can postMessage be intercepted?

A malicious site can change the location of the window without your knowledge, and therefore it can intercept the data sent using postMessage .

How do you communicate between two iframes?

Communicating directly between iframes is also possible by combining window. parent with target as defined above. In conclusion, the postMessage method is a more dynamic alternative to the single DOM, better suited if you load multiple pages in one iframe, but not always easier and it still requires the use of the DOM.


2 Answers

There's generally no direct way of accessing a different-origin window object. If you want to securely communicate between content scripts in different frames, you have to send a message to the background page which in turn sends the message back to the tab.

Here is an example:

Part of manifest.json:

"background": {"scripts":["bg.js"]},
"content_scripts": [
    {"js": ["main.js"], "matches": ["<all_urls>"]},
    {"js": ["sub.js"], "matches": ["<all_urls>"], "all_frames":true}
]

main.js:

var isTop = true;
chrome.runtime.onMessage.addListener(function(details) {
    alert('Message from frame: ' + details.data);
});

sub.js:

if (!window.isTop) { // true  or  undefined
    // do something...
    var data = 'test';
    // Send message to top frame, for example:
    chrome.runtime.sendMessage({sendBack:true, data:data});
}

Background script 'bg.js':

chrome.runtime.onMessage.addListener(function(message, sender) {
    if (message.sendBack) {
        chrome.tabs.sendMessage(sender.tab.id, message.data);
    }
});

An alternative method is to use chrome.tabs.executeScript in bg.js to trigger a function in the main content script.

Relevant documentation

  • Message passing c.runtime.sendMessage / c.tabs.sendMessage / c.runtime.onMessage
  • MessageSender and Tab types.
  • Content scripts
  • chrome.tabs.executeScript
like image 54
Rob W Avatar answered Oct 02 '22 08:10

Rob W


I understand that this is an old question but I recently spent half a day in order to solve it. Usually creating of a iframe looks something like that:

var iframe = document.createElement('iframe');
iframe.src = chrome.extension.getURL('iframe-content-page.html');

This frame will have different origin with a page and you will not be able to obtain its DOM. But if you create iframe just for css isolation you can do this in another way:

var iframe = document.createElement('iframe');
document.getElementById("iframe-parent").appendChild(iframe);
iframe.contentDocument.write(getFrameHtml('html/iframe-content-page.html'));
.......
function getFrameHtml(htmlFileName) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("GET", chrome.extension.getURL(html/htmlFileName), false);
    xmlhttp.send();

    return xmlhttp.responseText;
}
.......
"web_accessible_resources": [   
    "html/htmlFileName.html",
    "styles/*",
    "fonts/*"
]

After that you can use iframe.contentDocument to access to iframe's DOM

like image 30
Eugene Titarchuk Avatar answered Oct 02 '22 08:10

Eugene Titarchuk