Не работает ли пост-сообщение с несколькими источниками в IE10?
Я пытаюсь сделать тривиальное postMessage
пример работы...
- в IE10
- между окнами / вкладками (против iframes)
- через происхождение
Удалите любое из этих условий, и все будет хорошо:-)
Но, насколько я могу судить, между окнами postMessage
работает только в IE10, когда оба окна имеют общий источник. (Ну, на самом деле - и странно - поведение немного более разрешающее, чем это: два разных источника, которые разделяют хост, похоже, тоже работают).
Это документированная ошибка? Есть обходные пути или другие советы?
(Примечание: этот вопрос касается вопросов, но его ответ касается 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). Но переместите вторую страницу куда-нибудь еще, и она не работает в IE10.
7 ответов
Я ошибся, когда впервые опубликовал этот ответ: на самом деле он не работает в IE10. Очевидно, люди нашли это полезным по другим причинам, поэтому я оставляю это для потомков. Оригинальный ответ ниже:
Стоит отметить: ссылка в этом ответе вы указали на государства, которые postMessage
не является перекрестным источником для отдельных окон в IE8 и IE9 - однако, он также был написан в 2009 году, до появления IE10. Так что я бы не стал воспринимать это как указание на то, что это исправлено в IE10.
Что касается postMessage
Сам по себе http://caniuse.com/ частности, указывает на то, что он все еще не работает в IE10, который, кажется, соответствует вашей демоверсии. Страница caniuse ссылается на эту статью, которая содержит очень актуальную цитату:
Internet Explorer 8+ частично поддерживает обмен сообщениями между документами: в настоящее время он работает с фреймами, но не с новыми окнами. Internet Explorer 10, однако, будет поддерживать MessageChannel. В настоящее время Firefox поддерживает обмен сообщениями между документами, но не MessageChannel.
Таким образом, ваш лучший выбор, вероятно, иметь MessageChannel
основанный путь кода и откат к postMessage
если этого не существует Он не получит поддержку IE8/IE9, но по крайней мере он будет работать с IE10.
Документы на MessageChannel
: http://msdn.microsoft.com/en-us/library/windows/apps/hh441303.aspx
Создайте страницу прокси на том же хосте, что и панель запуска. Страница прокси имеет iframe
с источником, установленным на удаленную страницу. PostMessage из разных источников теперь будет работать в IE10 следующим образом:
- Использование удаленной страницы
window.parent.postMessage
передать данные на страницу прокси. Поскольку он использует iframes, он поддерживается 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>
Основываясь на ответе путаницей, я добился успеха в IE11 [и эмулировал режим IE10], используя следующий фрагмент:
var submitWindow = window.open("/", "processingWindow");
submitWindow.location.href = 'about:blank';
submitWindow.location.href = 'remotePage to comunicate with';
Затем я смог общаться с помощью обычного стека postMessage, в моем сценарии я использую один глобальный статический мессенджер (хотя я не думаю, что это имеет какое-либо значение, я также присоединяю свой класс мессенджера)
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)
Опираясь на ответы 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.
Прямо сейчас, (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 из прокси-фрейма на главную страницу.
Это решение включает добавление сайта в доверенные сайты Internet Explore, а не на сайты локальной интрасети. Я тестировал это решение в 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 ("Сервис"> "Свойства обозревателя"> "Безопасность"> "Надежные сайты"> "Сайты") и добавьте страницу, здесь я использую * для сопоставления всех поддоменов. Убедитесь, что страница не указана на сайтах локальной интрасети (Сервис> Свойства обозревателя> Безопасность> Локальная интрасеть> Сайты> Дополнительно). Перезапустите браузер и протестируйте снова.
В Windows 10 / Microsoft Edge вы найдете эту конфигурацию в Панели управления> Свойства обозревателя.
ОБНОВИТЬ
Если это не сработает, попробуйте сбросить все настройки в " Инструменты"> "Свойства обозревателя"> "Дополнительные настройки"> "Сбросить настройки Internet Explorer", а затем "Сброс": используйте его с осторожностью! Тогда вам нужно будет перезагрузить вашу систему. После этого добавьте сайты в Надежные сайты.
Посмотрите, в какой зоне находится ваша страница в File > Properties или используя правую кнопку мыши.
ОБНОВИТЬ
Я нахожусь в корпоративной интрасети, иногда это работает, а иногда нет (автоматическая настройка? Я даже начал обвинять корпоративный прокси). В конце концов я использовал это решение /questions/20978328/ne-rabotaet-li-post-soobschenie-s-neskolkimi-istochnikami-v-ie10/20978343#20978343.
Этот Q старый, но это то, для чего предназначен easyXDM, возможно, проверьте его как потенциальный запасной вариант, когда вы обнаружите браузер, который не поддерживает html5.postMessage:
Он использует оболочку VBObject и все типы вещей, с которыми вы никогда не захотите иметь дело, для отправки междоменных сообщений между окнами или фреймами, где window.postMessage не работает для различных версий IE (и, возможно, край, все еще не уверен на 100% в поддержке Edge имеет, но, похоже, также нуждается в обходном пути для.postMessage)
MessageChannel не работает для IE 9-11 между окнами / вкладками, поскольку он опирается на postMessage, который все еще не работает в этом сценарии. "Лучший" обходной путь - это вызов функции через window.opener (т.е. window.opener.somefunction("somedata")).