如何使用页面 JavaScript 检查是否安装了 Firefox WebExtension?

Man*_*der 6 javascript mozilla google-chrome-extension firefox-addon-webextensions

我已经为 Firefox 开发了一个 WebExtension,我的网站以该扩展程序为先决条件。我需要以编程方式检查扩展是否安装,如果没有要求用户安装它。

我无法找到如何检查我的扩展程序是否已安装在用户浏览器中的操作。

编者注:Firefox 中可用的方法与Chrome 中可用的方法不同,因此此问题不重复。

Xan*_*Xan 8

开始时的重要说明:如果没有扩展程序的明确帮助,页面无法查询是否安装了扩展程序。这样做是为了防止浏览器指纹识别和/或防止网站在安装了某些扩展程序时拒绝内容。

WebExtensions 主要建立在与 Chrome 扩展程序相同的原则上。因此,这个问题是相关的:检查用户是否安装了 Chrome 扩展程序

但是,Chrome 中可用的一些最佳方法目前在 Firefox 中不可用

然后可以使用如下 URL 访问这些文件:

moz-extension://<random-UUID>/<path/to/resource>
Run Code Online (Sandbox Code Playgroud)

此 UUID 是为每个浏览器实例随机生成的,不是您的扩展程序的 ID。这可以防止网站对用户已安装的扩展程序进行指纹识别。

因此,您有什么选择?页面不能直接与扩展上下文(后台)对话,后台不能直接影响页面;您需要一个内容脚本来与页面内容进行交互。

页面代码和内容脚本如何通信?它们彼此隔离,除非内容脚本对此做些什么。

首先,适用于 FF 和 Chrome 的通用技巧:

  • 您可以从内容脚本创建或修改页面上的DOM 元素,并在页面中查找这些修改。

      // 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
      }
    
    Run Code Online (Sandbox Code Playgroud)
  • 您可以用于postMessage在上下文之间进行通信,尽管用作双向通道很笨拙。

    这是文档示例 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
        }
      });
    
    Run Code Online (Sandbox Code Playgroud)
  • 您可以以类似的方式使用自定义 DOM 事件

还有一些有趣的特定于 Firefox 的方法:

  • 您可以使用或与页面共享代码exportFunctioncloneInto

      // 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
      }
    
    Run Code Online (Sandbox Code Playgroud)