Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to postMessage into iFrame?

I am developing a Chrome extension to use with my own Web-application, processing Web-pages (including cross-domain ones), loaded into iFrame on my application's main page. So I have to send message, containing the URL of the page to be processed, from my main page to the content script, injected into the target iFrame to get access to the processed page's window.

I try to implement the approach, described here. Below are the essential parts of all files involved:

index.html:

...
<head>
    ...
    <script type="text/javascript" src="base.js"></script>
</head>
<body>
    <div>
        <input type="text" id="page_url">&nbsp;<input type="button" id="get_page" value="Get page">
    </div>
    <iframe id="cross_domain_page" src=""></iframe>
</body>

base.js:

(function() {
    "use strict";
    function pageProcessing() {
        let urlButton = window.document.getElementById("get_page");
        urlButton.addEventListener("click", () => {
            let url = window.document.getElementById("page_url").value;
            window.postMessage(
                {
                    sender: "get_page_button1",
                    message: url
                },
                "*"
            );
            window.postMessage(
                {
                    sender: "get_page_button2",
                    message: url
                },
                "*"
            );
        });
    }
    window.document.addEventListener('readystatechange', () => {
            if (window.document.readyState == 'complete') {
                pageProcessing();
            }
        }
    );
})();

manifest.json:

{
  "manifest_version": 2,
  "name": "GetPage",
  "version": "0.1",
  "content_scripts": [
    { "js": ["main.js"], "matches": ["<all_urls>"] },
    { "js": ["frame.js"], "matches": ["<all_urls>"], "all_frames": true, "match_about_blank": true }
  ],
  "permissions": ["activeTab"]
}

main.js:

(function() {
    "use strict";
    window.isTop = true;
})();

frame.js:

(function() {
    "use strict";
    window.addEventListener("message", (event) => {
        if (event.data &&
            event.data.sender == "get_page_button1") {
            if (window.isTop) {
                alert("Main window alert");
            } else {
                alert("Frame window alert 1");
            }
        }
    });
    if (!window.isTop) {
        window.addEventListener("message", (event) => {
            if (event.data &&
                event.data.sender == "get_page_button2") {
                alert("Frame window alert 2");
            }
        });
    }
})();

The problem is that when I click "get_page" button the only alert I see is the main window alert. As for my understanding it means that the message, posted from the main window, does not reach the content script, injected into iFrame.

What is wrong with my script and how to fix the problem?

like image 753
Kostiantyn Ivashchenko Avatar asked May 01 '20 18:05

Kostiantyn Ivashchenko


People also ask

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.

Does iframe have its own window?

In action: iframeAn <iframe> tag hosts a separate embedded window, with its own separate document and window objects.


Video Answer


1 Answers

window.postMessage in your web app sends to the main document's window, not to the iframe's.

Specify the iframe's window object:

document.getElementById('cross_domain_page').contentWindow.postMessage(.......)

Alternatively, you can switch to the more secure externally_connectable messaging.

like image 95
wOxxOm Avatar answered Oct 17 '22 23:10

wOxxOm