javascript - Chrome 扩展中的持久服务 worker

标签 javascript google-chrome google-chrome-extension request xmlhttprequest

我需要在我的 Chrome 扩展程序中将我的 Service Worker 定义为持久的,因为我使用 webRequest API 来拦截在表单中为特定请求传递的一些数据,但我不知道如何做到这一点。我已经尝试了所有方法,但我的 Service Worker 一直在卸载。
如何保持加载并等待请求被拦截?

最佳答案

在你的情况下,它可能是 ManifestV3 中的一个错误,https://crbug.com/1024211 :工作人员不会因 webRequest 事件而醒来。所以只要使用 ManifestV2 直到它被修复,因为没有持久化服务 worker 这样的东西。
防止扩展的 Service Worker 卸载的解决方法:
0. 精简版:通过 waitUntil 最多五分钟

  • 示例 1,硬编码超时:
    self.onactivate = e => {
      e.waitUntil(new Promise(resolve => setTimeout(resolve, 5 * 60e3)));
    };
    
  • 示例 2,等待 promise :
    let allDone;
    self.onactivate = e => e.waitUntil(new Promise(r => { allDone = r; })));
    //................
    chrome.some.event.addListener(() => {
      foo().bar().finally(allDone);
    });
    

  • 1. 通过运行时端口永远保持事件状态
    开一个 runtime来自任何选项卡的端口 content script或来自扩展程序的另一个页面,如弹出页面。此端口将持续五分钟(服务 worker 的固有限制),因此您必须使用计时器和端口的 onDisconnect 事件再次与某个随机选项卡重新连接。
    缺点:
  • 需要网页选项卡或扩展选项卡/弹出窗口。
  • 内容脚本的广泛主机权限(如 <all_urls>*://*/* ),将大多数扩展放入网上商店的慢速审查队列。

  • 实现示例:
  • manifest.json,相关部分:
      "permissions": ["scripting"],
      "host_permissions": ["<all_urls>"],
      "background": {"service_worker": "bg.js"}
    
    
  • 后台服务 worker bg.js:
    let lifeline;
    
    keepAlive();
    
    chrome.runtime.onConnect.addListener(port => {
      if (port.name === 'keepAlive') {
        lifeline = port;
        setTimeout(keepAliveForced, 295e3); // 5 minutes minus 5 seconds
        port.onDisconnect.addListener(keepAliveForced);
      }
    });
    
    function keepAliveForced() {
      lifeline?.disconnect();
      lifeline = null;
      keepAlive();
    }
    
    async function keepAlive() {
      if (lifeline) return;
      for (const tab of await chrome.tabs.query({ url: '*://*/*' })) {
        try {
          await chrome.scripting.executeScript({
            target: { tabId: tab.id },
            function: () => chrome.runtime.connect({ name: 'keepAlive' }),
            // `function` will become `func` in Chrome 93+
          });
          chrome.tabs.onUpdated.removeListener(retryOnTabUpdate);
          return;
        } catch (e) {}
      }
      chrome.tabs.onUpdated.addListener(retryOnTabUpdate);
    }
    
    async function retryOnTabUpdate(tabId, info, tab) {
      if (info.url && /^(file|https?):/.test(info.url)) {
        keepAlive();
      }
    }
    

  • 2. 替代方法:专用选项卡
    打开一个带有扩展页面的新标签页,例如chrome.tabs.create({url: 'bg.html'}) .
    它将具有与 ManifestV2 的持久背景页面相同的功能,但是 a) 它是可见的并且 b) 无法通过 chrome.extension.getBackgroundPage 访问(可以用 chrome.extension.getViews 替换)。
    缺点:
  • 消耗更多内存,
  • 浪费标签条中的空间,
  • 分散用户的注意力,
  • 当多个扩展程序打开这样一个选项卡时,缺点会滚雪球并成为真正的 PITA。

  • 您可以通过向页面添加信息/日志/图表/仪表板并添加 beforeunload 来让您的用户更容易忍受。监听器以防止选项卡被意外关闭。
    ManifestV3 的 future
    让我们希望 Chromium 能够提供一个 API 来控制这种行为,而无需求助于这种肮脏的黑客和可悲的解决方法。同时在 crbug.com/1152255 中描述您的用例如果尚未在此处进行描述,以帮助 Chromium 团队了解一个既定事实,即许多扩展可能需要在任意时间段内使用持久性后台脚本,并且大多数扩展用户可能至少安装了一个此类扩展。

    关于javascript - Chrome 扩展中的持久服务 worker ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66618136/

    相关文章:

    css - 谷歌浏览器逆时针旋转但应该是顺时针

    javascript - 在 chrome 上使用 javascript 下载使用 HTML5 filespace api 创建的文本文件

    javascript - 我可以使用 brython 开发 Chrome 扩展吗?

    javascript - 每个页面/用户的 Google map API 请求。如何最好地减少请求?

    javascript - 实现 Chrome 扩展开/关切换按钮

    javascript - 如何创建 pdf 文件并通过 Node.js 应用程序下载

    javascript - 如何从 Chrome REPL 调试 React 变量

    google-chrome - 在后台运行 Chrome 扩展程序

    javascript - Android WebView 缓存 list 应用程序不刷新 Javascript 文件

    javascript - Jquery 显示或隐藏子链接(如果可用)