Chrome扩展程序在浏览YouTube时无法加载

19

假设我有一个扩展程序,会在你打开YouTube视频页面时加载。我发现当你使用Chrome浏览器的前进和后退按钮切换页面时,这个扩展程序很可能不会被加载。

举个例子,我有两个文件,一个是清单:

{
    "name": "back forth",
    "version": "0.1",
    "manifest_version": 2,
    "description": "back forth",
    "permissions": ["storage", "*://www.youtube.com/watch*"],
    "content_scripts": [
        {
            "matches": ["*://www.youtube.com/watch*"],
            "js": ["contentscript.js"]
        }
    ]
}

和内容脚本

alert("loaded");

当来回导航时,警报并不总是显示出来。我该如何克服这个问题,以便扩展程序每次都能加载?


1
类似于 https://dev59.com/ElsX5IYBdhLWcg3wPdU7#34100952 - Dennis
1个回答

27

YouTube正在使用基于pushState的导航进行试验。一般情况下,只能通过注入代码来拦截对history.replaceState / history.pushState的调用(或在后台页面中使用chrome.webNavigation.onHistoryStateUpdated事件)在内容脚本中检测到这样的导航。

本答案剩余部分仅适用于YouTube。
YouTube在加载期间在页面顶部显示(红色)进度条。该进度条是使用CSS转换进行动画处理的。由于转换事件会冒泡,因此可以将转换事件侦听器绑定到<body>并在这些情况下检查导航。

您必须将内容脚本插入到*://www.youtube.com/*而不是*://www.youtube.com/watch*,因为pushState可用于从/导航到/watch..

function afterNavigate() {
    if ('/watch' === location.pathname) {
        alert('Watch page!');
    }
}
(document.body || document.documentElement).addEventListener('transitionend',
  function(/*TransitionEvent*/ event) {
    if (event.propertyName === 'width' && event.target.id === 'progress') {
        afterNavigate();
    }
}, true);
// After page load
afterNavigate();

注意:此方法依赖于进度条被插入的事实。每当谷歌决定重命名进度条的ID,或者干脆删除进度条时,你的代码将无法运行。

注意2:这仅适用于活动选项卡。如果您需要在选项卡未聚焦时检测导航更改,则需要绑定window.onfocuswindow.onblur事件,并检查这些事件之间document.title是否发生了变化。


1
@Noitidart 如果你真的想尽快得到通知,你可以绑定到 transitionstart 事件,使用 setTimeoutsetInterval 轮询文档更改。当你找到所需的元素时,注销 transitionstart 事件 + 停止轮询 + 调用你的自定义回调函数。为了确保不浪费 CPU 循环,结合 transitionend 事件;如果你的轮询逻辑在那时没有检测到任何东西,删除事件监听器,停止轮询并调用回调函数。 - Rob W
location.pathundefined,所以我最后使用了location.pathname。对此有什么意见吗?除此之外,它完美地运行着。 - sports
2
@sports location.path 是一个打字错误,应该是 location.pathname - Rob W
Sheesh Rob,伙计,你得到了一些简单的堆栈点:P不错;不过,对于Firefox来说,使用nsIWebProgressListener会给我们提供一个绝对可靠的方法来监视YouTube页面的加载,不是吗? - Noitidart
1
@Noitidart 是的,nsIWebProgressListener 可能是 Firefox 中与 chrome.webNavigation.onHistoryStateUpdated 相当的接口(但仅在主/后台脚本中,而不是在内容脚本中,就像 Chrome 一样)。 - Rob W
显示剩余4条评论

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