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

如何在Manifest V3 Chrome扩展中检测自定义协议请求

拦截Manifest V3扩展中的自定义协议请求

Chrome的webRequest API确实仅支持官方文档列出的标准协议,自定义协议(如internal://)不在其拦截范围内,这就是你的代码无法触发的原因。要捕获这类请求,需要从页面上下文入手,拦截发起请求的行为,具体方案如下:

实现步骤

1. 配置Manifest.json

在扩展配置中添加内容脚本,确保脚本在页面加载初期注入(覆盖页面原生方法):

{
  "manifest_version": 3,
  "name": "自定义协议拦截工具",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": ["*://目标网站域名/*"], // 替换为实际目标网站的匹配规则
      "js": ["content.js"],
      "run_at": "document_start" // 关键:在页面脚本执行前注入
    }
  ],
  "permissions": ["runtime"]
}

2. 编写内容脚本(content.js)

在页面上下文里重写各类请求发起方法,拦截自定义协议:

// 拦截location.href赋值
const originalHrefSetter = Object.getOwnPropertyDescriptor(window.location.__proto__, 'href').set;
Object.defineProperty(window.location.__proto__, 'href', {
  set: function(value) {
    if (value.startsWith('internal://')) {
      // 向后台发送拦截到的URL
      chrome.runtime.sendMessage({ type: 'customProtocol', url: value });
      return; // 阻止默认跳转行为
    }
    originalHrefSetter.call(this, value);
  }
});

// 拦截window.open调用
const originalOpen = window.open;
window.open = function(url) {
  if (url?.startsWith('internal://')) {
    chrome.runtime.sendMessage({ type: 'customProtocol', url: url });
    return null; // 阻止打开新窗口
  }
  return originalOpen.apply(this, arguments);
};

// 拦截<a>标签跳转
document.addEventListener('click', e => {
  const link = e.target.closest('a');
  if (link?.href.startsWith('internal://')) {
    e.preventDefault();
    chrome.runtime.sendMessage({ type: 'customProtocol', url: link.href });
  }
});

// 拦截fetch请求
const originalFetch = window.fetch;
window.fetch = function(resource) {
  const url = typeof resource === 'string' ? resource : resource.url;
  if (url?.startsWith('internal://')) {
    chrome.runtime.sendMessage({ type: 'customProtocol', url: url });
    return Promise.reject(new Error('自定义协议请求已拦截'));
  }
  return originalFetch.apply(this, arguments);
};

// 拦截XMLHttpRequest请求
const originalXHR = XMLHttpRequest;
XMLHttpRequest = function() {
  const xhr = new originalXHR();
  const originalOpen = xhr.open;
  xhr.open = function(method, url) {
    if (url?.startsWith('internal://')) {
      chrome.runtime.sendMessage({ type: 'customProtocol', url: url });
      this.abort(); // 终止XHR请求
      return;
    }
    originalOpen.apply(this, arguments);
  };
  return xhr;
};

3. 后台脚本接收拦截信息

在后台脚本(如background.js)中监听内容脚本发送的消息,处理拦截到的URL:

chrome.runtime.onMessage.addListener((message, sender) => {
  if (message.type === 'customProtocol') {
    console.log('捕获到自定义协议请求:', message.url);
    // 在这里添加你的业务逻辑
  }
});

关键注意事项

  • run_at: "document_start"必须设置,确保内容脚本在页面原生脚本执行前加载,保证重写的方法生效。
  • 根据目标网站的实际请求方式,选择性保留上述拦截逻辑(比如如果确认没有fetch/XHR请求,可以去掉对应部分)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:32:40