【问题标题】:Content script doesn't get injected on every page load内容脚本不会在每次页面加载时都被注入
【发布时间】:2014-10-12 16:45:09
【问题描述】:

我的 manifest.json 文件中有一个基本内容脚本,我让它匹配某个 URL 并加载脚本。

"content_scripts": [
    {
        "matches": ["http://www.urlhere.com/videos/*"],
        "js": ["scripts/jquery-2.1.1.min.js", "scripts/csScript.js"]
    }
],

csScript.js 获取页面上的一个属性,并通过消息将其发送回background.js 脚本。

chrome.runtime.sendMessage({url: getUrl()});

function getUrl() {
  url = $('meta[itemprop=contentURL]').attr('content');
  return url;
}

background.js 页面获取带有属性值的消息,对其进行操作,然后显示page_action 图标。

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    url = manipulateUrl(request.url);
    chrome.pageAction.show(sender.tab.id);
});

chrome.pageAction.onClicked.addListener(function(tab) {
console.log("url: " + url);
});

这一切都在第一个页面加载时正常运行 - 内容脚本被执行并且消息被传递。但是,该页面包含指向其他视频的链接...当我单击其中一个时,我注意到 Chrome 微调器在地址栏中加载了一个新 URL,但内容脚本没有再次执行。

当我点击我的page_action 图标时,我得到了传递的旧 URL,这表明内容脚本没有去获取页面的新 URL。

有什么想法吗?

【问题讨论】:

  • 只是偶然,但是您确定单击链接时的新 URL 也与该字符串匹配吗?可能它会下降http 或变成https
  • 几乎肯定它没有改变。 https 从未出现在任何视频页面中,所以我认为这不是问题。我猜想必须在 DOM 中保持一致,以免内容脚本再次被注入,但我对扩展开发太陌生了,不知道。我也尝试过 programmatic injection 在单击 page_icon 时注入脚本,但同样的问题发生了——我从“旧”DOM 中获取旧 url 数据。
  • 它是一个全新的 URL 还是只是改变的哈希部分(window.location.hash)?
  • 绝对是一个新的 URL。如果我回到主页,然后单击一个视频,它工作正常。但是在视频结束后,我会得到一个建议视频的列表——如果我点击一个,微调器会旋转并加载一个新的 URL,但不会注入任何内容脚本。对我来说没有多大意义。

标签: javascript google-chrome-extension


【解决方案1】:

URL 可能通过历史操作或 URL 片段更改而更改,但实际上并未重新加载页面。

如果是URL片段变化,可以使用window.onhashchange事件。

如果 URL 完全改变但页面没有重新加载,可能是通过 history.pushStatehistory.replaceState 函数实现的。不幸的是,它们不会触发任何事件。因此,检测起来很棘手。

一个 hacky 解决方案是将inject code 插入页面到页面上下文中的replace history.pushState function,这样它还可以执行您可以从内容脚本中检测到的一些事情。它可以是 DOM 更改、自定义事件或 window.postMessage 调用。


编辑:来自linked question,更好的解决方案是听chrome.webNavigation.onHistoryStateUpdated(感谢joshft91)

【讨论】:

  • 有什么好方法可以判断是不是片段变化?如果是这样的话,我不会感到惊讶,因为除了最后一个片段是标题之外,一切都是一样的。但是,Chrome 微调器正在旋转,所以我认为它正在加载一个新页面。我会看看你的解决方案,看看我能不能得到任何工作。谢谢。
  • 查看window.onhashchange在发生时是否被触发,例如设置window.onhashchange = function(e){console.dir(e);}
  • judgeja 链接到这个可能的解决方案 (stackoverflow.com/questions/20865581/…),这似乎让我更接近。每次我点击一个相关视频时,我都会收到内容脚本已运行的警报,但它仍然是从旧的原始 DOM 中提取的。很有趣。
  • 页面的 JavaScript 可能会在更新 DOM 之前更新历史状态。然后你处于竞争状态。尝试延迟重新注入一段时间。
  • 目前我的 .onHistoryStateUpdated() 注入内容脚本的方法如下所示:jsfiddle.net/uu4tbnrw 无论如何我都不是 Javascript 开发人员,经过一番谷歌搜索后,我不确定会是什么延迟注射的最佳方法。这样做的最佳做法是什么?
猜你喜欢
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
相关资源
最近更新 更多