当标签页重新加载时,如何运行此脚本(Chrome扩展程序)?

11

我希望当特定网址的标签页重新加载时运行脚本。虽然它几乎可用,但实际上并不是这样 :) 以下是我的清单文件:

{
"manifest_version": 2,

"name": "Sample Extension",
"description": "Sample Chrome Extension",
"version": "1.0",

"content_scripts":
[
    {
      "matches": ["http://translate.google.hu/*"],
      "js": ["run.js"]
    }
],

"permissions":
[
    "activeTab",
    "tabs"
],

"browser_action":
{
    "default_title": "Sample",
    "default_icon": "icon.png"
}
}

这是 run.js 文件:

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

programs.js仅仅弹出了一些文本(目前为止)。当我在run.js的第一行放置一个警报时,它会弹出警报,但是当我把它放在if中时,它不会弹出。我找不到问题所在。我有打错吗?


你有在开发控制台中检查错误吗?我认为你需要从后台页面运行它,而不是内容脚本。我相信内容脚本只能利用chrome.extension,而所有其他API方法都需要在background.js页面上调用。 - QFDev
Hooking 钩子 https://stackoverflow.com/q/23333771/632951 - Pacerier
3个回答

17

假设您希望在重新加载时注入代码的页面是 http://translate.google.hu/*,您需要以稍微不同的方式进行操作。目前,您总是向这些页面注入代码(而且没有获得许可),然后尝试在该内容脚本内部使用chrome.tabs api,但您不能这样做。相反,我们将在后台页面中放置监听器,并仅在页面刷新时注入代码,就像您想要的那样。首先是清单文件

{
  "manifest_version": 2,
  "name": "Sample Extension",
  "description": "Sample Chrome Extension",
  "version": "1.0",
  "background": {
    "scripts": ["background.js"]
  },
  "permissions":[
    "http://translate.google.hu/*", "tabs"
  ]
}

background.js

chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
  if (tab.url.indexOf("http://translate.google.hu/") > -1 && 
      changeInfo.url === undefined){
    chrome.tabs.executeScript(tabId, {file: "program.js"} );
  }
});
这将监听 onUpdated 事件,检查它是否为我们要注入的 url 之一,然后检查页面是否已重新加载。最后一步是通过检查 changeInfo.url 是否存在来完成的。如果存在,则意味着 URL 已更改,因此不是刷新。相反,如果不存在,则页面必须仅被刷新过。

1
谢谢,这个可行,但如果顶部有另一个选项卡,我该如何运行此脚本? - András Geiszl
@Geiszla,你说的另一个选项卡是指顶部的吗? - BeardFist
1
所以当我重新加载选项卡,但更改选项卡时。然后脚本不会运行,因为那不是该网站(例如translate.google.hu)。 - András Geiszl
太好了!我为我的扩展写了同样的函数,但我不知道 onUpdate 回调参数。谢谢,这帮了我很多 +1 - Mohammad Kermani
2
@BeardFist,您确定这个能按预期工作吗?即使是changeInfo.status和等等等等这些情况也会触发吗? - Pacerier
我同意@Pacerier的观点。我不确定"changeInfo.url === undefined"是否按预期工作。它将在实际选项卡上进行任何更改时触发,而不仅仅是在选项卡刷新时。 - Lowtrux

10

2021

如果您想在清单3(也许是2)的background.js中检测重新加载,chrome.tabs.onUpdated方法对我来说不起作用:/ 它被调用了太多次。

最终对我有用的方法!

// --- On Reloading or Entering example.com --- 
chrome.webNavigation.onCommitted.addListener((details) => {
    if (["reload", "link", "typed", "generated"].includes(details.transitionType) &&
        details.url === "http://example.com/") {

        codeAfterReload();

        // If you want to run only when the reload finished (at least the DOM was loaded)
        chrome.webNavigation.onCompleted.addListener(function onComplete() {

            codeAfterReloadAndFinishSomeLoading();

            chrome.webNavigation.onCompleted.removeListener(onComplete);
        });
    }
});

更多过渡类型请参考:https://developer.chrome.com/docs/extensions/reference/history/#transition_types

祝好运 :)


2
请记住,这些API需要webNavigation权限,显示“此扩展程序可以查看您的所有浏览内容”消息。 - fregante
回调函数的第二个参数中有额外的信息:changeInfo。当加载时,changeInfo.status == "loading",当加载完成时,它是"complete"。通过检查changeInfo.status,您可以确保它只运行一次。 - kuzdogan

4

content_scripts会在每次页面(重新)加载时运行,因此最好只使用这些来检测它。

这样做还可以避免在content_script准备好接收任何消息之前,在background中运行任何代码的风险。


似乎存在Chrome的一个bug,有时manifest contentscript在页面加载时不会运行。请参见https://dev59.com/zWIk5IYBdhLWcg3wg-jK#qnYeoYgBc1ULPQZFqAG9 - Pacerier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接