diff options
author | Kris Maglione <maglione.k@gmail.com> | 2010-12-01 21:57:51 -0500 |
---|---|---|
committer | Kris Maglione <maglione.k@gmail.com> | 2010-12-01 21:57:51 -0500 |
commit | 5d51fd491a2c065e98e3d1b16ff9b476b2f5511e (patch) | |
tree | 3d28028db8794fb4ffb0d8bd21d72cc25461ea1d /common/modules | |
parent | 0bf9cfb0bc1bad386d463d6111533653d776e4b7 (diff) | |
download | pentadactyl-5d51fd491a2c065e98e3d1b16ff9b476b2f5511e.tar.gz |
Do away with services.(get|create), and move the prefs module to its own file.
Diffstat (limited to 'common/modules')
-rw-r--r-- | common/modules/base.jsm | 12 | ||||
-rw-r--r-- | common/modules/bookmarkcache.jsm | 10 | ||||
-rw-r--r-- | common/modules/prefs.jsm | 346 | ||||
-rw-r--r-- | common/modules/sanitizer.jsm | 50 | ||||
-rw-r--r-- | common/modules/services.jsm | 30 | ||||
-rw-r--r-- | common/modules/storage.jsm | 23 | ||||
-rw-r--r-- | common/modules/styles.jsm | 6 | ||||
-rw-r--r-- | common/modules/util.jsm | 358 |
8 files changed, 429 insertions, 406 deletions
diff --git a/common/modules/base.jsm b/common/modules/base.jsm index e145d551..590ee4ec 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -124,7 +124,7 @@ defineModule.dump = function dump_() { msg = util.objectToString(msg); return msg; }).join(", "); - let name = loaded.services ? services.get("dactyl:").name : "dactyl"; + let name = loaded.services ? services["dactyl:"].name : "dactyl"; dump(String.replace(msg, /\n?$/, "\n") .replace(/^./gm, name + ": $&")); } @@ -199,9 +199,9 @@ Runnable.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.nsIRunnable]); * @returns [jsdIProperty] */ function debuggerProperties(obj) { - if (loaded.services && services.get("debugger").isOn) { + if (loaded.services && services.debugger.isOn) { let ret = {}; - services.get("debugger").wrapValue(obj).getProperties(ret, {}); + services.debugger.wrapValue(obj).getProperties(ret, {}); return ret.value; } } @@ -227,7 +227,7 @@ function properties(obj, prototypes, debugger_) { for (; obj; obj = prototypes && prototype(obj)) { try { - if (sandbox.Object.getOwnPropertyNames || !debugger_ || !services.get("debugger").isOn) + if (sandbox.Object.getOwnPropertyNames || !debugger_ || !services.debugger.isOn) var iter = values(Object.getOwnPropertyNames(obj)); } catch (e) {} @@ -798,7 +798,7 @@ Class.prototype = { timeout: function (callback, timeout) { const self = this; let notify = { notify: function notify(timer) { try { callback.apply(self); } catch (e) { util.reportError(e); } } }; - let timer = services.create("timer"); + let timer = services.Timer(); timer.initWithCallback(notify, timeout || 0, timer.TYPE_ONE_SHOT); return timer; } @@ -939,7 +939,7 @@ let StructBase = Class("StructBase", Array, { const Timer = Class("Timer", { init: function (minInterval, maxInterval, callback) { - this._timer = services.create("timer"); + this._timer = services.Timer(); this.callback = callback; this.minInterval = minInterval; this.maxInterval = maxInterval; diff --git a/common/modules/bookmarkcache.jsm b/common/modules/bookmarkcache.jsm index 5d67428a..29299ef1 100644 --- a/common/modules/bookmarkcache.jsm +++ b/common/modules/bookmarkcache.jsm @@ -18,10 +18,10 @@ Bookmark.prototype.__defineGetter__("extra", function () [ ["tags", this.tags.join(", "), "Tag"] ].filter(function (item) item[1])); -const annotation = services.get("annotation"); -const bookmarks = services.get("bookmarks"); -const history = services.get("history"); -const tagging = services.get("tagging"); +const annotation = services.annotation; +const bookmarks = services.bookmarks; +const history = services.history; +const tagging = services.tagging; const name = "bookmark-cache"; const BookmarkCache = Module("BookmarkCache", XPCOM(Ci.nsINavBookmarkObserver), { @@ -85,7 +85,7 @@ const BookmarkCache = Module("BookmarkCache", XPCOM(Ci.nsINavBookmarkObserver), isRegularBookmark: function isRegularBookmark(id) { do { var root = id; - if (services.get("livemark") && services.get("livemark").isLivemark(id)) + if (services.livemark && services.livemark.isLivemark(id)) return false; id = bookmarks.getFolderIdForItem(id); } while (id != bookmarks.placesRoot && id != root); diff --git a/common/modules/prefs.jsm b/common/modules/prefs.jsm new file mode 100644 index 00000000..8c852395 --- /dev/null +++ b/common/modules/prefs.jsm @@ -0,0 +1,346 @@ +// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org> +// Copyright (c) 2007-2010 by Doug Kearns <dougkearns@gmail.com> +// Copyright (c) 2008-2010 by Kris Maglione <maglione.k@gmail.com> +// +// This work is licensed for reuse under an MIT license. Details are +// given in the LICENSE.txt file included with this file. +"use strict"; + +Components.utils.import("resource://dactyl/base.jsm"); +defineModule("prefs", { + exports: ["Prefs", "prefs"], + require: ["services", "util"], + use: ["template"] +}); + +const Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), { + SAVED: "extensions.dactyl.saved.", + RESTORE: "extensions.dactyl.restore.", + + init: function () { + this._prefContexts = []; + + util.addObserver(this); + this._branch = services.pref.getBranch("").QueryInterface(Ci.nsIPrefBranch2); + this._branch.addObserver("", this, false); + this._observers = {}; + + this.restore(); + }, + + observe: { + "nsPref:changed": function (subject, data) { + let observers = this._observers[data]; + if (observers) { + let value = this.get(data, false); + this._observers[data] = observers.filter(function (callback) { + if (!callback.get()) + return false; + util.trapErrors(callback.get(), null, value); + return true; + }); + } + } + }, + + /** + * Adds a new preference observer for the given preference. + * + * @param {string} pref The preference to observe. + * @param {function(object)} callback The callback, called with the + * new value of the preference whenever it changes. + */ + watch: function (pref, callback, strong) { + if (!this._observers[pref]) + this._observers[pref] = []; + this._observers[pref].push(!strong ? Cu.getWeakReference(callback) : { get: function () callback }); + }, + + /** + * Lists all preferences matching *filter* or only those with changed + * values if *onlyNonDefault* is specified. + * + * @param {boolean} onlyNonDefault Limit the list to prefs with a + * non-default value. + * @param {string} filter The list filter. A null filter lists all + * prefs. + * @optional + */ + list: function list(onlyNonDefault, filter) { + if (!filter) + filter = ""; + + let prefArray = this.getNames(); + prefArray.sort(); + function prefs() { + for (let [, pref] in Iterator(prefArray)) { + let userValue = services.pref.prefHasUserValue(pref); + if (onlyNonDefault && !userValue || pref.indexOf(filter) == -1) + continue; + + let value = this.get(pref); + + let option = { + isDefault: !userValue, + default: this._load(pref, null, true), + value: <>={template.highlight(value, true, 100)}</>, + name: pref, + pre: "\u00a0\u00a0" // Unicode nonbreaking space. + }; + + yield option; + } + }; + + return template.options(services["dactyl:"].host + " Preferences", prefs.call(this)); + }, + + /** + * Returns the value of a preference. + * + * @param {string} name The preference name. + * @param {value} defaultValue The value to return if the preference + * is unset. + */ + get: function (name, defaultValue) this._load(name, defaultValue), + + /** + * Returns the default value of a preference + * + * @param {string} name The preference name. + * @param {value} defaultValue The value to return if the preference + * has no default value. + */ + getDefault: function (name, defaultValue) this._load(name, defaultValue, true), + + /** + * Returns the names of all preferences. + * + * @param {string} branch The branch in which to search preferences. + * @default "" + */ + getNames: function (branch) services.pref.getChildList(branch || "", { value: 0 }), + + _checkSafe: function (name, message, value) { + let curval = this._load(name, null, false); + if (arguments.length > 2 && curval === value) + return; + let defval = this._load(name, null, true); + let saved = this._load(this.SAVED + name); + + if (saved == null && curval != defval || curval != saved) { + let msg = "Warning: setting preference " + name + ", but it's changed from its default value."; + if (message) + msg += " " + message; + util.dactyl.echomsg(msg); + } + }, + + /** + * Resets the preference *name* to *value* but warns the user if the value + * is changed from its default. + * + * @param {string} name The preference name. + * @param {value} value The new preference value. + */ + safeReset: function (name, message) { + this._checkSafe(name, message); + this.reset(name); + this.reset(this.SAVED + name); + }, + + /** + * Sets the preference *name* to *value* but warns the user if the value is + * changed from its default. + * + * @param {string} name The preference name. + * @param {value} value The new preference value. + */ + safeSet: function (name, value, message, skipSave) { + this._checkSafe(name, message, value); + this._store(name, value); + this[skipSave ? "reset" : "_store"](this.SAVED + name, value); + }, + + /** + * Sets the preference *name* to *value*. + * + * @param {string} name The preference name. + * @param {value} value The new preference value. + */ + set: function (name, value) { + this._store(name, value); + }, + + /** + * Saves the current value of a preference to be restored at next + * startup. + * + * @param {string} name The preference to save. + */ + save: function (name) { + let val = this.get(name); + this.set(this.RESTORE + name, val); + this.safeSet(name, val); + }, + + /** + * Restores saved preferences in the given branch. + * + * @param {string} branch The branch from which to restore + * preferences. @optional + */ + restore: function (branch) { + this.getNames(this.RESTORE + (branch || "")).forEach(function (pref) { + this.safeSet(pref.substr(this.RESTORE.length), this.get(pref), null, true) + this.reset(pref); + }, this); + }, + + /** + * Resets the preference *name* to its default value. + * + * @param {string} name The preference name. + */ + reset: function (name) { + try { + services.pref.clearUserPref(name); + } + catch (e) {} // ignore - thrown if not a user set value + }, + + /** + * Toggles the value of the boolean preference *name*. + * + * @param {string} name The preference name. + */ + toggle: function (name) { + util.assert(services.pref.getPrefType(name) === Ci.nsIPrefBranch.PREF_BOOL, + "E488: Trailing characters: " + name + "!"); + this.set(name, !this.get(name)); + }, + + /** + * Pushes a new preference context onto the context stack. + * + * @see #withContext + */ + pushContext: function () { + this._prefContexts.push({}); + }, + + /** + * Pops the top preference context from the stack. + * + * @see #withContext + */ + popContext: function () { + for (let [k, v] in Iterator(this._prefContexts.pop())) + this._store(k, v); + }, + + /** + * Executes *func* with a new preference context. When *func* returns, the + * context is popped and any preferences set via {@link #setPref} or + * {@link #invertPref} are restored to their previous values. + * + * @param {function} func The function to call. + * @param {Object} func The 'this' object with which to call *func* + * @see #pushContext + * @see #popContext + */ + withContext: function (func, self) { + try { + this.pushContext(); + return func.call(self); + } + finally { + this.popContext(); + } + }, + + _store: function (name, value) { + if (this._prefContexts.length) { + let val = this._load(name, null); + if (val != null) + this._prefContexts[this._prefContexts.length - 1][name] = val; + } + + function assertType(needType) + util.assert(type === Ci.nsIPrefBranch.PREF_INVALID || type === needType, + type === Ci.nsIPrefBranch.PREF_INT + ? "E521: Number required after =: " + name + "=" + value + : "E474: Invalid argument: " + name + "=" + value); + + let type = services.pref.getPrefType(name); + switch (typeof value) { + case "string": + assertType(Ci.nsIPrefBranch.PREF_STRING); + + let supportString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); + supportString.data = value; + services.pref.setComplexValue(name, Ci.nsISupportsString, supportString); + break; + case "number": + assertType(Ci.nsIPrefBranch.PREF_INT); + + services.pref.setIntPref(name, value); + break; + case "boolean": + assertType(Ci.nsIPrefBranch.PREF_BOOL); + + services.pref.setBoolPref(name, value); + break; + default: + throw FailedAssertion("Unknown preference type: " + typeof value + " (" + name + "=" + value + ")"); + } + }, + + _load: function (name, defaultValue, defaultBranch) { + if (defaultValue == null) + defaultValue = null; + + let branch = defaultBranch ? services.pref.getDefaultBranch("") : services.pref; + let type = services.pref.getPrefType(name); + try { + switch (type) { + case Ci.nsIPrefBranch.PREF_STRING: + let value = branch.getComplexValue(name, Ci.nsISupportsString).data; + // try in case it's a localized string (will throw an exception if not) + if (!services.pref.prefIsLocked(name) && !services.pref.prefHasUserValue(name) && + RegExp("chrome://.+/locale/.+\\.properties").test(value)) + value = branch.getComplexValue(name, Ci.nsIPrefLocalizedString).data; + return value; + case Ci.nsIPrefBranch.PREF_INT: + return branch.getIntPref(name); + case Ci.nsIPrefBranch.PREF_BOOL: + return branch.getBoolPref(name); + default: + return defaultValue; + } + } + catch (e) { + return defaultValue; + } + } +}, { +}, { + completion: function (dactyl, modules) { + modules.completion.preference = function preference(context) { + context.anchored = false; + context.title = [services["dactyl:"].host + " Preference", "Value"]; + context.keys = { text: function (item) item, description: function (item) prefs.get(item) }; + context.completions = prefs.getNames(); + }; + }, + javascript: function (dactyl, modules) { + modules.JavaScript.setCompleter([this.get, this.safeSet, this.set, this.reset, this.toggle], + [function (context) (context.anchored=false, prefs.getNames().map(function (pref) [pref, ""]))]); + } +}); + +endModule(); + +// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);} + +// vim: set fdm=marker sw=4 ts=4 et ft=javascript: diff --git a/common/modules/sanitizer.jsm b/common/modules/sanitizer.jsm index 7b84799b..326f3889 100644 --- a/common/modules/sanitizer.jsm +++ b/common/modules/sanitizer.jsm @@ -15,11 +15,11 @@ Components.utils.import("resource://dactyl/base.jsm"); defineModule("sanitizer", { exports: ["Range", "Sanitizer", "sanitizer"], - require: ["services", "storage", "template", "util"] + require: ["prefs", "services", "storage", "template", "util"] }); let tmp = {}; -services.get("subscriptLoader").loadSubScript("chrome://browser/content/sanitize.js", tmp); +services.subscriptLoader.loadSubScript("chrome://browser/content/sanitize.js", tmp); tmp.Sanitizer.prototype.__proto__ = Class.prototype; const Range = Struct("min", "max"); @@ -92,7 +92,7 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR action: function (range, host) { for (let c in Sanitizer.iterCookies(host)) if (range.contains(c.creationTime) || timespan.isSession && c.isSession) - services.get("cookies").remove(c.host, c.name, c.path, false); + services.cookies.remove(c.host, c.name, c.path, false); }, override: true }); @@ -105,23 +105,23 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR return; if (host) { for (let p in Sanitizer.iterPermissions(host)) { - services.get("permissions").remove(util.createURI(p.host), p.type); - services.get("permissions").add(util.createURI(p.host), p.type, 0); + services.permissions.remove(util.createURI(p.host), p.type); + services.permissions.add(util.createURI(p.host), p.type, 0); } - for (let p in iter(services.get("contentprefs").getPrefs(util.createURI(host)))) - services.get("contentprefs").removePref(util.createURI(host), p.QueryInterface(Ci.nsIProperty).name); + for (let p in iter(services.contentprefs.getPrefs(util.createURI(host)))) + services.contentprefs.removePref(util.createURI(host), p.QueryInterface(Ci.nsIProperty).name); } else { // "Allow this site to open popups" ... - services.get("permissions").removeAll(); + services.permissions.removeAll(); // Zoom level, ... - services.get("contentprefs").removeGroupedPrefs(); + services.contentprefs.removeGroupedPrefs(); } // "Never remember passwords" ... - for each (let domain in services.get("loginmanager").getAllDisabledHosts()) + for each (let domain in services.loginmanager.getAllDisabledHosts()) if (!host || util.isSubdomain(domain, host)) - services.get("loginmanager").setLoginSavingEnabled(host, true); + services.loginmanager.setLoginSavingEnabled(host, true); }, override: true }); @@ -153,7 +153,7 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR append: { SanitizeDialogPane: <groupbox orient="horizontal" xmlns={XUL}> - <caption label={services.get("dactyl:").appName + " (see :help privacy)"}/> + <caption label={services["dactyl:"].appName + " (see :help privacy)"}/> <grid flex="1"> <columns><column flex="1"/><column flex="1"/></columns> <rows>{ @@ -178,7 +178,7 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR { template.map(ourItems(), function ([item, desc]) <listitem xmlns={XUL} type="checkbox" - label={services.get("dactyl:").appName + " " + desc} + label={services["dactyl:"].appName + " " + desc} preference={branch + item} onsyncfrompreference="return gSanitizePromptDialog.onReadGeneric();"/>) } @@ -328,14 +328,14 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR prefToArg: function (pref) pref.replace(/.*\./, "").toLowerCase(), iterCookies: function iterCookies(host) { - for (let c in iter(services.get("cookies"))) { + for (let c in iter(services.cookies)) { c.QueryInterface(Ci.nsICookie2); if (!host || util.isSubdomain(c.rawHost, host)) yield c; } }, iterPermissions: function iterPermissions(host) { - for (let p in iter(services.get("permissions"))) { + for (let p in iter(services.permissions)) { p.QueryInterface(Ci.nsIPermission); if (!host || util.isSubdomain(p.host, host)) yield p; @@ -393,7 +393,7 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR args["-host"].forEach(function (host) { sanitizer.sanitizing = true; if (items.indexOf("history") > -1) - services.get("privateBrowsing").removeDataFromDomain(host); + services.privateBrowsing.removeDataFromDomain(host); sanitizer.sanitizeItems(items, range, host) }); } @@ -438,13 +438,13 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR function getPerms(host) { let uri = util.createURI(host); if (uri) - return Sanitizer.UNPERMS[services.get("permissions").testPermission(uri, "cookie")]; + return Sanitizer.UNPERMS[services.permissions.testPermission(uri, "cookie")]; return "unset"; } function setPerms(host, perm) { let uri = util.createURI(host); - services.get("permissions").remove(uri, "cookie"); - services.get("permissions").add(uri, "cookie", Sanitizer.PERMS[perm]); + services.permissions.remove(uri, "cookie"); + services.permissions.add(uri, "cookie", Sanitizer.PERMS[perm]); } commands.add(["cookies", "ck"], "Change cookie permissions for sites", @@ -458,14 +458,14 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR switch (cmd) { case "clear": for (let c in Sanitizer.iterCookies(host)) - services.get("cookies").remove(c.host, c.name, c.path, false); + services.cookies.remove(c.host, c.name, c.path, false); break; case "clear-persistent": session = false; case "clear-session": for (let c in Sanitizer.iterCookies(host)) if (c.isSession == session) - services.get("cookies").remove(c.host, c.name, c.path, false); + services.cookies.remove(c.host, c.name, c.path, false); return; case "list": @@ -524,16 +524,16 @@ const Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakR }, options: function (dactyl, modules) { const options = modules.options; - if (services.get("privateBrowsing")) + if (services.privateBrowsing) options.add(["private", "pornmode"], "Set the 'private browsing' option", "boolean", false, { initialValue: true, - getter: function () services.get("privateBrowsing").privateBrowsingEnabled, + getter: function () services.privateBrowsing.privateBrowsingEnabled, setter: function (value) { - if (services.get("privateBrowsing").privateBrowsingEnabled != value) - services.get("privateBrowsing").privateBrowsingEnabled = value + if (services.privateBrowsing.privateBrowsingEnabled != value) + services.privateBrowsing.privateBrowsingEnabled = value }, persist: false }); diff --git a/common/modules/services.jsm b/common/modules/services.jsm index cb534236..844c2dd9 100644 --- a/common/modules/services.jsm +++ b/common/modules/services.jsm @@ -56,16 +56,16 @@ const Services = Module("Services", { this.add("windowMediator", "@mozilla.org/appshell/window-mediator;1", Ci.nsIWindowMediator); this.add("windowWatcher", "@mozilla.org/embedcomp/window-watcher;1", Ci.nsIWindowWatcher); - this.addClass("file", "@mozilla.org/file/local;1", Ci.nsILocalFile); - this.addClass("file:", "@mozilla.org/network/protocol;1?name=file", Ci.nsIFileProtocolHandler); - this.addClass("find", "@mozilla.org/embedcomp/rangefind;1", Ci.nsIFind); - this.addClass("htmlConverter","@mozilla.org/widget/htmlformatconverter;1", Ci.nsIFormatConverter); - this.addClass("htmlEncoder", "@mozilla.org/layout/htmlCopyEncoder;1", Ci.nsIDocumentEncoder); - this.addClass("process", "@mozilla.org/process/util;1", Ci.nsIProcess); - this.addClass("string", "@mozilla.org/supports-string;1", Ci.nsISupportsString); - this.addClass("timer", "@mozilla.org/timer;1", Ci.nsITimer); - this.addClass("xmlhttp", "@mozilla.org/xmlextras/xmlhttprequest;1", Ci.nsIXMLHttpRequest); - this.addClass("zipWriter", "@mozilla.org/zipwriter;1", Ci.nsIZipWriter); + this.addClass("File", "@mozilla.org/file/local;1", Ci.nsILocalFile); + this.addClass("File:", "@mozilla.org/network/protocol;1?name=file", Ci.nsIFileProtocolHandler); + this.addClass("Find", "@mozilla.org/embedcomp/rangefind;1", Ci.nsIFind); + this.addClass("HtmlConverter","@mozilla.org/widget/htmlformatconverter;1", Ci.nsIFormatConverter); + this.addClass("HtmlEncoder", "@mozilla.org/layout/htmlCopyEncoder;1", Ci.nsIDocumentEncoder); + this.addClass("Process", "@mozilla.org/process/util;1", Ci.nsIProcess); + this.addClass("String", "@mozilla.org/supports-string;1", Ci.nsISupportsString); + this.addClass("Timer", "@mozilla.org/timer;1", Ci.nsITimer); + this.addClass("Xmlhttp", "@mozilla.org/xmlextras/xmlhttprequest;1", Ci.nsIXMLHttpRequest); + this.addClass("ZipWriter", "@mozilla.org/zipwriter;1", Ci.nsIZipWriter); }, _create: function (classes, ifaces, meth) { @@ -102,7 +102,9 @@ const Services = Module("Services", { */ add: function (name, class_, ifaces, meth) { const self = this; - this.services.__defineGetter__(name, function () { + if (name in this && !this.__lookupGetter__(name) && !(this[name] instanceof Ci.nsISupports)) + throw TypeError(); + this.__defineGetter__(name, function () { delete this[name]; return this[name] = self._create(class_, ifaces, meth); }); @@ -118,7 +120,7 @@ const Services = Module("Services", { */ addClass: function (name, class_, ifaces) { const self = this; - return this.classes[name] = function () self._create(class_, ifaces, "createInstance"); + return this[name] = function () self._create(class_, ifaces, "createInstance"); }, /** @@ -126,14 +128,14 @@ const Services = Module("Services", { * * @param {string} name The class's cache key. */ - create: function (name) this.classes[name](), + create: function (name) this[name[0].toUpperCase() + name.substr(1)], /** * Returns the cached service with the specified name. * * @param {string} name The service's cache key. */ - get: function (name) this.services[name], + get: function (name) this[name], }, { }, { init: function (dactyl, modules) { diff --git a/common/modules/storage.jsm b/common/modules/storage.jsm index 6c55e9f1..9a548508 100644 --- a/common/modules/storage.jsm +++ b/common/modules/storage.jsm @@ -14,7 +14,7 @@ defineModule("storage", { require: ["services", "util"] }); -const win32 = /^win(32|nt)$/i.test(services.get("runtime").OS); +const win32 = /^win(32|nt)$/i.test(services.runtime.OS); function getFile(name) { let file = storage.infoPath.clone(); @@ -27,7 +27,7 @@ function loadData(name, store, type) { if (storage.infoPath) var file = getFile(name).read(); if (file) - var result = services.get("json").decode(file); + var result = services.json.decode(file); if (result instanceof type) return result; } @@ -265,12 +265,12 @@ const Storage = Module("Storage", { */ const File = Class("File", { init: function (path, checkPWD) { - let file = services.create("file"); + let file = services.File(); if (path instanceof Ci.nsIFile) file = path.QueryInterface(Ci.nsIFile); else if (/file:\/\//.test(path)) - file = services.create("file:").getFileFromURLSpec(path); + file = services["File:"]().getFileFromURLSpec(path); else { try { let expandedPath = File.expandPath(path); @@ -484,7 +484,7 @@ const File = Class("File", { */ get PATH_SEP() { delete this.PATH_SEP; - let f = services.get("directory").get("CurProcD", Ci.nsIFile); + let f = services.directory.get("CurProcD", Ci.nsIFile); f.append("foo"); return this.PATH_SEP = f.path.substr(f.parent.path.length, 1); }, @@ -497,6 +497,7 @@ const File = Class("File", { defaultEncoding: "UTF-8", expandPath: function (path, relative) { + function getenv(name) services.environment.get(name); // expand any $ENV vars - this is naive but so is Vim and we like to be compatible // TODO: Vim does not expand variables set to an empty string (and documents it). @@ -505,7 +506,7 @@ const File = Class("File", { function expand(path) path.replace( !win32 ? /\$(\w+)\b|\${(\w+)}/g : /\$(\w+)\b|\${(\w+)}|%(\w+)%/g, - function (m, n1, n2, n3) services.get("environment").get(n1 || n2 || n3) || m + function (m, n1, n2, n3) getenv(n1 || n2 || n3) || m ); path = expand(path); @@ -513,12 +514,12 @@ const File = Class("File", { // Yuck. if (!relative && RegExp("~(?:$|[/" + util.escapeRegexp(File.PATH_SEP) + "])").test(path)) { // Try $HOME first, on all systems - let home = services.get("environment").get("HOME"); + let home = getenv("HOME"); // Windows has its own idiosyncratic $HOME variables. - if (win32 && (!home || !File(home) || !File(home).exists())) - home = services.get("environment").get("USERPROFILE") || - services.get("environment").get("HOMEDRIVE") + services.get("environment").get("HOMEPATH"); + if (win32 && (!home || !File(home).exists())) + home = getenv("USERPROFILE") || + getenv("HOMEDRIVE") + getenv("HOMEPATH"); path = home + path.substr(1); } @@ -533,7 +534,7 @@ const File = Class("File", { isAbsolutePath: function (path) { try { - services.create("file").initWithPath(path); + services.File().initWithPath(path); return true; } catch (e) { diff --git a/common/modules/styles.jsm b/common/modules/styles.jsm index 9c6c499f..af4aaa73 100644 --- a/common/modules/styles.jsm +++ b/common/modules/styles.jsm @@ -11,7 +11,7 @@ defineModule("styles", { use: ["template"] }); -const sss = services.get("stylesheet"); +const sss = services.stylesheet; function cssUri(css) "chrome-data:text/css," + encodeURI(css); const namespace = "@namespace html " + XHTML.uri.quote() + ";\n" + "@namespace xul " + XUL.uri.quote() + ";\n" + @@ -219,7 +219,7 @@ const Styles = Module("Styles", { * already registered. */ registerSheet: function registerSheet(url, agent, reload) { - let uri = services.get("io").newURI(url, null, null); + let uri = services.io.newURI(url, null, null); if (reload) this.unregisterSheet(url, agent); if (reload || !sss.sheetRegistered(uri, agent ? sss.AGENT_SHEET : sss.USER_SHEET)) @@ -233,7 +233,7 @@ const Styles = Module("Styles", { * @param {boolean} agent If true, sheet is registered as an agent sheet. */ unregisterSheet: function unregisterSheet(url, agent) { - let uri = services.get("io").newURI(url, null, null); + let uri = services.io.newURI(url, null, null); if (sss.sheetRegistered(uri, agent ? sss.AGENT_SHEET : sss.USER_SHEET)) sss.unregisterSheet(uri, agent ? sss.AGENT_SHEET : sss.USER_SHEET); }, diff --git a/common/modules/util.jsm b/common/modules/util.jsm index 1ad9cd50..9c208074 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -1,5 +1,5 @@ // Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org> -// Copyright (c) 2007-2009 by Doug Kearns <dougkearns@gmail.com> +// Copyright (c) 2007-2010 by Doug Kearns <dougkearns@gmail.com> // Copyright (c) 2008-2010 by Kris Maglione <maglione.k@gmail.com> // // This work is licensed for reuse under an MIT license. Details are @@ -10,7 +10,7 @@ try { Components.utils.import("resource://dactyl/base.jsm"); defineModule("util", { - exports: ["FailedAssertion", "Math", "NS", "Prefs", "Util", "XHTML", "XUL", "prefs", "util"], + exports: ["FailedAssertion", "Math", "NS", "Util", "XHTML", "XUL", "util"], require: ["services"], use: ["highlight", "template"] }); @@ -46,7 +46,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) }, // FIXME: Only works for Pentadactyl - get activeWindow() services.get("windowMediator").getMostRecentWindow("navigator:browser"), + get activeWindow() services.windowMediator.getMostRecentWindow("navigator:browser"), dactyl: { __noSuchMethod__: function (meth, args) { let win = util.activeWindow; @@ -69,9 +69,9 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) addObserver: function (obj) { let observers = obj.observe; function register(meth) { - services.get("observer")[meth](obj, "quit-application", true); + services.observer[meth](obj, "quit-application", true); for (let target in keys(observers)) - services.get("observer")[meth](obj, target, true); + services.observer[meth](obj, target, true); } Class.replaceProperty(obj, "observe", function (subject, target, data) { @@ -155,7 +155,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) */ createURI: function createURI(str) { try { - return services.get("urifixup").createFixupURI(str, services.get("urifixup").FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP); + return services.urifixup.createFixupURI(str, services.urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP); } catch (e) { return null; @@ -225,20 +225,20 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) } let doc = (node.getRangeAt ? node.getRangeAt(0) : node).startContainer.ownerDocument; - let encoder = services.create("htmlEncoder"); + let encoder = services.HtmlEncoder(); encoder.init(doc, "text/unicode", encoder.OutputRaw|encoder.OutputPreformatted); if (node instanceof Ci.nsISelection) encoder.setSelection(node); else if (node instanceof Ci.nsIDOMRange) encoder.setRange(node); - let str = services.create("string"); + let str = services.String(); str.data = encoder.encodeToString(); if (html) return str.data; let [result, length] = [{}, {}]; - services.create("htmlConverter").convert("text/html", str, str.data.length*2, "text/unicode", result, length); + services.HtmlConverter().convert("text/html", str, str.data.length*2, "text/unicode", result, length); return result.value.QueryInterface(Ci.nsISupportsString).data; }, @@ -424,7 +424,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) * * @param {string} ver The required version. */ - haveGecko: function (ver) services.get("versionCompare").compare(services.get("runtime").platformVersion, ver) >= 0, + haveGecko: function (ver) services.versionCompare.compare(services.runtime.platformVersion, ver) >= 0, /** * Sends a synchronous or asynchronous HTTP request to *url* and returns @@ -438,7 +438,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) */ httpGet: function httpGet(url, callback) { try { - let xmlhttp = services.create("xmlhttp"); + let xmlhttp = services.Xmlhttp(); xmlhttp.mozBackgroundRequest = true; if (callback) xmlhttp.onreadystatechange = function () { @@ -490,7 +490,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) /** Dactyl's notion of the current operating system platform. */ OS: { - _arch: services.get("runtime").OS, + _arch: services.runtime.OS, /** * @property {string} The normalised name of the OS. This is one of * "Windows", "Mac OS X" or "Unix". @@ -564,7 +564,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) * @returns {nsIURI} */ // FIXME: createURI needed too? - newURI: function (uri, charset, base) services.get("io").newURI(uri, charset, base), + newURI: function (uri, charset, base) services.io.newURI(uri, charset, base), /** * Pretty print a JavaScript object. Use HTML markup to color certain items @@ -873,7 +873,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) let base = host.replace(/.*\.(.+?\..+?)$/, "$1"); try { - base = services.get("tld").getBaseDomainFromHost(host); + base = services.tld.getBaseDomainFromHost(host); } catch (e) {} @@ -915,7 +915,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) * @param {number} delay The time period for which to sleep in milliseconds. */ sleep: function (delay) { - let mainThread = services.get("threading").mainThread; + let mainThread = services.threading.mainThread; let end = Date.now() + delay; while (Date.now() < end) @@ -994,7 +994,7 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) }, threadYield: function (flush, interruptable) { - let mainThread = services.get("threading").mainThread; + let mainThread = services.threading.mainThread; /* FIXME */ util.interrupted = false; do { @@ -1067,332 +1067,6 @@ const Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) Array: array }); -const Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), { - SAVED: "extensions.dactyl.saved.", - RESTORE: "extensions.dactyl.restore.", - - - init: function () { - this._prefContexts = []; - - util.addObserver(this); - this._branch = services.get("pref").getBranch("").QueryInterface(Ci.nsIPrefBranch2); - this._branch.addObserver("", this, false); - this._observers = {}; - - this.restore(); - }, - - observe: { - "nsPref:changed": function (subject, data) { - let observers = this._observers[data]; - if (observers) { - let value = this.get(data, false); - this._observers[data] = observers.filter(function (callback) { - if (!callback.get()) - return false; - util.trapErrors(callback.get(), null, value); - return true; - }); - } - } - }, - - /** - * Adds a new preference observer for the given preference. - * - * @param {string} pref The preference to observe. - * @param {function(object)} callback The callback, called with the - * new value of the preference whenever it changes. - */ - watch: function (pref, callback, strong) { - if (!this._observers[pref]) - this._observers[pref] = []; - this._observers[pref].push(!strong ? Cu.getWeakReference(callback) : { get: function () callback }); - }, - - /** - * Lists all preferences matching *filter* or only those with changed - * values if *onlyNonDefault* is specified. - * - * @param {boolean} onlyNonDefault Limit the list to prefs with a - * non-default value. - * @param {string} filter The list filter. A null filter lists all - * prefs. - * @optional - */ - list: function list(onlyNonDefault, filter) { - if (!filter) - filter = ""; - - let prefArray = this.getNames(); - prefArray.sort(); - function prefs() { - for (let [, pref] in Iterator(prefArray)) { - let userValue = services.get("pref").prefHasUserValue(pref); - if (onlyNonDefault && !userValue || pref.indexOf(filter) == -1) - continue; - - let value = this.get(pref); - - let option = { - isDefault: !userValue, - default: this._load(pref, null, true), - value: <>={template.highlight(value, true, 100)}</>, - name: pref, - pre: "\u00a0\u00a0" // Unicode nonbreaking space. - }; - - yield option; - } - }; - - return template.options(services.get("dactyl:").host + " Preferences", prefs.call(this)); - }, - - /** - * Returns the value of a preference. - * - * @param {string} name The preference name. - * @param {value} defaultValue The value to return if the preference - * is unset. - */ - get: function (name, defaultValue) this._load(name, defaultValue), - - /** - * Returns the default value of a preference - * - * @param {string} name The preference name. - * @param {value} defaultValue The value to return if the preference - * has no default value. - */ - getDefault: function (name, defaultValue) this._load(name, defaultValue, true), - - /** - * Returns the names of all preferences. - * - * @param {string} branch The branch in which to search preferences. - * @default "" - */ - getNames: function (branch) services.get("pref").getChildList(branch || "", { value: 0 }), - - _checkSafe: function (name, message, value) { - let curval = this._load(name, null, false); - if (arguments.length > 2 && curval === value) - return; - let defval = this._load(name, null, true); - let saved = this._load(this.SAVED + name); - - if (saved == null && curval != defval || curval != saved) { - let msg = "Warning: setting preference " + name + ", but it's changed from its default value."; - if (message) - msg += " " + message; - util.dactyl.echomsg(msg); - } - }, - - /** - * Resets the preference *name* to *value* but warns the user if the value - * is changed from its default. - * - * @param {string} name The preference name. - * @param {value} value The new preference value. - */ - safeReset: function (name, message) { - this._checkSafe(name, message); - this.reset(name); - this.reset(this.SAVED + name); - }, - - /** - * Sets the preference *name* to *value* but warns the user if the value is - * changed from its default. - * - * @param {string} name The preference name. - * @param {value} value The new preference value. - */ - safeSet: function (name, value, message, skipSave) { - this._checkSafe(name, message, value); - this._store(name, value); - this[skipSave ? "reset" : "_store"](this.SAVED + name, value); - }, - - /** - * Sets the preference *name* to *value*. - * - * @param {string} name The preference name. - * @param {value} value The new preference value. - */ - set: function (name, value) { - this._store(name, value); - }, - - /** - * Saves the current value of a preference to be restored at next - * startup. - * - * @param {string} name The preference to save. - */ - save: function (name) { - let val = this.get(name); - this.set(this.RESTORE + name, val); - this.safeSet(name, val); - }, - - /** - * Restores saved preferences in the given branch. - * - * @param {string} branch The branch from which to restore - * preferences. @optional - */ - restore: function (branch) { - this.getNames(this.RESTORE + (branch || "")).forEach(function (pref) { - this.safeSet(pref.substr(this.RESTORE.length), this.get(pref), null, true) - this.reset(pref); - }, this); - }, - - /** - * Resets the preference *name* to its default value. - * - * @param {string} name The preference name. - */ - reset: function (name) { - try { - services.get("pref").clearUserPref(name); - } - catch (e) {} // ignore - thrown if not a user set value - }, - - /** - * Toggles the value of the boolean preference *name*. - * - * @param {string} name The preference name. - */ - toggle: function (name) { - util.assert(services.get("pref").getPrefType(name) === Ci.nsIPrefBranch.PREF_BOOL, - "E488: Trailing characters: " + name + "!"); - this.set(name, !this.get(name)); - }, - - /** - * Pushes a new preference context onto the context stack. - * - * @see #withContext - */ - pushContext: function () { - this._prefContexts.push({}); - }, - - /** - * Pops the top preference context from the stack. - * - * @see #withContext - */ - popContext: function () { - for (let [k, v] in Iterator(this._prefContexts.pop())) - this._store(k, v); - }, - - /** - * Executes *func* with a new preference context. When *func* returns, the - * context is popped and any preferences set via {@link #setPref} or - * {@link #invertPref} are restored to their previous values. - * - * @param {function} func The function to call. - * @param {Object} func The 'this' object with which to call *func* - * @see #pushContext - * @see #popContext - */ - withContext: function (func, self) { - try { - this.pushContext(); - return func.call(self); - } - finally { - this.popContext(); - } - }, - - _store: function (name, value) { - if (this._prefContexts.length) { - let val = this._load(name, null); - if (val != null) - this._prefContexts[this._prefContexts.length - 1][name] = val; - } - - function assertType(needType) - util.assert(type === Ci.nsIPrefBranch.PREF_INVALID || type === needType, - type === Ci.nsIPrefBranch.PREF_INT - ? "E521: Number required after =: " + name + "=" + value - : "E474: Invalid argument: " + name + "=" + value); - - let type = services.get("pref").getPrefType(name); - switch (typeof value) { - case "string": - assertType(Ci.nsIPrefBranch.PREF_STRING); - - let supportString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); - supportString.data = value; - services.get("pref").setComplexValue(name, Ci.nsISupportsString, supportString); - break; - case "number": - assertType(Ci.nsIPrefBranch.PREF_INT); - - services.get("pref").setIntPref(name, value); - break; - case "boolean": - assertType(Ci.nsIPrefBranch.PREF_BOOL); - - services.get("pref").setBoolPref(name, value); - break; - default: - throw FailedAssertion("Unknown preference type: " + typeof value + " (" + name + "=" + value + ")"); - } - }, - - _load: function (name, defaultValue, defaultBranch) { - if (defaultValue == null) - defaultValue = null; - - let branch = defaultBranch ? services.get("pref").getDefaultBranch("") : services.get("pref"); - let type = services.get("pref").getPrefType(name); - try { - switch (type) { - case Ci.nsIPrefBranch.PREF_STRING: - let value = branch.getComplexValue(name, Ci.nsISupportsString).data; - // try in case it's a localized string (will throw an exception if not) - if (!services.get("pref").prefIsLocked(name) && !services.get("pref").prefHasUserValue(name) && - RegExp("chrome://.+/locale/.+\\.properties").test(value)) - value = branch.getComplexValue(name, Ci.nsIPrefLocalizedString).data; - return value; - case Ci.nsIPrefBranch.PREF_INT: - return branch.getIntPref(name); - case Ci.nsIPrefBranch.PREF_BOOL: - return branch.getBoolPref(name); - default: - return defaultValue; - } - } - catch (e) { - return defaultValue; - } - } -}, { -}, { - completion: function (dactyl, modules) { - modules.completion.preference = function preference(context) { - context.anchored = false; - context.title = [services.get("dactyl:").host + " Preference", "Value"]; - context.keys = { text: function (item) item, description: function (item) prefs.get(item) }; - context.completions = prefs.getNames(); - }; - }, - javascript: function (dactyl, modules) { - modules.JavaScript.setCompleter([this.get, this.safeSet, this.set, this.reset, this.toggle], - [function (context) (context.anchored=false, prefs.getNames().map(function (pref) [pref, ""]))]); - } -}); /** * Math utility methods. |