Cette traduction est incomplète. Aidez à traduire cet article depuis l'anglais.

Natives messaging permet qu'une extension puisse échanger des messages avec une extension native installlée sur l'ordinateur de l'utilisateur. Ceci permet que des applications natives puisse fournir un service à des extensions sans avoir le besoin d'être atteignable via internet. Un des exemples typiques est le gestionnaire de mots de passe : l'application native s'occupe du stockage et de l'encryption des mots de passe, et communique avec l'extension afin de remplir les formulaires web. Native messaging permet aussi que les extensions puisse accéder à des ressources qui ne sont pas accessible via les API WebExtension, par exemple, l'accès à du matériel hardware particulier.

L'application native n'est pas installée ou gérée pour le navigateur : Il est installé à l'aide du système d'installation du système d'exploitation sous-jacent. En plus de l'application native elle-même, vous devrez fournir un fichier JSON appelé «manifeste hôte»(host manifest) ou «manifeste d'application» (app manifest) et l'installer dans un emplacement défini sur l'ordinateur de l'utilisateur. Le fichier manifeste de l'application décrit comment le navigateur peut se connecter à l'application native.

L'extension doit demander l'autorisation "nativeMessaging" dans son fichier manifest.json. À l'inverse, l'application native doit accorder l'autorisation à l'extension en incluant son ID dans le champ "allowed_extensions" (extensions autorisées) du manifeste de l'application.

Par la suite, l'extension pourra échanger des messages en JSON avec l'application native en utilisant une série de fonctions de l'API runtime. Du côté de l'application native, les messages seront reçus en utilisant l'entrée standart (stdin, standart input) et en envoyer en utilisant la sortie standart (stdout, standart output).

Le support de native messaging dans les extensions est généralement compatible avec Chrome, avec deux grandes différences :

  • La liste "allowed_extensions" du manifeste de l'application est un tableau d'ID d'applications, tandis que pour Chrome c'est un tableau d'url de  "chrome-extension".
  • Le manifeste de l'application est enregistré à un endroit différent que Chrome/

Il y a un exemple complet (en anglais) dans le répertoire "native-messaging" du dépôt  "webextensions-examples" sur GitHub. La plus grande partie du code de cet article est repris de cet exemple.

Mise en oeuvre

Le manifeste de l'extension (Extension manifest)

Si vous souhaitez que votre extension puisse communiquer avec une application native, alors :

  • Vous devez ajouter la permission dans son fichier manifest.json.
  • Vous devriez probablement spécifier explicitement l'id de votre add-on, en utilisant la clé de manifeste des applications ( Parce que le manifeste de l'application identifiera le jeu d'extensions qui sont autorisées à se connecter à elle via la liste de leur ID).

Voici un exemple du fichier "manifest.json" :

{

  "description": "Native messaging example extension",
  "manifest_version": 2,
  "name": "Native messaging example",
  "version": "1.0",
  "icons": {
    "48": "icons/message.svg"
  },

  "applications": {
    "gecko": {
      "id": "ping_pong@example.org",
      "strict_min_version": "50.0"
    }
  },

  "background": {
    "scripts": ["background.js"]
  },

  "browser_action": {
    "default_icon": "icons/message.svg"
  },
 
  "permissions": ["nativeMessaging"]

}

Le manifeste de l'application (App manifest)

Le manifeste de l'application décrit au navigateur la manière avec laquelle il peut se connecter à l'application native.

Le fichier de manifeste de l'apllication doit être installé à côté de l'application native. Cela étant, le navigateur lit et valide les manifestes de l'application mais il ne les installe pas et ne les gère pas. Ainsi, le modèle de sécurité de quand et comment ces fichiers sont installés et sont mis à jour est beaucoup plus similaire à celui des applications natives que celles des extensions utilisant les API WebExtension.

Le manifeste de l'application contient un seul objet JSON avec les propriétés suivantes :

Nom Type Description
name Chaîne

Nom de l'application native.

Il doit correspondre au nom passé comme argument dans  runtime.connectNative() ou runtime.sendNativeMessage() par l'extension.

Sur Mac OS X ou sur Linux, il doit correspondre au nom de fichier du fichier de manifeste de l'application (en supprimant l'extension the ".json" ).

Pour Windows, il doit correspondre au nom de la clé de registre que vous avez créée, et qui contient l'emplacement du manifeste de l'application.

Le nom ne peut contenir que des caractères minuscules alphanumériques, des traits de soulignements ou des points. Il ne peut ni commencer ni terminer par un point, et un point ne peut pas suivre un autre point.

description Chaîne Description de l'application native
path Chaîne

Chemin vers l'application native.

Sur Windows, le chemin peut être relatif por rapport au ma,ifeste lui-même. Sur OS X et Linux, el doit être absolut.

type Chaîne

Décrit la méthode utilisée pour connecter l'extension à l'application.

Pour l'instant, une seule valeur est possible, "stdio" (standart input-output), ce qui indique que les messages sont reçus par l'application en utilisant l'entrée standart (stdin, standart input) et envoyés via la sortie standart (stdout, standart output).

allowed_extensions Tableau de chaînes

Un tableau de valeurs ID de Add-on. Chaque valeur représente une extension qui est autorisée à communiquer avec cette application native.

Notez bien que cela implique que vous voudrez probalement inclure les clés des applications dans le fichier de manifeste de votre extension, et donc vous pouvez définir un ID explicite lors du développement.

Note that this means you will probably want to include the applications key in your extension's manifest.json file, so you can set an explicit ID during development.

Par exemple, voici le manifeste pour l'application native "ping-pong" :

{
  "name": "ping_pong",
  "description": "Example host for native messaging",
  "path": "/path/to/native-messaging/app/ping_pong.py",
  "type": "stdio",
  "allowed_extensions": [ "ping_pong@example.org" ]
}

Ceci autorise à l'application dont l'ID est "ping_pong@example.org" de se connecter, en passant le nom "ping_pong" comme paramètre à la fonction de l'API runtime concernée. L'application, elle-même se trouve dans le fichier "/path/to/native-messaging/app/ping_pong.py".

Remarque pour Windows: dans l'exemple ci-dessus, l'application native est un script Python. Il peut être compliqué d'amener Windows à faire fonctionner correctement des scripts Python, une méthode alternative est de fournir un fichier .bat, et de l'indiquer dans le manifeste :

{
  "name": "ping_pong",
  "description": "Example host for native messaging",
  "path": "c:\\path\\to\\native-messaging\\app\\ping_pong_win.bat",
  "type": "stdio",
  "allowed_extensions": [ "ping_pong@example.org" ]
}

Le fichier batch invoquera alors le script Python:

@echo off

python -u "c:\\path\\to\\native-messaging\\app\\ping_pong.py"

 

Localisation du manifeste de l'application

Le manifeste de l'application doit être enregistré dans une localisation connue sur l'ordinateur de l'utilisateur, ce qui permettra au navigateur de pouvoir le retrouver. Cette localisation est différente selon le système d'exploitation, et il est différent aussi selon que l'application doit être accessible globalement ou uniquement pour un seul utilisateur.

The app manifest needs to be stored in a known location on the user's computer, so the browser knows where to find it. This location is different for different operating systems, and different depending on whether the app should be made available globally or only to a single user.

Dans toutes les options ci-dessous, "<nom>" est la valeur de "name" dans le manifeste : donc,  "ping_pong", dans l'exemple de ci-dessus.

Windows

Pour une visibilité globale, créez une clé de registre avec le nom suivant :

HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\NativeMessagingHosts\<name>

La clé ne devrait avoir qu'une seule valeur, le chemin de répertoire vers le manifeste.

Note that this key should not be created under Wow6432Node, even if the app is 32-bit. The browser will always look for the key under the "native" view of the registry, not the 32-bit emulation. To ensure that the key is created in the "native" view, you can pass the KEY_WOW64_64KEY or KEY_WOW64_32KEY flags into RegCreateKeyEx. See Accessing an Alternate Registry View.

Pour une visibilité par utilisateur, créez une clé de registre avec le nom suivant :

HKEY_CURRENT_USER\SOFTWARE\Mozilla\NativeMessagingHosts\<name>

La clé ne devrait avoir qu'une seule valeur, le chemin de répertoire vers le manifeste.

Par exemple, si le nom de l'application native est "ping_pong" et que son manifeste se situe à  "C:\path\to\ping_pong.json", alors vous pouvez ajouter la clé en utilisant la commande  REG ADD suivante:

REG ADD "HKEY_CURRENT_USER\SOFTWARE\Mozilla\NativeMessagingHosts\ping_pong" /ve /d "C:\path\to\ping_pong.json" /f

Mac OS X

Pour une visibilité globale, enregistrez le manifeste à l'endroit suivant :

/Library/Application Support/Mozilla/NativeMessagingHosts/<name>.json

Pour une visibilité par utilisateur, enregistrez le manifeste à l'endroit suivant :

~/Library/Application Support/Mozilla/NativeMessagingHosts/<name>.json

Linux

Pour une visibilité globale, enregistrez le manifeste à l'un des endroits suivants :

/usr/lib/mozilla/native-messaging-hosts/<name>.json

/usr/lib64/mozilla/native-messaging-hosts/<name>.json

Pour une visibilité par utilisateur, enregistrez le manifeste à l'endroit suivant :

~/.mozilla/native-messaging-hosts/<name>.json

Opérations d'échange des  messages

Ayant appliqué la configuration de ci-dessus, une extension peut échanger des messages JSON avec une application native.

Du côté de l'extension

Si vous avez utilisé les API de messagerie pour communiquer avec des scripts de contenus, ceci devrait vous sembler familier. Ils y a deux manières de faire : messagerie basée sur une connexion et messagerie sans connexion.

Messagerie basée sur une connexion

Avec cette manière de faire, vous appeler la fonction runtime.connectNative(), en lui passant comme paramètre le nom de l'application (la valeur de la propriété "name" du manifeste de l'application). Ceci lance l'application si elle n'est pas encore démarrée et renverra un objet  runtime.Port à l'extension.

L'application native passe deux arguments lorsqu'elle démarre:

  • le chemin complet du manifeste de l'application
  • (nouveau dans Firefox 55), l'ID (comme indiqué dans la clé du manifest.json) de l'add-on qui l'a démarré.

L'aplication continue a fonctionner jusqu'à ce que l'extension invoque Port.disconnect() ou que la page connectée à elle est fermée.

Pour envoyer des messages en utilisant  Port, utilisez sa fonction postMessage() , en passant le message JSON à envoyer. Pour écouter les messages en utilisant Port, ajouter un écouteur (listener) en utilisant sa fonction  onMessage.addListener().

Voici un exemple de script "background" qui établit une connection avec l'application "ping_pong", qui écoute à l'attente de messages de celle-ci et qui lui envoie un message "ping" à chaque fois que  l'utilisateur clique sur l'action du navigateur (browser action) :

/*
On startup, connect to the "ping_pong" app.
*/
var port = browser.runtime.connectNative("ping_pong");

/*
Listen for messages from the app.
*/
port.onMessage.addListener((response) => {
  console.log("Received: " + response);
});

/*
On a click on the browser action, send the app a message.
*/
browser.browserAction.onClicked.addListener(() => {
  console.log("Sending:  ping");
  port.postMessage("ping");
});

Messagerie sans connexion

Avec cette manière de faire, vous invoquer la fonction  runtime.sendNativeMessage(), en lui passant comme arguments :

  • le nom de l'application,
  • le message JSON à envoyer,
  • et optionnellement un callback.

Une nouvelle instance de l'application sera créée pour chaque message. L'application native passe deux arguments lorsqu'elle démarre:

A new instance of the app is created for each message. The app is passed two arguments when it starts:

  • le chemin complet du manifeste de l'application
  • (nouveau dans Firefox 55), l'ID (comme indiqué dans la clé du manifest.json) de l'add-on qui l'a démarré.

Le premier message envoyé par l'application est traité comme une réponse à l'invocation de la fonction sendNativeMessage(), et sera passé dans le callback.

Voici l'exemple antérieur réécrit en utilisant runtime.sendNativeMessage():

function onResponse(response) {
  console.log("Received " + response);
}

function onError(error) {
  console.log(`Error: ${error}`);
}

/*
On a click on the browser action, send the app a message.
*/
browser.browserAction.onClicked.addListener(() => {
  console.log("Sending:  ping");
  var sending = browser.runtime.sendNativeMessage(
    "ping_pong",
    "ping");
  sending.then(onResponse, onError);
});

Du côté de l'application

Du côté de l'application, vous utilisez l'entrée standart (standart input) pour recevoir les messages, et la sortie standart (standart output) pour les envoyer.

Chaque message est sérialisé sous forme de JSON, est encodé en UTF-8 et est précédé d'une valeur 32 bits qui contient la longueur du message dans l'ordre des octets natifs.

La taille maximum d'un seul message envoyé par l'application est de 1MB. La taille maximum d'un message envoyé vers l'application est de 4GB.

Voici un exemple écrit e, Python. Il est à l'écoute de messages envoyés par l'extension. Si le message est "ping", alors il répondra par "pong" :

#!/usr/bin/python -u
# Note that running python with the `-u` flag is required on Windows,
# in order to ensure that stdin and stdout are opened in binary, rather
# than text, mode.

import sys, json, struct

# Read a message from stdin and decode it.
def getMessage():
  rawLength = sys.stdin.read(4)
  if len(rawLength) == 0:
      sys.exit(0)
  messageLength = struct.unpack('@I', rawLength)[0]
  message = sys.stdin.read(messageLength)
  return json.loads(message)

# Encode a message for transmission, given its content.
def encodeMessage(messageContent):
  encodedContent = json.dumps(messageContent)
  encodedLength = struct.pack('@I', len(encodedContent))
  return {'length': encodedLength, 'content': encodedContent}

# Send an encoded message to stdout.
def sendMessage(encodedMessage):
  sys.stdout.write(encodedMessage['length'])
  sys.stdout.write(encodedMessage['content'])
  sys.stdout.flush()

while True:
  receivedMessage = getMessage()
  if (receivedMessage == "ping"):
    sendMessage(encodeMessage("pong"))

Fremture de l'application native

Si vous vous êtes connecté à l'application  native en utilisant  runtime.connectNative(), alors elle continuera à fonctionner jusqu'à ce que l'extension appelle Port.disconnect() ou que la page qui y est connectée soit fermée. Si vous avez démarré l'application native en  utilisant runtime.sendNativeMessage(), alors elle sera fermée après qu'elle ait reçu le message et envoyé une réponse.

Pour fermer l'application native :

  • Sur les système d'exploitation *.nix comme Linux ou OS X, le navigateur envoie un SIGTERM à l'application native, puis un SIGKILL après que l'application ait eût l'occasion de finir de manière normale. Ces signaux sont propagés à tous sous-processus sauf pour ceux qui se trouvent dans de nouveaux groupes de processus
    On *nix systems like OS X and Linux, the browser sends SIGTERM to the native application, then SIGKILL after the application has had a chance to exit gracefully. These signals propagate to any subprocesses unless they break away into a new process group.
  • On Windows, the browser puts the native application's process into a Job object, and kills the job. If the native application launches any additional processes and wants them to remain open after the native application itself is killed, then the native application must launch the additional process with the CREATE_BREAKAWAY_FROM_JOB flag.

Dépannage

Si quelque-chose se passe mal, vérifier dans la console du navigateur. Si l'application native renvoit quelque-chose vers stderr (strandart error), le navigateur le renverra vers la console du navigateur. Donc si vous avez réussi à lancer l'application native, vous verrez toutes les messages d'erreurs qu'elle émet.

Si vous n'avez pas réussi à démarrer l'application, vous devriez voir un message d'erreur vous donnant un indice sur le problème.

"No such native application <name>"
  •  Vérifiez que le nom passé comme argument à la fonction runtime.connectNative() correspond au nom dans le manifeste de l'application
  • OS X/Linux : vérifiez que le nom du fichier de manifeste de l'application est  <name>.json.
  • Windows: vérifiez que la clé de registre est dans l'endroit correcte, et que son nom correspond au "name" dans le manifeste de l'application.
  • Windows: verifiez que le chemin donné dans la clé de registre pointe vers le manifeste de l'application.
"Error: Invalid application <name>"
  • Vérifier que le nom de l'application ne contient pas de caractères invalides.
"'python' is not recognized as an internal or external command, ..."
  • Windows: Si votre application est un script écrit en Python, vérifiez que Python est installé est qui vous avez un chemin définit pour lui.
"File at path <path> does not exist, or is not executable"
  • Si vous voyez ce message, alors le fichier de manifeste de l'application a été trouvé.
  • Vérifier que le "chemin" dans le manifeste de l'application est correcte.
  • Windows : vérifiez que vous avez "échappé" les séparateurs du chemin ("c:\\path\\to\\file").
  • Vérifiez que l'application se trouve bien dans la localisation indiquée dans la propriété "path" dans le manifeste de l'application.
  • Vérifiez que l'application est exécutable.
"This extension does not have permission to use native application <name>"
  • Vérifier que le tableau  "allowed_extensions" dans le manifeste de l'application contient l'ID de l'add-on.
"TypeError: browser.runtime.connectNative is not a function"
  • Vérifiez que l'extension à la permission "nativeMessaging"
"[object Object]       NativeMessaging.jsm:218"
  • Il y a eut un problème lors du démarrage de l'application.

Incompatibilités avec Chrome incompatibilities

Command-line arguments

On Linux and Mac, Chrome passes one argument to the native app, which is the origin of the extension that started it, in the form: chrome-extension://[extensionID]. This enables the app to identify the extension.

On Windows, Chrome passes two arguments: the first is the origin of the extension, and the second is a handle to the Chrome native window that started the app.

allowed_extensions

In Chrome, the allowed_extensions key in the app manifest is called allowed_origins instead.

App manifest location

Chrome expects to find the app manifest in a different place. See Native messaging host location in the Chrome docs. 

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : m4ucoder
 Dernière mise à jour par : m4ucoder,