Communication avec une iframe d'un autre domaine

crossdomain Vous savez sans doute ce qu’est un widget, ces petits bidules qui envahissent les applications web ou desktop. Là je me suis intéressé à la communication Javascript entre un site et un contenu d’un autre domaine dans une iframe. Concrètement, ça peut servir à une application web qui communique avec ses widgets de manière sécurisée.

Problème

J’ai une application fait en Javascript/html et je veux autoriser l’ajout de modules externes (toujours en Javascript) sans pour autant ouvrir des failles. On opte pour une insertion des modules par iframe. Mais il faut quand même qu’il y ait une intéraction dans tout ce bazar, car si l’application et les modules ne sont pas dans le même domaine, alors le navigateur interdit les échanges Javascript.

Solutions

Utiliser Flash

Première solution de flasheur : utiliser les LocalConnection.

Sauf que j’ai eu une très mauvaise surprise récemment. J’ai découvert que le plugin Flash sur Mac limitait le nombre de connexion par LocalConnection. Et c’est un bug qui date depuis longtemps quand on cherche sur google.

Donc, je zappe puisque dans mon problème, il aurait fallu un LocalConnection pour l’application et un pour chaque module.

Echange d’objets Javascript

C’est la solution que j’ai retenu pour l’instant et que je vais expliquer ici. Merci à Collin Jackson pour son document sur la communication cross-domain.

Dans le PDF, l’auteur explique 2 méthodes différentes tournant autour d’un même principe: faire transiter un objet javascript d’un domaine vers un autre.

Pour qu’une iframe accède au javascript de son parent, il faut que les 2 soient du même domaine. A l’aide d’iframes intermédiaires et la modification de document.domain, on peut s’arranger pour que les 2 parties gardent une référence d’un objet Javascript appartement à l’autre. Il y a tout de même une restriction au changement de domaine: on ne peut que réduire l’espace de nom.

Par exemple, www.neolao.com ne peut se changer qu’en neolao.com, le domaine com tout seul étant interdit.

Méthode Top Untrusted Access (TUA)

js

Ca consiste à passer l’objet Javascript de A à B en passant par M et N.

  1. Ma page principale est www.neolao.com/app.html (A)
  2. Sur cette dernière, je crée une iframe qui a comme contenu www.neolao.com/mediator.html (M)
  3. M récupère l’objet Javascript appObject contenu dans A simplement en faisant appObject = parent.appObject;
  4. M change son domaine avec document.domain = "neolao.com";
  5. M se rend facilement accessible en se référencant dans A: parent.mediatorPage = this;
  6. A crée une iframe qui a comme contenu widget1.neolao.com/widget.html (B)
  7. B crée aussi une iframe qui a comme contenu widget1.neolao.com/access.html (N)
  8. N récupère un objet Javascript widgetObject contenu dans B: widgetObject = parent.widgetObject;
  9. N change son domaine: document.domain = "neolao.com";
  10. N récupère appObject en faisant appObject = top.mediatorPage.appObject;

Après tout ça, N possède appObject et widgetObject. Ces 2 objets Javascript n’ont plus qu’à se référencer mutuellement :

widgetObject.appObject = appObject;
appObject.widgetObject = widgetObject;

Et enfin, on peut détruire les iframes intermédiaires, on n’en a plus besoin

Méthode Top Mediator Untrusted (TMU)

js2

Cette fois ci, l’iframe B est contenu dans M et le reste. Le passage des objets se fait de la même façon que la première méthode.

On utilise ce procédé quand on ne peut pas accéder aux DOM ni aux variable du top.

Variantes

Attention tout de même, on ne peut pas forcément appeler les fonctions contenues dans les objets sans problème. Il y a 2 variantes pour chaque méthodes :

Et ouais, le polling est inévitable pour certains navigateurs comme Safari ou Opera. Ca sera donc à l’aide d’un setInterval vérifiant en permanence une variable qu’on va pouvoir exécuter des actions venues d’ailleurs.

Conclusion

Je trouve que les restrictions sont énormes :

Et la surprise pour la fin … j’ai tenté de créer un outil facilitant la communication :

Commentaires