2

我正在使用基于 Chrome 的 Firefox 的新 webExtensions 框架编写一个 webextension。所有示例扩展都在 Nightly 构建中工作,所以这就是我要测试的地方。我想要做的是在内容页面加载时运行一个脚本。这是我的 background.js 页面:

背景.js

"use strict";

function onCompletedFunc(details) {
    var script = 'console.log("ok");';
    console.log("Details are %o", details);
    chrome.tabs.executeScript(details['tabId'], {
        code: script,
        runAt: 'document_end'
    });
};
chrome.webRequest.onCompleted.addListener(onCompletedFunc, 
                                     {'urls': ['<all_urls>']}, 
                                     ['responseHeaders']);
//Does not work:
/*
chrome.webRequest.onCompleted.addListener(onCompletedFunc, 
                                     {'urls': ['<all_urls>'], 'types':["main_frame"]}, 
                                     ['responseHeaders']);
*/

这适用于每晚。我从背景页面获取详细信息列表(“详细信息是...”),并在内容页面的控制台上获取几行“ok”,每个资源对应一个加载的资源。它在 Chrome 中运行相同(清单文件略有不同)。

我想要的是第二种变体,它只在页面上运行一次。这在 Chrome 中运行良好。在 Nightly 中,它显示来自主框架的一条“详细信息”消息,但内容页面的控制台中没有显示任何内容。

我确定这是一个时间问题,但这里有什么问题?


manifest.json(删除 "applications":{...} 以与 Chrome 一起使用)

{

  "description": "",
  "manifest_version": 2,
  "name": "execute_script",
  "version": "1.0",

  "applications": {
    "gecko": {
      "id": "user-agent-rewriter@mozilla.org",
      "strict_min_version": "45.0"
    }
  },

  "permissions": [
    "webRequest", "webRequestBlocking", "<all_urls>" 
  ],

  "background": {
    "scripts": ["background.js"]
  }

}
4

1 回答 1

1

您的第一个片段(没有types)仅适用,因为您不仅收到对 的请求main_frame,而且还收到另一个子资源。webRequest.onCompleted如果要注入脚本,则不是正确的事件。无法保证选项卡中的页面与您收到请求的页面匹配。

如果要无条件运行代码,只需在清单文件中声明内容脚本即可。有关详细信息,请参阅内容脚本文档

如果必须使用程序注入,请使用chrome.webNavigation.onCommitted事件而不是 webRequest 事件。通过此事件,您知道该选项卡现在显示对给定 URL 的响应。例如:

chrome.webNavigation.onCommitted.addListener(function(details) {
    // Example: Only run in main frame and URLs containing "example"
    if (details.frameId === 0 && details.url.includes('example')) {
        chrome.tabs.executeScript(details.tabId, {
            code: 'console.log("Injected at " + document.URL);',
            runAt: 'document_end'
        });
    }
});
// filter (the second parameter, not used above) is supported as of Firefox 50.

如果使用事件webNavigation.onCommitted,则必须考虑 API 是非阻塞的。有可能(但概率很低)会发生以下情况:

  1. 用户开始请求。
  2. webNavigation.onCompleted火灾。
  3. 你调用tabs.executeScript.
  4. 同时,标签导航到其他站点。
  5. tabs.executeScript请求到达选项卡,同时切换到不同的 URL 。
  6. 糟糕,您刚刚在与您预期的页面不同的页面中注入了一个脚本。

如果不希望 URL 不匹配,则在继续执行内容脚本逻辑之前检查document.URL或具有预期值。location

于 2016-07-28T09:02:23.133 回答