From 06e230f7209606d667730a6fe9b3a26096152dae Mon Sep 17 00:00:00 2001 From: dan oak Date: Sat, 20 Apr 2024 18:33:06 +0300 Subject: [PATCH 01/13] native-messaging: fix not to fail on missing HKCU when HKLM is set there was a bug when missing key in HKEY_CURRENT_USER would throw from `winreg.OpenKey` call --- native-messaging/check_config_win.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/native-messaging/check_config_win.py b/native-messaging/check_config_win.py index 3bbfcaf2..d1d0ae3d 100755 --- a/native-messaging/check_config_win.py +++ b/native-messaging/check_config_win.py @@ -16,21 +16,15 @@ # Assuming current user overrides local machine. key_roots = ['HKEY_CURRENT_USER', 'HKEY_LOCAL_MACHINE'] -found_key = False - -for root in key_roots: - key = winreg.OpenKey(getattr(winreg, root), key_path) +for key_root in key_roots: try: - print('Checking:', root, key_path) + print('Checking:', key_root, key_path) + key = winreg.OpenKey(getattr(winreg, key_root), key_path) res = winreg.QueryValueEx(key, '') + break except FileNotFoundError: - print('...error finding key') - continue - - found_key = True - break - -if not found_key: + print('... error finding key') +else: raise ValueError('Could not find a registry entry, aborting.') json_path = res[0] From 2a93ff804a84cacb27d2619090787b510e653b23 Mon Sep 17 00:00:00 2001 From: dan oak Date: Sat, 20 Apr 2024 18:33:42 +0300 Subject: [PATCH 02/13] native-messaging README: replace Python 2 doc link to Python 3 --- native-messaging/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native-messaging/README.md b/native-messaging/README.md index 60fce8a0..8d69c6a5 100644 --- a/native-messaging/README.md +++ b/native-messaging/README.md @@ -16,7 +16,7 @@ To get this working, there's a little setup to do. ### Windows setup ### -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/2/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. +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. From 5dcff0bef00eb2deccda0c22fa911ead576aa0dc Mon Sep 17 00:00:00 2001 From: S C P <26688071+s-c-p@users.noreply.github.com> Date: Sat, 11 May 2024 09:24:33 +0530 Subject: [PATCH 03/13] Illustrative function name updateActiveTab has ambiguous meaning, most prominent of which doesn't mean what we are actually trying to do. --- bookmark-it/background.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bookmark-it/background.js b/bookmark-it/background.js index 8e76f2bd..b4d73e68 100644 --- a/bookmark-it/background.js +++ b/bookmark-it/background.js @@ -39,7 +39,7 @@ browser.browserAction.onClicked.addListener(toggleBookmark); /* * Switches currentTab and currentBookmark to reflect the currently active tab */ -function updateActiveTab(tabs) { +function updateAddonStateForActiveTab(tabs) { function isSupportedProtocol(urlString) { let supportedProtocols = ["https:", "http:", "ftp:", "file:"]; @@ -68,19 +68,19 @@ function updateActiveTab(tabs) { } // listen for bookmarks being created -browser.bookmarks.onCreated.addListener(updateActiveTab); +browser.bookmarks.onCreated.addListener(updateAddonStateForActiveTab); // listen for bookmarks being removed -browser.bookmarks.onRemoved.addListener(updateActiveTab); +browser.bookmarks.onRemoved.addListener(updateAddonStateForActiveTab); // listen to tab URL changes -browser.tabs.onUpdated.addListener(updateActiveTab); +browser.tabs.onUpdated.addListener(updateAddonStateForActiveTab); // listen to tab switching -browser.tabs.onActivated.addListener(updateActiveTab); +browser.tabs.onActivated.addListener(updateAddonStateForActiveTab); // listen for window switching -browser.windows.onFocusChanged.addListener(updateActiveTab); +browser.windows.onFocusChanged.addListener(updateAddonStateForActiveTab); // update when the extension loads initially -updateActiveTab(); +updateAddonStateForActiveTab(); From 91c8d7e7086fbc7bdb3032a217e63cc44a3b9320 Mon Sep 17 00:00:00 2001 From: echo Date: Sun, 2 Jun 2024 20:36:47 +0330 Subject: [PATCH 04/13] fixed typo in imagify/manifest.json (#563) --- imagify/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imagify/manifest.json b/imagify/manifest.json index 93fcd5aa..a4bec808 100644 --- a/imagify/manifest.json +++ b/imagify/manifest.json @@ -1,6 +1,6 @@ { - "description": "Adds a sidebar offerin a file picker and drap and drop zone. When an image file is chosen the active tab's body content is replaced with file selected. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#imagify", + "description": "Adds a sidebar offering a file picker and drap and drop zone. When an image file is chosen the active tab's body content is replaced with file selected. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#imagify", "manifest_version": 2, "name": "Imagify", "version": "1.0", From b5260e150a3fb351f6233d970811b27dd9056116 Mon Sep 17 00:00:00 2001 From: Simeon Vincent Date: Fri, 12 Jul 2024 18:42:56 -0700 Subject: [PATCH 05/13] Update native-messaging to use python3, clarify instructions Fixes #560 --- native-messaging/README.md | 56 ++++++++++++++++++-------- native-messaging/add-on/background.js | 18 ++++++++- native-messaging/add-on/manifest.json | 2 +- native-messaging/app/ping_pong.json | 2 +- native-messaging/app/ping_pong.py | 7 ++-- native-messaging/app/ping_pong_win.bat | 2 +- 6 files changed, 63 insertions(+), 24 deletions(-) diff --git a/native-messaging/README.md b/native-messaging/README.md index 60fce8a0..86228a95 100644 --- a/native-messaging/README.md +++ b/native-messaging/README.md @@ -4,36 +4,60 @@ 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. +1. Make sure that you have Python 3 installed, and that your system's PATH environment variable includes the path to Python by executing the following command: -### Windows setup ### + ```bash + > which python3 + /usr/local/bin/python3 + ``` -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/2/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. + If you don't see the path of the application as above, you most likely need to install Python 3 on your computer. See [Using Python on Unix platforms](https://docs.python.org/3/using/unix.html) or [Using Python on a Mac](https://docs.python.org/3/using/windows.html). Restart the web browser after making this change in order for Firefox to pick up the new PATH environment variable. -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. +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. -## Testing the example ## +3. Update the `"path"` field in `app/ping_pong.json` to be the full path to your `app/ping_pong.py` file. -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". + For example, if you cloned this repository into `/Users/MDN/webextensions-examples/`, you would update the file like this: -Now, open the extension's console using the "Inspect" button - this is where you'll see communication between the browser and native app. + ```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). You'll need to restart the web browser after making this change, or the browser won't pick up the new 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'll need to escape the Windows directory separator (`\`). + + For example, if you cloned this repository into `C:\Users\MDN\webextensions-examples\`, you would 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'll 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. - 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. diff --git a/native-messaging/add-on/background.js b/native-messaging/add-on/background.js index 020e6edd..d1e07dcf 100644 --- a/native-messaging/add-on/background.js +++ b/native-messaging/add-on/background.js @@ -4,14 +4,28 @@ 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. + 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"); diff --git a/native-messaging/add-on/manifest.json b/native-messaging/add-on/manifest.json index 0a7800c1..d0555584 100644 --- a/native-messaging/add-on/manifest.json +++ b/native-messaging/add-on/manifest.json @@ -22,7 +22,7 @@ "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 index a257b181..a19e0c29 100644 --- a/native-messaging/app/ping_pong.json +++ b/native-messaging/app/ping_pong.json @@ -1,7 +1,7 @@ { "name": "ping_pong", "description": "Example host for native messaging", - "path": "/path/to/native-messaging/app/ping_pong.py", + "path": "/Users/svincent/dev/webextensions-examples/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 index e9343800..895d5e5e 100755 --- a/native-messaging/app/ping_pong.py +++ b/native-messaging/app/ping_pong.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sys import json @@ -19,7 +19,7 @@ def getMessage(): # 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 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. @@ -37,6 +37,7 @@ def sendMessage(encodedMessage): 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. @@ -52,7 +53,7 @@ def getMessage(): # 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 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. diff --git a/native-messaging/app/ping_pong_win.bat b/native-messaging/app/ping_pong_win.bat index aac2019f..0d52af96 100644 --- a/native-messaging/app/ping_pong_win.bat +++ b/native-messaging/app/ping_pong_win.bat @@ -1,3 +1,3 @@ @echo off -call python C:\path\to\ping_pong.py +call python3 C:\path\to\ping_pong.py From 55c434810eca5f5b1a4be4d0a5b821d47b884d39 Mon Sep 17 00:00:00 2001 From: Simeon Vincent Date: Wed, 17 Jul 2024 12:28:41 -0700 Subject: [PATCH 06/13] Remove Python 2 support --- native-messaging/app/ping_pong.py | 97 ++++++++++--------------------- 1 file changed, 30 insertions(+), 67 deletions(-) diff --git a/native-messaging/app/ping_pong.py b/native-messaging/app/ping_pong.py index 895d5e5e..39e3d117 100755 --- a/native-messaging/app/ping_pong.py +++ b/native-messaging/app/ping_pong.py @@ -4,70 +4,33 @@ import json import struct -try: - # Python 3.x version - # Read a message from stdin and decode it. - def getMessage(): - rawLength = sys.stdin.buffer.read(4) - if len(rawLength) == 0: - sys.exit(0) - messageLength = struct.unpack('@I', rawLength)[0] - message = sys.stdin.buffer.read(messageLength).decode('utf-8') - 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=(',', ':')).encode('utf-8') - encodedLength = struct.pack('@I', len(encodedContent)) - return {'length': encodedLength, 'content': encodedContent} - - # 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: - 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")) +# Read a message from stdin and decode it. +def getMessage(): + rawLength = sys.stdin.buffer.read(4) + if len(rawLength) == 0: + sys.exit(0) + messageLength = struct.unpack('@I', rawLength)[0] + message = sys.stdin.buffer.read(messageLength).decode('utf-8') + 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=(',', ':')).encode('utf-8') + encodedLength = struct.pack('@I', len(encodedContent)) + return {'length': encodedLength, 'content': encodedContent} + +# 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: + receivedMessage = getMessage() + if receivedMessage == "ping": + sendMessage(encodeMessage("pong")) From 2d767fa652a97837edbcd1ee8ce2f5fc3fc2c063 Mon Sep 17 00:00:00 2001 From: Simeon Vincent Date: Wed, 17 Jul 2024 12:29:06 -0700 Subject: [PATCH 07/13] Add doc link for additional help --- native-messaging/add-on/background.js | 1 + 1 file changed, 1 insertion(+) diff --git a/native-messaging/add-on/background.js b/native-messaging/add-on/background.js index d1e07dcf..f4c9b092 100644 --- a/native-messaging/add-on/background.js +++ b/native-messaging/add-on/background.js @@ -20,6 +20,7 @@ port.onDisconnect.addListener((port) => { // 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); } }); From cdf409a9bfe04ff2135ec414405a309658216686 Mon Sep 17 00:00:00 2001 From: Simeon Vincent Date: Wed, 17 Jul 2024 12:34:18 -0700 Subject: [PATCH 08/13] Note directory restrictions on macOS --- native-messaging/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/native-messaging/README.md b/native-messaging/README.md index 86228a95..a3de3a09 100644 --- a/native-messaging/README.md +++ b/native-messaging/README.md @@ -10,6 +10,8 @@ To get this working, there's a little setup to do. ### Linux/macOS setup +0. (macOS) Make sure that you did not copy this extension into the Desktop, Documents, or Downloads folders in your home directory. macOS has access restrictions on these directories that will prevent the Python script from executing as expected. + 1. Make sure that you have Python 3 installed, and that your system's PATH environment variable includes the path to Python by executing the following command: ```bash From 8a66c92283db0976fb2c1f13faec321ac8cc201f Mon Sep 17 00:00:00 2001 From: Simeon Vincent Date: Wed, 17 Jul 2024 12:35:32 -0700 Subject: [PATCH 09/13] Update native-messaging/app/ping_pong.json Co-authored-by: Rob Wu --- native-messaging/app/ping_pong.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native-messaging/app/ping_pong.json b/native-messaging/app/ping_pong.json index a19e0c29..a257b181 100644 --- a/native-messaging/app/ping_pong.json +++ b/native-messaging/app/ping_pong.json @@ -1,7 +1,7 @@ { "name": "ping_pong", "description": "Example host for native messaging", - "path": "/Users/svincent/dev/webextensions-examples/native-messaging/app/ping_pong.py", + "path": "/path/to/native-messaging/app/ping_pong.py", "type": "stdio", "allowed_extensions": [ "ping_pong@example.org" ] } From d2d2255f77b425fffec3710e16663ed45d98e0a4 Mon Sep 17 00:00:00 2001 From: Simeon Vincent Date: Thu, 18 Jul 2024 15:22:39 -0700 Subject: [PATCH 10/13] Apply suggestions from code review Co-authored-by: rebloor --- native-messaging/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/native-messaging/README.md b/native-messaging/README.md index a3de3a09..2b8febf3 100644 --- a/native-messaging/README.md +++ b/native-messaging/README.md @@ -10,16 +10,16 @@ To get this working, there's a little setup to do. ### Linux/macOS setup -0. (macOS) Make sure that you did not copy this extension into the Desktop, Documents, or Downloads folders in your home directory. macOS has access restrictions on these directories that will prevent the Python script from executing as expected. +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. -1. Make sure that you have Python 3 installed, and that your system's PATH environment variable includes the path to Python by executing the following command: +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: ```bash > which python3 /usr/local/bin/python3 ``` - If you don't see the path of the application as above, you most likely need to install Python 3 on your computer. See [Using Python on Unix platforms](https://docs.python.org/3/using/unix.html) or [Using Python on a Mac](https://docs.python.org/3/using/windows.html). Restart the web browser after making this change in order for Firefox to pick up the new PATH environment variable. + 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. 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. @@ -35,11 +35,11 @@ To get this working, there's a little setup to do. ### 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). You'll need to restart the web browser after making this change, or the browser won't pick up the new environment variable. +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'll need to escape the Windows directory separator (`\`). +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 would update the JSON file like this: + 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" @@ -55,7 +55,7 @@ To assist in troubleshooting on Windows, there is a script next to this README f 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'll see communication between the browser and native app. +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: From cc4236edfb1f59794e9a50e079aeeeaf2659195f Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 12 Aug 2024 10:05:28 +0200 Subject: [PATCH 11/13] fix(examples.json): remove ​ There are two ​ (zero width space) in the examples.json --- examples.json | 1224 ++++++++++++++++++++++++------------------------- 1 file changed, 598 insertions(+), 626 deletions(-) diff --git a/examples.json b/examples.json index 994dd9ce..124cf1c1 100644 --- a/examples.json +++ b/examples.json @@ -1,628 +1,600 @@ [ - { - "description": "Displays a sidebar that lets you take notes on web pages.", - "javascript_apis": [ - "storage.local", - "tabs.onActivated", - "tabs.onUpdated", - "tabs.query", - "tabs.Tab", - "windows.getCurrent", - "windows​.Window" - ], - "name": "annotate-page" - }, - { - "description": "Adds a page action to the toolbar. Click the button to apply a red border using injected CSS. Click the button again to remove the CSS.", - "javascript_apis": [ - "pageAction.getTitle", - "pageAction.onClicked", - "pageAction.setIcon", - "pageAction.setTitle", - "pageAction.show", - "tabs.insertCSS", - "tabs.onUpdated", - "tabs.query", - "tabs.removeCSS", - "tabs.Tab" - ], - "name": "apply-css" - }, - { - "description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast.", - "javascript_apis": [ - "extension.getURL", - "runtime.onMessage", - "tabs.executeScript", - "tabs.insertCSS", - "tabs.query", - "tabs.removeCSS", - "tabs.sendMessage", - "tabs.Tab" - ], - "name": "beastify" - }, - { - "description": "Adds a bookmark button to the toolbar. Click the button to toggle a bookmark for the current page.", - "javascript_apis": [ - "bookmarks.create", - "bookmarks.onCreated", - "bookmarks.onRemoved", - "bookmarks.remove", - "bookmarks.search", - "browserAction.onClicked", - "browserAction.setIcon", - "browserAction.setTitle", - "tabs.onActivated", - "tabs.onUpdated", - "tabs.query", - "tabs.Tab", - "windows.onFocusChanged" - ], - "name": "bookmark-it" - }, - { - "description": "Adds a solid red border to all webpages matching mozilla.org.", - "javascript_apis": [], - "name": "borderify" - }, - { - "description": "Show a page action after a period of inactivity. Show cat gifs when the page action is clicked.", - "javascript_apis": [ - "alarms.clearAll", - "alarms.create", - "alarms.onAlarm", - "pageAction.hide", - "pageAction.onClicked", - "pageAction.show", - "tabs.get", - "tabs.onActivated", - "tabs.onUpdated", - "tabs.query", - "tabs.update" - ], - "name": "chill-out" - }, - { - "description": "Demonstrates using the commands API to set up a keyboard shortcut. The shortcut created is accessed using Ctrl+Shift+U (Command+Shift+U on a Mac).", - "javascript_apis": [ - "commands.getAll", - "commands.onCommand", - "commands.reset", - "commands.update", - "tabs.create" - ], - "name": "commands" - }, - { - "description": "Illustrates how an extension can register URL-matching content scripts at runtime.", - "javascript_apis": [ - "contentScripts.register", - "runtime.onMessage", - "runtime.sendMessage" - ], - "name": "content-script-register" - }, - { - "description": "Add a context menu option to links to copy the link to the clipboard, as plain text and as a link in rich HTML.", - "javascript_apis": [ - "contextMenus.create", - "contextMenus.onClicked", - "tabs.executeScript" - ], - "name": "context-menu-copy-link-with-types" - }, - { - "description": "List, create, and remove contextual identities.", - "javascript_apis": [ - "contextualIdentities.query", - "tabs.create", - "tabs.query", - "tabs.remove" - ], - "name": "contextual-identities" - }, - { - "description": "Allows the user to customize the background color and tiled pattern on sites they visit, and also saves their preferences via a cookie, reapplying them whenever they revisit a site they previously customized.", - "javascript_apis": [ - "cookies.get", - "cookies.onChanged", - "cookies.remove", - "cookies.set", - "extension.getURL", - "runtime.onMessage", - "tabs.onActivated", - "tabs.onUpdated", - "tabs.query", - "tabs.Tab", - "tabs.sendMessage" - ], - "name": "cookie-bg-picker" - }, - { - "description": "Demonstrates some of the devtools APIs.", - "javascript_apis": [ - "devtools.inspectedWindow", - "devtools.panels", - "runtime.getURL", - "runtime.onMessage", - "runtime.sendMessage", - "tabs.executeScript" - ], - "name": "devtools-panels" - }, - { - "description": "Demonstrates adding a custom search engine with the chrome_settings_overrides key.", - "javascript_apis": [], - "name": "discogs-search" - }, - { - "description": "Demonstrates how to block network requests without host permissions using the declarativeNetRequest API with the `declarative_net_request` manifest key.", - "javascript_apis": [ - "declarativeNetRequest.Rule", - "declarativeNetRequest.RuleAction", - "declarativeNetRequest.RuleCondition" - ], - "name": "dnr-block-only" - }, - { - "description": "Demonstrates a generic way to request host permissions and register declarativeNetRequest rules to modify network requests, without any install-time permission warnings. The options_ui page offers a way to request permissions and register DNR rules.", - "javascript_apis": [ - "declarativeNetRequest.Rule", - "declarativeNetRequest.getDynamicRules", - "declarativeNetRequest.getSessionRules", - "declarativeNetRequest.updateDynamicRules", - "declarativeNetRequest.updateSessionRules", - "permissions.getAll", - "permissions.remove", - "permissions.request" - ], - "name": "dnr-dynamic-with-options" - }, - { - "description": "Demonstrates multiple ways to redirect requests using the declarativeNetRequest API through the `declarative_net_request` manifest key. Demonstrates aspects of Manifest Version 3 (MV3): action, host_permissions, and web_accessible_resources, and includes a comparison with Manifest Version 2 (MV2).", - "javascript_apis": [ - "declarativeNetRequest.Redirect", - "declarativeNetRequest.Rule", - "declarativeNetRequest.RuleAction", - "declarativeNetRequest.RuleCondition", - "declarativeNetRequest.URLTransform", - "permissions.contains", - "permissions.remove", - "permissions.request" - ], - "name": "dnr-redirect-url" - }, - { - "description": "Dynamic theme example", - "javascript_apis": [ - "alarms.create", - "alarms.onAlarm", - "theme.update" - ], - "name": "dynamic-theme" - }, - { - "description": "Replaces words with emojis.", - "javascript_apis": [], - "name": "emoji-substitution" - }, - { - "description": "Demonstrates how to configure an extension with eslint.", - "javascript_apis": [], - "name": "eslint-example" - }, - { - "description": "Demonstrates how to use export helpers like cloneInto to share objects with page scripts.", - "javascript_apis": [ - "notifications.create", - "runtime.onMessage", - "runtime.sendMessage" - ], - "name": "export-helpers" - }, - { - "description": "An example options page, letting you store your favourite colour.", - "javascript_apis": [ - "browserAction.onClicked", - "runtime.openOptionsPage", - "storage.managed", - "storage.sync" - ], - "name": "favourite-colour" - }, - { - "description": "Demonstration of the find API.", - "javascript_apis": [ - "browserAction.onClicked", - "extension.getBackgroundPage", - "find.find", - "find.highlightResults", - "runtime.getURL", - "runtime.onMessage", - "runtime.sendMessage", - "tabs.create", - "tabs.query", - "tabs.Tab" - ], - "name": "find-across-tabs" - }, - { - "description": "Demonstrates how to use the omnibox API.", - "javascript_apis": [ - "omnibox.onInputChanged", - "omnibox.onInputEntered", - "omnibox.setDefaultSuggestion", - "tabs.create", - "tabs.update" - ], - "name": "firefox-code-search" - }, - { - "description": "Demonstrates how to use the browsingData API.", - "javascript_apis": [ - "browserAction.onClicked", - "browsingData.remove", - "notifications.create", - "storage.local" - ], - "name": "forget-it" - }, - { - "description": "Demonstrates how to use the identity API.", - "javascript_apis": [ - "browserAction.onClicked", - "identity.getRedirectURL", - "identity.launchWebAuthFlow", - "notifications.create" - ], - "name": "google-userinfo" - }, - { - "description": "History API demo: deletes history items for a given domain", - "javascript_apis": [ - "history.deleteUrl", - "history.search", - "pageAction.show", - "tabs.onUpdated", - "tabs.query" - ], - "name": "history-deleter" - }, - { - "description": "Demonstrates how to rewrite HTTP responses using the webRequest.filterResponseData() API.", - "javascript_apis": [ - "webRequest.filterResponseData", - "webRequest.onBeforeRequest" - ], - "name": "http-response" - }, - { - "description": "Using a sidebar, illustrates the use of file picker and drag and drop. A content script replaces the current page content with the chosen image.", - "javascript_apis": [ - "extension.getURL", - "runtime.onMessage", - "tabs.executeScript", - "tabs.query", - "tabs.sendMessage" - ], - "name": "imagify" - }, - { - "description": "Shows the last downloaded item, and lets you open or delete it.", - "javascript_apis": [ - "downloads.erase", - "downloads.getFileIcon", - "downloads.open", - "downloads.removeFile", - "downloads.search" - ], - "name": "latest-download" - }, - { - "description": "This extensions list the cookies in the active tab.", - "javascript_apis": [ - "cookies.getAll", - "tabs.query" - ], - "name": "list-cookies" - }, - { - "description": "Shows how to set up a single letter access key for a menu item.", - "javascript_apis": [ - "i18n.getMessage", - "menus.update", - "menus.create", - "menus.onClicked" - ], - "name": "menu-accesskey-visible" - }, - { - "description": "Demonstrates adding and manipulating menu items using the menus API.", - "javascript_apis": [ - "i18n.getMessage", - "menus.create", - "menus.onClicked", - "menus.remove", - "menus.update", - "runtime.lastError", - "tabs.executeScript" - ], - "name": "menu-demo" - }, - { - "description": "Shows how an extension can listen for the display of a menu and then add, remove, or update its menu items.", - "javascript_apis": [ - "menus.create", - "menus.onClicked", - "menus.onShown", - "menus.refresh", - "menus.update", - "tabs.update" - ], - "name": "menu-labelled-open" - }, - { - "description": "Shows how to detect the page element at the cursor position and remove that element, or a parent element, from the page. This example includes use of the polyfill, illustrating cross-browser extension development.", - "javascript_apis": [ - "menus.create", - "menus.onClicked", - "menus.getTargetElement", - "pageAction.openPopup", - "pageAction.show", - "tabs.executeScript" - ], - "name": "menu-remove-element" - }, - { - "description": "Illustrates how to retrieve a list of search engines and issue a search request, using search engine details added to the context menu for selected text.", - "javascript_apis": [ - "search.search", - "search.get", - "menus.create", - "menus.onClicked" - ], - "name": "menu-search" - }, - { - "description": "This example shows two methods of testing an extension: running tests from within the extension, and running tests from the command line using Karma.", - "javascript_apis": [ - "runtime.onMessage", - "runtime.sendMessage" - ], - "name": "mocha-client-tests" - }, - { - "description": "Example of native messaging, including a Python application and an extension which exchanges messages with it.", - "javascript_apis": [ - "browserAction.onClicked", - "runtime.connectNative" - ], - "name": "native-messaging" - }, - { - "description": "Demonstration of the webNavigation API, showing basic stats about which pages you've visited.", - "javascript_apis": [ - "storage.local", - "webNavigation.onCommitted", - "webNavigation.onCompleted" - ], - "name": "navigation-stats" - }, - { - "description": "Shows a localized notification when the user clicks on links.", - "javascript_apis": [ - "extension.getURL", - "i18n.getMessage", - "notifications.create", - "runtime.onMessage", - "runtime.sendMessage" - ], - "name": "notify-link-clicks-i18n" - }, - { - "description": "Adds a browser action icon to the toolbar. When the browser action is clicked, the add-on opens a page that was packaged with it.", - "javascript_apis": [ - "browserAction.onClicked", - "tabs.create" - ], - "name": "open-my-page-button" - }, - { - "description": "Demonstrates how a web page and a content script can exchange messages. Visit https://mdn.github.io/webextensions-examples/content-script-page-script-messaging.html for the demo.", - "javascript_apis": [], - "name": "page-to-extension-messaging" - }, - { - "description": "Demonstrates optional permissions using the permissions API.", - "javascript_apis": [ - "browserAction.onClicked", - "permissions.getAll", - "permissions.remove", - "permissions.request", - "runtime.getURL", - "tabs.create" - ], - "name": "permissions" - }, - { - "description": "Example dynamic theme: sets a dark theme for private windows.", - "javascript_apis": [ - "theme.reset", - "theme.update", - "windows.getAll", - "windows.onCreated" - ], - "name": "private-browsing-theme" - }, - { - "description": "Uses the proxy API to block requests to hosts specified on a list.", - "javascript_apis": [ - "extension.getURL", - "proxy.onRequest", - "proxy.onError", - "storage.local", - "storage.onChanged" - ], - "name": "proxy-blocker" - }, - { - "description": "Allows the user to make quick notes by clicking a button and entering text into the resulting popup. The notes are saved in storage.", - "javascript_apis": [ - "storage.local" - ], - "name": "quicknote" - }, - { - "description": "Shows how to get details about a request's TLS connection.", - "javascript_apis": [ - "webRequest.getSecurityInfo" - ], - "name": "root-cert-stats" - }, - { - "description": "Demo of various runtime APIs.", - "javascript_apis": [ - "browserAction.onClicked", - "notifications.create", - "runtime.getManifest", - "runtime.onInstalled", - "runtime.reload" - ], - "name": "runtime-examples" - }, - { - "description": "Demonstrates how to write to the clipboard from a content script", - "javascript_apis": [], - "name": "selection-to-clipboard" - }, - { - "description": "Demonstrates how to retrieve extension-defined state from restored tabs.", - "javascript_apis": [ - "menus.create", - "menus.onClicked", - "sessions.getTabValue", - "sessions.setTabValue", - "tabs.insertCSS", - "tabs.onCreated", - "tabs.onUpdated", - "tabs.query" - ], - "name": "session-state" - }, - { - "description": "Demonstrates how to use the idb-file-storage library to store and manipulate files in an extension.", - "javascript_apis": [ - "browserAction.onClicked", - "contextMenus.create", - "contextMenus.onClicked", - "runtime.onMessage", - "runtime.sendMessage", - "tabs.create", - "windows.create" - ], - "name": "store-collected-images" - }, - { - "description": "Performs basic authentication by supplying stored credentials.", - "javascript_apis": [ - "storage.local", - "webRequest.onAuthRequired", - "webRequest.onCompleted", - "webRequest.onErrorOccurred" - ], - "name": "stored-credentials" - }, - { - "description": "Demonstrates tab manipulation: opening, closing, moving, zooming tabs.", - "javascript_apis": [ - "browserAction.setBadgeBackgroundColor", - "browserAction.setBadgeText", - "tabs.create", - "tabs.duplicate", - "tabs.getZoom", - "tabs.move", - "tabs.onCreated", - "tabs.onMoved", - "tabs.onRemoved", - "tabs.query", - "tabs.reload", - "tabs.remove", - "tabs.setZoom", - "tabs.Tab", - "tabs.update" - ], - "name": "tabs-tabs-tabs" - }, - { - "description": "A sidebar that integrates with the current theme.", - "javascript_apis": [ - "theme.getCurrent", - "theme.onUpdated", - "windows.getCurrent" - ], - "name": "theme-integrated-sidebar" - }, - { - "description": "An example of how to use the management API for themes.", - "javascript_apis": [ - "management.getAll", - "management.setEnabled" - ], - "name": "theme-switcher" - }, - { - "description": "A collection of themes illustrating:
  • weta_fade: a basic theme employing a single image specified in theme_frame:.
  • weta_fade_chrome: the weta_fade theme implemented with Chrome compatible manifest keys.
  • weta_tiled: a theme using a tiled image.
  • weta_mirror: a theme using multiple images and aligning those images in the header.
  • animated: use of an animated PNG.
", - "javascript_apis": [], - "name": "themes" - }, - { - "description": "Demonstration of the topSites API.", - "javascript_apis": [ - "topSites.get" - ], - "name": "top-sites" - }, - { - "description": "Demonstrates using the webRequest API to rewrite the User-Agent HTTP header.", - "javascript_apis": [ - "extension.getBackgroundPage", - "webRequest.onBeforeSendHeaders" - ], - "name": "user-agent-rewriter" - }, - { - "description": "Illustrates how an extension can register URL-matching user scripts at runtime.", - "javascript_apis": [ - "userScripts.register", - "runtime.onMessage", - "runtime.sendMessage" - ], - "name": "user-script-register" - }, - { - "description": "Demonstrates how to use webpack to package npm modules in an extension.", - "javascript_apis": [ - "runtime.onMessage", - "runtime.sendMessage" - ], - "name": "webpack-modules" - }, - { - "description": "Demonstrates how to manipulate windows: opening, closing, resizing windows.", - "javascript_apis": [ - "windows.create", - "windows.getAll", - "windows.getCurrent", - "windows.remove", - "windows.update", - "windows​.Window" - ], - "name": "window-manipulator" - }, - { - "description": "Demonstrates the use of protocol handlers.", - "javascript_apis": [], - "name": "open-irc-links" - } + { + "description": "Displays a sidebar that lets you take notes on web pages.", + "javascript_apis": [ + "storage.local", + "tabs.onActivated", + "tabs.onUpdated", + "tabs.query", + "tabs.Tab", + "windows.getCurrent", + "windows.Window" + ], + "name": "annotate-page" + }, + { + "description": "Adds a page action to the toolbar. Click the button to apply a red border using injected CSS. Click the button again to remove the CSS.", + "javascript_apis": [ + "pageAction.getTitle", + "pageAction.onClicked", + "pageAction.setIcon", + "pageAction.setTitle", + "pageAction.show", + "tabs.insertCSS", + "tabs.onUpdated", + "tabs.query", + "tabs.removeCSS", + "tabs.Tab" + ], + "name": "apply-css" + }, + { + "description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast.", + "javascript_apis": [ + "extension.getURL", + "runtime.onMessage", + "tabs.executeScript", + "tabs.insertCSS", + "tabs.query", + "tabs.removeCSS", + "tabs.sendMessage", + "tabs.Tab" + ], + "name": "beastify" + }, + { + "description": "Adds a bookmark button to the toolbar. Click the button to toggle a bookmark for the current page.", + "javascript_apis": [ + "bookmarks.create", + "bookmarks.onCreated", + "bookmarks.onRemoved", + "bookmarks.remove", + "bookmarks.search", + "browserAction.onClicked", + "browserAction.setIcon", + "browserAction.setTitle", + "tabs.onActivated", + "tabs.onUpdated", + "tabs.query", + "tabs.Tab", + "windows.onFocusChanged" + ], + "name": "bookmark-it" + }, + { + "description": "Adds a solid red border to all webpages matching mozilla.org.", + "javascript_apis": [], + "name": "borderify" + }, + { + "description": "Show a page action after a period of inactivity. Show cat gifs when the page action is clicked.", + "javascript_apis": [ + "alarms.clearAll", + "alarms.create", + "alarms.onAlarm", + "pageAction.hide", + "pageAction.onClicked", + "pageAction.show", + "tabs.get", + "tabs.onActivated", + "tabs.onUpdated", + "tabs.query", + "tabs.update" + ], + "name": "chill-out" + }, + { + "description": "Demonstrates using the commands API to set up a keyboard shortcut. The shortcut created is accessed using Ctrl+Shift+U (Command+Shift+U on a Mac).", + "javascript_apis": [ + "commands.getAll", + "commands.onCommand", + "commands.reset", + "commands.update", + "tabs.create" + ], + "name": "commands" + }, + { + "description": "Illustrates how an extension can register URL-matching content scripts at runtime.", + "javascript_apis": [ + "contentScripts.register", + "runtime.onMessage", + "runtime.sendMessage" + ], + "name": "content-script-register" + }, + { + "description": "Add a context menu option to links to copy the link to the clipboard, as plain text and as a link in rich HTML.", + "javascript_apis": [ + "contextMenus.create", + "contextMenus.onClicked", + "tabs.executeScript" + ], + "name": "context-menu-copy-link-with-types" + }, + { + "description": "List, create, and remove contextual identities.", + "javascript_apis": [ + "contextualIdentities.query", + "tabs.create", + "tabs.query", + "tabs.remove" + ], + "name": "contextual-identities" + }, + { + "description": "Allows the user to customize the background color and tiled pattern on sites they visit, and also saves their preferences via a cookie, reapplying them whenever they revisit a site they previously customized.", + "javascript_apis": [ + "cookies.get", + "cookies.onChanged", + "cookies.remove", + "cookies.set", + "extension.getURL", + "runtime.onMessage", + "tabs.onActivated", + "tabs.onUpdated", + "tabs.query", + "tabs.Tab", + "tabs.sendMessage" + ], + "name": "cookie-bg-picker" + }, + { + "description": "Demonstrates some of the devtools APIs.", + "javascript_apis": [ + "devtools.inspectedWindow", + "devtools.panels", + "runtime.getURL", + "runtime.onMessage", + "runtime.sendMessage", + "tabs.executeScript" + ], + "name": "devtools-panels" + }, + { + "description": "Demonstrates adding a custom search engine with the chrome_settings_overrides key.", + "javascript_apis": [], + "name": "discogs-search" + }, + { + "description": "Demonstrates how to block network requests without host permissions using the declarativeNetRequest API with the `declarative_net_request` manifest key.", + "javascript_apis": [ + "declarativeNetRequest.Rule", + "declarativeNetRequest.RuleAction", + "declarativeNetRequest.RuleCondition" + ], + "name": "dnr-block-only" + }, + { + "description": "Demonstrates a generic way to request host permissions and register declarativeNetRequest rules to modify network requests, without any install-time permission warnings. The options_ui page offers a way to request permissions and register DNR rules.", + "javascript_apis": [ + "declarativeNetRequest.Rule", + "declarativeNetRequest.getDynamicRules", + "declarativeNetRequest.getSessionRules", + "declarativeNetRequest.updateDynamicRules", + "declarativeNetRequest.updateSessionRules", + "permissions.getAll", + "permissions.remove", + "permissions.request" + ], + "name": "dnr-dynamic-with-options" + }, + { + "description": "Demonstrates multiple ways to redirect requests using the declarativeNetRequest API through the `declarative_net_request` manifest key. Demonstrates aspects of Manifest Version 3 (MV3): action, host_permissions, and web_accessible_resources, and includes a comparison with Manifest Version 2 (MV2).", + "javascript_apis": [ + "declarativeNetRequest.Redirect", + "declarativeNetRequest.Rule", + "declarativeNetRequest.RuleAction", + "declarativeNetRequest.RuleCondition", + "declarativeNetRequest.URLTransform", + "permissions.contains", + "permissions.remove", + "permissions.request" + ], + "name": "dnr-redirect-url" + }, + { + "description": "Dynamic theme example", + "javascript_apis": ["alarms.create", "alarms.onAlarm", "theme.update"], + "name": "dynamic-theme" + }, + { + "description": "Replaces words with emojis.", + "javascript_apis": [], + "name": "emoji-substitution" + }, + { + "description": "Demonstrates how to configure an extension with eslint.", + "javascript_apis": [], + "name": "eslint-example" + }, + { + "description": "Demonstrates how to use export helpers like cloneInto to share objects with page scripts.", + "javascript_apis": [ + "notifications.create", + "runtime.onMessage", + "runtime.sendMessage" + ], + "name": "export-helpers" + }, + { + "description": "An example options page, letting you store your favourite colour.", + "javascript_apis": [ + "browserAction.onClicked", + "runtime.openOptionsPage", + "storage.managed", + "storage.sync" + ], + "name": "favourite-colour" + }, + { + "description": "Demonstration of the find API.", + "javascript_apis": [ + "browserAction.onClicked", + "extension.getBackgroundPage", + "find.find", + "find.highlightResults", + "runtime.getURL", + "runtime.onMessage", + "runtime.sendMessage", + "tabs.create", + "tabs.query", + "tabs.Tab" + ], + "name": "find-across-tabs" + }, + { + "description": "Demonstrates how to use the omnibox API.", + "javascript_apis": [ + "omnibox.onInputChanged", + "omnibox.onInputEntered", + "omnibox.setDefaultSuggestion", + "tabs.create", + "tabs.update" + ], + "name": "firefox-code-search" + }, + { + "description": "Demonstrates how to use the browsingData API.", + "javascript_apis": [ + "browserAction.onClicked", + "browsingData.remove", + "notifications.create", + "storage.local" + ], + "name": "forget-it" + }, + { + "description": "Demonstrates how to use the identity API.", + "javascript_apis": [ + "browserAction.onClicked", + "identity.getRedirectURL", + "identity.launchWebAuthFlow", + "notifications.create" + ], + "name": "google-userinfo" + }, + { + "description": "History API demo: deletes history items for a given domain", + "javascript_apis": [ + "history.deleteUrl", + "history.search", + "pageAction.show", + "tabs.onUpdated", + "tabs.query" + ], + "name": "history-deleter" + }, + { + "description": "Demonstrates how to rewrite HTTP responses using the webRequest.filterResponseData() API.", + "javascript_apis": [ + "webRequest.filterResponseData", + "webRequest.onBeforeRequest" + ], + "name": "http-response" + }, + { + "description": "Using a sidebar, illustrates the use of file picker and drag and drop. A content script replaces the current page content with the chosen image.", + "javascript_apis": [ + "extension.getURL", + "runtime.onMessage", + "tabs.executeScript", + "tabs.query", + "tabs.sendMessage" + ], + "name": "imagify" + }, + { + "description": "Shows the last downloaded item, and lets you open or delete it.", + "javascript_apis": [ + "downloads.erase", + "downloads.getFileIcon", + "downloads.open", + "downloads.removeFile", + "downloads.search" + ], + "name": "latest-download" + }, + { + "description": "This extensions list the cookies in the active tab.", + "javascript_apis": ["cookies.getAll", "tabs.query"], + "name": "list-cookies" + }, + { + "description": "Shows how to set up a single letter access key for a menu item.", + "javascript_apis": [ + "i18n.getMessage", + "menus.update", + "menus.create", + "menus.onClicked" + ], + "name": "menu-accesskey-visible" + }, + { + "description": "Demonstrates adding and manipulating menu items using the menus API.", + "javascript_apis": [ + "i18n.getMessage", + "menus.create", + "menus.onClicked", + "menus.remove", + "menus.update", + "runtime.lastError", + "tabs.executeScript" + ], + "name": "menu-demo" + }, + { + "description": "Shows how an extension can listen for the display of a menu and then add, remove, or update its menu items.", + "javascript_apis": [ + "menus.create", + "menus.onClicked", + "menus.onShown", + "menus.refresh", + "menus.update", + "tabs.update" + ], + "name": "menu-labelled-open" + }, + { + "description": "Shows how to detect the page element at the cursor position and remove that element, or a parent element, from the page. This example includes use of the polyfill, illustrating cross-browser extension development.", + "javascript_apis": [ + "menus.create", + "menus.onClicked", + "menus.getTargetElement", + "pageAction.openPopup", + "pageAction.show", + "tabs.executeScript" + ], + "name": "menu-remove-element" + }, + { + "description": "Illustrates how to retrieve a list of search engines and issue a search request, using search engine details added to the context menu for selected text.", + "javascript_apis": [ + "search.search", + "search.get", + "menus.create", + "menus.onClicked" + ], + "name": "menu-search" + }, + { + "description": "This example shows two methods of testing an extension: running tests from within the extension, and running tests from the command line using Karma.", + "javascript_apis": ["runtime.onMessage", "runtime.sendMessage"], + "name": "mocha-client-tests" + }, + { + "description": "Example of native messaging, including a Python application and an extension which exchanges messages with it.", + "javascript_apis": ["browserAction.onClicked", "runtime.connectNative"], + "name": "native-messaging" + }, + { + "description": "Demonstration of the webNavigation API, showing basic stats about which pages you've visited.", + "javascript_apis": [ + "storage.local", + "webNavigation.onCommitted", + "webNavigation.onCompleted" + ], + "name": "navigation-stats" + }, + { + "description": "Shows a localized notification when the user clicks on links.", + "javascript_apis": [ + "extension.getURL", + "i18n.getMessage", + "notifications.create", + "runtime.onMessage", + "runtime.sendMessage" + ], + "name": "notify-link-clicks-i18n" + }, + { + "description": "Adds a browser action icon to the toolbar. When the browser action is clicked, the add-on opens a page that was packaged with it.", + "javascript_apis": ["browserAction.onClicked", "tabs.create"], + "name": "open-my-page-button" + }, + { + "description": "Demonstrates how a web page and a content script can exchange messages. Visit https://mdn.github.io/webextensions-examples/content-script-page-script-messaging.html for the demo.", + "javascript_apis": [], + "name": "page-to-extension-messaging" + }, + { + "description": "Demonstrates optional permissions using the permissions API.", + "javascript_apis": [ + "browserAction.onClicked", + "permissions.getAll", + "permissions.remove", + "permissions.request", + "runtime.getURL", + "tabs.create" + ], + "name": "permissions" + }, + { + "description": "Example dynamic theme: sets a dark theme for private windows.", + "javascript_apis": [ + "theme.reset", + "theme.update", + "windows.getAll", + "windows.onCreated" + ], + "name": "private-browsing-theme" + }, + { + "description": "Uses the proxy API to block requests to hosts specified on a list.", + "javascript_apis": [ + "extension.getURL", + "proxy.onRequest", + "proxy.onError", + "storage.local", + "storage.onChanged" + ], + "name": "proxy-blocker" + }, + { + "description": "Allows the user to make quick notes by clicking a button and entering text into the resulting popup. The notes are saved in storage.", + "javascript_apis": ["storage.local"], + "name": "quicknote" + }, + { + "description": "Shows how to get details about a request's TLS connection.", + "javascript_apis": ["webRequest.getSecurityInfo"], + "name": "root-cert-stats" + }, + { + "description": "Demo of various runtime APIs.", + "javascript_apis": [ + "browserAction.onClicked", + "notifications.create", + "runtime.getManifest", + "runtime.onInstalled", + "runtime.reload" + ], + "name": "runtime-examples" + }, + { + "description": "Demonstrates how to write to the clipboard from a content script", + "javascript_apis": [], + "name": "selection-to-clipboard" + }, + { + "description": "Demonstrates how to retrieve extension-defined state from restored tabs.", + "javascript_apis": [ + "menus.create", + "menus.onClicked", + "sessions.getTabValue", + "sessions.setTabValue", + "tabs.insertCSS", + "tabs.onCreated", + "tabs.onUpdated", + "tabs.query" + ], + "name": "session-state" + }, + { + "description": "Demonstrates how to use the idb-file-storage library to store and manipulate files in an extension.", + "javascript_apis": [ + "browserAction.onClicked", + "contextMenus.create", + "contextMenus.onClicked", + "runtime.onMessage", + "runtime.sendMessage", + "tabs.create", + "windows.create" + ], + "name": "store-collected-images" + }, + { + "description": "Performs basic authentication by supplying stored credentials.", + "javascript_apis": [ + "storage.local", + "webRequest.onAuthRequired", + "webRequest.onCompleted", + "webRequest.onErrorOccurred" + ], + "name": "stored-credentials" + }, + { + "description": "Demonstrates tab manipulation: opening, closing, moving, zooming tabs.", + "javascript_apis": [ + "browserAction.setBadgeBackgroundColor", + "browserAction.setBadgeText", + "tabs.create", + "tabs.duplicate", + "tabs.getZoom", + "tabs.move", + "tabs.onCreated", + "tabs.onMoved", + "tabs.onRemoved", + "tabs.query", + "tabs.reload", + "tabs.remove", + "tabs.setZoom", + "tabs.Tab", + "tabs.update" + ], + "name": "tabs-tabs-tabs" + }, + { + "description": "A sidebar that integrates with the current theme.", + "javascript_apis": [ + "theme.getCurrent", + "theme.onUpdated", + "windows.getCurrent" + ], + "name": "theme-integrated-sidebar" + }, + { + "description": "An example of how to use the management API for themes.", + "javascript_apis": ["management.getAll", "management.setEnabled"], + "name": "theme-switcher" + }, + { + "description": "A collection of themes illustrating:
  • weta_fade: a basic theme employing a single image specified in theme_frame:.
  • weta_fade_chrome: the weta_fade theme implemented with Chrome compatible manifest keys.
  • weta_tiled: a theme using a tiled image.
  • weta_mirror: a theme using multiple images and aligning those images in the header.
  • animated: use of an animated PNG.
", + "javascript_apis": [], + "name": "themes" + }, + { + "description": "Demonstration of the topSites API.", + "javascript_apis": ["topSites.get"], + "name": "top-sites" + }, + { + "description": "Demonstrates using the webRequest API to rewrite the User-Agent HTTP header.", + "javascript_apis": [ + "extension.getBackgroundPage", + "webRequest.onBeforeSendHeaders" + ], + "name": "user-agent-rewriter" + }, + { + "description": "Illustrates how an extension can register URL-matching user scripts at runtime.", + "javascript_apis": [ + "userScripts.register", + "runtime.onMessage", + "runtime.sendMessage" + ], + "name": "user-script-register" + }, + { + "description": "Demonstrates how to use webpack to package npm modules in an extension.", + "javascript_apis": ["runtime.onMessage", "runtime.sendMessage"], + "name": "webpack-modules" + }, + { + "description": "Demonstrates how to manipulate windows: opening, closing, resizing windows.", + "javascript_apis": [ + "windows.create", + "windows.getAll", + "windows.getCurrent", + "windows.remove", + "windows.update", + "windows.Window" + ], + "name": "window-manipulator" + }, + { + "description": "Demonstrates the use of protocol handlers.", + "javascript_apis": [], + "name": "open-irc-links" + } ] From 1d8a18aa1ef818dbe360277fee51189abff9bf38 Mon Sep 17 00:00:00 2001 From: rebloor Date: Mon, 9 Sep 2024 16:26:27 +1200 Subject: [PATCH 12/13] Automatic theme switching support in favorite colours (#567) * Automatic theme switching support in favorite colours * Ref to dark theme Co-authored-by: Rob Wu --------- Co-authored-by: Rob Wu --- favourite-colour/README.md | 10 +++++----- favourite-colour/options.html | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/favourite-colour/README.md b/favourite-colour/README.md index 820fc084..e0cc7815 100644 --- a/favourite-colour/README.md +++ b/favourite-colour/README.md @@ -1,15 +1,15 @@ # Favourite Colour -Shows and stores your favourite colour, in storage.sync in the about:addons page for the add-on. +Shows and stores your favourite colour, in storage.sync in the extension's about:addons page. Demonstrates: * storing data with storage.sync +* reading data from storage.managed +* creating an options page and opening it with `runtime.openOptionsPage()` +* best practice for supporting automatic theme switching (dark theme) in the options page -* reading data from storage.managed, -* creating an options page and opening it with `runtime.openOptionsPage()`. - -To have Firefox read data from storage.managed, create a file with the following contents: +To have Firefox read data from storage.managed, create a file with this content: { "name": "favourite-colour-examples@mozilla.org", diff --git a/favourite-colour/options.html b/favourite-colour/options.html index 6b117280..604761a3 100644 --- a/favourite-colour/options.html +++ b/favourite-colour/options.html @@ -3,6 +3,7 @@ + From 735dee777c51ca595bbca0311ce239e312764674 Mon Sep 17 00:00:00 2001 From: rebloor Date: Wed, 23 Oct 2024 14:29:04 +1300 Subject: [PATCH 13/13] Update README.md Example now simply returns "pong" --- native-messaging/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native-messaging/README.md b/native-messaging/README.md index 2b8febf3..1cb028dc 100644 --- a/native-messaging/README.md +++ b/native-messaging/README.md @@ -60,6 +60,6 @@ Now, open the extension's console using the "Inspect" button. This is where you 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 + 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.