Change pushState - Equivalent to Chrome extension onHistoryStateUpdated

I am migrating a Chrome extension to a Firefox extension and due to the nature of the website it runs on, I need to track pushState

.

In Chrome Extensions have a convenient way to handle this: chrome.webNavigation.onHistoryStateUpdated

. The way I use it in a Chrome extension is as follows:

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);
  });
 }
});

      

I need to do the same for a Firefox extension, but I haven't found any good answers. I tried to do the answer mentioned here: How to get notified of history changes 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);

      

The problem is that when I do cfx run

, it complains that history/window is undefined

and therefore never shows up. I think it has to do with the fact that it is in the SDK, but I don't know how to do it.

Any thoughts?

Edit: I looked at @ willma's answer below and I don't think it will work for me. The problem is that the url is updated through pushState

, but the DOM is not ... Is there a good way to replicate what I am doing in a chrome extension?

Edit: here's the pageMod

part

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);
    });
  }
});

      

+1


source to share


1 answer


This history code must be entered into the tab using content script

. Right now your logic is saying that when the history event occurs, check if the url is actually a tab stop.

In Firefox, the logic will be the other way around: when a tab is open, check if its url is valid, and if so, add a script to it that will track the history event. For this you need to use Page Mod

.


Edit: all code

One key concept you are missing is the difference between the script content and the main / library script. Library scripts are stored in lib

and have access to all SDK modules, but do not have access to the DOM window object ... Content scripts are stored in data

, injected into the page using PageMod

or tabs

, can access dom and window objects, but do not have access to any- or SDK modules. Content scripts are essentially like page scripts that you would attach to your standard HTML page (with <script></script>

), with the caveat that they cannot pass variables to other scripts on the page, but they can bind to main scripts.

The only reason I am explaining this is because your original problem was trying to access the object window

from the main script, and the problem in your fiddle is that you are trying to access the module tabs

inside the content script. The top-most link in this answer is worth reading if it is still confusing.



main.js

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);
  }
});

      

content.js

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); 

      

Following are the docs of the Query Module for XHR generation.

NB: if you don't want to use the request module (the only reason is that you already have the standard XHR code for your chrome extension and you don't want to waste time learning / rewriting that code) you can send the standard one XHR

from the content script, but you risk allowing the user to close the tab and thus destroy the script before your XHR callbacks are executed.

+1


source







All Articles