[Ce billet a été publié en janvier 2011 et est toujours très consulté - c'est pourquoi nous le gardons en ligne].
Chez Cakemail, nous construisons actuellement une plateforme qui permettra à nos utilisateurs de créer des formulaires et de les intégrer directement dans leur site Web (par exemple, un formulaire d'inscription à une liste d'adresses électroniques). Nous avions donc besoin d'un contrôle javascript dans le parent et dans l'enfant.
Nous devions résoudre deux problèmes liés à l'intégration. Le premier consistait à modifier la hauteur de l'iframe de manière dynamique (il était hors de question de sauvegarder la hauteur de l'iframe dans une base de données). Et parfois, en fonction des fonctionnalités intégrées par nos utilisateurs dans leur site web, nous devions rediriger la page parentale.
Pourquoi c'est si difficile ?
La sécurité: Je suis sûr que je n'ai pas besoin de vous dire ce qu'un intrus pourrait faire à votre site Web s'il avait accès à votre document. Il pourrait se lier à votre processus de connexion et obtenir l'adresse électronique et le mot de passe de tous vos utilisateurs, rediriger votre site Web, etc. C'est pourquoi la mise en place d'une communication inter-domaines ne doit pas être prise à la légère.
Même si vous le faites correctement, vous devez penser à ce qui pourrait se passer si votre script intégré était compromis. Surtout si vous intégrez ce script dans d'autres sites Web qui ne sont pas les vôtres !
Accès à une fenêtre et à un document parent
L'accès à un document parent est vraiment simple lorsque vous êtes sur le même domaine, vous faites un rapide window.opener.MyParentFunction(), et vous avez terminé.
Cependant, faire cela à travers le domaine ? Pas si facile. Vous obtiendrez quelque chose du type : Le document enfant n'a pas le droit d'accéder au document parent. En fait, il y a beaucoup de documentation sur le web sur la façon d'y parvenir, mais le problème est qu'elle est souvent dépassée, avec des solutions qui ne fonctionnent souvent que dans un couple de navigateurs.
On le fait à l'ancienne : Une iframe dans une iframe dans une iframe
Une idée astucieuse qui est apparue il y a quelque temps : intégrer un iframe dans votre fenêtre enfant qui se trouve sur le même domaine que votre fenêtre parent. Cela fonctionne, la plupart du temps, mais il existe des variantes de cette technique dont certaines fonctionnent et d'autres non. Certaines variantes impliquent que l'url utilise un hash pour passer les données (#), ce qui est vraiment mauvais si vous voulez passer beaucoup de données, et fait également un bruit ennuyeux dans IE et un historique de navigation horrible.
Mais n'oubliez pas qu'il s'agit toujours d'un piratage. Vous contournez la protection à l'aide d'une idée quelque peu ingénieuse, et il y a toujours une chance que cela cesse de fonctionner un jour avec une mise à jour du navigateur.
Une belle ressource pour les vieux briscards
Ce site Web explique en détail comment faire fonctionner les bidouillages d'iframe. Il est très utile si vous voulez comprendre en détail le fonctionnement de la politique d'inter-domaines des iframes.
La méthode HTML5
Ahhh HTML5, le sauveur de tous nos problèmes - n'est-ce pas ? Pour le problème de l'inter-domaine, HTML5 a implémenté une nouvelle méthode javascript, postmessage.
window.postmessage a été spécifiquement implémenté pour résoudre le problème de la politique inter-domaines, en toute sécurité (enfin, aussi sûre que possible...). Voici à quoi ressemblerait une communication :
Il est fourni avec 2 options pour le rendre aussi sûr que possible, l'origine et la source. L'origine étant l'origine du domaine du message et la source étant une référence à l'objet fenêtre.
Et pour ie ?
Postmessage est dans ie8, cependant il n'est pas dans ie7 & ie6 (évidemment). Si vous devez prendre en charge ces navigateurs, vous devrez recourir à une autre technique.
Vous pouvez obtenir une description très complète et des exemples de postmessage sur le site de la documentation javascript de Mozilla.
Comme d'habitude, pour une bonne solution multi-navigateur, nous devons faire des compromis.
Comme pour beaucoup de choses avec le DOM, la meilleure façon de le faire dans un autre navigateur est d'utiliser la meilleure solution possible, et de s'appuyer sur des astuces pour les anciens navigateurs.
Heureusement, c'est exactement ce qu'easyXDM a fait pour vous. Cette bibliothèque est (ou a été) utilisée par de nombreux sites web, dont Twitter et Disqus ! Elle vous donne une belle api qui fonctionne partout. Jetons un coup d'oeil :
En ce qui concerne IE, comment easyXDM fait-il fonctionner sa magie ?
On pourrait penser qu'easyXDM utilise le simple truc des iframes pour fonctionner dans ie7 et ie6, mais en fait il utilise un hack beaucoup plus intelligent. Il utilise un protocole réservé à ie (une sorte de vbscript) qui rend possible la communication inter-domaine, le NixTransport.
"Cette implémentation enveloppe donc les objets JavaScript utilisés à l'intérieur d'une classe VBScript. Étant donné que les objets VBScript sont transmis dans JavaScript en tant qu'enveloppe COM (comme les objets DOM), ils sont donc opaques à JavaScript (sauf pour l'interface qu'ils exposent). Cela constitue donc une méthode de transport sûre. Initialement basé sur FrameElementTransport qui partage certaines similitudes avec cette méthode. "
Limites
Une limitation claire que j'ai remarquée en utilisant cette bibliothèque est que le chargement d'une fenêtre enfant sans être incorporée du parent fait qu'easyXDM jette une erreur js. Il y a des moyens sur le forum pour corriger cela en utilisant une troisième fenêtre mais ce n'est pas vraiment pratique, j'ai aussi fait quelques tests avec l'option onReady. J'ai aussi fait quelques tests avec l'option onReady. Cela a semblé fonctionner au début, mais il arrive que l'erreur se produise quand même.
Pour ce que ça vaut, c'est toujours la bibliothèque la plus puissante que j'ai trouvée, j'ai envoyé un message de 1mb et il est toujours passé, même dans IE7, et il est vraiment rapide.
C'est ça !
J'espère que cela vous aidera à mettre en place votre communication inter-domaines !
Cet article a été écrit par Cedric Dugas, ancien développeur d'interface de Cakemail. Vous pouvez suivre Cedric sur twitter @posabsolute.