问题
I have developed a WebExtension for Firefox and my website works with the extension as a prerequisite. I need to check programmatically whether the extension is installed or not and if not ask the user to install it.
I am not able to find a way how to check this operation of whether my extension is already installed in the user's browser.
Editor note: Methods available in Firefox differ from those available in Chrome, so this question is not a duplicate.
回答1:
Important note to begin with: A page can't query if an extension is installed without explicit help from the extension. This is done to prevent browser fingerprinting and/or preventing sites from denying content if certain extensions are installed.
WebExtensions are largely built upon the same principles as Chrome extensions. As such, this question is relevant: Check whether user has a Chrome extension installed.
However, some of the best methods available in Chrome are currently unavailable in Firefox:
You can't use external messaging from a webpage (through
externally_connectable
) as it's not available in FF.You can't use web-accessible resources for checking presence since Firefox intentionally shields them from fingerprinting:
The files will then be available using a URL like:
moz-extension://<random-UUID>/<path/to/resource>
This UUID is randomly generated for every browser instance and is not your extension's ID. This prevents websites from fingerprinting the extensions a user has installed.
As such, what are your options? The page can't talk directly to the extension context (background), and the background can't directly affect the page; you need a Content script to interact with the page content.
How can page code and a content script communicate? They are isolated from each other unless content script does something about it.
First off, generic tricks that work in both FF and Chrome:
You can create or modify a DOM element on the page from a content script and look for those modifications in the page.
// Content script let beacon = document.createElement("div"); beacon.classname = browser.runtime.id; document.body.appendChild(beacon); // Page script // Make sure this runs after the extension code if (document.getElementsByClassName("expected-extension-id").length) { // Installed } else { // Not installed }
You can use
postMessage
to communicate between contexts, though it's clunky to use as a bidirectional channel.Here's documentation and sample WebExtension.
// Content script code window.postMessage({ direction: "from-content-script", message: "Message from extension" }, "*"); // Page code window.addEventListener("message", function(event) { if (event.source == window && event.data.direction && event.data.direction == "from-content-script") { // Assume extension is now installed } });
You can use custom DOM events in a similar way.
There are interesting Firefox-specific approaches as well:
You can share code with the page using
exportFunction
orcloneInto
:// Content script function usefulFunction() { /* ... */ } const extensionInterface = { usefulFunction } window.wrappedJSObject.extensionInterface = cloneInto(extensionInterface, window, {cloneFunctions: true}); // Page code if (typeof window.extensionInterface !== "undefined") { // Installed window.extensionInterface.usefulFunction(); } else { // Not installed }
来源:https://stackoverflow.com/questions/46727370/how-to-check-if-a-firefox-webextension-is-installed-or-not-with-page-javascript