[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [vidalia/alpha] Adds the helperprocess part
commit 25950fa9ceeb6ce44924fb607b54691601adb66c
Author: Tomas Touceda <chiiph@xxxxxxxxxx>
Date: Fri Apr 8 20:26:20 2011 -0300
Adds the helperprocess part
---
src/vidalia/CMakeLists.txt | 2 +
src/vidalia/MainWindow.cpp | 236 ++++++++++++++++++++++++++++++++++++++++++++
src/vidalia/MainWindow.h | 27 +++++
3 files changed, 265 insertions(+), 0 deletions(-)
diff --git a/src/vidalia/CMakeLists.txt b/src/vidalia/CMakeLists.txt
index c9803e9..22a869f 100644
--- a/src/vidalia/CMakeLists.txt
+++ b/src/vidalia/CMakeLists.txt
@@ -163,6 +163,7 @@ set(vidalia_SRCS ${vidalia_SRCS}
ControlPasswordInputDialog.cpp
VidaliaTab.cpp
StatusTab.cpp
+ HelperProcess.cpp
)
qt4_wrap_cpp(vidalia_SRCS
Vidalia.h
@@ -173,6 +174,7 @@ qt4_wrap_cpp(vidalia_SRCS
ControlPasswordInputDialog.h
VidaliaTab.h
StatusTab.h
+ HelperProcess.h
)
if (USE_MINIUPNPC)
diff --git a/src/vidalia/MainWindow.cpp b/src/vidalia/MainWindow.cpp
index ac048e5..d61b5e8 100644
--- a/src/vidalia/MainWindow.cpp
+++ b/src/vidalia/MainWindow.cpp
@@ -383,6 +383,24 @@ MainWindow::createConnections()
connect(UPNPControl::instance(), SIGNAL(error(UPNPControl::UPNPError)),
this, SLOT(upnpError(UPNPControl::UPNPError)));
#endif
+ /* Create a new HelperProcess object, used to start the web browser */
+ _browserProcess = new HelperProcess(this);
+ connect(_browserProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(onSubprocessFinished(int, QProcess::ExitStatus)));
+ connect(_browserProcess, SIGNAL(startFailed(QString)),
+ this, SLOT(onBrowserFailed(QString)));
+
+ /* Create a new HelperProcess object, used to start the IM client */
+ _imProcess = new HelperProcess(this);
+ connect(_imProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
+ this, SLOT(onSubprocessFinished(int, QProcess::ExitStatus)));
+ connect(_imProcess, SIGNAL(startFailed(QString)),
+ this, SLOT(onIMFailed(QString)));
+
+ /* Create a new HelperProcess object, used to start the proxy server */
+ _proxyProcess = new HelperProcess(this);
+ connect(_proxyProcess, SIGNAL(startFailed(QString)),
+ this, SLOT(onProxyFailed(QString)));
}
/** Called when the application is closing, by selecting "Exit" from the tray
@@ -431,6 +449,10 @@ MainWindow::running()
start();
}
+ /* Start the proxy server, if configured */
+ if (settings.runProxyAtStart())
+ startProxy();
+
#if defined(USE_AUTOUPDATE)
if (settings.isAutoUpdateEnabled()) {
QDateTime lastCheckedAt = settings.lastCheckedForUpdates();
@@ -476,9 +498,33 @@ MainWindow::aboutToQuit()
ServerSettings settings(_torControl);
settings.cleanupPortForwarding();
+ if (_proxyProcess->state() != QProcess::NotRunning) {
+ /* Close the proxy server (Polipo ignores the WM_CLOSE event sent by
+ * terminate() so we have to kill() it) */
+ _proxyProcess->kill();
+ }
+
/* Kill the browser and IM client if using the new launcher */
VidaliaSettings vidalia_settings;
+ if (! vidalia_settings.getBrowserDirectory().isEmpty()) {
+ /* Disconnect the finished signals so that we won't try to exit Vidalia again */
+ QObject::disconnect(_browserProcess, SIGNAL(finished(int, QProcess::ExitStatus)), 0, 0);
+ QObject::disconnect(_imProcess, SIGNAL(finished(int, QProcess::ExitStatus)), 0, 0);
+
+ /* Use QProcess terminate function */
+ if (_browserProcess->state() == QProcess::Running)
+ _browserProcess->terminate();
+
+#if defined(Q_OS_WIN)
+ /* Kill any processes which might have been forked off */
+ win32_end_process_by_filename(vidalia_settings.getBrowserExecutable());
+#endif
+
+ if (_imProcess->state() == QProcess::Running)
+ _imProcess->terminate();
+ }
+
/* Disconnect all of the TorControl object's signals */
QObject::disconnect(_torControl, 0, 0, 0);
}
@@ -1009,6 +1055,7 @@ MainWindow::circuitEstablished()
// TODO: fix hardcoded total length
setStartupProgress(130,
tr("Connected to the Tor network!"));
+ startSubprocesses();
#if defined(USE_AUTOUPDATE)
VidaliaSettings settings;
@@ -1722,3 +1769,192 @@ MainWindow::installUpdatesFailed(const QString &errmsg)
#endif
+/** Called when browser or IM client have exited */
+void
+MainWindow::onSubprocessFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ Q_UNUSED(exitCode)
+ Q_UNUSED(exitStatus)
+
+ /* Get path to browser and IM client */
+ VidaliaSettings settings;
+ QString browserExecutable = settings.getBrowserExecutable();
+ QString browserDirectory = settings.getBrowserDirectory();
+ QString imExecutable = settings.getIMExecutable();
+
+ /* A subprocess is finished if it successfully exited or was never asked to start */
+ bool browserDone = (browserExecutable.isEmpty()
+ && browserDirectory.isEmpty())
+ || _browserProcess->isDone();
+ bool imDone = imExecutable.isEmpty() || _imProcess->isDone();
+
+ /* Exit if both subprocesses are finished */
+ if (browserDone && imDone) {
+ if (browserDirectory.isEmpty()) {
+ /* We are using the standard launcher, exit immediately */
+ vApp->quit();
+ } else {
+ /* We are using the alternate launcher, wait until the browser has really died */
+ QTimer *browserWatcher = new QTimer(this);
+ connect(browserWatcher, SIGNAL(timeout()), this, SLOT(onCheckForBrowser()));
+ browserWatcher->start(2000);
+ }
+ }
+}
+
+/** Called periodically to check if the browser is running. If it is not,
+ * exit Vidalia cleanly */
+void
+MainWindow::onCheckForBrowser()
+{
+/* This only works on Windows for now */
+#if defined(Q_OS_WIN)
+
+ VidaliaSettings settings;
+ QString browserDirectoryFilename = settings.getBrowserExecutable();
+
+ /* Get list of running processes */
+ QHash<qint64, QString> procList = win32_process_list();
+
+ /* On old versions of Windows win32_process_list() will return
+ an empty list. In this case, just keep Vidalia open */
+ if (procList.isEmpty()) {
+ return;
+ }
+
+ /* Loop over all processes or until we find <browserDirectoryFilename> */
+ QHashIterator<qint64, QString> i(procList);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value().toLower() == browserDirectoryFilename) {
+ /* The browser is still running, so Vidalia should keep running too */
+ return;
+ }
+ }
+
+ /* The browser isn't running, exit Vidalia */
+ vApp->quit();
+#endif
+}
+
+/** Called when the web browser failed to start, for example, because the path
+ * specified to the web browser executable didn't lead to an executable. */
+void
+MainWindow::onBrowserFailed(QString errmsg)
+{
+ Q_UNUSED(errmsg);
+
+ /* Display an error message and see if the user wants some help */
+ VMessageBox::warning(this, tr("Error starting web browser"),
+ tr("Vidalia was unable to start the configured web browser"),
+ VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape);
+}
+
+/** Called when the IM client failed to start, for example, because the path
+ * specified to the IM client executable didn't lead to an executable. */
+void
+MainWindow::onIMFailed(QString errmsg)
+{
+ Q_UNUSED(errmsg);
+
+ /* Display an error message and see if the user wants some help */
+ VMessageBox::warning(this, tr("Error starting IM client"),
+ tr("Vidalia was unable to start the configured IM client"),
+ VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape);
+}
+
+/** Starts the proxy server, if appropriately configured */
+void
+MainWindow::startProxy()
+{
+ VidaliaSettings settings;
+ QString executable = settings.getProxyExecutable();
+ _proxyProcess->start(executable, settings.getProxyExecutableArguments());
+}
+
+/** Called when the proxy server fails to start, for example, because
+ * the path specified didn't lead to an executable. */
+void
+MainWindow::onProxyFailed(QString errmsg)
+{
+ Q_UNUSED(errmsg);
+
+ /* Display an error message and see if the user wants some help */
+ VMessageBox::warning(this, tr("Error starting proxy server"),
+ tr("Vidalia was unable to start the configured proxy server"),
+ VMessageBox::Ok|VMessageBox::Default|VMessageBox::Escape);
+}
+
+/** Start a web browser when given the directory containing the executable and profile */
+void
+MainWindow::launchBrowserFromDirectory()
+{
+ VidaliaSettings settings;
+
+ QString browserDirectory = settings.getBrowserDirectory();
+ QString browserDirectoryFilename = settings.getBrowserExecutable();
+
+ /* Set TZ=UTC (to stop leaking timezone information) and
+ * MOZ_NO_REMOTE=1 (to allow multiple instances of Firefox */
+ QStringList env = QProcess::systemEnvironment();
+ env << "TZ=UTC";
+ env << "MOZ_NO_REMOTE=1";
+ _browserProcess->setEnvironment(env);
+
+ /* The browser is in <browserDirectory>/App/Firefox/<browserDirectoryFilename> */
+ QString browserExecutable =
+ QDir::toNativeSeparators(browserDirectory + "/App/Firefox/" + browserDirectoryFilename);
+ /* The profile is in <browserDirectory>/Data/profile */
+ QString profileDir =
+ QDir::toNativeSeparators(browserDirectory + "/Data/profile");
+
+ /* Copy the profile directory if it's not already there */
+ QDir browserDirObj = QDir(browserDirectory);
+
+ /* Copy the profile directory if it's not already there */
+ if (!browserDirObj.exists("Data/profile")) {
+ browserDirObj.mkdir("Data/profile");
+ copy_dir(browserDirectory + "/App/DefaultData/profile", browserDirectory + "/Data/profile");
+ }
+
+ /* Copy the plugins directory if it's not already there */
+ if (!browserDirObj.exists("Data/plugins")) {
+ browserDirObj.mkdir("Data/plugins");
+ copy_dir(browserDirectory + "/App/DefaultData/plugins", browserDirectory + "/Data/plugins");
+ }
+
+ /* Build the command line arguments */
+ QStringList commandLine;
+ // Is this better or worse than MOZ_NO_REMOTE?
+ //commandLine << "-no-remote";
+ commandLine << "-profile";
+ commandLine << profileDir;
+
+ /* Launch the browser */
+ _browserProcess->start(browserExecutable, commandLine);
+}
+
+/** Starts the web browser and IM client, if appropriately configured */
+void
+MainWindow::startSubprocesses()
+{
+ VidaliaSettings settings;
+ QString subprocess;
+
+ /* Launch the web browser */
+ if (!(subprocess = settings.getBrowserDirectory()).isEmpty()) {
+ /* The user has set BrowserDirectory; use this */
+ launchBrowserFromDirectory();
+ } else if (!(subprocess = settings.getBrowserExecutable()).isEmpty()) {
+ /* BrowserDirectory is not set, but BrowserExecutable is; use this */
+ _browserProcess->setEnvironment(QProcess::systemEnvironment() << "TZ=UTC");
+ _browserProcess->start(subprocess, QStringList());
+ }
+
+ /* Launch the IM client */
+ subprocess = settings.getIMExecutable();
+
+ if (!subprocess.isEmpty())
+ _imProcess->start(subprocess, QStringList());
+}
+
diff --git a/src/vidalia/MainWindow.h b/src/vidalia/MainWindow.h
index 20f5ef1..51722cb 100644
--- a/src/vidalia/MainWindow.h
+++ b/src/vidalia/MainWindow.h
@@ -24,6 +24,7 @@
#include "ConfigDialog.h"
#include "MessageLog.h"
#include "NetViewer.h"
+#include "HelperProcess.h"
#if defined(USE_AUTOUPDATE)
#include "UpdateProcess.h"
#include "UpdateProgressDialog.h"
@@ -138,6 +139,18 @@ private slots:
/** Deletes the tab at index if it exists and it isn't the Status tab */
void delTab(int index = -1);
+ /** Called when the web browser or IM client have stopped */
+ void onSubprocessFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ /** Called periodically to check if the browser is running. If it is not,
+ * exit Vidalia cleanly */
+ void onCheckForBrowser();
+ /** Called web the web browser failed to start */
+ void onBrowserFailed(QString errmsg);
+ /** Called web the IM client failed to start */
+ void onIMFailed(QString errmsg);
+ /** Called when the proxy server fails to start */
+ void onProxyFailed(QString errmsg);
+
#if defined(USE_AUTOUPDATE)
/** Called when the user clicks the 'Check Now' button in the General
* settings page. */
@@ -240,6 +253,20 @@ private:
/** The Vidalia icon that sits in the tray. */
QSystemTrayIcon _trayIcon;
+ /** Start a web browser when given the directory containing the executable and profile */
+ void launchBrowserFromDirectory();
+ /** Starts the web browser, if appropriately configured */
+ void startSubprocesses();
+ /** Starts the proxy server, if appropriately configured */
+ void startProxy();
+
+ /** A HelperProcess object that manages the web browser */
+ HelperProcess* _browserProcess;
+ /** A HelperProcess object that manages the IM client */
+ HelperProcess* _imProcess;
+ /** A HelperProcess object that manages the proxy server */
+ HelperProcess* _proxyProcess;
+
#if defined(USE_AUTOUPDATE)
/** Timer used to remind us to check for software updates. */
QTimer _updateTimer;
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits