commit 949379555010a04633c64b08ed52896a86c2cce6 Author: Matthew Finkel Matthew.Finkel@gmail.com Date: Fri May 4 14:26:32 2018 +0000
Load default prefs during initialization
In bug 1413413 Mozilla ripped out support for loading default prefs from extensions. Unfortunately, backing out that changeset is non-trivial so it is easier if we set the default prefs manually.
Here we define a function named pref() and it sets the preference based on the type of the pref's value. We only support a few types: boolean, number, and string. All other types are handled by the default case where a message is logged and the pref is skipped. The default prefs must be set before Tor Launcher begins making decisions based on them. An exception is thrown with Cr.NS_ERROR_NOT_INITIALIZED when this requirement is violated. --- src/components/tl-process.js | 23 ++++++++- src/modules/tl-util.jsm | 108 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-)
diff --git a/src/components/tl-process.js b/src/components/tl-process.js index 8d3efb7..1c67817 100644 --- a/src/components/tl-process.js +++ b/src/components/tl-process.js @@ -19,6 +19,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "TorLauncherLogger",
function TorProcessService() { + this.mDefaultPreferencesAreLoaded = TorLauncherUtil.loadDefaultPreferences(); + if (!this.mDefaultPreferencesAreLoaded) + { + throw Components.Exception("Setting (some) default preferences failed!", + Cr.NS_ERROR_NOT_INITIALIZED); + } + this.wrappedJSObject = this; this.mProtocolSvc = Cc["@torproject.org/torlauncher-protocol-service;1"] .getService(Ci.nsISupports).wrappedJSObject; @@ -98,6 +105,13 @@ TorProcessService.prototype = this.mObsSvc.addObserver(this, kUserQuitTopic, false); this.mObsSvc.addObserver(this, kBootstrapStatusTopic, false);
+ if (!this.mDefaultPreferencesAreLoaded) + { + throw Components.Exception("Default preferences not loaded at " + + "profile-after-change notification!", + Cr.NS_ERROR_NOT_INITIALIZED); + } + if (TorLauncherUtil.shouldOnlyConfigureTor) { this._controlTor(true, false); @@ -304,6 +318,13 @@ TorProcessService.prototype =
TorStartAndControlTor: function(aForceDisableNetwork) { + if (!this.mDefaultPreferencesAreLoaded) + { + throw Components.Exception("TorLauncher is starting Tor but " + + "the default preferences were not set!", + Cr.NS_ERROR_NOT_INITIALIZED); + } + this._startTor(aForceDisableNetwork); let isRunningTor = (this.mTorProcessStatus == this.kStatusStarting) || (this.mTorProcessStatus == this.kStatusRunning); @@ -333,7 +354,7 @@ TorProcessService.prototype = mQuitSoon: false, // Quit was requested by the user; do so soon. mLastTorWarningPhase: null, mLastTorWarningReason: null, - + mDefaultPreferencesAreLoaded: false,
// Private Methods ///////////////////////////////////////////////////////// _startTor: function(aForceDisableNetwork) diff --git a/src/modules/tl-util.jsm b/src/modules/tl-util.jsm index d669112..292f88b 100644 --- a/src/modules/tl-util.jsm +++ b/src/modules/tl-util.jsm @@ -226,6 +226,11 @@ let TorLauncherUtil = // Public },
// Preferences + loadDefaultPreferences: function() + { + return TLUtilInternal._loadPreferences(); + }, + getBoolPref: function(aPrefName, aDefaultVal) { var rv = (undefined != aDefaultVal) ? aDefaultVal : false; @@ -749,6 +754,9 @@ let TLUtilInternal = // Private mAppDir: null, // nsIFile (cached; access via this._appDir) mDataDir: null, // nsIFile (cached; access via this._dataDir) mIsFirstIPCPathRequest : true, + mNumDefaultPrefsDefined: 0, + mNumDefaultPrefsLoaded: 0, + mDefaultPreferencesLoaded: false,
_init: function() { @@ -756,6 +764,106 @@ let TLUtilInternal = // Private .getService(Ci.nsIPrefBranch); },
+ _getPrefDefaultBranch: function(aBranchName) + { + return Cc["@mozilla.org/preferences-service;1"] + .getService(Ci.nsIPrefService) + .getDefaultBranch(aBranchName); + }, + + _setPref: function(aSetPrefFunc, aPrefName, aValue) + { + try + { + aSetPrefFunc(aPrefName, aValue); + } + catch(e) + { + TorLauncherLogger.log(5, "Setting default pref '" + aPrefName + + "' threw exception: " + e); + return false; + } + + return true; + }, + + pref: function (aPrefName, aValue) + { + // Increment this counter for each pref() call. + this.mNumDefaultPrefsDefined += 1; + + let lastPeriod = aPrefName.lastIndexOf("."); + // This pref doesn't contain a period (".") + // or the period is the first character. + if (lastPeriod == 0 || lastPeriod == -1) + { + TorLauncherLogger.log(5, "Ignoring invalid pref '" + aPrefName + "'"); + return; + } + // This pref has a period at the last character, we can't set + // a default value on a pref root. + if (aPrefName.length == (lastPeriod + 1)) + { + TorLauncherLogger.log(5, + "Ignoring invalid pref ending with a period: '" + aPrefName + "'"); + return; + } + + let prefRoot = aPrefName.substring(0, lastPeriod + 1); + let defaultBranch = this._getPrefDefaultBranch(prefRoot); + let prefName = aPrefName.substring(lastPeriod + 1); + let setPrefFunc; + switch (typeof aValue) + { + case "boolean": + setPrefFunc = defaultBranch.setBoolPref; + if (!this._setPref(setPrefFunc, prefName, aValue)) + { + return; + } + break; + case "number": + setPrefFunc = defaultBranch.setIntPref; + if (!this._setPref(setPrefFunc, prefName, aValue)) + { + return; + } + break; + case "string": + setPrefFunc = defaultBranch.setCharPref; + if (!this._setPref(setPrefFunc, prefName, aValue)) + { + return; + } + break; + default: + TorLauncherLogger.log(5, "Cowardly not setting pref '" + + aPrefName + "' of type '" + (typeof aValue) + "'"); + return; + } + + // Increment this counter for each pref() call where the default preference + // was successfully set. + this.mNumDefaultPrefsLoaded += 1; + }, + + _loadPreferences: function() + { + if (this.mDefaultPreferencesLoaded) + { + return this.mDefaultPreferencesLoaded; + } + + var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader); + loader.loadSubScript( + "resource://torlauncher/defaults/preferences/prefs.js", this); + + this.mDefaultPreferencesLoaded = + (this.mNumDefaultPrefsDefined == this.mNumDefaultPrefsLoaded); + return this.mDefaultPreferencesLoaded; + }, + get _stringBundle() { if (!this.mStringBundle)