2012-09-28 20 views
9

Me he quedado atrapado en esto durante horas.Problemas con window.postMessage en Chrome

Tengo a.html en http://example.com que contiene un iframe con src a b.html en http://subdomain.example.com. a.html tiene algún código JS para enviar un mensaje al iframe.

El código para postMessage es simple:

iframe_window.postMessage('message', iframe_element.src) 

Pero de esta manera, Chrome genera un error:

Unable to post message to http://subdomain.example.com. Recipient has origin null. 

También he intentado:

iframe_window.postMessage('message', 'http://subdomain.example.com') 

pero no hubo suerte!

Esta es la única manera funciona:

iframe_window.postMessage('message', '*') 

Pero he oído '*' no es bueno para su uso.

Sin problemas en Firefox.

+0

Solo para aclarar, en su código actual, ¿está usando un sitio web real? –

Respuesta

15

Parece que esto podría ser un problema con el iframe hijo no cargado en el momento en que se envía la señal, por lo que iframe.src no tiene el valor adecuado.

Hice algunas pruebas y obtuve el mismo error que tú, pero cuando envolví la llamada postMessage en un setTimeout y esperé 100ms, no hubo ningún error, lo que me indica que se trata de una condición de carrera de inicialización.

Así es como he implementado una solución más limpia sin el setTimeout:

Padres:

window.addEventListener("DOMContentLoaded", function() { 

    var iframe = document.querySelector("iframe") 
     , _window = iframe.contentWindow 

    window.addEventListener("message", function(e) { 

     // wait for child to signal that it's loaded. 
     if (e.data === "loaded" && e.origin === iframe.src.split("/").splice(0, 3).join("/")) { 

      // send the child a message. 
      _window.postMessage("Test", iframe.src) 
     } 
    }) 

}, false) 

Niño:

window.addEventListener("DOMContentLoaded", function() { 

    // signal the parent that we're loaded. 
    window.parent.postMessage("loaded", "*") 

    // listen for messages from the parent. 
    window.addEventListener("message", function(e) { 

     var message = document.createElement("h1") 

     message.innerHTML = e.data 

     document.body.appendChild(message) 

    }, false) 

}, false) 

Esta es una solución simple en el que el niño va a señalar a cualquiera que está cargado (usando "*", que está bien, porque no se envía nada sensible). El padre escucha un evento cargado y comprueba que es el hijo que está entre ested en eso lo está emitiendo.

El padre envía un mensaje al niño, que está listo para recibirlo. Cuando el niño recibe el mensaje pone los datos en un <h1> y lo agrega al cuerpo < >.

He probado esto en Chrome con subdominios reales y esta solución funcionó para mí.

+0

La primera oración 'Parece que esto podría ser un problema con el niño iframe que no se carga en el momento en que se envía la señal' era la pista que necesitaba para que funcionara la comunicación iframe ... ¡gracias! – RamRaider

Cuestiones relacionadas