Bug 950241 - Replace misc. restart boolean flags with an enum and cleanup CEH Execute. r=bbondy, a=lsblakk
authorJim Mathies <jmathies@mozilla.com>
Thu, 30 Jan 2014 13:32:48 -0600
changeset 176260 5b3201c97b299af764c1654e93677e3c364934cd
parent 176259 dddf11dc7526f5bdc1b26dd94ccb6f25de58c8d0
child 176261 10bed2ab6575a5c902d604884966e475753328f2
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy, lsblakk
bugs950241
milestone28.0
Bug 950241 - Replace misc. restart boolean flags with an enum and cleanup CEH Execute. r=bbondy, a=lsblakk
browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
--- a/browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
+++ b/browser/metro/shell/commandexecutehandler/CommandExecuteHandler.cpp
@@ -27,20 +27,20 @@
 
 // Heartbeat timer duration used while waiting for an incoming request.
 #define HEARTBEAT_MSEC 1000
 // Total number of heartbeats we wait before giving up and shutting down.
 #define REQUEST_WAIT_TIMEOUT 30
 // Pulled from desktop browser's shell
 #define APP_REG_NAME L"Firefox"
 
-static const WCHAR* kFirefoxExe = L"firefox.exe";
-static const WCHAR* kMetroFirefoxExe = L"firefox.exe";
+const WCHAR* kFirefoxExe = L"firefox.exe";
 static const WCHAR* kDefaultMetroBrowserIDPathKey = L"FirefoxURL";
 static const WCHAR* kMetroRestartCmdLine = L"--metro-restart";
+static const WCHAR* kMetroUpdateCmdLine = L"--metro-update";
 static const WCHAR* kDesktopRestartCmdLine = L"--desktop-restart";
 
 static bool GetDefaultBrowserPath(CStringW& aPathBuffer);
 
 /*
  * Retrieve our module dir path.
  *
  * @aPathBuffer Buffer to fill
@@ -90,19 +90,17 @@ public:
 
   CExecuteCommandVerb() :
     mRef(1),
     mShellItemArray(nullptr),
     mUnkSite(nullptr),
     mTargetIsFileSystemLink(false),
     mTargetIsDefaultBrowser(false),
     mTargetIsBrowser(false),
-    mIsDesktopRequest(true),
-    mIsRestartMetroRequest(false),
-    mIsRestartDesktopRequest(false),
+    mRequestType(DEFAULT_LAUNCH),
     mRequestMet(false),
     mVerb(L"open")
   {
   }
 
   bool RequestMet() { return mRequestMet; }
   long RefCount() { return mRef; }
 
@@ -140,20 +138,22 @@ public:
     mKeyState = aKeyState;
     return S_OK;
   }
 
   IFACEMETHODIMP SetParameters(PCWSTR aParameters)
   {
     Log(L"SetParameters: '%s'", aParameters);
 
-    if (_wcsicmp(aParameters, kMetroRestartCmdLine) == 0) {
-      mIsRestartMetroRequest = true;
+    if (!_wcsicmp(aParameters, kMetroRestartCmdLine)) {
+      mRequestType = METRO_RESTART;
+    } else if (_wcsicmp(aParameters, kMetroUpdateCmdLine) == 0) {
+      mRequestType = METRO_UPDATE;
     } else if (_wcsicmp(aParameters, kDesktopRestartCmdLine) == 0) {
-      mIsRestartDesktopRequest = true;
+      mRequestType = DESKTOP_RESTART;
     } else {
       mParameters = aParameters;
     }
     return S_OK;
   }
 
   IFACEMETHODIMP SetPosition(POINT aPoint)
   { return S_OK; }
@@ -250,62 +250,67 @@ public:
     return mUnkSite ? mUnkSite->QueryInterface(aRefID, aInt) : E_FAIL;
   }
 
   // IExecuteCommandApplicationHostEnvironment
   IFACEMETHODIMP GetValue(AHE_TYPE *aLaunchType)
   {
     Log(L"IExecuteCommandApplicationHostEnvironment::GetValue()");
     *aLaunchType = GetLaunchType();
-    mIsDesktopRequest = (*aLaunchType == AHE_DESKTOP);
     return S_OK;
   }
 
   /**
    * Choose the appropriate launch type based on the user's previously chosen
    * host environment, along with system constraints.
    *
    * AHE_DESKTOP = 0, AHE_IMMERSIVE = 1
    */
-  AHE_TYPE GetLaunchType() {
+  AHE_TYPE GetLaunchType()
+  {
     AHE_TYPE ahe = GetLastAHE();
     Log(L"Previous AHE: %d", ahe);
 
-    if (!mIsRestartMetroRequest && IsProcessRunning(kFirefoxExe, false)) {
-      Log(L"Returning AHE_DESKTOP because desktop is already running");
-      return AHE_DESKTOP;
-    } else if (!mIsRestartDesktopRequest && IsProcessRunning(kMetroFirefoxExe, true)) {
-      Log(L"Returning AHE_IMMERSIVE because Metro is already running");
-      return AHE_IMMERSIVE;
-    }
-
-    if (mIsRestartDesktopRequest) {
+    // Default launch settings from GetLastAHE() can be overriden by
+    // custom parameter values we receive. 
+    if (mRequestType == DESKTOP_RESTART) {
       Log(L"Restarting in desktop host environment.");
       return AHE_DESKTOP;
-    }
-
-    if (mIsRestartMetroRequest) {
+    } else if (mRequestType == METRO_RESTART) {
       Log(L"Restarting in metro host environment.");
       ahe = AHE_IMMERSIVE;
+    } else if (mRequestType == METRO_UPDATE) {
+      // Shouldn't happen from GetValue above, but might from other calls.
+      ahe = AHE_IMMERSIVE;
     }
 
     if (ahe == AHE_IMMERSIVE) {
       if (!IsDefaultBrowser()) {
         Log(L"returning AHE_DESKTOP because we are not the default browser");
         return AHE_DESKTOP;
       }
 
       if (!IsDX10Available()) {
         Log(L"returning AHE_DESKTOP because DX10 is not available");
         return AHE_DESKTOP;
       }
     }
     return ahe;
   }
 
+  bool DefaultLaunchIsDesktop()
+  {
+    return GetLaunchType() == AHE_DESKTOP;
+  }
+
+  bool DefaultLaunchIsMetro()
+  {
+    return GetLaunchType() == AHE_IMMERSIVE;
+  }
+
   /*
    * Retrieve the target path if it is the default browser
    * or if not default, retreives the target path if it is a firefox browser
    * or if the target is not firefox, relies on a hack to get the
    * 'module dir path\firefox.exe'
    * The reason why it's not good to rely on the CEH path is because there is
    * no guarantee win8 will use the CEH at our expected path.  It has an in
    * memory cache even if the registry is updated for the CEH path.
@@ -379,31 +384,41 @@ public:
 private:
   ~CExecuteCommandVerb()
   {
     SafeRelease(&mShellItemArray);
     SafeRelease(&mUnkSite);
   }
 
   void LaunchDesktopBrowser();
+  bool LaunchMetroBrowser();
   bool SetTargetPath(IShellItem* aItem);
 
+  /*
+   * Defines the type of startup request we receive.
+   */
+  enum RequestType {
+    DEFAULT_LAUNCH,
+    DESKTOP_RESTART,
+    METRO_RESTART,
+    METRO_UPDATE,
+  };
+
+  RequestType mRequestType;
+
   long mRef;
   IShellItemArray *mShellItemArray;
   IUnknown *mUnkSite;
   CStringW mVerb;
   CStringW mTarget;
   CStringW mParameters;
   bool mTargetIsFileSystemLink;
   bool mTargetIsDefaultBrowser;
   bool mTargetIsBrowser;
   DWORD mKeyState;
-  bool mIsDesktopRequest;
-  bool mIsRestartMetroRequest;
-  bool mIsRestartDesktopRequest;
   bool mRequestMet;
 };
 
 /*
  * Retrieve the current default browser's path.
  *
  * @aPathBuffer Buffer to fill
  */
@@ -576,17 +591,17 @@ void LaunchDesktopBrowserWithParams(CStr
   }
 
   // Tack on any extra parameters we received (for example -profilemanager)
   if (!aParameters.IsEmpty()) {
     params += " ";
     params += aParameters;
   }
 
-  Log(L"Desktop Launch: verb:%s exe:%s params:%s", aVerb, aBrowserPath, params);
+  Log(L"Desktop Launch: verb:'%s' exe:'%s' params:'%s'", aVerb, aBrowserPath, params);
 
   // Relaunch in Desktop mode uses a special URL to trick Windows into
   // switching environments. We shouldn't actually try to open this URL.
   if (!_wcsicmp(aTarget, L"http://-desktop/")) {
     // Ignore any params and just launch on desktop
     params.Empty();
   }
 
@@ -612,122 +627,123 @@ void LaunchDesktopBrowserWithParams(CStr
   if (!AllowSetForegroundWindow(procInfo.dwProcessId)) {
     Log(L"AllowSetForegroundWindow failed! (%d)", GetLastError());
   }
   CloseHandle(procInfo.hThread);
   CloseHandle(procInfo.hProcess);
   Log(L"Desktop browser process id: %d", procInfo.dwProcessId);
 }
 
-void CExecuteCommandVerb::LaunchDesktopBrowser()
+void
+CExecuteCommandVerb::LaunchDesktopBrowser()
 {
   CStringW browserPath;
   if (!GetDesktopBrowserPath(browserPath)) {
     return;
   }
 
   LaunchDesktopBrowserWithParams(browserPath, mVerb, mTarget, mParameters,
                                  mTargetIsDefaultBrowser, mTargetIsBrowser);
 }
 
-class AutoSetRequestMet
-{
-public:
-  explicit AutoSetRequestMet(bool* aFlag) :
-    mFlag(aFlag) {}
-  ~AutoSetRequestMet() { if (mFlag) *mFlag = true; }
-private:
-  bool* mFlag;
-};
-
-static HRESULT
+static bool
 PrepareActivationManager(CComPtr<IApplicationActivationManager> &activateMgr)
 {
   HRESULT hr = activateMgr.CoCreateInstance(CLSID_ApplicationActivationManager,
                                             nullptr, CLSCTX_LOCAL_SERVER);
   if (FAILED(hr)) {
     Log(L"CoCreateInstance failed, launching on desktop.");
-    return E_FAIL;
+    return false;
   }
 
   // Hand off focus rights to the out-of-process activation server. Without
   // this the metro interface won't launch.
   hr = CoAllowSetForegroundWindow(activateMgr, nullptr);
   if (FAILED(hr)) {
     Log(L"CoAllowSetForegroundWindow result %X", hr);
-    return E_FAIL;
-  }
-
-  return S_OK;
-}
-
-IFACEMETHODIMP CExecuteCommandVerb::Execute()
-{
-  Log(L"Execute()");
-
-  if (!mTarget.GetLength()) {
-    // We shut down when this flips to true
-    mRequestMet = true;
-    return E_FAIL;
+    return false;
   }
 
-  if (mIsRestartDesktopRequest) {
-    CStringW browserPath;
-    if (!GetDesktopBrowserPath(browserPath)) {
-      return E_FAIL;
-    }
+  return true;
+}
 
-    LaunchDesktopBrowserWithParams(browserPath,
-                                   mVerb,
-                                   mTarget,
-                                   mParameters,
-                                   mTargetIsDefaultBrowser,
-                                   mTargetIsBrowser);
-    return S_OK;
-  }
-
-  // We shut down when this flips to true
-  AutoSetRequestMet asrm(&mRequestMet);
-
-  // Launch on the desktop
-  if (mIsDesktopRequest) {
-    LaunchDesktopBrowser();
-    return S_OK;
-  }
-
+bool
+CExecuteCommandVerb::LaunchMetroBrowser()
+{
+  // Launch in metro
   CComPtr<IApplicationActivationManager> activateMgr;
-  if (FAILED(PrepareActivationManager(activateMgr))) {
-      LaunchDesktopBrowser();
-      return S_OK;
+  if (!PrepareActivationManager(activateMgr)) {
+    return false;
   }
 
   HRESULT hr;
   WCHAR appModelID[256];
   if (!GetDefaultBrowserAppModelID(appModelID)) {
-    Log(L"GetDefaultBrowserAppModelID failed, launching on desktop.");
-    LaunchDesktopBrowser();
-    return S_OK;
+    Log(L"GetDefaultBrowserAppModelID failed.");
+    return false;
   }
 
-  Log(L"Metro Launch: verb:%s appid:%s params:%s", mVerb, appModelID, mTarget);
+  Log(L"Metro Launch: verb:'%s' appid:'%s' params:'%s'", mVerb, appModelID, mTarget);
 
   // shortcuts to the application
   DWORD processID;
   if (mTargetIsDefaultBrowser) {
     hr = activateMgr->ActivateApplication(appModelID, L"", AO_NONE, &processID);
     Log(L"ActivateApplication result %X", hr);
   // files
   } else if (mTargetIsFileSystemLink) {
     hr = activateMgr->ActivateForFile(appModelID, mShellItemArray, mVerb, &processID);
     Log(L"ActivateForFile result %X", hr);
   // protocols
   } else {
     hr = activateMgr->ActivateForProtocol(appModelID, mShellItemArray, &processID);
     Log(L"ActivateForProtocol result %X", hr);
   }
+  return true;
+}
+
+class AutoSetRequestMet
+{
+public:
+  explicit AutoSetRequestMet(bool* aFlag) :
+    mFlag(aFlag) {}
+  ~AutoSetRequestMet() { if (mFlag) *mFlag = true; }
+private:
+  bool* mFlag;
+};
+
+IFACEMETHODIMP CExecuteCommandVerb::Execute()
+{
+  Log(L"Execute()");
+
+  if (!mTarget.GetLength()) {
+    // We shut down when this flips to true
+    mRequestMet = true;
+    return E_FAIL;
+  }
+
+  // We shut down when this flips to true
+  AutoSetRequestMet asrm(&mRequestMet);
+
+  // Launch on the desktop
+  if (mRequestType == DESKTOP_RESTART ||
+      (mRequestType == DEFAULT_LAUNCH && DefaultLaunchIsDesktop())) {
+    LaunchDesktopBrowser();
+    return S_OK;
+  }
+
+  // Deal with metro restart for an update - launch desktop with a command
+  // that tells it to run updater then launch the metro browser.
+  if (mRequestType == METRO_UPDATE) {
+    mParameters = kMetroUpdateCmdLine;
+    LaunchDesktopBrowser();
+    return S_OK;
+  }
+
+  LaunchMetroBrowser();
   return S_OK;
 }
 
 class ClassFactory : public IClassFactory 
 {
 public:
   ClassFactory(IUnknown *punkObject);
   ~ClassFactory();