为什么某些网站的webNavigation Listener失败?

时间:2019-08-01 17:45:43

标签: javascript google-chrome-extension

我正在尝试使用chrome扩展程序从科学网获取一些数据。第一步,我想创建一个新的选项卡并等待它加载。因此,在创建标签后,我添加了一个webNavigation侦听器。我发现听众效果很好 仅适用于某些网站。如果我将目标网址(科学网络)用作以下代码,则不会收到警报窗口。但是,如果我使用目标“ https://stackoverflow.com/questions/ask”,它将成功发出警报。为什么会这样?谁能告诉我原因?真的很感谢。

background.js

chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      var activeTab = tabs[0];
      tabId = activeTab.id;
      chrome.tabs.sendMessage(tabId, {"message": "clicked_browser_action"});
    });
});

var link = 'https://apps.webofknowledge.com/OneClickSearch.do?product=UA&search_mode=OneClickSearch&excludeEventConfig=ExcludeIfFromFullRecPage&SID=7ENVgUT3nRKp41VVlhe&field=AU&value=Leroux,%20E.'; // failed in this url

//var link = 'https://stackoverflow.com/questions/ask'; //success in this url
function listener1(){
    chrome.webNavigation.onCompleted.removeListener(listener1);
    chrome.tabs.sendMessage(tabId, {"message": "to content"});
    alert('listener succeed');
}

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        if (request.joke == 'content initial'){
            chrome.tabs.create({ url: link });
            chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
                var activeTab = tabs[0];
                tabId = activeTab.id;
            });
            //alert(link);
            chrome.webNavigation.onCompleted.addListener(listener1, {url: [{urlMatches : link}]});
        }
    }
)

content.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        if( request.message === "clicked_browser_action" ) {
            console.log('content initial');
            chrome.runtime.sendMessage({joke: 'content initial'}, function(response) {
            });
        }   
    }
)

manifest.json

{
    "manifest_version": 2,
    "name": "citation",
    "version": "1",

    "background": {
        "scripts": ["background.js"],
        "persistent": false
    },
    "browser_action": {},

    "content_scripts": [{
        "matches": ["<all_urls>"],
        "run_at": "document_idle",
        "js": ["content.js"]
    }], 
    "permissions": [
        "downloads",
        "webNavigation",
        "tabs",
        "<all_urls>"
    ]
}

1 个答案:

答案 0 :(得分:1)

主要问题是urlMatches是RE2语法中的正则表达式,正如您在documentation中看到的那样,因此URL中的各种特殊符号(如?)的解释不同。解决方案:使用urlEquals或其他文字字符串比较。

还有其他问题:

  • API是异步的,因此将来将以无法预测的顺序创建和查询选项卡。解决方案:使用create()的回调。
  • 所有选项卡均在webNavigation侦听器中报告,而不仅仅是活动的选项卡,因此从理论上讲,存在一个问题,即在不同的选项卡中报告了两个相同的URL。同样,API过滤参数也无法处理带有#hash部分的URL解决方案:记住要在变量中监视的标签ID,并在侦听器中进行比较,然后在过滤器中明确剥离#hash部分。
  • 该网站可能会重定向页面的最终URL,因此可能由于您的过滤器而未得到报告。解决方案:仅在过滤器中指定主机名。
  • 向您发送消息或执行导航的选项卡可能处于无效状态。解决方案:使用侦听器参数中的选项卡ID。

chrome.browserAction.onClicked.addListener(tab => {
  chrome.tabs.sendMessage(tab.id, {message: 'clicked_browser_action'});
});

var link = '...............';

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.joke === 'content initial') {
    chrome.tabs.create({url: link}, tab => {
      chrome.webNavigation.onCompleted.addListener(function onCompleted(info) {
        if (info.tabId === tab.id && info.frameId === 0) {
          chrome.webNavigation.onCompleted.removeListener(onCompleted);
          chrome.tabs.sendMessage(tab.id, {message: 'to content'});
          console.log('listener succeeded');
        }
      }, {
        url: [{urlPrefix: new URL(link).origin + '/'}],
      });
    });
  }
});

注意:

  • 如果只需要按需处理,请避免在manifest.json中为所有URL声明content_scripts。在这种情况下,请使用programmatic injection
  • 在断点或后台页面(more info)的console.log()之类的devtools中,而不是alert()使用适当的调试。