[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[vidalia-svn] r3504: Merge Steven's alt-launcher branch into trunk. (in vidalia/trunk/src: common vidalia vidalia/config)
Author: edmanm
Date: 2009-02-02 21:09:39 -0500 (Mon, 02 Feb 2009)
New Revision: 3504
Modified:
vidalia/trunk/src/common/file.cpp
vidalia/trunk/src/common/file.h
vidalia/trunk/src/vidalia/config/vidaliasettings.cpp
vidalia/trunk/src/vidalia/config/vidaliasettings.h
vidalia/trunk/src/vidalia/mainwindow.cpp
vidalia/trunk/src/vidalia/mainwindow.h
Log:
Merge Steven's alt-launcher branch into trunk.
Modified: vidalia/trunk/src/common/file.cpp
===================================================================
--- vidalia/trunk/src/common/file.cpp 2009-02-02 17:47:07 UTC (rev 3503)
+++ vidalia/trunk/src/common/file.cpp 2009-02-03 02:09:39 UTC (rev 3504)
@@ -64,6 +64,43 @@
return true;
}
+/** Recursively copy the contents of one directory to another. The
+ * destination must already exist. Returns true on success, and false
+ * otherwise. */
+bool
+copy_dir(QString source, QString dest)
+{
+ /* Source and destination as QDir's */
+ QDir src(source);
+ QDir dst(dest);
+
+ /* Get contents of the directory */
+ QFileInfoList contents = src.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
+
+ /* Copy each entry in src to dst */
+ foreach (QFileInfo fileInfo, contents) {
+ /* Get absolute path of source and destination */
+ QString fileName = fileInfo.fileName();
+ QString srcFilePath = src.absoluteFilePath(fileName);
+ QString dstFilePath = dst.absoluteFilePath(fileName);
+
+ if (fileInfo.isDir()) {
+ /* This is a directory, make it and recurse */
+ if (!dst.mkdir(fileName))
+ return false;
+ if (!copy_dir(srcFilePath, dstFilePath))
+ return false;
+ } else if (fileInfo.isFile()) {
+ /* This is a file, copy it */
+ if (!QFile::copy(srcFilePath, dstFilePath))
+ return false;
+ }
+ /* Ignore special files (e.g. symlinks, devices) */
+
+ }
+ return true;
+}
+
/** Expands <b>filename</b> if it starts with "~/". On Windows, this will
* expand "%APPDATA%" and "%PROGRAMFILES%". If <b>filename</b> does not
* start with a shortcut, <b>filename</b> will be returned unmodified. */
Modified: vidalia/trunk/src/common/file.h
===================================================================
--- vidalia/trunk/src/common/file.h 2009-02-02 17:47:07 UTC (rev 3503)
+++ vidalia/trunk/src/common/file.h 2009-02-03 02:09:39 UTC (rev 3504)
@@ -32,6 +32,11 @@
* expand "%APPDATA%" and "%PROGRAMFILES%". If <b>filename</b> does not
* start with a shortcut, <b>filename</b> will be returned unmodified. */
QString expand_filename(QString filename);
+
+/** Recursively copy the contents of one directory to another. The
+ * destination must already exist. Returns true on success, and false
+ * otherwise. */
+bool copy_dir(QString source, QString dest);
#endif
Modified: vidalia/trunk/src/vidalia/config/vidaliasettings.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/vidaliasettings.cpp 2009-02-02 17:47:07 UTC (rev 3503)
+++ vidalia/trunk/src/vidalia/config/vidaliasettings.cpp 2009-02-03 02:09:39 UTC (rev 3504)
@@ -32,6 +32,7 @@
#define SETTING_DATA_DIRECTORY "DataDirectory"
#define SETTING_SHOW_MAINWINDOW_AT_START "ShowMainWindowAtStart"
#define SETTING_BROWSER_EXECUTABLE "BrowserExecutable"
+#define SETTING_BROWSER_DIRECTORY "BrowserDirectory"
#define SETTING_IM_EXECUTABLE "IMExecutable"
#define SETTING_RUN_PROXY_AT_START "RunProxyAtStart"
#define SETTING_PROXY_EXECUTABLE "ProxyExecutable"
@@ -175,8 +176,9 @@
#endif
}
-/** Returns a fully-qualified path to the web browser, including the
- * executable name. */
+/** If browserDirectory is empty, returns a fully-qualified path to
+ * the web browser, including the executable name. If browserDirectory
+ * is set, then returns the basename of the configured web browser */
QString
VidaliaSettings::getBrowserExecutable() const
{
@@ -191,6 +193,21 @@
setValue(SETTING_BROWSER_EXECUTABLE, browserExecutable);
}
+/** Returns a fully-qualified path to the web browser directory */
+QString
+VidaliaSettings::getBrowserDirectory() const
+{
+ return QDir::convertSeparators(value(SETTING_BROWSER_DIRECTORY).toString());
+}
+
+/** Sets the location and name of the web browser directory to the given string.
+ * If set to the empty string, the browser will not be started. */
+void
+VidaliaSettings::setBrowserDirectory(const QString &browserDirectory)
+{
+ setValue(SETTING_BROWSER_DIRECTORY, browserDirectory);
+}
+
/** Returns a fully-qualified path to the IM client, including the
* executable name. */
QString
Modified: vidalia/trunk/src/vidalia/config/vidaliasettings.h
===================================================================
--- vidalia/trunk/src/vidalia/config/vidaliasettings.h 2009-02-02 17:47:07 UTC (rev 3503)
+++ vidalia/trunk/src/vidalia/config/vidaliasettings.h 2009-02-03 02:09:39 UTC (rev 3504)
@@ -62,13 +62,20 @@
/** Set whether to run Vidalia on system boot. */
void setRunVidaliaOnBoot(bool run);
- /** Returns a fully-qualified path to the web browser, including the
- * executable name. */
+ /** If browserDirectory is empty, returns a fully-qualified path to
+ * the web browser, including the executable name. If browserDirectory
+ * is set, then returns the basename of the configured web browser */
QString getBrowserExecutable() const;
/** Sets the location and name of the web browser executable to the given
* string. If set to the empty string, the browser will not be started. */
void setBrowserExecutable(const QString &browserExecutable);
+ /** Returns a fully-qualified path to the web browser directory */
+ QString getBrowserDirectory() const;
+ /** Sets the location and name of the web browser directory to the given string.
+ * If set to the empty string, the browser will not be started. */
+ void setBrowserDirectory(const QString &browserDirectory);
+
/** Returns a fully-qualified path to the IM client, including the
* executable name. */
QString getIMExecutable() const;
Modified: vidalia/trunk/src/vidalia/mainwindow.cpp
===================================================================
--- vidalia/trunk/src/vidalia/mainwindow.cpp 2009-02-02 17:47:07 UTC (rev 3503)
+++ vidalia/trunk/src/vidalia/mainwindow.cpp 2009-02-03 02:09:39 UTC (rev 3504)
@@ -32,6 +32,8 @@
#include <vmessagebox.h>
#include <procutil.h>
+#include "procutil.h"
+
#include "mainwindow.h"
#include "controlpasswordinputdialog.h"
@@ -151,7 +153,6 @@
this, SLOT(onSubprocessFinished(int, QProcess::ExitStatus)));
connect(_browserProcess, SIGNAL(startFailed(QString)),
this, SLOT(onBrowserFailed(QString)));
- _browserProcess->setEnvironment(QProcess::systemEnvironment() << "TZ=UTC");
/* Create a new HelperProcess object, used to start the IM client */
_imProcess = new HelperProcess(this);
@@ -551,20 +552,77 @@
#endif
}
+/** 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 executable = settings.getBrowserExecutable();
-
- if (!executable.isEmpty())
- _browserProcess->start(executable, QStringList());
+ QString subprocess;
- executable = settings.getIMExecutable();
+ /* 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());
+ }
- if (!executable.isEmpty())
- _imProcess->start(executable, QStringList());
+ /* Launch the IM client */
+ subprocess = settings.getIMExecutable();
+
+ if (!subprocess.isEmpty())
+ _imProcess->start(subprocess, QStringList());
}
/** Called when browser or IM client have exited */
@@ -577,17 +635,62 @@
/* 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() || _browserProcess->isDone();
+ bool browserDone = (browserExecutable.isEmpty() && browserDirectory.isEmpty()) || _browserProcess->isDone();
bool imDone = imExecutable.isEmpty() || _imProcess->isDone();
/* Exit if both subprocesses are finished */
- if (browserDone && imDone)
- shutdown();
+ if (browserDone && imDone) {
+ if (browserDirectory.isEmpty()) {
+ /* We are using the standard launcher, exit immediately */
+ shutdown();
+ } 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 */
+ shutdown();
+#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
Modified: vidalia/trunk/src/vidalia/mainwindow.h
===================================================================
--- vidalia/trunk/src/vidalia/mainwindow.h 2009-02-02 17:47:07 UTC (rev 3503)
+++ vidalia/trunk/src/vidalia/mainwindow.h 2009-02-03 02:09:39 UTC (rev 3504)
@@ -111,6 +111,9 @@
void toggleShowOnStartup(bool checked);
/** 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 */
@@ -168,6 +171,8 @@
/** Updates the UI to reflect Tor's current <b>status</b>. Returns the
* previously set TorStatus value. */
TorStatus updateTorStatus(TorStatus status);
+ /** 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 */