标签: chrome.scripting

  • Chrome Extension MV3 在 background script 里扫描二维码并传出结果

    Chrome Extension MV3 在 background script 里扫描二维码并传出结果

    升级浏览器扩展到 MV3 时,因为 MV3 不再允许使用 background 页面,必须使用 service worker 类型的 background script。这样一来,就没有 window 对象,会遇到很多问题。

    今天分享下如何在 service worker 类型的 background script 里完成扫描二维码并传出结果。比如我帮朋友升级 二维码生成器 (Quick QR) 这个扩展,它有个功能是通过右键菜单扫描页面中的二维码,并返回扫描结果。这个过程只能在 background script 里完成,于是升级时就给我带来了不小的麻烦。

    首先,右键菜单的响应事件只能得到图片 URL。其次,扫描功能需要用到 jsqr,它接受 imageData 作为参数,可以返回扫描结果。所以我们就需要把 URL 转换成 imageData,过程如下:

    // service worker 里可以使用 `fetch()` 请求服务器
    const response = await fetch(src);
    const blob = await response.blob();
    // 使用 `createImageBitmap` 可以将支持的图片格式转换成位图
    const bitmap = await createImageBitmap(blob);
    const {width, height} = bitmap;
    // 在 service worker 里,需要使用 OffscreenCanvas
    const canvas = new OffscreenCanvas(width, height);
    // 注意,这里只能是 `2d`,`bitmaprenderer` 无法使用 `getImageData` 方法
    const context = canvas.getContext('2d');
    context.drawImage(bitmap, 0, 0);
    const imageData = context.getImageData(0, 0, width, height);
    // 接下来识别就好
    const data = jsQR(imageData.data, width, height);
    const [tab] = await getActiveTab();
    // 因为没有 `window`,`alert()`、`prompt()` 都不能用,只能通过在目标页面执行脚本的方式输出结果。注意,`tab.executeScript` 也没有了,必须用下面这个新 API,并且要提前申请权限
    await chrome.scripting.executeScript({
      args: [i18n(SCAN_RESULT), data.data],
      target: {
        tabId: tab.id,
      },
      func: (message, result) => {
        result = prompt(message, result);
        if (result) {
          navigator.clipboard.writeText(result)
            .catch(() => void 0);
        }
      },
    });

    大概过程如上面代码所示,需要注意的东西我都放在注释里了。

    关于 MV3 的其它升级经验,我会更新在 Chrome Extension Manifest V3 升级笔记,欢迎常来看看。

    (更多…)