You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展Manifest V3中二维码识别的脚本通信与API调用问题

解决Manifest 3下Chrome扩展二维码识别的跨脚本权限问题

核心思路是拆分功能到不同权限的脚本:

  • Content Script:负责定位页面中的二维码元素,获取裁剪坐标
  • Background Service Worker:调用tabs.captureVisibleTab截图,作为消息中转
  • Offscreen Document:处理图片裁剪与二维码解析(拥有DOM访问权限,可使用canvas和QRCode库)

1. 配置Manifest.json

确保声明所需权限和脚本入口:

{
  "manifest_version": 3,
  "name": "二维码识别工具",
  "version": "1.0",
  "permissions": ["tabs", "activeTab", "offscreen"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ],
  "offscreen": {
    "matches": ["<all_urls>"],
    "default_path": "offscreen.html"
  }
}

2. Content Script (content.js)

负责触发识别、获取元素坐标,给Background发消息:

// 示例:假设用户点击页面中的二维码元素触发识别
document.addEventListener('click', async (e) => {
  // 这里替换成你的二维码元素判断逻辑
  if (e.target.classList.contains('qr-code')) {
    const rect = e.target.getBoundingClientRect();
    // 发送坐标和当前tab信息给Background
    chrome.runtime.sendMessage({
      type: 'CAPTURE_QR',
      tabId: (await chrome.tabs.getCurrent()).id,
      left: rect.left,
      top: rect.top,
      width: rect.width,
      height: rect.height
    });
  }
});

// 接收Background返回的解析结果
chrome.runtime.onMessage.addListener((msg) => {
  if (msg.type === 'QR_RESULT') {
    console.log('解析结果:', msg.data);
    // 这里可以处理结果,比如弹窗展示
  }
});

3. Background Service Worker (background.js)

处理截图请求,管理Offscreen文档,中转消息:

// 确保Offscreen文档已创建
async function ensureOffscreenDocument() {
  if (await chrome.offscreen.hasDocument()) return;
  await chrome.offscreen.createDocument({
    url: 'offscreen.html',
    reasons: ['DOM_SCRAPING'],
    justification: '解析二维码需要DOM环境处理图片'
  });
}

// 监听Content Script的消息
chrome.runtime.onMessage.addListener(async (msg, sender) => {
  if (msg.type === 'CAPTURE_QR') {
    await ensureOffscreenDocument();
    // 调用截图API
    chrome.tabs.captureVisibleTab(sender.tab.windowId, { format: 'png' }, async (dataUrl) => {
      // 把截图和裁剪参数发给Offscreen
      chrome.runtime.sendMessage({
        type: 'PROCESS_QR',
        dataUrl,
        left: msg.left,
        top: msg.top,
        width: msg.width,
        height: msg.height,
        tabId: msg.tabId
      });
    });
  }
});

// 接收Offscreen返回的解析结果,转发给Content Script
chrome.runtime.onMessage.addListener((msg) => {
  if (msg.type === 'QR_RESULT') {
    chrome.tabs.sendMessage(msg.tabId, {
      type: 'QR_RESULT',
      data: msg.data
    });
  }
});

4. Offscreen相关文件

offscreen.html

<!DOCTYPE html>
<html>
<body>
  <script src="qrcode.min.js"></script> <!-- 引入QRCode解析库 -->
  <script src="offscreen.js"></script>
</body>
</html>

offscreen.js

负责图片裁剪和二维码解析:

chrome.runtime.onMessage.addListener(async (msg) => {
  if (msg.type === 'PROCESS_QR') {
    const { dataUrl, left, top, width, height, tabId } = msg;
    const img = new Image();
    img.src = dataUrl;
    
    img.onload = () => {
      // 创建canvas裁剪指定区域
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, left, top, width, height, 0, 0, width, height);
      
      // 解析二维码
      const qrReader = new QRCode();
      qrReader.callback = (error, result) => {
        if (error) {
          console.error('解析失败:', error);
          chrome.runtime.sendMessage({
            type: 'QR_RESULT',
            tabId,
            data: null
          });
        } else {
          chrome.runtime.sendMessage({
            type: 'QR_RESULT',
            tabId,
            data: result
          });
        }
      };
      qrReader.decode(canvas.toDataURL());
    };
  }
});

关键说明

  • 为什么用Offscreen?因为Background是Service Worker,无DOM环境;Content Script不能调用tabs.captureVisibleTab;Offscreen是唯一同时拥有DOM访问和消息传递能力的环境。
  • 权限注意:activeTab权限确保只在用户交互时访问当前标签,offscreen权限用于创建Offscreen文档。
  • 原getQr函数的问题:混合了需要tabs权限的截图操作和需要DOM的canvas操作,拆分后各脚本各司其职。

内容的提问来源于stack exchange,提问作者Juan Rodriguez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 11:21:00