user3522371
user3522371

Reputation:

How to read firefox's about:config entries using Python?

How could I read about:config entries for firefox version 30.0 using Python ? I tried to use what is pointed by this answer (in JavaScript) but it did not help.

Upvotes: 0

Views: 1054

Answers (1)

nmaier
nmaier

Reputation: 33162

Yeah, that's a problem. Firefox comes with default values for most preferences, and only stores values different from the default in the profile. Added to this, each add-on may come with additional default values and create new preferences at runtime.

The default pref files might be contained within zip files, which complicates matters a little.

Files

Files you'd have to check for default preferences (in a standard Firefox distribution)

  • $APPDIR/omni.ja:greprefs.js
  • $APPDIR/omni.ja:defaults/preferences/*.js
  • $APPDIR/browser/omni.ja:greprefs.js
  • $APPDIR/browser/omni.ja:defaults/preferences/*.js
  • $PROFILE/extensions/*/defaults/preferences/*.js
  • $PROFILE/extensions/*.xpi:defaults/preferences/*.js

While preferences that were overridden from the default reside in $PROFILE/prefs.js.

So first you need to figure out $APPDIR (installation path of Firefox) and then $PROFILE (Firefox user profile path).

Then you need to read some files either in some directories (easy) or in some zip files (hard). A major problem is that you cannot just use zipfile to read omni.ja (and potentially some of the xpi files) because a typical python zipfile implementation is too rigid in the interpretation of the zip structure and fails to open these files. So you'd need your own zipfile implementation that can deal with this.

Format

In the *.js files there are essentially two types of lines (+ blank lines, comment lines):

pref("name", value)
user_pref("name", value)

The pref lines are default preferences, user_pref lines are user preferences (overridden from default).

Values

value is a Javascript expression such as "abc", true, 1 or 2 * 3. The latter is a problem, as you'd need a JS engine to properly evaluate it. But this isn't really a problem in practice, as you won't find expressions computing something in the wild (usually).

Conclusion

Really replicating the preferences system (or about:config) isn't an easy task and full of obstacles. It is probably far easier just reading user pref.js to see what's overridden and knowing the default values.

Example (just prefs.js)

import re
import json

PROFILE = "/path/to/firefox/profile"


def read_user_prefs(preffile):
    r = re.compile(r"\s*user_pref\(([\"'])(.+?)\1,\s*(.+?)\);")
    rv = {}
    for l in preffile:
        m = r.match(l)
        if not m:
            continue
        k, v = m.group(2), m.group(3)
        try:
            rv[k] = json.loads(v)
        except Exception as ex:
            print "failed to parse", k, v, ex
    return rv


with open("{}/prefs.js".format(PROFILE), "rb") as p:
    prefs = read_user_prefs(p)
    for k, v in prefs.items():
        print u"({type:<16}) {key}: {value}".format(
            key=k, value=v, type=str(type(v)))

    print
    print "Chrome debugging enabled:",
    print prefs.get("devtools.chrome.enabled", False)
    print "Last sync:",
    print prefs.get("services.sync.tabs.lastSync", 0.0)
    print "Pref that might not exist:",
    print prefs.get("does.not.exist", "default")

Alternatives

Write a that dumps interesting Preferences to a known file, or uses another form of IPC (sockets, whatever) to communicate with your python script.

Upvotes: 3

Related Questions