web-dev-qa-db-fra.com

Le message postMessage cross-Origin est-il endommagé dans IE10?

J'essaie de faire un exemple postMessage trivial ...

  • dans IE10
  • entre fenêtres/onglets (vs iframes)
  • à travers les origines

Supprimez l'une de ces conditions, et tout fonctionne bien :-)

Mais pour autant que je sache, entre-fenêtre postMessage ne semble fonctionner dans IE10 que lorsque les deux fenêtres partagent une origine. (Eh bien, en fait - et bizarrement - le comportement est légèrement plus permissif que cela: deux origines différentes qui partagent un hôte semblent également fonctionner).

Est-ce un bug documenté? Des solutions de contournement ou d'autres conseils?

(Remarque: Cette question touche aux problèmes, mais sa réponse concerne IE8 et IE9 - pas 10)


Plus de détails + exemple ...

page lanceur démo

<!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>

page lancée démo

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

Cela fonctionne à: http://jsbin.com/ahuzir/1 - car les deux pages sont hébergées à la même origine (jsbin.com). Mais déplacez la deuxième page n'importe où ailleurs, et cela échoue dans IE10.

87
Bosh

Je me suis trompé lorsque j'ai posté cette réponse: cela ne fonctionne pas réellement dans IE10. Apparemment, les gens ont trouvé cela utile pour d'autres raisons, alors je m'en remets à la postérité. Réponse originale ci-dessous:


A noter: le lien dans cette réponse vous a lié à des états que postMessage ne croise pas l'origine pour des fenêtres séparées dans IE8 et IE9 - cependant, cela a également été écrit en 2009, avant que IE10 ne soit disponible. Donc, je ne prendrais pas cela comme une indication que c'est corrigé dans IE10.

En ce qui concerne postMessage lui-même, http://caniuse.com/#feat=x-doc-messaging indique notamment qu'il est toujours défectueux dans IE10, ce qui semble correspondre à votre démo. La page caniuse renvoie à cet article , qui contient une citation très pertinente:

Internet Explorer 8+ prend en charge partiellement la messagerie entre documents: it fonctionne actuellement avec les iframes, mais pas avec les nouvelles fenêtres. Internet Explorer 10, cependant, supportera MessageChannel. Firefox supporte actuellement messagerie entre documents, mais pas MessageChannel.

Donc, votre meilleur choix est probablement d'avoir un chemin de code basé sur MessageChannel et un repli sur postMessage si cela n'existe pas. Cela ne vous apportera pas le support IE8/IE9, mais au moins cela fonctionnera avec IE10.

Docs on MessageChannel: http://msdn.Microsoft.com/en-us/library/windows/apps/hh441303.aspx

59
ShZ

En me basant sur réponse par confusion, j’ai eu du succès avec IE11 [et le mode IE10 émulé] en utilisant le fragment suivant:

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

Ensuite, j'ai pu communiquer en utilisant une pile postMessage typique, j'utilise un messager statique global dans mon scénario (même si je suppose que cela n'a aucune signification, j'attache également ma classe messenger)

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;
    }
}

Malgré tous mes efforts, je n’étais pas capable de faire fonctionner les choses avec IE9 et IE8.

Ma config où ça marche:
Version IE: 11.0.10240.16590, versions de mise à jour: 11.0.25 (KB3100773)

22
Bruno Laurinec

S'appuyant sur les réponses de LyphTEC et Akrikos, un autre moyen consiste à créer un <iframe> dans une fenêtre contextuelle vierge, ce qui évite de créer une page proxy séparée, car la fenêtre contextuelle vierge a la même origine que son ouvre.

Launcher page at 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>

Page distante à 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>

Je ne sais pas à quel point cela est fragile, mais cela fonctionne dans IE 11 et Firefox 40.0.3.

2
tangle

Pour le moment (2014-09-02), votre meilleur choix est d’utiliser un cadre proxy, comme indiqué dans le billet de blog msdn qui détaille une solution de contournement pour ce problème: https://blogs.msdn.Microsoft.com/ieinternals/2009/09/15/html5-implementation-issues-in-ie8-and-later/

Voici l'exemple de travail: http://www.debugtheweb.com/test/xdm/Origin/

Vous devez configurer un cadre de proxy sur votre page ayant la même origine que la fenêtre contextuelle. Envoyez les informations de la fenêtre contextuelle au cadre proxy en utilisant window.opener.frames[0]. Ensuite, utilisez postMessage du cadre proxy à la page principale.

1
Akrikos

Cette solution implique l'ajout du site aux sites de confiance d'Internet Explore et à non sur les sites Intranet locaux. J'ai testé cette solution sous Windows 10/IE 11.0.10240.16384, Windows 10/Microsoft Edge 20.10240.16384.0 et Windows 7 SP1/IE 10.0.9200.17148. _ {La page ne doit pas être incluse dans la zone intranet).

Alors ouvrez la configuration d'Internet Explorer (Outils> Options Internet> Sécurité> Sites de confiance> Sites), et ajoutez la page, ici j'utilise * pour correspondre à tous les sous-domaines. Assurez-vous que la page n'est pas répertoriée dans les sites intranet locaux (Outils> Options Internet> Sécurité> Intranet local> Sites> Avancés). _ Redémarrez votre navigateur et testez à nouveau.

 Add to trusted sites in Internet Explorer

Dans Windows 10/Microsoft Edge, vous trouverez cette configuration dans Panneau de configuration> Options Internet.

METTRE &AGRAVE; JOUR

Si cela ne fonctionne pas, vous pouvez essayer de réinitialiser tous vos paramètres dans Outils> Options Internet> Paramètres avancés> Réinitialiser les paramètres d'Internet Explorer, puis réinitialiser: utilisez-le avec caution. ! Ensuite, vous devrez redémarrer votre système. Après cela, ajoutez les sites aux sites de confiance. 

Voir dans quelle zone se trouve votre page dans Fichier> Propriétés ou en utilisant un clic droit. 

 Page properties in internet Explorer

METTRE &AGRAVE; JOUR

Je suis dans un intranet d'entreprise et parfois, cela fonctionne et parfois non (configuration automatique? J'ai même commencé à blâmer le proxy d'entreprise). Finalement, j'ai utilisé cette solution https://stackoverflow.com/a/36630058/2692914

0
lmiguelmh