How to add observer for nsIBrowserSearchService

385 views Asked by At

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

1

There are 1 answers

6
Noitidart On BEST ANSWER

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.