From 31b3f1b3ee5f7e5f17ef728f36ffc9f05ca8691f Mon Sep 17 00:00:00 2001 From: Will Bamberg Date: Fri, 26 Aug 2016 22:05:31 -0700 Subject: [PATCH] Added native messaging example --- native-messaging/README.md | 12 +++++++++ native-messaging/add-on/background.js | 19 ++++++++++++++ native-messaging/add-on/icons/LICENSE | 1 + native-messaging/add-on/icons/message.svg | 8 ++++++ native-messaging/add-on/manifest.json | 28 +++++++++++++++++++++ native-messaging/app/ping_pong.json | 7 ++++++ native-messaging/app/ping_pong.py | 30 +++++++++++++++++++++++ 7 files changed, 105 insertions(+) create mode 100644 native-messaging/README.md create mode 100644 native-messaging/add-on/background.js create mode 100644 native-messaging/add-on/icons/LICENSE create mode 100644 native-messaging/add-on/icons/message.svg create mode 100644 native-messaging/add-on/manifest.json create mode 100644 native-messaging/app/ping_pong.json create mode 100755 native-messaging/app/ping_pong.py diff --git a/native-messaging/README.md b/native-messaging/README.md new file mode 100644 index 0000000..e2bf293 --- /dev/null +++ b/native-messaging/README.md @@ -0,0 +1,12 @@ +This is a very simple example of how to use native messaging to exchange messages between a WebExtension and a native application. + +The WebExtension, which can be found under "add-on", connects to the native application and listens to messages from it. It then sends a message to the native application when the user clicks on the WebExtension's browser action. The message payload is just "ping". + +The native application, which can be found under "app", listens for messages from the WebExtension. When it receives a message, the native application sends a response message whose payload is just "pong". The native application is written in Python. + +To get this working, there's a little setup to do: + +* edit the "path" property of "app/ping_pong.json" to point to the location of "app/ping_pong.py" on your computer +* copy "app/ping_pong.json" to the correct location on your computer. See [host manifest locations]() to find the correct location for your OS. + +Then just install the add-on as usual, by visiting about:debugging, clicking "Load Temporary Add-on", and selecting the add-on's "manifest.json". diff --git a/native-messaging/add-on/background.js b/native-messaging/add-on/background.js new file mode 100644 index 0000000..4cdabef --- /dev/null +++ b/native-messaging/add-on/background.js @@ -0,0 +1,19 @@ +/* +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"); +}); diff --git a/native-messaging/add-on/icons/LICENSE b/native-messaging/add-on/icons/LICENSE new file mode 100644 index 0000000..c4e7bdc --- /dev/null +++ b/native-messaging/add-on/icons/LICENSE @@ -0,0 +1 @@ +The icon used here is taken from the "Miscellany Web icons" set by Maria & Guillem (https://www.iconfinder.com/andromina), and is used under the Creative Commons (Attribution 3.0 Unported) license. diff --git a/native-messaging/add-on/icons/message.svg b/native-messaging/add-on/icons/message.svg new file mode 100644 index 0000000..7ee68e2 --- /dev/null +++ b/native-messaging/add-on/icons/message.svg @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/native-messaging/add-on/manifest.json b/native-messaging/add-on/manifest.json new file mode 100644 index 0000000..bd3ba1f --- /dev/null +++ b/native-messaging/add-on/manifest.json @@ -0,0 +1,28 @@ +{ + + "description": "Native messaging example add-on", + "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"] + +} diff --git a/native-messaging/app/ping_pong.json b/native-messaging/app/ping_pong.json new file mode 100644 index 0000000..a257b18 --- /dev/null +++ b/native-messaging/app/ping_pong.json @@ -0,0 +1,7 @@ +{ + "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" ] +} diff --git a/native-messaging/app/ping_pong.py b/native-messaging/app/ping_pong.py new file mode 100755 index 0000000..ce06c7e --- /dev/null +++ b/native-messaging/app/ping_pong.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +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"))