javascript - event - ¿PostMessage sigue roto en IE11?
javascript parent iframe (4)
Parece que window.postMessage todavía está roto en IE 11 cuando el mensaje es
- entre una ventana y un elemento secundario emergente / pestaña con window.open
- cuando se envía desde diferentes dominios [o el mismo dominio en algún caso, consulte la actualización 16/01]
Hubo problemas similares con IE 8/9/10, pero esta característica se marcó como ''compatible'' en IE 11 desde ''parcialmente compatible'' en IE 10
Hay un ejemplo del código que funciona en chrome / ff pero no en IE:
El abridor (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'');
});
});
La ventana emergente secundaria (jsbin) : (no funcionará si no está abierta por jsfiddle)
$(document).ready(function() {
$(''body'').append(''sending...'');
window.opener.postMessage("Hello?", "http://fiddle.jshell.net");
$(''body'').append(''sent...'');
});
Leí de la publicación ¿Está roto el mensaje de origen cruzado en IE10? que podemos usar un MessageChannel
lugar de postMessage
, pero al leer el documento, no encontré cómo usarlo en mi caso real, porque tiene que pasar el puerto a la ventana secundaria.
Hay una cadena de redireccionamiento antes de que tenga que enviar mi mensaje, así que incluso si pudiera enviar un puerto, perderé cualquier objeto js enviado inicialmente / antes de las redirecciones.
¿Alguna idea para un reemplazo?
Actualización 14/01 : Estoy pensando en pasar mis datos en el título de la ventana / pestaña y revisar regularmente este título del padre ... pero esto sería un truco bastante sucio.
Actualización 16/01 : la parte realmente mala es que se rompe incluso si el mensaje se envía desde el mismo dominio, pero luego de ser redirigido por otro dominio.
Aquí está el ejemplo: http://jsfiddle.net/L4YzG/13/ abre la ventana emergente http://jsbin.com/eQeSeros/4/edit que redirige a http://jsfiddle.net/mxS8Q/2/ (que publica el mensaje)
Si cambia la ventana emergente de la URL directamente con la URL final, se redirige a http://jsfiddle.net/mxS8Q/2/show esto funciona en IE porque no hay otro dominio entre la apertura y la publicación.
Todavía estoy trabajando en el truco sucio de mi título de ventana. no podemos recibir el título de la ventana cuando está en otro dominio, pero si vuelve a aparecer en jsfiddle, el título está disponible (no existe el problema anterior con postMessage). Aquí está el ejemplo: http://jsfiddle.net/L4YzG/14/ ... Esta puede ser una solución alternativa, pero acabo de ver algo acerca de pasar los datos en una cookie, solo necesita ser probada.
Actualización 04/02 : Pasar las informaciones en el título no es suficiente, si funciona bien si los dominios finales son los mismos pero no en el dominio cruzado. Quería inyectar un iframe del mismo dominio para pasar estas informaciones pero tampoco puedo compartir el objeto de la ventana secundaria (postMessage necesita un objeto serializable).
Finalmente, traté de compartir una cookie (creada y recibida en js) entre el iframe inyectado y la ventana secundaria, esto funciona bien en Chrome & Ff pero aún no se pudo recibir correctamente con IE. Después de agregar encabezados P3P funcionó bien, esta parece ser la verdadera solución. Safari parece tener algunos problemas con esta técnica, así que mantengo esta técnica como alternativa.
Actualización 16/01: la parte realmente mala es que se rompe incluso si el mensaje se envía desde el mismo dominio, pero luego de ser redirigido por otro dominio.
Hilarantemente, esta "característica de seguridad" se puede usar a la inversa para evitar por completo la restricción de dominio cruzado.
En la ventana principal en example.com
:
<script>
window.open("http://example.com/dummy_redirect");
window.addEventListener(''message'', function(ev) {console.log(ev.data)})
</script>
En el servidor example.com
:
GET /dummy_redirect 302 http://jsfiddle.net/b6yfbunw/
Se abrirá una ventana emergente a su dominio, se redireccionará a jsfiddle y la llamada postMessage funcionará en IE. Incluso puede navegar a cualquier dominio después de eso y continuar haciendo llamadas de PostMessage a la ventana principal.
¿Esta roto? Especie de.
Probé varias ideas y no pude hacer funcionar el código de tu jsFiddle . Mirando esta publicación de MSDN Blog , encontramos que postMessage
solo funciona entre IFrames en versiones anteriores de IE, que aún no se ha corregido para IE 11.
Ese artículo enlaza a una demo del problema. Hay un par de soluciones que implican la llamada de scripts en el window.opener
. Sin embargo, como dice ese blog (el énfasis es mío):
Desafortunadamente, esta solución a menudo no es posible, porque la política del mismo origen dicta que la ventana emergente y la página window.opener deben ser del mismo origen para poder llamar a las funciones de script del otro.
Así que parece que la única manera de hacer esto es algo como this , donde el niño está alojado en un IFrame en el padre. He creado una demostración similar here , basada en el código del tuyo. Es bastante simple, pero publica un mensaje en la contentWindow
de contentWindow
de IFrame, que a su vez responde.
Veo la recomendación de usar MessageChannel
lugar, pero también me pregunto si vale la pena investigar el uso de Trabajadores Web , aunque su uso, por supuesto, dependerá de la naturaleza de su tarea. También está la respuesta a esta question , donde se usó el enfoque de IFrame, pero se usó un diálogo de jQuery UI para mostrarlo. Me imagino que podría hacer lo mismo con los modales en Bootstrap si así lo prefiere.
Para referencia:
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>
Guión de los padres
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'');
});
});
Niño HTML y 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>
Descubrí que si abro otra ventana, abro mi ventana, luego cierro la otra ventana, entonces puedo trabajar con mi ventana muy bien.
vvWindow0 = window.open("http://apsed4065:8047/virtualviewer/index.html");
vvWindow = window.open("http://apsed4065:8047/virtualviewer/index.html");
vvWindow0.close(); <!-- to close the window -->
vvWindow.postMessage(message, ''http://apsed4065:8047'');
Hay algunas menciones de una solución de iframe
, pero las únicas que he visto están enviando un mensaje al iframe
.
Aquí hay un ejemplo de cómo recibir un mensaje del iframe
lugar:
Página principal (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>
Página del niño (http://second-domain.com/send-message.html)
<html>
<head>
<script>
window.parent.postMessage(''hi there'', ''*'');
</script>
</head>
<body></body>
</html>