Подтвердить что ты не робот

PostMessage все еще разбит на IE11?

Кажется, что window.postMessage все еще сломан на IE 11, когда сообщение

  • между окном и дочерним всплывающим окном с вкладкой window.open
  • когда он отправляется из разных доменов [или одного домена в некотором случае, c.f. update 16/01]

Были проблемы с IE 8/9/10, но эта функция отмечена как "поддерживаемая" в IE 11 из "частично поддерживаемой" в IE 10

Существует пример кода, который работает на chrome/ff, но не в IE:

openener (jsfiddle):

$(document).ready(function() {
    $('#log').append('listening...');
    window.addEventListener("message", function(e){
        $('#log').append("Received message: " + JSON.stringify(e.data));
    }, false);
    $('button').click(function() {
        window.open('http://jsbin.com/eQeSeros/1', 'popup','menubar=no, status=no, scrollbars=no, menubar=no, width=200, height=100');
    });
});

дочернее всплывающее окно (jsbin): (не будет работать, если не открыть jsfiddle)

$(document).ready(function() {
   $('body').append('sending...');
   window.opener.postMessage("Hello?", "http://fiddle.jshell.net");
   $('body').append('sent...');
});

Я читал из сообщения Является ли перекрестная ссылка postMessage в IE10?, что мы можем использовать MessageChannel вместо postMessage, но чтение документа, я не нашел, как использовать его в моем реальном случае, потому что вы должны передать порт дочернему окну.

Перед отправкой моего сообщения есть цепочка перенаправления, поэтому даже если я могу отправить порт, я потеряю любой объект js, отправленный изначально/перед перенаправлением.

Любая идея для замены?

Обновление 14/01. Я думаю о передаче моих данных в заголовок окна/вкладки и регулярно проверяю этот заголовок у родителя... но это было бы довольно грязным трюком.

Обновление 16/01. Очень плохо, что он работает, даже если сообщение отправлено из того же домена, но после перенаправления другим доменом.

вот пример: http://jsfiddle.net/L4YzG/13/ открывает всплывающее окно http://jsbin.com/eQeSeros/4/edit, которое перенаправляет на http://jsfiddle.net/mxS8Q/2/ (который отправляет сообщение)

Если вы измените всплывающее окно URL-адреса непосредственно на окончательный URL-адрес перенаправления на http://jsfiddle.net/mxS8Q/2/show, это работает на IE, потому что нет другого домена между открытие и пост

Я все еще работаю над своим грязным трюком. мы не можем получить заголовок окна, когда он находится в другом домене, но если он возвращается на jsfiddle, доступный заголовок доступен (нет предыдущей проблемы с postMessage). Вот пример: http://jsfiddle.net/L4YzG/14/... Это может быть альтернативное решение, но я только что увидел что-то о передаче данных в cookie, его просто нужно проверить.

Обновление 04/02. Передача информации в заголовке недостаточна, если работает хорошо, если конечные домены совпадают, но не в перекрестном домене. Я хотел бы ввести iframe того же домена, чтобы передать эту информацию, но я не могу совместно использовать объект дочернего окна (postMessage нужен сериализуемый объект).

Наконец, я попытался разделить куки файлы (созданные и полученные в js) между введенным iframe и дочерним окном, это хорошо работает на chrome и ff, но все равно не может получить его правильно с IE. После добавления заголовков P3P он работал нормально, это, по-видимому, настоящее решение. У Safari, похоже, есть некоторые проблемы с этой техникой, поэтому я просто сохраняю эту технику как резерв.

4b9b3361

Ответ 1

Разрушено? Ну, вроде.

Я пробовал различные идеи и не мог получить код в jsFiddle для работы. Глядя на это сообщение MSDN Blog, мы обнаруживаем, что postMessage работает только между IFrames в более старых версиях IE, который еще не исправлен для IE 11.

В этой статье ссылка на демонстрацию проблемы. Существует несколько способов обхода, связанных с вызовами сценариев на window.opener. Однако, как говорится в этом блоге (внимание мое):

К сожалению, это обходное решение часто невозможно, поскольку политика того же происхождения указывает, что всплывающее окно и страница window.opener должны быть от одного и того же происхождения, чтобы звонить друг другу script.

Итак, похоже, что единственный способ сделать это - это this, где ребенок размещен в IFrame в родительском. Я создал аналогичную демо здесь, основываясь на вашем коде. Это довольно просто, но отправляет сообщение в contentWindow IFrame, которое в свою очередь отвечает.

Я вижу рекомендацию использовать MessageChannel вместо этого, но я также задаюсь вопросом, стоит ли использовать Web Workers, хотя их использование конечно, будет зависеть от характера вашей задачи. Существует также ответ на этот question, где использовался подход IFrame, но для его отображения был использован диалог интерфейса jQuery. Я бы предположил, что вы можете сделать то же самое с модалами в Bootstrap, если вы предпочитаете это.


Для справки:

HTML

<iframe id="iframe" src="http://jsbin.com/iLapokOS/7/"></iframe>
<div id="log"></div>
<button id="post-message-button">Post message to window</button>

Родитель script

var wnd;

$(document).ready(function() {
    $('#log').append('listening...');

    wnd = $('#iframe')[0].contentWindow;

    window.addEventListener('message', function(e){
      $('#log').append('<br/>Received message: ' + JSON.stringify(e.data));
    }, false);

    $('#post-message-button').click(function() {
        if(!wnd){
            return;
        }
        $('#log').append('<br/>sending...');
        wnd.postMessage('Hello?', 'http://jsbin.com');
    });
});

Детский HTML и JS

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
  <script>
    $(document).ready(function() {

      window.addEventListener("message", function(e){
        $('body').append('<br/>Origin: ' + e.origin);        
        $('body').append("<br/>Received message: " + JSON.stringify(e.data));

        e.source.postMessage('Hello yourself', e.origin);
      }, false);
    });
  </script>


</body>
</html>

Ответ 2

Обновление 16/01: Очень плохая часть - это то, что она сломается, даже если сообщение отправлено из того же домена, но после перенаправления другим доменом.

Как ни странно, эта "функция безопасности" может использоваться в обратном порядке, чтобы полностью обходить ограничение crossdomain.

В родительском окне example.com:

<script>
  window.open("http://example.com/dummy_redirect");
  window.addEventListener('message', function(ev) {console.log(ev.data)})
</script>

На сервере example.com:

GET /dummy_redirect 302 http://jsfiddle.net/b6yfbunw/

Всплывающее окно откроется в вашем домене, перенаправит его на jsfiddle, а вызов postMessage будет работать в IE. Вы можете даже перейти в любой домен после этого и продолжать делать вызовы postMessage в родительском окне.

Ответ 3

Есть несколько упоминаний об обходном пути iframe, но единственные, которые я видел, отправляют сообщение в iframe.

Вот пример получения сообщения от iframe:

Родительская страница (http и двоеточие; //first -domain.com/receive-message.html)

<html>
  <head>
    <script>
      window.addEventListener('message', console.log.bind(console, 'Got message:'));
    </script>
  </head>
  <body>
    <iframe src="http://second-domain.com/send-message.html"></iframe>
  </body>
</html>

Страница с дочерью (http и двоеточие; //second -domain.com/send-message.html)

<html>
  <head>
    <script>
      window.parent.postMessage('hi there', '*');
    </script>
  </head>
  <body></body>
</html>