クロスオリジンのpostMessageはIE10で壊れていますか?


91

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

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

これらの条件のいずれかを削除すると、物事はうまくいきます:-)

しかし、私の知る限りでは、ウィンドウ間はpostMessage、両方のウィンドウがオリジンを共有している場合にのみIE10で機能するように見えます。(まあ、実際-そして奇妙なことに-振る舞いはそれよりも少し寛容です:ホストを共有する2つの異なるオリジンも機能しているようです)。

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

(注:この質問問題に触れていますが、答えは10ではなくIE8とIE9についてです)


詳細+例...

ランチャーページのデモ

<!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で失敗します。



5
MessageChannelを機能させるためにpostMessageが必要な場合は、受け入れられた回答を、MessageChannelを最善策としてリストするものではなく、質問に回答する回答に変更することを検討してください。MessageChannelを1時間以上使ってみましたが、唯一の実行可能なソリューションがiframeプロキシであることがわかりました。
Akrikos 2014年

1
window.openが単なるポップアップダイアログである場合は、それを完全に回避して、jsモーダルでiframeを使用できます。jQuery DialogBootstrap Modalのようなものが実装方法です。その後window.parent.postMessage、IEで使用できます。
スタイフル2015

@Bosh私の答えは、2018年に動作しているようですし、何のプロキシフレームを必要としないので、あなたはそれが私たちに助けに思えるようまだ古いすなわちをサポートする必要が不幸なものは、受け入れ答えとしてthatoneを設定する気だろう
ブルーノLaurinec

回答:


62

この回答を最初に投稿したとき、私は誤っていました。IE10では実際には機能しません。どうやら人々はこれが他の理由で役立つと思ったので、私は後世のためにそれを残しておきます。以下の元の答え:


注目に値する:その回答のリンクはpostMessage、IE8とIE9の別々のウィンドウの出所をクロスしていない状態にリンクしていましたが、IE10が登場する前の2009年にも書かれていました。そのため、IE10で修正されていることを示すものとは考えていません。

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

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

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

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


8
機能する- MessageChannelベースのコードパスをどのように作成しますか?postMessageチャネルのポートを他のウィンドウに取得するための機能がまだ必要です。
balpha 2013年

1
postMessage新しいMessageChannelAPIで使用すると、新しいウィンドウとオリジンで機能します。動作は少し厄介だと思いますが、基本的には:postMessage('foo', '*')悪い、postMessage('foo', [messageChannel.port2])良いです。
ShZ 2013年

3
最新バージョンのIE(11)とMessageChannel APIを使用して、クロスドメインポップアップウィンドウでpostMessageを動作させることはできません。そして正直なところ、この特定のシナリオが機能することを示すこの回答以外に、InterWebで他の場所を見つけることはできません。誰かがそれが機能することを証明する例を指摘できますか?永遠に感謝します。
トッドメニア2014年

4
MessageChannelは、postMessageが機能しないのと同じ理由で機能しないはずです。マイクロソフトは、クロスプロセスマーシャリングを修正する必要があります。blogs.msdn.com/b/ieinternals/archive/2009/09/15/...
EricLaw

9
この答えは、私たちに誤った希望を与えるので、迷惑です。答えは次のとおりです。メッセージチャネルを機能せるにはpostMessageが必要なため(少なくとも私が見たすべてのデモで)、プロキシがないと機能しません。postChannelまたはpostMessage( 'name'、 '<domain>'、[messageChannel.port2])なしで動作するMessageChannelのデモを誰かが私に見せない限り、私はそれを動作させることができませんでしたが、これは信じられませんプロキシフレームなしで動作します。
Akrikos 2014年

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>

他の回答でリンクされているMicrosoftのサンプルページと回避策ページへのリンクが含まれている場合、あなたの回答はより良いでしょう。回避策:blogs.msdn.com/b/ieinternals/archive/2009/09/16/...例(回避策ページから):debugtheweb.com/test/xdm/origin
Akrikos

また、サンプルページは、見つからないgodaddyページにリンクしています。
Akrikos

8
え?...すべてのURLを..あなたはそれが作業を取得するために何をすべきかを決定することができます記載されているソースから...一例であり、既存のページに実際にポイントに意図されていない
LyphTEC

説明をありがとう。:-)
Akrikos 2014年

29

== 2020年のiframeなしのワーキングソリューション==

もつれによる答えに基づいて、私は次のスニペットを使用してIE11(およびエミュレートされたIE10モード)で成功しました:

var submitWindow = window.open("/", "processingWindow");
submitWindow.location.href = 'about:blank';
submitWindow.location.href = 'remotePage to comunicate with';

次に、典型的なpostMessageスタックを使用して通信することができました。シナリオでは1つのグローバル静的メッセンジャーを使用しています(重要ではないと思いますが、メッセンジャークラスもアタッチしています)。

var messagingProvider = {
    _initialized: false,
    _currentHandler: null,

    _init: function () {
        var self = this;
        this._initialized = true;
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

        eventer(messageEvent, function (e) {
            var callback = self._currentHandler;
            if (callback != null) {
                var key = e.message ? "message" : "data";
                var data = e[key];
                callback(data);
            }
        }, false);
    },

    post: function (target, message) {
        target.postMessage(message, '*');
    },

    setListener: function (callback) {
        if (!this._initialized) {
            this._init();
        }

        this._currentHandler = callback;
    }
}

どんなに頑張っても、IE9とIE8で機能させることができませんでした。

動作している私の構成:
IEバージョン:11.0.10240.16590、更新バージョン:11.0.25(KB3100773)


6
私が言っておく必要があるのは、誰かがこの回避策を「いや、それを修正することができなかった」と考えている場合です-はい、IE11のwindow.openerにメッセージをポストできない問題を実際に修正しました。信じられない。
dkr88

1
まさか…私は2日間試してみて、これで問題を「解決」した
lmiguelmh

魅力的で神秘的な作品!(IE10.0.9200、win7)
Simon

この回避策の完全な例を提供できますか?
msm2020

1
@SidJonnalaはそうではありませんが、お勧めします。実際のリモートページにすぐに再割り当てし、ページの読み込みに3〜4秒かかる場合があります[時々発生する可能性があります] window.open( '/')ページが読み込まれ、ユーザーを混乱させるリスクがあります
Bruno Laurinec

2

LyphTECとAkrikosによる回答に基づいて、別の回避策<iframe>は空白のポップアップウィンドウ内にを作成することです。空白のポップアップはオープナーと同じ起源を持つため、別のプロキシページの必要性を回避します。

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

<html>
  <head>
    <title>postMessage launcher</title>
    <script>
      function openWnd() {
        var w = window.open("", "theWnd", "resizeable,status,width=400,height=300"),
            i = w.document.createElement("iframe");

        i.src = "http://example.net/remote.htm";
        w.document.body.appendChild(i);

        w.addEventListener("message", function (e) {
          console.log("message from " + e.origin + ": " + e.data);

          // Send a message back to the source
          e.source.postMessage("reply", e.origin);
        });
      }
    </script>
  </head>
  <body>
    <h2>postMessage launcher</h2>
    <p><a href="javascript:openWnd();">click me</a></p>
  </body>
</html>

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

<html>
  <head>
    <title>postMessage remote</title>
    <script>
      window.addEventListener("message", function (e) {
        alert("message from " + e.origin + ": " + e.data);
      });

      // Send a message to the parent window every 5 seconds
      setInterval(function () {
        window.parent.postMessage("hello", "*");
      }, 5000);
    </script>
  </head>
  <body>
    <h2>postMessage remote</h2>
  </body>
</html>

これがどれほど脆弱かはわかりませんが、IE 11とFirefox 40.0.3で機能しています。


1
...そして<iframe>、IE 11 で動作しなくなりました(ポップアップウィンドウで方向を示すサイレントエラー)(11.0.9600.18036バージョンの更新11.0.23 (KB3087038))。おそらく、最新のセキュリティ更新(KB3087038)が関係していると考えられます。
もつれ

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を使用します。


1

このソリューションでは、ローカルイントラネットサイトではなく、Internet Explorerの信頼済みサイトにサイトを追加します。このソリューションは、Windows 10 / IE 11.0.10240.16384、Windows 10 / Microsoft Edge 20.10240.16384.0、およびWindows 7 SP1 / IE 10.0.9200.17148でテストしました。ページをイントラネットゾーンに含めないでください

したがって、Internet Explorerの設定([ツール]> [インターネットオプション]> [セキュリティ]> [信頼済みサイト]> [サイト])を開き、ページを追加します。ここでは、*を使用してすべてのサブドメインを照合します。ページローカルイントラネットサイト([ツール]> [インターネットオプション]> [セキュリティ]> [ローカルイントラネット]> [サイト]> [詳細設定])に表示されていないことを確認します。ブラウザを再起動して、もう一度テストしてください。

Internet Explorerの信頼済みサイトに追加する

Windows 10 /マイクロソフトエッジ [コントロールパネル]> [インターネットオプション]でこの設定を見つけます。

更新

これが機能しない場合は、[ ツール]> [インターネットオプション]> [詳細設定]> [Internet Explorerの設定リセット]ですべての設定をリセットしてからリセットしてください注意して使用してください。次に、システムを再起動する必要があります。その後、サイトを信頼済みサイトに追加します。

[ファイル]> [プロパティ]で、または右クリックを使用して、ページがどのゾーンにあるかを確認します。

Internet Explorerのページプロパティ

更新

私は企業イントラネットを利用していますが、機能する場合と機能しない場合があります(自動構成ですか?企業プロキシのせいにし始めました)。最後に、私はこのソリューションを使用しましたhttps://stackoverflow.com/a/36630058/2692914


0

このQは古いですが、easyXDMの目的はこれです。html5.postMessageをサポートしていないブラウザーを検出したときに、フォールバックの可能性があることを確認してください。

https://easyxdm.net/

これは、VBObjectラッパーと、ウィンドウまたはフレーム間でクロスドメインメッセージを送信するために処理する必要のないすべてのタイプの要素を使用します。 Edgeにはありますが、.postMessageの回避策も必要と思われます)


-3

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

ここでの回避策の詳細


1
これは、問題の前提条件の1つであるクロスオリジン設定では機能しません。
PhistucK 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.