我已将Chrome扩展程序移植到Firefox扩展程序,并且由于其运行的网站的性质,我需要监控pushState
。
Chrome扩展程序有一个方便的方法来解决这个问题:chrome.webNavigation.onHistoryStateUpdated
。我在Chrome扩展程序中使用它的方式如下:
chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) {
var tabUrl = details.url;
if (isTabUrlValid(tabUrl)) {
$.get(tabUrl, function(data) {
var videoUrl = $(data).find('meta[itemprop=contentURL]').prop('content');
videoUrl = validateUrl(videoUrl);
videoUrl5k = make5kUrl(videoUrl);
});
}
});
我需要为Firefox扩展做同样的事情,但我还没有找到任何好的答案。我尝试过这里提到的答案:How to get notified about changes of the history via history.pushState?
(function(history) {
var pushState = history.pushState;
history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state});
}
var tabUrl = tabs.activeTab.url;
console.log("UPDATED TAB URL: " + tabUrl);
if (isTabUrlValid(tabUrl)) {
$.get(tabUrl, function(data) {
var videoUrl = $(data).find('meta[itemprop=contentURL]').prop('content');
videoUrl = validateUrl(videoUrl);
videoUrl5k = make5kUrl(videoUrl);
});
}
return pushState.apply(history, arguments);
};
})(window.history);
问题在于,当我cfx run
时,它会抱怨history/window is undefined
,因此永远不会被检测到。我认为这是因为它属于SDK,但我不知道一个好的解决方法。
有什么想法吗?
编辑:我查看了下面的@willma的答案,我认为这对我没用。问题是URL是通过pushState
更新的,而DOM不是......有没有什么好方法可以复制我在chrome扩展中做的事情?
修改:此处是pageMod
部分
pageMod.PageMod({
attachTo: 'top', // Don't attach to iFrames --> http://goo.gl/b6b1Iv
include: [URLs],
contentScriptFile: [data.url("jquery-2.1.1.min.js"),
data.url("csScript.js")],
onAttach: function(worker) {
worker.port.on('url', function(url) {
var videoUrl = validateUrl(url);
videoUrl5k = make5kUrl(videoUrl);
console.log("--5K URL--: " + videoUrl5k);
});
}
});
答案 0 :(得分:1)
需要使用content script
将历史记录代码注入到标签中。现在您的逻辑说明历史事件发生时,检查选项卡URL是否有效。
在Firefox中,逻辑将是另一种方式:打开选项卡时,检查其URL是否有效,如果是,则附加一个脚本,以监视历史事件。为此,您需要使用Page Mod
。
编辑:所有代码
您缺少的一个关键概念是内容脚本和主/库脚本之间的区别。库脚本存储在lib
中并且可以访问所有SDK模块,但是无法访问DOM,窗口对象......内容脚本存储在data
中,被注入使用PageMod
或tabs
模块的页面可以访问dom和window对象,但无法访问任何SDK模块。内容脚本基本上类似于您附加标准HTML页面(包含<script></script>
)的页面脚本,以及他们无法共享其他页面脚本变量的警告,但他们可以与主要脚本沟通。
我提出这个问题的唯一原因是因为您最初的问题是尝试从主脚本访问window
对象,并且您的小提琴中的问题是您尝试访问{{1内容脚本中的模块。如果这仍然令人困惑,那么值得阅读本回答中最重要的链接。
tabs
const { PageMod } = require('sdk/page-mod');
var sendXHR = function(url) {
// Do something with the new URL
// See Request Module docs (below) for sending XHRs from main script.
}
const pageMod = PageMod({
attachTo: 'top',
include: '*',
onAttach: function(worker) {
worker.port.on('newURL', sendXHR);
}
});
以下是制作XHR的request module docs。
注意:如果您不想使用请求模块(唯一的原因是您的Chrome扩展程序已经有标准XHR代码,并且不想花时间学习/重写代码),您可以从内容脚本发送标准var sendNewUrlToMain = function() {
self.port.emit('newURL', location.href);
}
var pushState = window.history.pushState;
window.history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state});
}
sendNewUrlToMain();
return pushState.apply(history, arguments);
}
window.addEventListener('hashchange', sendNewUrlToMain);
,但这样做可能会让用户关闭选项卡,从而在执行XHR回调之前销毁脚本。