谷歌chrome扩展:如何在页面重新加载后立即注入脚本?

时间:2017-02-10 04:06:46

标签: javascript google-chrome google-chrome-extension background-process

我有一个后台脚本,定期重新加载当前标签。

var code = 'window.location.reload();';
chrome.tabs.executeScript(my_active_tab, {code: code});

每次重新加载页面后,我想立即注入另一个脚本。

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab){
    if (changeInfo.status == 'complete') {
        chrome.tabs.executeScript(tabId, { file: "my_script.js" });
    }
});

以上是我目前的代码。问题是,它有效,但速度太慢,因为它在每个图像加载后都会等待。

我的目标是在DOM加载后立即执行脚本。有什么想法吗?

1 个答案:

答案 0 :(得分:7)

使用带有content_scripts

manifest.json "run_at": "document_start"条目

manifest.json content_scripts条目与"run_at": "document_start"一起使用是唯一可以保证的方式页面存在。此时注入的代码会发现document.bodydocument.head都是null

使用tabs.executeScript()

注入的最早时间

致电tabs.executeScript()的最早时间是在您感兴趣的页面导航的webRequest.onHeadersReceived事件后触发的webNavigation.onBeforeNavigate事件中。事先使用tabs.executeScript()此事件可能导致您的脚本没有被注入新页面而没有任何报告错误。鉴于后台脚本与加载页面的过程之间的时间固有的异步性质,此类故障可能是间歇性的,并且将受到OS /系统配置和正在加载的确切页面的影响。事实上,我webRequest.onHeadersReceived将发挥作用的声明基于测试,而不是在Chrome源代码中进行验证。因此,可能存在我未测试的极端情况。

此时注入始终有效,但注入与页面加载相关的时间有些不一致。有时,document.headdocument.body将为nullmanifest.json content_scripts注入"run_at":"document_start"的情况总是如此。其他时候,document.headdocument.body将包含有效的DOM。由于后台脚本和内容位于不同的进程中,似乎不可能使此时间更紧密(即始终具有document.headdocument.bodynull):因此,本质上是异步的。

使用webNavigation.onBeforeNavigate而不是至少等待相关的webRequest.onHeadersReceived事件为时太早且无法正常运行(未注入内容脚本)。换句话说,即使是相关的webRequest.onSendHeaders事件也为时过早。

显然,为了尽早注入内容脚本,您必须在调用tabs.executeScript()时指定runAt:'document_start'

在DOM存在之后注入:webNavigation.onCommitted

如果您想要更容易的东西,并且导致内容脚本在除主HTML文档之外的页面中的任何内容之前注入,那么您可以使用webNavigation.onCommitted事件来获取所需的URL触发你的tabs.executeScript()。这将导致注入的内容脚本在主HTML文档之后立即加载。使用webNavigation.onCommitted变得更加容易,因为它可以为您的活动指定过滤器。因此,您只能为您感兴趣的URL调用事件侦听器。

webNavigation.onCommitted事件在主HTML页面的webRequest.ResponseStarted事件之后,但在获取任何资源之前(即在页面资源的任何webRequest.BeforeRequest事件之前)触发。有趣的是,它在声明tabs.onUpdated的{​​{1}}事件后触发。带有status:'loading'的{​​{1}}事件本身并不是一个好的触发器,因为它可能因其他相同属性的原因而触发,但不会指示页面加载/重新加载。< / p>

如果您只想在页面上tabs.onUpdated 重新加载

status:'loading'事件侦听器会收到一个属性:transitionType,根据导航原因,它将为different values。其中一个值是tabs.executeScript(),您可以使用它来过滤页面重新加载。

鉴于您对页面重新加载感兴趣,而不是加载框架,您需要确保webNavigation.onCommitted事件适用于'reload'

这些是当您通过单击&#34;重新加载此页面重新加载标签时发生的事件&#34;按钮:

webNavigation

注意:此信息基于我自己的测试。我没有找到Google提供的具有此级别特异性的文档。实际工作的确切时间可能会在未来版本的Chrome中发生变化。