Javascript 仅当用户单击链接打开时,才在重定向新选项卡/窗口之前阻止初始webRequest

Javascript 仅当用户单击链接打开时,才在重定向新选项卡/窗口之前阻止初始webRequest,javascript,google-chrome,google-chrome-extension,Javascript,Google Chrome,Google Chrome Extension,我正在开发一个Chrome扩展。我想完成的是重定向在新窗口或新选项卡中打开的超链接。我已经对下面的代码进行了实验,虽然这确实重定向了选项卡,但并没有阻止提交原始页面请求,这也是我想要完成的 chrome.webNavigation.onCreatedNavigationTarget.addListener(function(details) { chrome.tabs.update(details.tabId, { url: 'http://www.google.com/

我正在开发一个Chrome扩展。我想完成的是重定向在新窗口或新选项卡中打开的超链接。我已经对下面的代码进行了实验,虽然这确实重定向了选项卡,但并没有阻止提交原始页面请求,这也是我想要完成的

chrome.webNavigation.onCreatedNavigationTarget.addListener(function(details) {
    chrome.tabs.update(details.tabId, {
        url: 'http://www.google.com/'
    });
});

我只想在用户在新窗口中打开超链接时重定向(例如shift/ctrl+单击、中键单击、关联菜单等)。如果窗口或选项卡是由于其他原因打开的,我不想重定向。

我不确定这一点,但您是否需要取消本机事件以支持您想要执行的操作,类似于
事件。preventedafult()

重定向仅通过链接打开的新选项卡/窗口,而不是直接打开 不幸的是,如果每个页面中都没有内容脚本,那么在传输webRequest之前,您无法区分用户单击链接和打开新选项卡或窗口的其他原因

在提供给
webNavigation.onCommitted
侦听器的详细信息中,
transitionType
属性的值清楚地指示了导致选项卡或窗口打开的webNavigation的类型。如果是用户单击某个链接,则
transitionType
属性的值将为
link
。如果请求来自链接,则在
webNavigation.onCommitted
事件之前,后台页面通常无法获取该信息

不幸的是,对于您想要的内容,
webNavigation.onCommitted
事件在页面URL的webRequest完成后触发。因此,如果之前没有某种方法知道转换是用户单击链接(例如使用内容脚本)的结果,您就无法知道当前转换是用户及时单击链接以选择重定向网页主URL的webRequest的结果

您可以做的是始终将初始请求重定向到
about:blank
。然后,一旦您获得
webNavigation.onCommitted
事件,您可以根据
transitionType
属性的值,选择将选项卡的URL更改为您最终想到的重定向URL,或者将其更改回原来预期页面的URL。此过程将导致丢失表示单击链接所在页面的
Referer
标题

显然,您可以使用最终目的地而不是
about:blank
。这可能更好,但会导致对该URL的webRequest,即使该选项卡最终被放回原始目标URL

下面是执行上述操作的代码:

background.js

var tabsBlockedOnce=newset();
var tabsRedirected=新映射();
chrome.webRequest.onBeforeRequest.addListener(函数(详细信息){
如果(!tabsBlockedOnce.has(details.tabId)){
tabsBlockedOnce.add(details.tabId);
tabsRedirected.set(details.tabId,details.url);
//重定向
返回{redirectUrl:'about:blank'};
//挡块
//返回{cancel:true};
}
},{url:['],类型:['main_frame']},['blocking']);
chrome.webNavigation.onCommitted.addListener(函数(细节){
if(tabsRedirected.has(details.tabId)){
//默认设置为不重定向
让url=tabsRedirected.get(details.tabId);
tabsredited.delete(details.tabId);
如果(details.transitionType==='link'){
//这是一个链接,转到我们想要重定向的地方。
url='1〕http://www.google.com/'; 
}
//把账单送到应该去的地方
update(details.tabId,{url:url});
}
});
//不要在任何已经存在的选项卡中阻止第一个请求。
//这是首次安装/重新加载扩展时的主要好处。
chrome.tabs.query({},函数(tabs){
tabs.forEach(函数(选项卡){
tabsBlockedOnce.add(tab.id);
});
});
manifest.json(部分):

“权限”:[
“网络导航”,
“网络请求”,
“webRequestBlocking”
],
“背景”:{
“脚本”:[“background.js”]
}
通过在每个页面中添加内容脚本,您可以直接执行 为了直接执行此操作(即,如果页面最终不会被重定向,则不会干扰原始webRequest),您必须知道webRequest的原因是在触发
webRequest.onBeforeRequest
事件之前单击了链接。要及时将此信息添加到后台脚本中,您必须在每个页面中插入一个内容脚本,并向后台脚本中插入一条消息,说明正在单击链接

根据测试,这样的消息将在触发
webRequest.onBeforeRequest
之前到达后台脚本。使用内容脚本是否能够做到这一点,取决于使用
runtime.sendMessage()
发送消息的内容脚本与触发
runtime.onMessage
事件与触发
webRequest.onBeforeRequest
事件之间异步通信的准确时间。测试表明,
mousedown
mouseup
click
事件(
click
并非总是针对所有鼠标按钮触发)可以发送后台脚本在触发
webRequest.onBeforeRequest
事件之前收到的消息。这一时机并不确定,但似乎有效

从用户体验的角度来看,这通常是个坏主意 您想要做的事情篡夺了用户使用UI交互在新选项卡或窗口中专门打开链接的选择。除非我专门寻找这个功能,否则我会觉得这很烦人,而且