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