Как вы используете window.postMessage в доменах?

89

Похоже, что смысл window.postMessage заключается в том, чтобы обеспечить безопасную связь между окнами / фреймами, размещенными в разных доменах, но на самом деле это не позволяет этого в Chrome.

Вот сценарий:

  1. Вставить <iframe> (с a srcв домене B * ) на страницу в домене A
  2. <iframe> оказывается в основном тегом <script>, в конце выполнения которого ...
  3. Я вызываю window.postMessage ( some_data , page_on_A )

<iframe> определенно находится в контексте домена B, и я подтвердил, что встроенный javascript в этом <iframe> выполняется правильно и вызывает postMessageправильные значения.

Я получаю это сообщение об ошибке в Chrome:

Невозможно опубликовать сообщение для A . Получатель имеет происхождение B .

Вот код, который регистрирует прослушиватель событий сообщения на странице A:

window.addEventListener(
  "message",
  function (event) {
    // Do something
  },
  false);

Я тоже пробовал позвонить window.postMessage(some_data, '*'), но все, что удалось , - это подавить ошибку.

Я просто упускаю из виду, что window.postMessage (...) не предназначен для этого? Или я просто делаю это ужасно неправильно?

* Mime-type text / html, который должен оставаться.

Кевин Монтроуз
источник
1
Вы, вероятно, уже знаете об этом, но у MDC есть отличное изложение postMessage: developer.mozilla.org/en/DOM/window.postMessage Очевидно, что для реализации FF, но, возможно, есть что-то, что объясняет, почему это не работает.
Пекка

Ответы:

79

Вот пример, который работает в Chrome 5.0.375.125.

Страница B (содержимое iframe):

<html>
    <head></head>
    <body>
        <script>
            top.postMessage('hello', 'A');
        </script>
    </body>
</html>

Обратите внимание на использование top.postMessageили parent.postMessageотсутствие window.postMessageздесь

Страница A:

<html>
<head></head>
<body>
    <iframe src="B"></iframe>
    <script>
        window.addEventListener( "message",
          function (e) {
                if(e.origin !== 'B'){ return; } 
                alert(e.data);
          },
          false);
    </script>
</body>
</html>

A и B должны быть чем-то вроде http://domain.com

РЕДАКТИРОВАТЬ:

Из другого вопроса , похоже, что домены (здесь A и B) должны иметь /для postMessageправильной работы.

Микрофон
источник
3
Когда страница A проверяет источник сообщения, источник НЕ будет содержать завершающего символа '/'. Кажется, не имеет значения, указывает ли страница B завершающий '/' или нет. Также следует отметить, что URL-адреса должны быть абсолютными.
Catch22,
1
Этот ответ немного сбил меня с толку, и я все еще искал ответ. blog.teamtreehouse.com/cross-domain-messaging-with-postmessage содержит очень хорошее объяснение postMessage. Важно то, что отправитель сообщения знает домен получателя. В приведенном выше примере A и B не обязательно должны быть одними и теми же доменами, но B должен точно знать, какой домен используется A.
Грег Богумил
7
Речь идет о междоменном. Принятый ответ относится к тому же домену.
stackular
@stackular, не совсем так. A и B могут быть любым доменом. Это основная причина наличияpostMessage
Mic
1
+1. Мы хотим подтвердить, что это решение сработало в нашем случае. У нас есть страница, содержащая iframe из другого домена . Обратите внимание, что это работает только в браузере Chrome, так как в firefox нам нужно использовать window.parent.postMessage вместо top . Хотя мы не знаем, применимо ли это к любому другому браузеру.
rahmatns
24

Вы должны отправить сообщение от фрейма к родительскому после загрузки.

скрипт кадра:

$(document).ready(function() {
    window.parent.postMessage("I'm loaded", "*");
});

И послушайте это в родительском:

function listenMessage(msg) {
    alert(msg);
}

if (window.addEventListener) {
    window.addEventListener("message", listenMessage, false);
} else {
    window.attachEvent("onmessage", listenMessage);
}

Используйте эту ссылку для получения дополнительной информации: http://en.wikipedia.org/wiki/Web_Messaging

Golyo
источник
2

Возможно, вы пытаетесь отправить свои данные с mydomain.com на www.mydomain.com или наоборот, ВНИМАНИЕ, вы пропустили «www». http://mydomain.com и http://www.mydomain.com - это разные домены для javascript.

Геторикс
источник
2
В проекте, над которым я работаю, я использую. file:/// Возможно ли получить ошибки домена при извлечении контента исключительно из локальной файловой системы?
Jacksonkr