chrome.webRequest.onBeforeRequest 行为不可预测

2024-02-05

我正在尝试制作一个网络过滤 Chrome 扩展程序,它将阻止某些网站并用扩展程序中包含的阻止页面替换它们的 html。

let bans = ["*://*.amazon.com/*", "*://*.youtube.com/*", "*://*.netflix.com/*","*://*.facebook.com/*", "*://*.twitter.com/*"];

chrome.webRequest.onBeforeRequest.addListener(
    function(details){
        try{
            chrome.tabs.executeScript(null, {file: "content.js"});
        }
        catch(error){
            console.error(error);
        }
        return {cancel: true};
    },
    {urls: bans},
    ["blocking"]
);

这应该意味着,如果我尝试访问该禁止列表上的任何网站,内容脚本应该用我自己的阻止页面替换该页面。然而,由于某种原因,有些网站永远不会加载阻止页面,其他网站根本不会被阻止,有些网站似乎工作正常。更奇怪的是,监听器似乎是在根本没有列在禁令数组中的网站上触发的。我无法找出这些行为之间的任何模式。

我不相信它们是问题的根源,但这是我的清单中的权限(清单 v2)

"web_accessible_resources": [
  "certBlockPage.html",
  "blockPageLight.html"
],

"incognito": "split",

"permissions": [
  "webNavigation",
  "webRequest",
  "webRequestBlocking",
  "tabs",
  "windows",
  "identity",
  "http://*/*",
  "https://*/*",
  "<all_urls>"
  ]

这是 content.js 文件

window.onload = function(){
fetch(chrome.runtime.getURL('certBlockPage.html'))
    .then(r => r.text())
    .then(html => {
        document.open();
        document.write(html);
        document.close;
  });

}


有几个问题。

  1. 你没有指定runAt: 'document_start'在executeScript 的选项中,因此如果您导航到被禁止的网站,而该选项卡中的旧页面仍在加载,它将等待。
  2. executeScript 是异步的,因此可以轻松运行load事件已经在选项卡中触发,因此您的 window.onload 将永远不会运行。不要使用onload,直接运行代码即可。
  3. 您始终在当前聚焦的选项卡中运行executeScript(术语是active)但该选项卡可能没有焦点(inactive)。你需要使用details.tabId and details.frameId.
  4. 用户可能打开了一个新选项卡并输入了被阻止的 URL 或单击了其链接,该链接已被您的阻止{cancel: true},但是执行脚本将会失败,因为当前显示在此选项卡中的新选项卡页面无法运行内容脚本。对于任何其他 chrome:// 或 chrome-extension:// 选项卡或选项卡内显示网络错误时,情况相同。
  5. 如果您再次调用 onBeforeRequest.addListener 而不删除先前的注册,则两者都将处于活动状态。
  6. document.write 在具有严格 CSP 的站点上将失败

解决方案一:网络请求 https://developer.chrome.com/extensions/webRequest + 执行脚本 https://developer.chrome.com/extensions/tabs#method-executeScript

后台脚本:

updateListener(['amazon.com', 'youtube.com', 'netflix.com']);

function updateListener(hosts) {
  chrome.webRequest.onBeforeRequest.removeListener(onBeforeRequest);
  chrome.webRequest.onBeforeRequest.addListener(
    onBeforeRequest, {
      types: ['main_frame', 'sub_frame'],
      urls: hosts.map(h => `*://*.${h}/*`),
    }, [
      'blocking',
    ]);
}

function onBeforeRequest(details) {
  const {tabId, frameId} = details;
  chrome.tabs.executeScript(tabId, {
    file: 'content.js',
    runAt: 'document_start',
    matchAboutBlank: true,
    frameId,
  }, () => chrome.runtime.lastError && redirectTab(tabId));
  // Cancel the navigation without showing that it was canceled
  return {redirectUrl: 'javascript:void 0'};
}

function redirectTab(tabId) {
  chrome.tabs.update(tabId, {url: 'certBlockPage.html'});
}

内容.js:

fetch(chrome.runtime.getURL('certBlockPage.html'))
  .then(r => r.text())
  .then(html => {
    try {
      document.open();
      document.write(html);
      document.close();
    } catch (e) {
      location.href = chrome.runtime.getURL('certBlockPage.html');
    }
  });

解决方案2:网络请求 https://developer.chrome.com/extensions/webRequest+ 重定向

不需要内容脚本。

const bannedHosts = ['amazon.com', 'youtube.com', 'netflix.com'];

chrome.webRequest.onBeforeRequest.addListener(
  details => ({
    redirectUrl: chrome.runtime.getURL('certBlockPage.html'),
  }), {
    types: ['main_frame', 'sub_frame'],
    urls: bannedHosts.map(h => `*://*.${h}/*`),
  }, [
    'blocking',
  ]);

解决方案3:声明式网络请求 https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/+ 重定向

这是最快的方法,但它仅限于一组非常简单的预定义操作。查看文档,不要忘记添加"declarativeNetRequest" to "permissions"在manifest.json中,以及"<all_urls>" to host_permissions(ManifestV3 仍然不支持可选权限)。

const bannedHosts = ['amazon.com', 'youtube.com', 'netflix.com'];

chrome.declarativeNetRequest.updateDynamicRules({
  removeRuleIds: bannedHosts.map((h, i) => i + 1),
  addRules: bannedHosts.map((h, i) => ({
    id: i + 1,
    action: {type: 'redirect', redirect: {extensionPath: '/certBlockPage.html'}},
    condition: {urlFilter: `||${h}/`, resourceTypes: ['main_frame', 'sub_frame']},
  })),
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

chrome.webRequest.onBeforeRequest 行为不可预测 的相关文章

随机推荐