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

Chrome扩展更新重注入脚本:如何检查URL匹配Manifest的matches模式?

问题背景与需求

我开发了一款Chrome扩展,利用chrome.runtime.onInstalled事件在扩展更新时重新注入脚本。在installContentScript()函数里,我尝试用以下代码给所有iframe重注入脚本,虽然能运行,但因为无差别注入导致报错:

chrome.webNavigation.getAllFrames({ tabId: id }, (frames) => {
  for (const frame of frames) {
    try {
      chrome.scripting.executeScript({
        target: { tabId: id, frameIds: [frame.frameId] },
        files: javaScripts,
      });
    } catch(e) {
      console.log(e);
    }
  }
});

我的核心问题是:给定一个URL,如何检查它是否匹配Manifest中内容脚本字段定义的matches模式?

Manifest示例:

{
  "matches": ["*://mail.google.com/*"],
  "js": ["script.js"],
  "all_frames": true,
  "run_at": "document_idle"
}
解决方案

你可以通过两种方式实现URL与Manifest中matches模式的匹配校验,以下是具体方法:

方法1:利用Chrome内置匹配API(推荐)

Chrome的declarativeContent模块提供原生的模式匹配能力,无需手动解析规则,直接调用即可:

async function isUrlMatchesManifest(url) {
  // 获取当前扩展的Manifest配置
  const manifest = chrome.runtime.getManifest();
  const contentScripts = manifest.content_scripts || [];

  for (const scriptConfig of contentScripts) {
    const matchPatterns = scriptConfig.matches || [];
    // 创建PageStateMatcher实例,传入匹配规则
    const matcher = new chrome.declarativeContent.PageStateMatcher({
      pageUrl: { urlMatches: matchPatterns.join(',') }
    });
    // 校验当前URL是否匹配
    const isMatch = await matcher.match({ url });
    if (isMatch) return true;
  }
  return false;
}

注意:使用该方法需要在Manifest中声明declarativeContent权限:

{
  "permissions": ["declarativeContent"]
}

方法2:手动实现模式转正则匹配

如果不想额外申请权限,可以手动将matches模式转换为正则表达式,再进行URL匹配:

// 单个模式与URL的匹配逻辑
function matchesPattern(url, pattern) {
  // 将Chrome匹配模式转换为正则表达式
  let regexStr = pattern
    .replace(/\*/g, '.*')   // 通配符*转为任意字符匹配
    .replace(/\?/g, '.')    // 通配符?转为单个字符匹配
    .replace(/\./g, '\\.')  // 转义点号
    .replace(/\^/g, '^');   // 保留^的起始匹配含义
  // 给正则添加首尾锚点,避免部分匹配
  regexStr = `^${regexStr}$`;
  return new RegExp(regexStr).test(url);
}

// 遍历Manifest中所有内容脚本规则,校验URL是否匹配
function isUrlMatchesManifest(url) {
  const manifest = chrome.runtime.getManifest();
  const contentScripts = manifest.content_scripts || [];

  for (const scriptConfig of contentScripts) {
    const matchPatterns = scriptConfig.matches || [];
    for (const pattern of matchPatterns) {
      if (matchesPattern(url, pattern)) return true;
    }
  }
  return false;
}

改造重注入逻辑

将匹配校验加入原注入代码,只给符合规则的iframe注入脚本:

chrome.webNavigation.getAllFrames({ tabId: id }, async (frames) => {
  for (const frame of frames) {
    try {
      // 先校验当前frame的URL是否符合规则
      const shouldInject = await isUrlMatchesManifest(frame.url);
      if (shouldInject) {
        chrome.scripting.executeScript({
          target: { tabId: id, frameIds: [frame.frameId] },
          files: javaScripts,
        });
      }
    } catch(e) {
      console.log(e);
    }
  }
});

内容的提问来源于stack exchange,提问作者Jesse Sliter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 07:09:57