Listening for changes to Firefox preferences

C

Csaba Gabor

This picks up on a comment in my reply to the "Writing Firefox's
prefs.js with javascript" thread:
http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/bd01516f89f682c0/

What I really wanted was an event driven method in Firefox to react to
changes in the user's preference settings. The code below does exactly
that - When a preference change is detected (say via the about:config
page), it will pop up a message box showing the new setting.

First, I have two question, then the code follows, then some caveats at
the end:
Q1. Each time a preference is changed, getValue has to create an
interface to a preferences branch (sorry if my terminology is off).
But that branch should be available in register() and it should be
possible (I would think) to save it onto this.myBranch so that getValue
doesn't have to reconstruct it each time. But I get a silent error
every way that I've tried it. It would be great if someone would make
the example code cleaner in this respect. In other words, I don't want
to have keep getting security dialogs every time a preference setting
is changed - cant' the appropriate object be cached/preserved?

Q2. If I refresh the test page (F5), then I get the same behaviour as
before I refreshed the page. However, if I make a change to the
underlying page, and afterwards refresh with F5, then I get any
observers from before, in addition to the new one from the refreshed
page. Shouldn't FF automatically unload observers when their
underlying page goes away? If the answer to that is no, upon what event
should I unload the observer?

Thanks,
Csaba Gabor from Vienna



<html><head><title>Pref Observer</title></head>
<body onload="window.setTimeout(setupPrefObserver,0)">
Change a preference in about:config and see that this page will detect
it.
<script type='text/javascript'>
function setupPrefObserver() {
var myPreferenceObserver = {
privError: "Unable to enable UniversalXPConnect privilege",

register: function() {
try { netscape.security.PrivilegeManager
.enablePrivilege("UniversalXPConnect");
} catch (ex) {
alert (this.privError + " in register");
return;
}
var prefService = Components
.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
this._branch = prefService.getBranch("");
this._branch
.QueryInterface(Components.interfaces.nsIPrefBranch2);
this._branch.addObserver("", this, false); },

unregister: function() {
if(!this._branch) return;
this._branch.removeObserver("", this); },

getValue: function(prefName, defaultValue) {
var prefType;
try { netscape.security.PrivilegeManager
.enablePrivilege("UniversalXPConnect");
} catch (ex) {
alert (this.privError + " within getValue");
return;
}
var prefBranch = Components
.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService)
.getBranch("");
prefType = prefBranch.getPrefType(prefName);
switch (prefType) {
case prefBranch.PREF_STRING:
return prefBranch.getCharPref(prefName);
case prefBranch.PREF_BOOL:
return prefBranch.getBoolPref(prefName);
case prefBranch.PREF_INT:
return prefBranch.getIntPref(prefName);
case prefBranch.PREF_INVALID:
return defaultValue;
default: // nothing found
return "unaccounted for condition in getValue: " + prefType;
}
},

observe: function(subject, topic, prefName) {
if(topic != "nsPref:changed") return;
// subject is the nsIPrefBranch we're observing
// prefName (relative to subject) has been changed
alert ("Subject: " + subject + "\n" +
"Preference name: " + prefName);
alert ("Preference value: " +
this.getValue(prefName, "not found"));
}
}
myPreferenceObserver.register();
}
</script>
</body>
</html>


The caveats in case you are testing with it:
C1. The code must be run from a local hard drive as a file in order to
be able to secure the necessary permissions. You can do this by
dragging the file onto FF (and then you'll also be able to see the
exact URL).
C2. If you make any changes to the code you must completely close FF
and bring it up fresh before restarting. See Question 2 for the
details.
C3. There are pesky security dialogs that you keep having to say yes
to, but I recommend keeping the checkbox clear (so that it asks you
every time). If you don't, you are really exposing your system because
any subsequent javascript on your local drive will then have those
capabilities without you knowing. For example, the tip of the iceburg
is that any preference settings you have (such as your email address
and GM values) could be read out and submitted to a remote website.
C4. This code is a learning vehicle for me and does not represent what
I will be doing in the end. My final intention is actually to hook the
preference listeners into the GreaseMonkey extension. Actually, the
hooks appear to already be there, and I'm hoping I only have to use
GM_Hitch.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,061
Latest member
KetonaraKeto

Latest Threads

Top