如何使用Background.js更新选项卡,然后执行内容脚本?

时间:2017-08-24 09:03:05

标签: javascript google-chrome-extension

我希望我的Chrome扩展程序能够像这样运行:

用户点击图标并显示硬编码的网址“www.example.com”。它不会打开新选项卡,而是更新窗口。然后,我想执行内容脚本,并能够在更新的页面上提醒“工作”。

这是我到目前为止所得到的:

Background.js

chrome.browserAction.onClicked.addListener(function(activeTab)
{
 chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function 
 (tabs) 
    {

chrome.tabs.update({
 url: "http://www.example.com/"
});
});
function test()
{
chrome.tabs.executeScript(null, {file: "myscript.js"}); 

}




chrome.tabs.onUpdated.addListener(function(tabid, changeinfo, tab) {
var url = tab.url;
    if (url !== undefined && changeinfo.status == "complete") {

    test();
}
});
});

内容脚本

alert('working');

结果很奇怪。当我点击图标时,它会使example.com运行正常,但有时警报会起作用,有时则不会。即使是更奇怪,如果我双击它会更频繁地工作,但是如果我多次点击它,警报会加起来,然后我会同时收到很多警报(我只想要一个)。

1 个答案:

答案 0 :(得分:3)

  • content.js 可以设置一个全局变量,以便您可以检查它以跳过重新注入。

    if (window[chrome.runtime.id]) {
      alert('Oi! Reinjected.');
    } else {
      window[chrome.runtime.id] = true;
      alert('Oi!');
    }
    
    // do something
    

    根据您在内容脚本中执行的操作,您可以添加message listener来处理来自后台页面的请求,而不是重新运行整个代码。

  • background.js 检查活动标签是否已导航到感兴趣的网站(或导航到该网站)并注入内容脚本(注释掉inject();以跳过再注入)。

    检查本身很简单:注入一个检查全局变量的内容脚本代码。此代码在与给定页面的其他内容脚本相同的上下文中运行(isolated world)。

    const SITE_URL = 'http://www.example.com';
    
    chrome.browserAction.onClicked.addListener(tab => {
      if (tab.url === new URL(SITE_URL).href) {
        checkIfInjected(tab).then(tab => {
          console.log('already injected in %d, reinjecting anyway', tab.id);
          inject(tab);
        }).catch(inject);
      } else {
        updateTabAndWaitForStart(tab.id, {url: SITE_URL})
          .then(inject);
      }
    });
    
    function checkIfInjected(tab) {
      return runContentScript(tab.id, {
        code: 'window[chrome.runtime.id]',
      }).then(results => {
        resolve(results[0] ? tab : Promise.reject(tab));
      });
    }
    
    function inject(tab) {
      return runContentScript(tab.id, {
        file: 'content.js',
        runAt: 'document_end',
        allFrames: false,
      });
    }
    
    function runContentScript(tabId, options) {
      return new Promise(resolve => {
        chrome.tabs.executeScript(tabId, options, resolve);
      });
    }
    

    // onUpdated listener waits for our tab to get an URL, detaches on success
    

    function updateTabAndWaitForStart(tabId, options) {
      return new Promise(resolve => {
        chrome.tabs.update(tabId, options, newTab => {
          chrome.tabs.onUpdated.addListener(
            function onUpdated(updatedId, info, updatedTab) {
              if (updatedId === newTab.id && info.url) {
                chrome.tabs.onUpdated.removeListener(onUpdated);
                resolve(updatedTab);
              }
            }
          );
        });
      });
    }
    
  • manifest.json 应包含您导航到的网站和活动标签的权限。

    当然,像<all_urls>这样的较大权限会包含这些权限,但确切列表的优势在于,扩展程序网络商店中的安装警告将仅显示该网站。

    站点中的

    * URL权限是可选的(与API设计相同) 最终/是强制性的(这是一条路径)。

    {
      "name": "test",
      "version": "0.0.1",
      "manifest_version": 2,
      "description": ".............",
      "background": {
        "scripts": ["background.js"],
        "persistent": false
      },
      "browser_action": {
        "default_title": "click me"
      },
      "permissions": ["activeTab", "http://www.example.com/*"]
    }