93

些細な例を機能させようとしていpostMessageます...

  • IE10で
  • ウィンドウ/タブ間 (対 iframe)
  • 起源を越えて

これらの条件のいずれかを削除すると、問題なく動作します:-)

しかし、私が知る限りpostMessage、両方のウィンドウがオリジンを共有している場合、ウィンドウ間は IE10 でのみ機能するようです。(実際には、奇妙なことに、動作はそれよりもわずかに寛大です。ホストを共有する 2 つの異なるオリジンも機能するようです)。

これは文書化されたバグですか? 回避策やその他のアドバイスはありますか?

(注:この質問は問題に触れていますが、その答えは IE8 と IE9 に関するもので、10 ではありません)


詳細と例...

ランチャーページのデモ

<!DOCTYPE html>
<html>
  <script>
    window.addEventListener("message", function(e){
      console.log("Received message: ", e);
    }, false);
  </script>
  <button onclick="window.open('http://jsbin.com/ameguj/1');">
    Open new window
  </button>
</html>

ページのデモを開始

<!DOCTYPE html>
<html>
  <script>
    window.opener.postMessage("Ahoy!", "*");
  </script>
</html>

これはhttp://jsbin.com/ahuzir/1で機能します-- 両方のページが同じオリジン (jsbin.com) でホストされているためです。しかし、2 番目のページを別の場所に移動すると、IE10 で失敗します。

4

8 に答える 8

62

この回答を最初に投稿したとき、私は間違っていました.IE10では実際には機能しません。どうやら人々はこれが他の理由で有用であることに気づいたので、後世のために残しておきます. 以下の元の回答:


注目に値する:IE8とIE9の別々のウィンドウのクロスオリジンではない状態にリンクしたその回答のリンクpostMessage-ただし、IE10が登場する前の2009年にも書かれました。だから私はそれがIE10で修正されたことを示しているとは思わない.

それpostMessage自体に関しては、http: //caniuse.com/#feat=x-doc-messaging は、IE10 ではまだ壊れていることを特に示しており、デモと一致しているようです。caniuse ページは、非常に関連性の高い引用を含むこの記事にリンクしています。

Internet Explorer 8 以降は、クロス ドキュメント メッセージングを部分的にサポートしています。現在、iframe で動作しますが、新しいウィンドウでは動作しません。ただし、Internet Explorer 10 は MessageChannel をサポートします。Firefox は現在、クロスドキュメント メッセージングをサポートしていますが、MessageChannel はサポートしていません。

したがって、あなたの最善の策は、おそらくベースのコードパスを持ち、それが存在しない場合にMessageChannelフォールバックすることです。postMessageIE8/IE9 のサポートは得られませんが、少なくとも IE10 では動作します。

ドキュメントMessageChannel: http://msdn.microsoft.com/en-us/library/windows/apps/hh441303.aspx

于 2013-05-01T05:49:47.930 に答える
30

ランチャーと同じホストにプロキシ ページを作成します。プロキシ ページには、iframeリモート ページに設定されたソースがあります。クロスオリジンの postMessage は、次のように IE10 で機能するようになりました。

  • リモート ページはwindow.parent.postMessage、データをプロキシ ページに渡すために使用します。これはiframeを使用するため、IE10でサポートされています
  • プロキシ ページはwindow.opener.postMessage、データをランチャー ページに戻すために使用します。これは同じドメイン上にあるため、クロスオリジンの問題はありません。postMessage を使用したくない場合は、ランチャー ページでグローバル メソッドを直接呼び出すこともできます。window.opener.someMethod(data)

サンプル (すべて架空の URL です)

のランチャーページhttp://example.com/launcher.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Test launcher page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function log(msg) {
            if (!msg) return;

            var logger = document.getElementById('logger');
            logger.value += msg + '\r\n';
        }            

        function toJson(obj) {
            return JSON.stringify(obj, null, 2);
        }

        function openProxy() {
            var url = 'proxy.htm';
            window.open(url, 'wdwProxy', 'location=no');
            log('Open proxy: ' + url);
        }

        window.addEventListener('message', function(e) {
            log('Received message: ' + toJson(e.data));
        }, false);
    </script>
    
    <button onclick="openProxy();">Open remote</button> <br/>
    <textarea cols="150" rows="20" id="logger"></textarea>

    </body>
</html>

プロキシページhttp://example.com/proxy.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Proxy page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function toJson(obj) {
            return JSON.stringify(obj, null, 2);
        }

        window.addEventListener('message', function(e) {
            console.log('Received message: ' + toJson(e.data));

            window.opener.postMessage(e.data, '*');
            window.close(self);
        }, false);
    </script>

    <iframe src="http://example.net/remote.htm" frameborder="0" height="300" width="500" marginheight="0" marginwidth="0" scrolling="auto"></iframe>

    </body>
</html>

のリモートページhttp://example.net/remote.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Remote page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function remoteSubmit() {
            var data = {
                message: document.getElementById('msg').value
            };

            window.parent.postMessage(data, '*');
        }
    </script>
    
    <h2>Remote page</h2>

    <input type="text" id="msg" placeholder="Type a message" /><button onclick="remoteSubmit();">Close</button>

    </body>
</html>
于 2014-07-01T13:39:36.833 に答える
1

現時点 (2014-09-02) では、この問題の回避策について詳しく説明している msdn ブログ投稿 ( https://blogs.msdn.microsoft.com/ieinternals/2009 ) に記載されているように、プロキシ フレームを使用することをお勧めします。 /09/15/html5-implementation-issues-in-ie8-and-later/

これが実際の例です: http://www.debugtheweb.com/test/xdm/origin/

ポップアップと同じオリジンを持つページにプロキシ フレームを設定する必要があります。を使用して、ポップアップからプロキシ フレームに情報を送信しwindow.opener.frames[0]ます。次に、プロキシ フレームからメイン ページへの postMessage を使用します。

于 2014-10-02T22:33:09.777 に答える
-3

MessageChannel は、IE 9 ~ 11 のウィンドウ/タブ間では機能しません。これは、このシナリオではまだ壊れている postMessage に依存しているためです。「最善の」回避策は、window.opener (つまり、 window.opener.somefunction("somedata") ) を介して関数を呼び出すことです。

回避策の詳細はこちら

于 2014-05-07T15:41:56.870 に答える