web-dev-qa-db-ja.com

Chromeのwindow.postMessageに関する問題

私はこれに何時間も立ち往生しています。

http://example.com にa.htmlがあり、 http://subdomain.example.com にsrcからb.htmlへのiframeが含まれています。 a.htmlには、postMessageをiframeに送信するためのJSコードがいくつかあります。

PostMessageのコードは単純です。

iframe_window.postMessage('message', iframe_element.src)

しかし、このように、Chromeはエラーをスローします:

Unable to post message to http://subdomain.example.com. Recipient has Origin null.

私も試しました:

iframe_window.postMessage('message', 'http://subdomain.example.com')

しかし、運はありません!

これが機能する唯一の方法です。

iframe_window.postMessage('message', '*')

しかし、「*」は使いにくいと聞きました。

Firefoxでは問題ありません。

12
user1437328

これは、シグナルの送信時に子iframeがロードされていないという問題である可能性があるため、iframe.srcに適切な値がありません。

いくつかのテストを行ったところ、同じエラーが発生しましたが、postMessage呼び出しをsetTimeoutでラップし、100ミリ秒待機したとこ​​ろ、エラーは発生しませんでした。これは、これが初期化の競合状態であることを示しています。

SetTimeoutなしでよりクリーンなソリューションを実装した方法は次のとおりです。

親:

window.addEventListener("DOMContentLoaded", function() {

    var iframe = document.querySelector("iframe")
      , _window = iframe.contentWindow

    window.addEventListener("message", function(e) {

        // wait for child to signal that it's loaded.
        if ( e.data === "loaded" && e.Origin === iframe.src.split("/").splice(0, 3).join("/")) {

            // send the child a message.
            _window.postMessage("Test", iframe.src)
        }
    })

}, false)

子:

window.addEventListener("DOMContentLoaded", function() {

    // signal the parent that we're loaded.
    window.parent.postMessage("loaded", "*")

    // listen for messages from the parent.
    window.addEventListener("message", function(e) {

        var message = document.createElement("h1")

        message.innerHTML = e.data

        document.body.appendChild(message)

    }, false)

}, false)

これは、子がロードされたことを誰にでも通知する単純なソリューションです(「*」を使用します。機密情報は送信されていないため、問題ありません)。親はロードされたイベントをリッスンし、関心があるのは子であることを確認しますその中でそれを放出しています。

次に、親は子にメッセージを送信し、子はそれを受信する準備ができています。子供がメッセージを受け取ると、データを<h1>に入れ、それを<body>に追加します。

私はこれをChromeで実際のサブドメインを使用してテストしましたが、このソリューションは私のために機能しました。

19
Luke Channings