mirror of
https://github.com/mdn/webextensions-examples.git
synced 2026-04-16 06:18:35 +02:00
Merge pull request #564 from dotproto/native-update
Update native-messaging to use python3, clarify instructions
This commit is contained in:
@@ -4,36 +4,62 @@ The WebExtension, which can be found under "add-on", connects to the native appl
|
||||
|
||||
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.
|
||||
|
||||
## Setup ##
|
||||
## Setup
|
||||
|
||||
To get this working, there's a little setup to do.
|
||||
|
||||
### Mac OS/Linux setup ###
|
||||
### Linux/macOS setup
|
||||
|
||||
1. Check that the [file permissions](https://en.wikipedia.org/wiki/File_system_permissions) for "ping_pong.py" include the `execute` permission.
|
||||
2. Edit the "path" property of "ping_pong.json" to point to the location of "ping_pong.py" on your computer.
|
||||
3. copy "ping_pong.json" to the correct location on your computer. See [App manifest location ](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_manifests#Manifest_location) to find the correct location for your OS.
|
||||
0. (macOS) Store this extension in a location other than the Desktop, Documents, or Downloads folders in your home directory. macOS has access restrictions on these directories that prevent the Python script from executing as expected.
|
||||
|
||||
### Windows setup ###
|
||||
1. Make sure you have Python 3 installed, and your system's PATH environment variable includes the path to Python. You can check by executing this command:
|
||||
|
||||
1. Check you have Python installed, and that your system's PATH environment variable includes the path to Python. See [Using Python on Windows](https://docs.python.org/3/using/windows.html). You'll need to restart the web browser after making this change, or the browser won't pick up the new environment variable.
|
||||
2. Edit the "path" property of "ping_pong.json" to point to the location of "ping_pong_win.bat" on your computer. Note that you'll need to escape the Windows directory separator, like this: `"path": "C:\\Users\\MDN\\native-messaging\\app\\ping_pong_win.bat"`.
|
||||
3. Edit "ping_pong_win.bat" to refer to the location of "ping_pong.py" on your computer.
|
||||
4. Add a registry key containing the path to "ping_pong.json" on your computer. See [App manifest location ](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_manifests#Manifest_location) to find details of the registry key to add.
|
||||
```bash
|
||||
> which python3
|
||||
/usr/local/bin/python3
|
||||
```
|
||||
|
||||
To assist in troubleshooting on Windows, there is a script called `check_config_win.py`. Running this from the command line should give you an idea of any problems.
|
||||
If you don't see the path for Python, install Python 3. See [Using Python on Unix platforms](https://docs.python.org/3/using/unix.html) (for Linux) or [Using Python on a Mac](https://docs.python.org/3/using/mac.html). After making this change, restart Firefox so it picks up the new PATH environment variable.
|
||||
|
||||
## Testing the example ##
|
||||
2. Make sure that the [file permissions](https://en.wikipedia.org/wiki/File_system_permissions) for `app/ping_pong.py` include the `execute` permission. See [this article by RedHat](https://www.redhat.com/sysadmin/linux-file-permissions-explained) for more information.
|
||||
|
||||
First, install the add-on. Visit `about:debugging#/runtime/this-firefox` or, from `about:debugging` click "This Firefox" (or "This Nightly" in the Nightly version of Firefox), click "Load Temporary Add-on", and open the add-on's "manifest.json".
|
||||
3. Update the `"path"` field in `app/ping_pong.json` to be the full path to your `app/ping_pong.py` file.
|
||||
|
||||
Now, open the extension's console using the "Inspect" button - this is where you'll see communication between the browser and native app.
|
||||
For example, if you cloned this repository into `/Users/MDN/webextensions-examples/`, you would update the file like this:
|
||||
|
||||
```json
|
||||
"path": "/Users/MDN/webextensions-examples/native-messaging/app/ping_pong.py"
|
||||
```
|
||||
|
||||
4. Copy `app/ping_pong.json` to the correct location on your computer. There are too many options to list here; see the [Linux](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#linux) and [macOS](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#macos) secitons of [App manifest location ](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_manifests#Manifest_location) to find the correct location for your OS and personal preference.
|
||||
|
||||
### Windows setup
|
||||
|
||||
1. Make sure that you have Python 3 installed and that your system's PATH environment variable includes the path to Python. See [Using Python on Windows](https://docs.python.org/3/using/windows.html). After making this change, restart Firefox so it picks up the new PATH environment variable.
|
||||
|
||||
2. Update the `"path"` field in `app\ping_pong.json` to use the full path of `app\ping_pong_win.bat` on your computer. Be aware that you must escape the Windows directory separator (`\`).
|
||||
|
||||
For example, if you cloned this repository into `C:\Users\MDN\webextensions-examples\`, you update the JSON file like this:
|
||||
|
||||
```json
|
||||
"path": "C:\\Users\\MDN\\webextensions-examples\\native-messaging\\app\\ping_pong_win.bat"
|
||||
```
|
||||
|
||||
3. Update `app\ping_pong_win.bat` to use the full path of `app\ping_pong.py` on your computer.
|
||||
|
||||
4. Add a registry key containing the full path of `app\ping_pong.json` on your computer. See [App manifest location](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_manifests#Manifest_location) to find details of the registry key to add.
|
||||
|
||||
To assist in troubleshooting on Windows, there is a script next to this README file named `check_config_win.py`. Running this in a command shell should help you discover of any problems.
|
||||
|
||||
## Testing the example
|
||||
|
||||
First, install the add-on. Visit `about:debugging#/runtime/this-firefox` or, from `about:debugging` click "This Firefox" (or "This Nightly" in the Nightly version of Firefox), click "Load Temporary Add-on", and open the add-on's `manifest.json`.
|
||||
|
||||
Now, open the extension's console using the "Inspect" button. This is where you see communication between the browser and native app.
|
||||
|
||||
You should see a new browser action icon in the toolbar. Click it. You should see output like this in the console:
|
||||
|
||||
Sending: ping
|
||||
Received: pong3
|
||||
|
||||
If you're running Python 2.x, you'll see "pong2" as the response instead.
|
||||
Received: pong
|
||||
|
||||
If you don't see this output, see the [Troubleshooting guide](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_messaging#Troubleshooting) for ideas.
|
||||
|
||||
@@ -4,14 +4,29 @@ On startup, connect to the "ping_pong" app.
|
||||
let port = browser.runtime.connectNative("ping_pong");
|
||||
|
||||
/*
|
||||
Listen for messages from the app.
|
||||
Listen for messages from the app and log them to the console.
|
||||
*/
|
||||
port.onMessage.addListener((response) => {
|
||||
console.log("Received: " + response);
|
||||
});
|
||||
|
||||
/*
|
||||
On a click on the browser action, send the app a message.
|
||||
Listen for the native messaging port closing.
|
||||
*/
|
||||
port.onDisconnect.addListener((port) => {
|
||||
if (port.error) {
|
||||
console.log(`Disconnected due to an error: ${port.error.message}`);
|
||||
} else {
|
||||
// The port closed for an unspecified reason. If this occurred right after
|
||||
// calling `browser.runtime.connectNative()` there may have been a problem
|
||||
// starting the the native messaging client in the first place.
|
||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#troubleshooting
|
||||
console.log(`Disconnected`, port);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
When the extension's action icon is clicked, send the app a message.
|
||||
*/
|
||||
browser.browserAction.onClicked.addListener(() => {
|
||||
console.log("Sending: ping");
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import json
|
||||
import struct
|
||||
|
||||
try:
|
||||
# Python 3.x version
|
||||
# Read a message from stdin and decode it.
|
||||
def getMessage():
|
||||
# Read a message from stdin and decode it.
|
||||
def getMessage():
|
||||
rawLength = sys.stdin.buffer.read(4)
|
||||
if len(rawLength) == 0:
|
||||
sys.exit(0)
|
||||
@@ -15,9 +13,8 @@ try:
|
||||
message = sys.stdin.buffer.read(messageLength).decode('utf-8')
|
||||
return json.loads(message)
|
||||
|
||||
# Encode a message for transmission,
|
||||
# given its content.
|
||||
def encodeMessage(messageContent):
|
||||
# Encode a message for transmission, given its content.
|
||||
def encodeMessage(messageContent):
|
||||
# https://docs.python.org/3/library/json.html#basic-usage
|
||||
# To get the most compact JSON representation, you should specify
|
||||
# (',', ':') to eliminate whitespace.
|
||||
@@ -27,46 +24,13 @@ try:
|
||||
encodedLength = struct.pack('@I', len(encodedContent))
|
||||
return {'length': encodedLength, 'content': encodedContent}
|
||||
|
||||
# Send an encoded message to stdout
|
||||
def sendMessage(encodedMessage):
|
||||
# Send an encoded message to stdout
|
||||
def sendMessage(encodedMessage):
|
||||
sys.stdout.buffer.write(encodedMessage['length'])
|
||||
sys.stdout.buffer.write(encodedMessage['content'])
|
||||
sys.stdout.buffer.flush()
|
||||
|
||||
while True:
|
||||
while True:
|
||||
receivedMessage = getMessage()
|
||||
if receivedMessage == "ping":
|
||||
sendMessage(encodeMessage("pong3"))
|
||||
except AttributeError:
|
||||
# Python 2.x version (if sys.stdin.buffer is not defined)
|
||||
# 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):
|
||||
# https://docs.python.org/3/library/json.html#basic-usage
|
||||
# To get the most compact JSON representation, you should specify
|
||||
# (',', ':') to eliminate whitespace.
|
||||
# We want the most compact representation because the browser rejects
|
||||
# messages that exceed 1 MB.
|
||||
encodedContent = json.dumps(messageContent, separators=(',', ':'))
|
||||
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("pong2"))
|
||||
sendMessage(encodeMessage("pong"))
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
@echo off
|
||||
|
||||
call python C:\path\to\ping_pong.py
|
||||
call python3 C:\path\to\ping_pong.py
|
||||
|
||||
Reference in New Issue
Block a user