Search code examples
javascriptfirefoxfirefox-addonfirefox-addon-sdkobservers

How to add observer for nsIBrowserSearchService


I'm having trouble adding an observer to watch for changes in firefox's search engines. I read the nsIBrowserSearchService page on the Mozilla Developer Site which suggests to use the init() method of the Services.search object.

void init([optional] in nsIBrowserSearchInitObserver observer);

I tried that and I managed to get it to execute the function once on start up but it never calls it again when I add or remove or reorder the search engines. So I'm doing something wrong.

I have experience with observers but only with using general preferences and I generally use add them and remove them using the code below. I'm not sure how to do it with the nsIBrowserSearchService . I would like to observe the nsIBrowserSearchService in the same or a similar way but I'm not sure what I would put for

branch = Services.prefs.getBranch("preferenceNameHere");

I'm not observing Services.prefs but Services.search I assume, and that has no getBranch method as far as I can tell.

This is how I normally add and remove the observer in Chrome.js

const {Ci, Cu} = require("chrome");
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});

branch = Services.prefs.getBranch("preferenceNameHere");
branch.addObserver("", observe, false);

function observe(subject, topic, data) {
// instanceof actually also "casts" subject
    if (!(subject instanceof Ci.nsIPrefBranch)) {
        return;
    }
    //do stuff here
};

exports.onUnload = function(reason) {
    // Need to remove our observer again! This isn't automatic and will leak
    // otherwise.

    branch.removeObserver("", observe);
    if(reason == "disable" || reason == "uninstall"){
        //restore changes made by addon
   }
};

Can anyone advise me on how to do this so I can observe for changes and ensure that I remove the observer properly with the search object. Thanks


Solution

  • What you are trying above is trying to use pref observer on non-prefs, this is not possible. You have to use the regular observer service like this.

    This notifies you when the user changes the engine.

    Cu.import('resource://gre/modules/Services.jsm'); 
    
    var observers = {
        'browser-search-engine-modified': {
            aTopic: 'browser-search-engine-modified',
            observe: function (aSubject, aTopic, aData) {
                if (aData == 'engine-current') {
                    console.log('current engine was changed!');
                    //console.log('aSubject on change:', aSubject.name, 'same as Services.search.currentEngine.name:', Services.search.currentEngine.name); //aSubject is the engine
                    //console.log('aTopic on change:', aTopic); //aTopic is obviously `browser-search-engine-modified`
                }
            },
            reg: function () {
                Services.obs.addObserver(observers[this.aTopic], this.aTopic, false);
            },
            unreg: function () {
                Services.obs.removeObserver(observers[this.aTopic], this.aTopic);
            }
        }
    };
    

    To start listening do this:

    for (var o in observers) {
        observers[o].reg();
    }
    

    To stop listening do this:

    for (var o in observers) {
        observers[o].unreg();
    }
    

    I'm not sure what happens when user adds a new engine but doenst select it. Or if he removes a engine. Please let me know what those messages are when user does that.