commit 949379555010a04633c64b08ed52896a86c2cce6
Author: Matthew Finkel <Matthew.Finkel(a)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)