commit 7c4d4c620ab5ef3f84725e674d0e9f98fa38e0d0 Author: Kathy Brade brade@pearlcrescent.com Date: Fri Sep 13 15:01:48 2013 -0400
Show "Tor unexpectedly exited" message inside Network Settings dialog.
Detect when the tor process exits, display an informative message along with a Restart button inside the Tor Network Settings dialog/wizard. --- src/chrome/content/network-settings-wizard.xul | 8 ++- src/chrome/content/network-settings.js | 81 +++++++++++++++++++----- src/chrome/content/network-settings.xul | 8 ++- src/chrome/locale/en/network-settings.dtd | 1 + src/chrome/locale/en/torlauncher.properties | 1 + src/chrome/skin/network-settings.css | 8 ++- src/components/tl-process.js | 28 ++++++-- 7 files changed, 110 insertions(+), 25 deletions(-)
diff --git a/src/chrome/content/network-settings-wizard.xul b/src/chrome/content/network-settings-wizard.xul index ed822f7..0002af4 100644 --- a/src/chrome/content/network-settings-wizard.xul +++ b/src/chrome/content/network-settings-wizard.xul @@ -129,7 +129,13 @@ <spring flex="1" /> <hbox> <spring flex="1" /> - <label value="&torsettings.startingTor;"/> + <description id="startingTorMessage">&torsettings.startingTor;</description> + <spring flex="1" /> + </hbox> + <hbox> + <spring flex="1" /> + <button id="restartButton" label="&torsettings.restart;" hidden="true" + oncommand="onRestartApp()" /> <spring flex="1" /> </hbox> <spring flex="1" /> diff --git a/src/chrome/content/network-settings.js b/src/chrome/content/network-settings.js index 573393d..27b6f58 100644 --- a/src/chrome/content/network-settings.js +++ b/src/chrome/content/network-settings.js @@ -144,19 +144,14 @@ function initDialog()
gObsService.addObserver(gObserver, kTorBootstrapErrorTopic, false); gObsService.addObserver(gObserver, kTorLogHasWarnOrErrTopic, false); + gObsService.addObserver(gObserver, kTorProcessExitedTopic, false);
+ var status = gTorProcessService.TorProcessStatus; if (TorLauncherUtil.shouldStartAndOwnTor && - !gTorProcessService.TorIsProcessReady) + (status != gTorProcessService.kStatusRunning)) { - showPanel("startingTor"); - if (haveWizard) - { - showOrHideButton("back", false, false); - showOrHideButton("next", false, false); - } - + showStartingTorPanel(status == gTorProcessService.kStatusExited); gObsService.addObserver(gObserver, kTorProcessReadyTopic, false); - gObsService.addObserver(gObserver, kTorProcessExitedTopic, false); gObsService.addObserver(gObserver, kTorProcessDidNotStartTopic, false); } else @@ -223,13 +218,9 @@ var gObserver = { return; }
- // Process events that only occur once. - gObsService.removeObserver(gObserver, kTorProcessReadyTopic); - gObsService.removeObserver(gObserver, kTorProcessExitedTopic); - gObsService.removeObserver(gObserver, kTorProcessDidNotStartTopic); - if (kTorProcessReadyTopic == aTopic) { + gObsService.removeObserver(gObserver, kTorProcessReadyTopic); var haveWizard = (getWizard() != null); showPanel(haveWizard ? "first" : "settings"); if (haveWizard) @@ -240,9 +231,15 @@ var gObserver = { readTorSettings(); } else if (kTorProcessDidNotStartTopic == aTopic) + { + gObsService.removeObserver(gObserver, kTorProcessDidNotStartTopic); showErrorPanel(); - else // kTorProcessExitedTopic - close(); + } + else if (kTorProcessExitedTopic == aTopic) + { + gObsService.removeObserver(gObserver, kTorProcessExitedTopic); + showStartingTorPanel(true); + } } };
@@ -295,6 +292,33 @@ function showPanel(aPanelID) }
+function showStartingTorPanel(aTorExited) +{ + if (aTorExited) + { + // Show "Tor exited; please restart" message and Restart button. + var elem = document.getElementById("startingTorMessage"); + if (elem) + { + var s1 = TorLauncherUtil.getLocalizedString("tor_exited"); + var s2 = TorLauncherUtil.getLocalizedString("please_restart_app"); + elem.textContent = s1 + "\n\n" + s2; + } + var btn = document.getElementById("restartButton"); + if (btn) + btn.removeAttribute("hidden"); + } + + showPanel("startingTor"); + var haveWizard = (getWizard() != null); + if (haveWizard) + { + showOrHideButton("back", false, false); + showOrHideButton("next", false, false); + } +} + + function showErrorPanel() { showPanel("errorPanel"); @@ -425,6 +449,31 @@ function onProxyTypeChange() }
+function onRestartApp() +{ + if (gIsInitialBootstrap) + { + // If the browser has not fully started yet, we cannot use the app startup + // service to restart it... so we use a delayed approach. + try + { + var obsSvc = Cc["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService); + obsSvc.notifyObservers(null, "TorUserRequestedQuit", "restart"); + + window.close(); + } catch (e) {} + } + else + { + // Restart now. + var asSvc = Cc["@mozilla.org/toolkit/app-startup;1"] + .getService(Ci.nsIAppStartup); + asSvc.quit(asSvc.eAttemptQuit | asSvc.eRestart); + } +} + + function onCancel() { if (gRestoreAfterHelpPanelID) // Is help open? diff --git a/src/chrome/content/network-settings.xul b/src/chrome/content/network-settings.xul index f50e4f6..ae4eb8d 100644 --- a/src/chrome/content/network-settings.xul +++ b/src/chrome/content/network-settings.xul @@ -57,7 +57,13 @@ <spring flex="1" /> <hbox> <spring flex="1" /> - <label value="&torsettings.startingTor;"/> + <description id="startingTorMessage">&torsettings.startingTor;</description> + <spring flex="1" /> + </hbox> + <hbox> + <spring flex="1" /> + <button id="restartButton" label="&torsettings.restart;" hidden="true" + oncommand="onRestartApp()" /> <spring flex="1" /> </hbox> <spring flex="1" /> diff --git a/src/chrome/locale/en/network-settings.dtd b/src/chrome/locale/en/network-settings.dtd index b9fedc3..3017865 100644 --- a/src/chrome/locale/en/network-settings.dtd +++ b/src/chrome/locale/en/network-settings.dtd @@ -27,6 +27,7 @@ <!-- Other: -->
<!ENTITY torsettings.startingTor "Waiting for Tor to start…"> +<!ENTITY torsettings.restart "Restart">
<!ENTITY torsettings.optional "Optional">
diff --git a/src/chrome/locale/en/torlauncher.properties b/src/chrome/locale/en/torlauncher.properties index 5ed593a..483ce43 100644 --- a/src/chrome/locale/en/torlauncher.properties +++ b/src/chrome/locale/en/torlauncher.properties @@ -4,6 +4,7 @@ torlauncher.error_title=Tor Launcher
torlauncher.tor_exited=Tor unexpectedly exited. +torlauncher.please_restart_app=Please restart this application. torlauncher.tor_controlconn_failed=Could not connect to Tor control port. torlauncher.tor_failed_to_start=Tor failed to start. torlauncher.tor_bootstrap_failed=Tor failed to establish a Tor network connection.\n\n%S diff --git a/src/chrome/skin/network-settings.css b/src/chrome/skin/network-settings.css index 1d92151..7ab28c1 100644 --- a/src/chrome/skin/network-settings.css +++ b/src/chrome/skin/network-settings.css @@ -95,9 +95,15 @@ button.firstAnswer { min-height: 300px; }
-#startingTor label { +wizardpage[pageid="startingTor"] description, +#startingTor description { font-size: 120%; font-weight: bold; + white-space: pre-wrap; +} + +#restartButton { + margin-top: 20px; }
dialog .help { diff --git a/src/components/tl-process.js b/src/components/tl-process.js index 17c4012..c4f977c 100644 --- a/src/components/tl-process.js +++ b/src/components/tl-process.js @@ -36,6 +36,11 @@ TorProcessService.prototype = kMaxControlConnRetryMS: 500, kControlConnTimeoutMS: 30000, // Wait at most 30 seconds for tor to start.
+ kStatusUnknown: 0, // Tor process status. + kStatusStarting: 1, + kStatusRunning: 2, + kStatusExited: 3, // Exited or failed to start. + // nsISupports implementation. QueryInterface: function(aIID) { @@ -114,6 +119,7 @@ TorProcessService.prototype = }
this.mTorProcess = null; + this.mTorProcessStatus = this.kStatusExited;
this.mObsSvc.notifyObservers(null, "TorProcessExited", null);
@@ -132,7 +138,7 @@ TorProcessService.prototype = if (haveConnection) { this.mControlConnTimer = null; - this.mIsTorProcessReady = true; + this.mTorProcessStatus = this.kStatusRunning; this.mProtocolSvc.TorStartEventMonitor();
this.mProtocolSvc.TorRetrieveBootstrapStatus(); @@ -164,7 +170,10 @@ TorProcessService.prototype = else if (kOpenNetworkSettingsTopic == aTopic) this._openNetworkSettings(false); else if (kUserQuitTopic == aTopic) + { this.mQuitSoon = true; + this.mRestartWithQuit = ("restart" == aParam); + } },
canUnload: function(aCompMgr) { return true; }, @@ -201,9 +210,9 @@ TorProcessService.prototype =
// Public Properties and Methods /////////////////////////////////////////// - get TorIsProcessReady() + get TorProcessStatus() { - return (this.mTorProcess) ? this.mIsTorProcessReady : false; + return this.mTorProcessStatus; },
get TorIsBootstrapDone() @@ -225,7 +234,7 @@ TorProcessService.prototype =
// Private Member Variables //////////////////////////////////////////////// - mIsTorProcessReady: false, + mTorProcessStatus: 0, // kStatusUnknown mIsBootstrapDone: false, mBootstrapErrorOccurred: false, mIsQuitting: false, @@ -237,6 +246,7 @@ TorProcessService.prototype = mControlConnTimer: null, mControlConnDelayMS: 0, mQuitSoon: false, // Quit was requested by the user; do so soon. + mRestartWithQuit: false, mLastTorWarningPhase: null, mLastTorWarningText: null,
@@ -244,7 +254,7 @@ TorProcessService.prototype = // Private Methods ///////////////////////////////////////////////////////// _startTor: function() { - this.mIsTorProcessReady = false; + this.mTorProcessStatus = this.kStatusUnknown;
var isInitialBootstrap = TorLauncherUtil.getBoolPref(this.kPrefPromptAtStartup); @@ -300,6 +310,8 @@ TorProcessService.prototype = args.push("1"); }
+ this.mTorProcessStatus = this.kStatusStarting; + var p = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); p.init(exeFile);
@@ -335,7 +347,10 @@ TorProcessService.prototype =
var asSvc = Cc["@mozilla.org/toolkit/app-startup;1"] .getService(Ci.nsIAppStartup); - asSvc.quit(asSvc.eAttemptQuit); + var flags = asSvc.eAttemptQuit; + if (this.mRestartWithQuit) + flags |= asSvc.eRestart; + asSvc.quit(flags); } catch (e) { @@ -344,6 +359,7 @@ TorProcessService.prototype = } catch (e) { + this.mTorProcessStatus = this.kStatusExited; var s = TorLauncherUtil.getLocalizedString("tor_failed_to_start"); TorLauncherUtil.showAlert(null, s); TorLauncherLogger.safelog(4, "_startTor error: ", e);
tor-commits@lists.torproject.org