9

I have an extension, functional on Chrome, that monitors the active Tab for URL changes.

Specifically, I need to detect when the URL changes, but there is no new page load or navigation. Some sites do this (e.g. when you click to view another video on YouTube).

On Chrome, I accomplished this with:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo && changeInfo.status == "complete") {
        //do stuff here
    }
});

How do I detect such changes in a Firefox add-on?

I've been told to use: Listening to events on all tabs, but I couldn't put it together. One of the problems was that gBrowser was not defined in the extension.

What am I doing wrong?

Is there a simpler way?

Makyen
  • 31,849
  • 12
  • 86
  • 121
tiagosilva
  • 1,695
  • 17
  • 31
  • nsIWebProgressListener - https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIWebProgressListener?redirectlocale=en-US&redirectslug=nsIWebProgressListener#onStatusChange%28%29 - i used it here: https://github.com/Noitidart/Listen-on-Repeat-Youtube-Video-Repeater – Noitidart May 26 '15 at 20:18
  • 1
    thx @Noitidart This seems so overly complex for such a simple task, but ok, i've defined the listener, how do i attached it using the firefox-addon sdk? i can't just do: gBrowser.addProgressListener(progListener); because i don't have access to gBrowser, i've tried to use the tab/utils and do this: `tabs.on('ready', function(tab) { var browser=gBrowser.getBrowserForTab(tab); browser.addProgressListener(progListener);` but browser is undefined – tiagosilva May 27 '15 at 10:39
  • I'm not too familiar with sdk. The reason its complex is it provides lots of important information on what caused the change and why. If you want to just listen for change you can probably use a MutationObserver https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver?redirectlocale=en-US&redirectslug=DOM%2FMutationObserver#MutationObserverInit use `characterData` and watch on the anonymous element otherwise it wont trigger. i think the observer will disconnect on tab change though im not sure. https://ask.mozilla.org/question/542/mutation-observer-disconnects-from-anonymous-element – Noitidart May 27 '15 at 12:51
  • @TiagoSilva There are a few ways of making add-ons for Firefox. If you only want answers pertaining to the Addon-SDK, then don't use the `firefox-addon` tag in the future. If you want to know the difference between bootstrapped and Addon-SDK extensions, see [my answer here](http://stackoverflow.com/a/21923179/1720014). – willlma May 27 '15 at 17:59
  • possible duplicate of [How can i check if url of current browser tab is changed?](http://stackoverflow.com/questions/2060779/how-can-i-check-if-url-of-current-browser-tab-is-changed) – Basilevs Jun 06 '15 at 05:53

3 Answers3

4

Use ProgressListener to be notified about location changes.

To install a listener, convert SDK tab to its raw (old) representation using viewFor. Backward conversion is possible with modelFor and getTabForContentWindow.

const tabs = require("sdk/tabs");
const {viewFor} = require('sdk/view/core');
const {modelFor} = require('sdk/model/core');
const {getBrowserForTab, getTabForContentWindow} = require("sdk/tabs/utils");
const {Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);

var progressListener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
    onLocationChange: function(aProgress, aRequest, aURI) {
        var highLevel= modelFor(getTabForContentWindow(aProgress.DOMWindow));
        console.log("onLocationChange ", highLevel.url);
    }
};

tabs.on('open', function(newTab) {
    var lowLevel = viewFor(newTab);
    var browser = getBrowserForTab(lowLevel);
    browser.addProgressListener(progressListener);
});

Don't forget to remove listeners on extension unload. Tab listeners are removed automagically, but ProgressListeners won't be.

Inspired by Converting to chrome windows

Basilevs
  • 22,440
  • 15
  • 57
  • 102
  • 1
    Very nice and simple solution thanks for it! A comment though, we don't have to attach this listener on every tab open. Only once per browser window. – Noitidart Jun 08 '15 at 17:09
  • Source: https://github.com/mozilla/addon-sdk/blob/master/lib/sdk/content/page-worker.js#L101-L120 – mate64 Dec 03 '15 at 00:33
  • This answer is now obsolete. Firefox deprecates chrome APIs in favor of WebExtensions. – Basilevs Dec 03 '15 at 03:20
  • 3
    One more notice, `progressListener` isn't removed on add-on shutdown in this case. If you don't remove it manually(`removeProgressListener()`) in [`exports.onUnload()`](https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Listening_for_load_and_unload#exports.onUnload%28%29) you'll have a lot of errors `TypeError: can't access dead object` after you disable/uninstall your add-on until Firefox restart. – traxium Mar 28 '16 at 05:16
0

If you're using the add-on SDK, you're looking at the wrong docs. Here are the tab docs.

As stated there, you create a listener like so:

var tabs = require("sdk/tabs");

// Listen for tab openings.
tabs.on('open', function onOpen(tab) {
  myOpenTabs.push(tab);
});

// Listen for tab content loads.
tabs.on('ready', function(tab) {
  console.log('tab is loaded', tab.title, tab.url);
});

All the docs you look at should be a subset of developer.mozilla.org/en-US/Add-ons/SDK.

willlma
  • 7,353
  • 2
  • 30
  • 45
0

I find that the activate and pageshow events, between the two of them, cover all changes in URL that I can conjure up between switching tabs, opening pages in a new tab, closing tabs, refreshing pages, and typing in new URL's.

var updateURL = function (tab) {
 var oldURL = url;
 var url = tab.url;
 console.log(url);
};

tabs.on("activate", updateURL);
tabs.on("pageshow", updateURL);
Lori
  • 1,392
  • 1
  • 21
  • 29
  • Please [edit] in an explanation of why/how this code answers the question. Code-only answers are discouraged, because they are not as easy to learn from as code with an explanation. Without an explanation it takes considerably more time and effort to understand what is being done, the changes made to the code, if the code answers the question, etc. The explanation is important both for people attempting to learn from the answer and those evaluating the answer to see if it is valid, or worth up voting. – Makyen May 29 '15 at 20:40
  • 2
    i said in my question: "url changed but there was no new page load or navigation", none of your examples: (cover all changes in URL that I can conjure up between switching tabs, opening pages in a new tab, closing tabs, refreshing pages, and typing in new URL's.) cover my example: (like youtube when you click to view another video) – tiagosilva Jun 01 '15 at 14:30