Bug 603903: use RegisterApplicationRestart behind a pref draft
authorAdam Gashlin <agashlin@mozilla.com>
Thu, 05 Apr 2018 16:11:51 -0700
changeset 778211 0187a385d69b056404aeadcf091d7108d72c6d05
parent 778203 7b40283bf1c7a2a3e6a8a5d00156a2f506ff465b
push id105433
push userbmo:agashlin@mozilla.com
push dateThu, 05 Apr 2018 23:12:08 +0000
bugs603903
milestone61.0a1
Bug 603903: use RegisterApplicationRestart behind a pref MozReview-Commit-ID: 6bMZHDRjW3T
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsWindowsRestart.cpp
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1879,17 +1879,51 @@ XRE_GetBinaryPath(nsIFile* *aResult)
   return mozilla::BinaryPath::GetFile(aResult);
 }
 
 #ifdef XP_WIN
 #include "nsWindowsRestart.cpp"
 #include <shellapi.h>
 
 typedef BOOL (WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
-#endif
+
+#define PREF_WIN_REGISTER_APPLICATION_RESTART "toolkit.winRegisterApplicationRestart"
+
+static void
+RegisterApplicationRestartChanged(const char* aPref, void* aData) {
+  if (Preferences::GetBool(PREF_WIN_REGISTER_APPLICATION_RESTART, false)) {
+    // Make the command line to use when restarting
+    wchar_t* restartCommandLine = nullptr;
+    if (gRestartArgc > 1) {
+      // excludes argv[0] because RegisterApplicationRestart adds the
+      // executable name
+      wchar_t** restartArgvConverted =
+        AllocConvertUTF8toUTF16Strings(gRestartArgc - 1, gRestartArgv + 1);
+
+      if (restartArgvConverted) {
+        restartCommandLine = MakeCommandLine(gRestartArgc - 1, restartArgvConverted);
+        FreeAllocStrings(gRestartArgc - 1, restartArgvConverted);
+      }
+    } else {
+      restartCommandLine = (wchar_t*) malloc(sizeof(wchar_t));
+      restartCommandLine[0] = L'\0';
+    }
+
+    if (restartCommandLine) {
+      // Flags RESTART_NO_PATCH and RESTART_NO_REBOOT are not set, so we
+      // should be restarted if terminated by an update or restart.
+      ::RegisterApplicationRestart(restartCommandLine, RESTART_NO_CRASH |
+                                                       RESTART_NO_HANG);
+      free(restartCommandLine);
+    }
+  } else {
+    ::UnregisterApplicationRestart();
+  }
+}
+#endif // XP_WIN
 
 // If aBlankCommandLine is true, then the application will be launched with a
 // blank command line instead of being launched with the same command line that
 // it was initially started with.
 static nsresult LaunchChild(nsINativeAppSupport* aNative,
                             bool aBlankCommandLine = false)
 {
   aNative->Quit(); // release DDE mutex, if we're holding it
@@ -4667,16 +4701,21 @@ XREMain::XRE_mainRun()
   SaveToEnv("NO_EM_RESTART=");
   SaveToEnv("XUL_APP_FILE=");
   SaveToEnv("XRE_BINARY_PATH=");
 
   if (!mShuttingDown) {
     rv = appStartup->CreateHiddenWindow();
     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
+#ifdef XP_WIN32
+    Preferences::RegisterCallbackAndCall(RegisterApplicationRestartChanged,
+                                         PREF_WIN_REGISTER_APPLICATION_RESTART);
+#endif
+
 #if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)
     nsGTKToolkit* toolkit = nsGTKToolkit::GetToolkit();
     if (toolkit && !mDesktopStartupID.IsEmpty()) {
       toolkit->SetDesktopStartupID(mDesktopStartupID);
     }
     // Clear the environment variable so it won't be inherited by
     // child processes and confuse things.
     g_unsetenv ("DESKTOP_STARTUP_ID");
--- a/toolkit/xre/nsWindowsRestart.cpp
+++ b/toolkit/xre/nsWindowsRestart.cpp
@@ -108,18 +108,16 @@ static wchar_t* ArgToString(wchar_t *d, 
   }
 
   return d;
 }
 
 /**
  * Creates a command line from a list of arguments. The returned
  * string is allocated with "malloc" and should be "free"d.
- *
- * argv is UTF8
  */
 wchar_t*
 MakeCommandLine(int argc, wchar_t **argv)
 {
   int i;
   int len = 0;
 
   // The + 1 of the last argument handles the allocation for null termination
@@ -173,16 +171,32 @@ FreeAllocStrings(int argc, wchar_t **arg
   while (argc) {
     --argc;
     delete [] argv[argc];
   }
 
   delete [] argv;
 }
 
+static wchar_t**
+AllocConvertUTF8toUTF16Strings(int argc, char **argv)
+{
+  wchar_t **argvConverted = new wchar_t*[argc];
+  if (!argvConverted)
+    return nullptr;
+
+  for (int i = 0; i < argc; ++i) {
+    argvConverted[i] = reinterpret_cast<wchar_t*>(AllocConvertUTF8toUTF16(argv[i]));
+    if (!argvConverted[i]) {
+      FreeAllocStrings(i, argvConverted);
+      return nullptr;
+    }
+  }
+  return argvConverted;
+}
 
 
 /**
  * Launch a child process with the specified arguments.
  * @note argv[0] is ignored
  * @note The form of this function that takes char **argv expects UTF-8
  */
 
@@ -193,28 +207,20 @@ WinLaunchChild(const wchar_t *exePath,
                HANDLE *hProcess = nullptr);
 
 BOOL
 WinLaunchChild(const wchar_t *exePath,
                int argc, char **argv,
                HANDLE userToken,
                HANDLE *hProcess)
 {
-  wchar_t** argvConverted = new wchar_t*[argc];
+  wchar_t **argvConverted = AllocConvertUTF8toUTF16Strings(argc, argv);
   if (!argvConverted)
     return FALSE;
 
-  for (int i = 0; i < argc; ++i) {
-      argvConverted[i] = reinterpret_cast<wchar_t*>(AllocConvertUTF8toUTF16(argv[i]));
-    if (!argvConverted[i]) {
-      FreeAllocStrings(i, argvConverted);
-      return FALSE;
-    }
-  }
-
   BOOL ok = WinLaunchChild(exePath, argc, argvConverted, userToken, hProcess);
   FreeAllocStrings(argc, argvConverted);
   return ok;
 }
 
 BOOL
 WinLaunchChild(const wchar_t *exePath,
                int argc,