Window.postMessage
==================

La méthode **`window.postMessage`** permet une communication inter-domaine en toute sécurité. Normalement, les scripts de différentes pages sont autorisés à accéder les uns aux autres si et seulement si les pages depuis lesquelles ils sont exécutés ont des URL de même origine, c'est-à-dire avec le même protocole (généralement `http` ou `https`), le même numéro de port (`80` étant le port par défaut pour `http`), et le même nom d'hôte (à condition que document.domain (en-US) soit initialisé à la même valeur par les deux pages). `window.postMessage` fournit un mécanisme contrôlé pour contourner cette restriction d'une manière sécurisée si bien utilisée.

La méthode `window.postMessage`, quand elle est appelée, provoque l'envoi d'un `MessageEvent` à la fenêtre ciblée une fois que tout script en attente a terminé son exécution (par exemple, les gestionnaires d'évènements restants si `window.postMessage` est appelée depuis un gestionnaire d'évènement, des timeouts en attente enregistrées auparavant, etc.) Le `MessageEvent` est de type `message`, a une propriété `data` qui est initialisée à la valeur du premier argument passé à `window.postMessage`, une propriété `origin` correspondant à l'origine du document principal de la fenêtre appelant `window.postMessage` au moment où `window.postMessage` a été appelée, et une propriété `source` qui est la fenêtre depuis laquelle `window.postMessage` est appelée (les autres propriétés standard d'évènement sont présentes avec leurs valeurs attendues).

Syntaxe
-------


```js
otherWindow.postMessage(message, targetOrigin, [transfer]);
```


`otherWindow`

Une référence à une autre fenêtre ; une telle référence peut être obtenue, par exemple, *via* la propriété `contentWindow` d'un élément `iframe`, l'objet retourné par window.open, ou par index nommé ou numérique de window.frames.

`message`

La donnée à envoyer à l'autre fenêtre. Elle est sérialisée en utilisant l'algorithme de clônage structuré (en-US). Cela signifie que vous pouvez passer sereinement une large variété d'objets de données à la fenêtre de destination sans avoir à les sérialiser vous-mêmes. [1]

`targetOrigin`

Indique quelle doit être l'origine de `otherWindow` pour l'évènement à envoyer, soit comme la chaîne littérale `"*"` (signifiant pas de préférence) soit comme une URI. Si, au moment où l'évènement est inscrit pour être envoyé, le protocole, le nom d'hôte ou le port du document de `otherWindow` ne correspond pas à ceux contenus dans `targetOrigin`, l'évènement ne sera pas envoyé ; il ne le sera que si les trois correspondent. Ce mécanisme permet de contrôler où les messages sont envoyés ; par exemple, si `postMessage` était utilisé pour transmettre un mot de passe, il serait absolument vital que cet argument soit une URI dont l'origine est la même que le récepteur prévu du message contenant le mot de passe, afin de prévenir l'interception du mot de passe par une tierce-partie malicieuse. **Fournissez toujours une `targetOrigin` spécifique, jamais `*`, si vous savez où le document de l'autre fenêtre est censé se trouver. Ne pas fournir une cible spécifique expose les données que vous envoyez à tout site malicieux à l'écoute.**

`transfer` Facultatif

Séquence d'objets `Transferable` qui sera transmise avec le message. La possession de ces objets est cédée à la destination et ils ne sont plus utilisables du côté de l'expéditeur.

L'évènement envoyé
------------------

`otherWindow` peut surveiller les messages envoyés en exécutant le JavaScript suivant :


```js
window.addEventListener("message", receiveMessage, false);

function receiveMessage(event) {
  if (event.origin !== "http://example.org:8080") return;

  // ...
}
```


Les propriétés du message envoyé sont :

`data`

L'objet passé depuis l'autre fenêtre.

`origin`

L'origine de la fenêtre qui a envoyé le message au moment où `postMessage` a été appelée. Des exemples typiques d'origines sont `https://example.org` (sous-entendu port `443`), `http://example.net` (sous-entendu port `80`), et `http://example.com:8080`. Notez qu'il n'est pas garanti que cette origine soit l'origine actuelle ou future de cette fenêtre, qui peut avoir été naviguée vers une adresse différente depuis l'appel à `postMessage`.

`source`

Une référence à l'objet `window` qui a envoyé le message ; vous pouvez utiliser ceci pour établir une communication dans les deux sens entre deux fenêtres ayant différentes origines.

Précautions de sécurité
-----------------------

**Si vous ne prévoyez pas de recevoir de messages depuis d'autres sites, n'ajoutez pas de gestionnaire d'évènement pour les évènements `message`.** C'est un moyen sûr d'éviter les problèmes de sécurité.

Si vous prévoyez de recevoir des messages depuis d'autres sites, **vérifiez toujours l'identité de l'expéditeur** à l'aide des propriétés `origin` et si possible `source`. Toute fenêtre (y compris, par exemple, `http://evil.example.com`) peut envoyer un message à toute autre fenêtre, et vous n'avez aucune garantie qu'un expéditeur inconnu ne va pas envoyer de message malicieux. Cependant, même si vous vérifiez l'identité, vous devriez **toujours vérifier la syntaxe du message reçu**. Dans le cas contraire, une faille de sécurité dans le site auquel vous faites confiance peut ouvrir une vulnérabilité XSS dans votre propre site.

**Spécifiez toujours explicitement une origine de destination, jamais `*`, quand vous utilisez `postMessage` pour envoyer des données à d'autres fenêtres.** Un site malicieux peut changer l'adresse de la fenêtre à votre insu, et ainsi intercepter les données envoyées à l'aide de `postMessage`.

Exemple
-------


```js
/\*
 \* Dans les scripts de la fenêtre A, avec A sur <http://example.com:8080>:
 \*/

var popup = window.open(...popup details...);

// Quand la popup est chargée, si pas bloquée par un bloqueur de popups:

// Ceci ne fait rien, en supposant que la fenêtre n'a pas changé d'adresse.
popup.postMessage("The user is 'bob' and the password is 'secret'",
                  "https://secure.example.net");

// Ceci va planifier l'envoi d'un message à la popup, en supposant que
// la fenêtre n'a pas changé d'adresse.
popup.postMessage("hello there!", "http://example.org");

function receiveMessage(event)
{
  // Faisons-nous confiance à l'expéditeur de ce message ? (il pourrait être
  // différent de la fenêtre que nous avons ouverte au départ, par exemple).
  if (event.origin !== "http://example.org")
    return;

  // event.source est la popup
  // event.data est "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
```



```js
/\*
 \* Dans les scripts de la popup, sur <http://example.org>:
 \*/

// Appelée quelques instants après que postMessage a été appelée
function receiveMessage(event) {
  // Faisons-nous confiance à l'expéditeur de ce message ?
  if (event.origin !== "http://example.com:8080") return;

  // event.source est window.opener
  // event.data est "hello there!"

  // Supposant que vous avez vérifié l'origine du message reçu
  // (ce que vous devriez faire en toutes circonstances),
  // un moyen pratique de répondre à un message est d'appeler postMessage
  // sur event.source et fournir event.origin comme targetOrigin.
  event.source.postMessage(
    "hi there yourself! the secret response " + "is: rheeeeet!",
    event.origin,
  );
}

window.addEventListener("message", receiveMessage, false);
```

### Notes

Toute fenêtre peut accéder à cette méthode sur toute autre fenêtre, à tout moment, peu importe l'adresse du document dans la fenêtre, pour y envoyer un message. Par conséquent, tout gestionnaire d'évènement utilisé pour recevoir des messages **doit** d'abord vérifier l'identité de l'expéditeur du message, en utilisant les propriétés `origin` et si possible `source`. Cela ne peut pas être minimisé : **ne pas vérifier les propriétés `origin` et si possible `source` permet des attaques inter-site.**

De même qu'avec les scripts exécutés de manière asynchrone (timeouts, evènements générés par l'utilisateur), il n'est pas possible pour l'appelant à `postMessage` de détecter quand un gestionnaire d'évènement écoutant des évènements envoyés par `postMessage` lance une exception.

La valeur de la propriété `origin` de l'évènement envoyé n'est pas affectée par la valeur actuelle de `document.domain` dans la fenêtre appelante.

Pour les noms d'hôte IDN uniquement, la valeur de la propriété `origin` n'est pas systématiquement Unicode ou punycode ; pour la plus grande compatibilité, testez à la fois les valeurs IDN et punycode quand vous utilisez cette propriété si vous attendez des messages de sites IDN. Cette valeur sera systématiquement IDN à l'avenir, mais pour l'instant vous devriez gérer à la fois les formes IDN et punycode.

La valeur de la propriété `origin` quand la fenêtre expéditrice contient une URL `javascript:` ou `data:` est l'origin du script qui a chargé cette URL.

### Utiliser window.postMessage dans les extensions 
Non-standard

`window.postMessage` est disponible depuis le JavaScript exécuté en code chrome (par exemple, dans les extensions et le code privilégié), mais la propriété `source` de l'évènement envoyé est toujours `null` par mesure de sécurité. (Les autres propriétés ont leurs valeurs usuelles.)

L'argument `targetOrigin` pour un message envoyé à une fenêtre située à une URL `chrome:` est actuellement mal interprété, si bien que la seule valeur qui conduit à l'envoi d'un message est `"*"`. Comme cette valeur n'est pas sûre quand la fenêtre ciblée peut être naviguée n'importe où par un site malicieux, il est recommandé de ne pas utiliser `postMessage` pour communiquer avec des pages `chrome:` pour l'instant ; utilisez une méthode différente (comme une chaîne de requête quand la fenêtre est ouverte) pour communiquer avec des fenêtres chrome.

Enfin, poster un message à une page à une URL `file:` requiert actuellement que l'argument `targetOrigin` soit `"*"`. `file://` ne peut pas être utilisé comme restriction de sécurité ; cette restriction pourrait être modifiée à l'avenir.

Spécifications
--------------

| Specification |
| --- |
| HTML Standard # dom-window-postmessage-options-dev |

Compatibilité des navigateurs
-----------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Voir aussi
----------

* Document.domain (en-US)
* CustomEvent
* Interaction entre les pages privilégiées et non privilégiées