只有当用户点击链接打开时,才能在重定向新标签页/窗口之前阻止初始webRequest [英] Prevent initial webRequest prior to redirecting new tab/window only when opened by user clicking link

查看:175
本文介绍了只有当用户点击链接打开时,才能在重定向新标签页/窗口之前阻止初始webRequest的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究Chrome扩展程序。我想完成的是重定向在新窗口或新选项卡中打开的超链接。我已经尝试了下面的代码,虽然这会重定向选项卡,但它并不妨碍提交原始页面请求,这也是我想要完成的。

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

我只想在用户在新窗口中打开超链接时重定向(例如shift / ctrl +点击,中点击,上下文菜单等)。我不希望重定向,如果窗口或标签,由于其他原因而被打开。 解决方案

重定向新仅由打开的标签/窗口链接,但不直接



不幸的是,如果没有每个页面中的内容脚本,则无法区分用户在发送webRequest之前,单击链接和其他原因以打开新的选项卡或窗口。

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

不幸的是,为了满足您的需求,在完成页面URL的webRequest后, webNavigation.onCommitted 事件触发。因此,如果没有某种方式可以提前知道转换是用户单击某个链接的结果(例如,使用内容脚本),则您无法知道当前转换是用户单击某个链接以及时点击选择的结果重定向页面主URL的webRequest。



您可以做的是始终 将初始请求重定向到关于:空白。然后,一旦获得 webNavigation.onCommitted 事件,您可以根据 transitionType 的值进行选择,属性,将选项卡的URL更改为您最终想到的重定向URL,或将其更改回原始的预期页面的URL。这个过程将导致 Referer 标题的丢失,表示链接被点击的页面。



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



这里是代码做上面描述的内容:

background.js

  var tabsBlockedOnce = new Set(); 
var tabsRedirected = new Map();
chrome.webRequest.onBeforeRequest.addListener(function(details){
if(!tabsBlockedOnce.has(details.tabId)){
tabsBlockedOnce.add(details.tabId);
tabsRedirected.set(details.tabId,details.url);
//重定向
return {redirectUrl:'about:blank'};
// Block
// return {cancel:true};
}
},{urls:['< all_urls>'],类型:['main_frame']},['blocking']);

chrome.webNavigation.onCommitted.addListener(function(details){
if(tabsRedirected.has(details.tabId)){
//默认为不重定向$ b (detail.transitionType ==='link'){
// $这是一个链接,转到我们想要重定向的位置。
url ='http://www.google.com/';
}
//发送标签去
chrome.tabs.update(details.tabId,{url:url});
}
});

//不要阻止已存在的任何选项卡中的第一个请求。
//这是首次安装/重新加载扩展时的主要优点。
chrome.tabs.query({,function(tabs){
tabs.forEach(function(tab){
tabsBlockedOnce.add(tab.id);
}) ;
});

manifest.json (部分):

permissions:[
webNavigation,
webRequest,
webRequestBlocking

background:{
scripts:[background.js]
}



使用每个页面的内容脚本,您可以直接执行此操作。



为了执行此操作直接地(即,如果页面最终不会被重定向,则不干扰原始webRequest),则必须知道webRequest的原因是在 webRequest.onBeforeRequest 事件触发。为了及时将这些信息提供给后台脚本,您必须在每个页面中注入内容脚本,并在后台脚本中添加 runtime.sendMessage()正在被点击的过程中。

基于测试,这样的消息将在 webRequest.onBeforeRequest 之前到达后台脚本。 code>射击。能够使用内容脚本执行此操作取决于发送消息的内容脚本与 runtime.sendMessage()之间的异步通信的确切时间,以及 runtime.onMessage 事件触发与 webRequest.onBeforeRequest 事件触发时。测试表明 mousedown mouseup 点击事件( 点击并不总是为所有鼠标按钮触发)可以发送后台脚本在 webRequest.onBeforeRequest 事件引发火灾。这个时间不能保证,但似乎工作。

从用户体验的角度来看,这通常是一个坏主意。



您希望做的事情篡改用户选择使用UI交互来在新选项卡或窗口中专门打开链接。除非我专门寻找这个功能,否则我会发现这个非常恼人,而且几乎肯定会立即卸载扩展。篡夺用户的机构来控制他们的机器应该只在非常有限的情况下才能完成。除非您身处专业环境,否则您提出的建议将违背大多数用户的期望。另外,它可能会中断与某些网站的互动。

I am working on a Chrome extension. What I would like to accomplish is redirecting hyperlinks that are opened in a new window or new tab. I've experimented with the code below and while this does redirect the tab it does not prevent the original page request from being submitted which is something I would also like to accomplish.

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

I only want to redirect if the user opens a hyperlink in a new window (e.g. shift/ctrl+click, middle click, context menu, etc.). I do not want to redirect if the window, or tab, is being opened for a reason other than those.

解决方案

Redirect new tabs/windows opened by only links, but not directly

Unfortunately, without a content script in every page, you can not differentiate between a user clicking a link and other reasons for opening a new tab or window, prior to the webRequest being transmitted.

The type of webNavigation that is causing the tab or window to be opened is clearly indicated by the value of the transitionType property, in the details supplied to a webNavigation.onCommitted listener. If it was from the user clicking a link, the transitionType property will have the value of link. If the request is from a link is not information that is normally available to the background page prior to the webNavigation.onCommitted event.

Unfortunately, for what you desire, the webNavigation.onCommitted event fires after the webRequest for the page's URL is complete. Thus, without some way to know earlier that the transition is the result of a user clicking a link (e.g. using a content script), you can't know that the current transition is the result of the user clicking a link in time to choose to redirect the webRequest for the main URL of the page.

What you can do is always redirect the initial request to about:blank. Then, once you get the webNavigation.onCommitted event, you can make the choice, based on the value of the transitionType property, to change the tab's URL to the redirect URL you ultimately have in mind, or change it back to the URL which was the original intended page. This process will result in the loss of the Referer header representing the page on which the link was clicked.

Obviously, you could use your ultimate destination instead of about:blank. This may be better, but will result in a webRequest to that URL even if the tab ultimately ends up being put back to the original destination URL.

Here is code that will do what is described above:

background.js

var tabsBlockedOnce = new Set();
var tabsRedirected = new Map();
chrome.webRequest.onBeforeRequest.addListener(function(details){
    if(!tabsBlockedOnce.has(details.tabId)){
        tabsBlockedOnce.add(details.tabId);
        tabsRedirected.set(details.tabId,details.url);
        //Redirect
        return {redirectUrl:'about:blank'};
        //Block
        //return {cancel:true};
    }
},{urls:['<all_urls>'],types:['main_frame']},['blocking']);

chrome.webNavigation.onCommitted.addListener(function(details){
    if(tabsRedirected.has(details.tabId)){
        //Default is to not redirect
        let url = tabsRedirected.get(details.tabId);
        tabsRedirected.delete(details.tabId);
        if(details.transitionType === 'link'){
            //It was a link, go to where we want to redirect.
            url = 'http://www.google.com/'; 
        }
        //Send the tab where it is supposed to go
        chrome.tabs.update(details.tabId,{url:url});
    }
});

//Don't block the first request in any tab that already exists.
//  This is of primary benefit when the extension is first installed/reloaded.
chrome.tabs.query({},function(tabs){
    tabs.forEach(function(tab){
        tabsBlockedOnce.add(tab.id);
    });
});

manifest.json (partial):

"permissions": [
    "webNavigation",
    "webRequest",
    "webRequestBlocking"
],
"background": {
    "scripts": ["background.js"]
}

With a content script in every page, you could do it directly

In order to perform this operation directly (i.e. not interfere with the original webRequest if the page is not ultimately going to be redirected), you have to know that the reason for the webRequest is that a link was clicked prior to the webRequest.onBeforeRequest event fires. To get this information to your background script in time, you would have to inject a content script in every page and runtime.sendMessage() a message to your background script that a link is in the process of being clicked.

Based on testing, such a message will get to the background script prior to the webRequest.onBeforeRequest firing. Being able to do this with a content script depends on the exact timing of the asynchronous communication between the content script sending a message with runtime.sendMessage() and when the runtime.onMessage event fires vs. when the webRequest.onBeforeRequest event fires. Testing indicates that the mousedown, mouseup and click events (click is not always fired for all mouse buttons) can send a message that the background script receives prior to the webRequest.onBeforeRequest event fires. This timing is not guaranteed, but appears to work.

From a User Experience point of view this is often a bad idea

What you desire to do usurps the user's choice to use a UI interaction to specifically open a link in a new tab or window. Unless I was specifically looking for this functionality, I would find this very annoying and, almost certainly, immediately uninstall the extension. Usurping the user's agency to control their machine is something that should be done only under very limited circumstances. Unless you are in a specialized environment, what you are proposing will be contrary to most user's expectations. In addition, it may break interactions with some websites.

这篇关于只有当用户点击链接打开时,才能在重定向新标签页/窗口之前阻止初始webRequest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆