[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r3511: Backport Steven's alt-launcher stuff to 0.1.x for TBB. (in vidalia/branches/vidalia-0.1: . src/common src/vidalia src/vidalia/config)



Author: edmanm
Date: 2009-02-04 19:56:16 -0500 (Wed, 04 Feb 2009)
New Revision: 3511

Modified:
   vidalia/branches/vidalia-0.1/
   vidalia/branches/vidalia-0.1/CHANGELOG
   vidalia/branches/vidalia-0.1/src/common/file.cpp
   vidalia/branches/vidalia-0.1/src/common/file.h
   vidalia/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.cpp
   vidalia/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.h
   vidalia/branches/vidalia-0.1/src/vidalia/mainwindow.cpp
   vidalia/branches/vidalia-0.1/src/vidalia/mainwindow.h
Log:

Backport Steven's alt-launcher stuff to 0.1.x for TBB.



Property changes on: vidalia/branches/vidalia-0.1
___________________________________________________________________
Modified: svn:mergeinfo
   - /vidalia/trunk:3482
   + /vidalia/trunk:3482,3504-3505

Modified: vidalia/branches/vidalia-0.1/CHANGELOG
===================================================================
--- vidalia/branches/vidalia-0.1/CHANGELOG	2009-02-04 20:31:41 UTC (rev 3510)
+++ vidalia/branches/vidalia-0.1/CHANGELOG	2009-02-05 00:56:16 UTC (rev 3511)
@@ -12,6 +12,8 @@
   o Backport a change that removes a verticalSpacing property from a .ui
     file, so Vidalia 0.1.x will still build on Qt 4.2. (Ticket #442)
   o Fix some memory leaks in the hidden service configuration dialog.
+  o Include a patch from Steven J. Murdoch that enables the Tor Browser
+    Bundle to launch Firefox itself without relying on Portable Firefox.
 
 
 0.1.10  02-Nov-2008

Modified: vidalia/branches/vidalia-0.1/src/common/file.cpp
===================================================================
--- vidalia/branches/vidalia-0.1/src/common/file.cpp	2009-02-04 20:31:41 UTC (rev 3510)
+++ vidalia/branches/vidalia-0.1/src/common/file.cpp	2009-02-05 00:56:16 UTC (rev 3511)
@@ -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/branches/vidalia-0.1/src/common/file.h
===================================================================
--- vidalia/branches/vidalia-0.1/src/common/file.h	2009-02-04 20:31:41 UTC (rev 3510)
+++ vidalia/branches/vidalia-0.1/src/common/file.h	2009-02-05 00:56:16 UTC (rev 3511)
@@ -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/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.cpp
===================================================================
--- vidalia/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.cpp	2009-02-04 20:31:41 UTC (rev 3510)
+++ vidalia/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.cpp	2009-02-05 00:56:16 UTC (rev 3511)
@@ -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"
@@ -167,8 +168,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
 {
@@ -183,6 +185,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/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.h
===================================================================
--- vidalia/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.h	2009-02-04 20:31:41 UTC (rev 3510)
+++ vidalia/branches/vidalia-0.1/src/vidalia/config/vidaliasettings.h	2009-02-05 00:56:16 UTC (rev 3511)
@@ -61,13 +61,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/branches/vidalia-0.1/src/vidalia/mainwindow.cpp
===================================================================
--- vidalia/branches/vidalia-0.1/src/vidalia/mainwindow.cpp	2009-02-04 20:31:41 UTC (rev 3510)
+++ vidalia/branches/vidalia-0.1/src/vidalia/mainwindow.cpp	2009-02-05 00:56:16 UTC (rev 3511)
@@ -30,6 +30,8 @@
 #include <vmessagebox.h>
 #include <procutil.h>
 
+#include "procutil.h"
+
 #include "mainwindow.h"
 #include "controlpasswordinputdialog.h"
 
@@ -143,7 +145,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);
@@ -453,20 +454,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());
   
 }
 
@@ -480,17 +538,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/branches/vidalia-0.1/src/vidalia/mainwindow.h
===================================================================
--- vidalia/branches/vidalia-0.1/src/vidalia/mainwindow.h	2009-02-04 20:31:41 UTC (rev 3510)
+++ vidalia/branches/vidalia-0.1/src/vidalia/mainwindow.h	2009-02-05 00:56:16 UTC (rev 3511)
@@ -104,6 +104,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 */
@@ -139,6 +142,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 */