[Este blogpost ha sido publicado en enero de 2011 y sigue siendo muy consultado - es por eso que lo mantenemos en línea]
Aquí en Cakemail estamos construyendo una plataforma que permitirá a nuestros usuarios crear formularios e incrustarlos en su sitio web directamente (piense en un formulario de suscripción a una lista de correo electrónico). Así que básicamente, necesitábamos tener el control de javascript en el padre y en el hijo.
Teníamos que resolver dos problemas basados en la incrustación. Uno de ellos era cambiar la altura del iframe de forma dinámica (de ninguna manera íbamos a guardar la altura del iframe en una base de datos). Y a veces, dependiendo de la funcionalidad que nuestros usuarios incrustaran en su sitio web, necesitábamos redirigir la página principal.
¿Por qué es tan difícil?
La seguridad: Estoy seguro de que no tengo que decirte lo que un intruso podría hacer a tu sitio web si tuviera acceso a tu documento. Podría vincularse a su proceso de inicio de sesión y simplemente obtener el correo electrónico/contraseña de todos sus usuarios, redirigir su sitio web, etc. Por eso, la implementación de una comunicación entre dominios no debe tomarse a la ligera.
Incluso si lo haces bien, tienes que pensar en lo que podría pasar si tu script incrustado se viera comprometido. ¡Especialmente si incrusta ese script en otros sitios web que no son el suyo!
Acceder a una ventana y a un documento principal
Acceder a un documento padre es realmente sencillo cuando estás en el mismo dominio, haces un rápido window.opener.MyParentFunction(), y ya está.
Sin embargo, ¿hacer esto entre dominios? No es tan fácil. Usted obtendrá algo en la línea de: El documento hijo no tiene derecho a acceder al documento padre. De hecho hay mucha documentación en la web sobre cómo conseguirlo, pero el problema es que suele estar desfasada, con soluciones que a menudo sólo funcionan en un par de navegadores.
Hacerlo a la antigua: Un iframe en un iframe en un iframe
Una idea ingeniosa que surgió hace algún tiempo: incrustar un iframe en la ventana secundaria que está en el mismo dominio que la ventana principal. Funciona, la mayoría de las veces, pero hay variantes de esta técnica donde algunas funcionan y otras no. Algunas variantes implican que la url use un hash para pasar datos (#), lo cual es realmente malo si quieres pasar muchos datos, y además hace un ruido molesto en IE y un historial de navegación horrible.
Pero recuerda que esto sigue siendo un hack. Estás eludiendo la protección utilizando una idea algo ingeniosa, y siempre existe la posibilidad de que deje de funcionar algún día con una actualización del navegador.
Un buen recurso para los antiguos hackers
Este sitio web realmente entra en detalles sobre cómo hacer funcionar los hacks de iframe. Es realmente útil si quieres entender en detalle cómo funciona la política de iframe cross-domain.
El camino de HTML5
Ahhh HTML5, el salvador de todos nuestros problemas - ¿verdad? Para el problema de los dominios cruzados, HTML5 implementó un nuevo y agradable método javascript, postmessage.
window.postmessage se implementó específicamente para resolver el problema de la política de dominio cruzado, de forma segura (bueno, tan segura como sea posible..). Así es como se vería una comunicación:
Viene con 2 opciones para hacerlo lo más seguro posible, origen y fuente. El origen es el origen del dominio del mensaje y la fuente es una referencia al objeto ventana.
¿Y qué pasa con el ie?
Postmessage está en ie8, pero no en ie7 e ie6 (obviamente). Si necesitas soportar esos navegadores tendrás que recurrir a otra técnica.
Puede obtener una descripción muy completa y ejemplos de postmessage en el sitio web de documentación de Mozilla javascript.
Como siempre, para una buena solución entre navegadores tenemos que comprometernos
Como con muchas cosas con el DOM, la mejor manera de hacerlo entre navegadores es utilizar la mejor solución posible, y confiar en los hacks para los navegadores más antiguos.
Afortunadamente, eso es exactamente lo que easyXDM hizo por ti. ¡Esta biblioteca es (o ha sido) utilizada por un montón de sitios web, incluyendo Twitter y Disqus! Te da una bonita api que funciona en todas partes. Vamos a echar un vistazo:
¿Y qué pasa con IE, cómo hace su magia easyXDM?
Se podría pensar que easyXDM utiliza el simple truco de iframes para trabajar en ie7 y ie6, pero en realidad utiliza un hack mucho más inteligente. Utiliza un protocolo exclusivo de ie (una especie de vbscript) que hace posible la comunicación entre dominios, el NixTransport.
"Esta implementación, por lo tanto, envuelve los objetos JavaScript utilizados dentro de una clase VBScript. Dado que los objetos VBScript se pasan en JavaScript como una envoltura COM (como los objetos DOM), son por tanto opacos a JavaScript (excepto por la interfaz que exponen). Por lo tanto, esto proporciona un método seguro de transporte. Inicialmente se basa en FrameElementTransport, que comparte algunas similitudes con este método. "
Limitaciones
Una clara limitación que noté usando esta librería es que cargar una ventana hija sin estar incrustada del padre hace que easyXDM arroje un error js. Hay formas en el foro de corregir esto usando una tercera ventana pero no es realmente conveniente, también hice algunas pruebas con la opción onReady. Parecía funcionar al principio, pero a veces sigue arrojando un error de todos modos.
Por si sirve de algo, sigue siendo la librería más potente que he encontrado por ahí, he enviado un mensaje de 1mb y aún así ha llegado, incluso en IE7, y es realmente rápido.
¡Eso es!
Espero que esto te ayude a poner en marcha tu comunicación entre dominios.
Este artículo ha sido escrito por Cedric Dugas, antiguo desarrollador de interfaces de Cakemail. Puedes seguir a Cedric en twitter @posabsolute.