Firefox pushState更改-相当于Chrome扩展名onHistoryStateUpdated

Firefox pushState更改-相当于Chrome扩展名onHistoryStateUpdated,firefox,firefox-addon,firefox-addon-sdk,pushstate,Firefox,Firefox Addon,Firefox Addon Sdk,Pushstate,我正在将Chrome扩展移植到Firefox扩展,由于它运行的网站的性质,我需要监控pushState Chrome扩展有一个简便的方法来处理这个问题:Chrome.webNavigation.onHistoryStateUpdated。我在Chrome扩展中使用它的方式如下: chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) { var tabUrl = details.url; if (i

我正在将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扩展做同样的事情,但我还没有找到任何好的答案。我尝试过这里提到的答案:

问题是,当我运行
cfx时,它会抱怨
历史记录/窗口未定义,因此从未被检测到。我认为这是因为它在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);
    });
  }
});

该历史代码需要使用。现在,您的逻辑是当历史事件发生时,检查选项卡URL是否有效

在Firefox中,逻辑是相反的:当一个选项卡打开时,检查它的URL是否有效,如果有效,然后附加一个脚本来监视历史事件。要做到这一点,您需要使用


编辑:所有代码

您缺少的一个关键概念是内容脚本和主/库脚本之间的区别。库脚本存储在
lib
中,可以访问所有SDK模块,但不能访问DOM、窗口对象……内容脚本存储在
data
中,使用
PageMod
tabs
模块注入页面,可以访问DOM和窗口对象,但无法访问任何SDK模块。内容脚本本质上类似于附加标准HTML页面(带有
)的页面脚本,但需要注意的是,它们不能与其他页面脚本共享变量,但可以与主脚本通信

我提出这个问题的唯一原因是,最初的问题是试图从主脚本访问
窗口
对象,而小提琴中的问题是试图访问内容脚本中的
选项卡
模块。如果这仍然令人困惑,那么值得阅读此答案中最上面的链接

main.js content.js 以下是制作XHR的步骤


注意:如果您不想使用请求模块(唯一的原因是您的chrome扩展已经有了标准的XHR代码,不想花时间学习/重写该代码),您可以从内容脚本发送标准的
XHR
,但这样做,您可能会允许用户关闭选项卡,从而在执行XHR回调之前销毁脚本

谢谢你的回复。如果某些URL被点击,我将使用Page Mod API注入内容脚本。但是,在我加载一个带有有效URL的页面并运行内容脚本后,您可以单击“相关视频”列表。单击其中一个后,URL会更新,但内容脚本不会被点击,因为DOM不会更新,这是因为页面加载了
pushState
,您需要将历史侦听器放在内容脚本中,而不是main.js中。因此,逻辑如下:使用
pageMod
检查原始URL是否有效。如果是这样,请插入具有一些主函数和历史事件侦听器的内容脚本。当事件监听器被触发时,检查新的URL是否有效,如果有效,再次调用main函数。嗯,这是一个有趣的方法。谢谢-我有时间的时候会试一试的;目前正在将我的代码库迁移到一台新的笔记本电脑上,所以我需要一点时间来测试它,但我感谢您的帮助。好吧,我做了更改,但似乎从未涉及历史事件。以下是内容脚本包含的内容:。如果一个历史状态被更新(假定),那么我想获取当前选项卡URL,发送一个XHR,获取新URL,然后将其发送回
main.js
查看我更新的答案。您只能从
pushstate
事件访问新的URL,因此如果您希望同时访问这两个URL,则需要将以前的URL存储在某个位置。请告诉我答案是否有用,或者您是否有任何问题。
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);
    });
  }
});
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);
  }
});
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);