Bug 519316 - faster remote starting for WinCE, r=mfinkle, blocking-fennec=blassey
authorBrian Crowder <crowder@fiverocks.com>
Tue, 01 Dec 2009 07:45:35 -0800
changeset 35299 568231ef38d94a9b32990b92cb457430ceadd20b
parent 35298 422dc39dad74a1012c7fa8dff0d5a130215a8829
child 35300 4f6f09ec444781ee31866476b2c5c4549b2d39f9
push idunknown
push userunknown
push dateunknown
reviewersmfinkle
bugs519316
milestone1.9.3a1pre
Bug 519316 - faster remote starting for WinCE, r=mfinkle, blocking-fennec=blassey
toolkit/xre/nsNativeAppSupportWin.cpp
xulrunner/stub/nsXULStub.cpp
--- a/toolkit/xre/nsNativeAppSupportWin.cpp
+++ b/toolkit/xre/nsNativeAppSupportWin.cpp
@@ -575,17 +575,22 @@ struct MessageWindow {
 
     // SendRequest: Pass the command line via WM_COPYDATA to message window.
     NS_IMETHOD SendRequest() {
         WCHAR *cmd = ::GetCommandLineW();
         WCHAR cwd[MAX_PATH];
         _wgetcwd(cwd, MAX_PATH);
 
         // Construct a narrow UTF8 buffer <commandline>\0<workingdir>\0
+#ifdef WINCE
+        NS_ConvertUTF16toUTF8 utf8buffer(L"dummy ");
+        AppendUTF16toUTF8(cmd, utf8buffer);
+#else
         NS_ConvertUTF16toUTF8 utf8buffer(cmd);
+#endif
         utf8buffer.Append('\0');
         AppendUTF16toUTF8(cwd, utf8buffer);
         utf8buffer.Append('\0');
 
         // We used to set dwData to zero, when we didn't send the working dir.
         // Now we're using it as a version number.
         COPYDATASTRUCT cds = {
             1,
--- a/xulrunner/stub/nsXULStub.cpp
+++ b/xulrunner/stub/nsXULStub.cpp
@@ -190,16 +190,53 @@ public:
 private:
   nsXREAppData* mAppData;
 };
 
 XRE_CreateAppDataType XRE_CreateAppData;
 XRE_FreeAppDataType XRE_FreeAppData;
 XRE_mainType XRE_main;
 
+
+#ifdef WINCE
+void
+ForwardToWindow(HWND wnd) {
+  // For WinCE, we're stuck with providing our own argv[0] for the remote
+  // command-line.
+  WCHAR wPath[MAX_PATH] = L"dummy ";
+  WCHAR *wCmd = ::GetCommandLineW();
+  WCHAR wCwd[MAX_PATH];
+  _wgetcwd(wCwd, MAX_PATH);
+
+  // Construct a narrow UTF8 buffer <path> <commandline>\0<workingdir>\0
+  size_t len = wcslen(wPath) + wcslen(wCmd) + wcslen(wCwd) + 3;
+  WCHAR *wMsg = (WCHAR *)malloc(len * sizeof(*wMsg));
+  wcscpy(wMsg, wPath);
+  wcscpy(wMsg + wcslen(wPath), wCmd);                // The command line
+  wcscpy(wMsg + wcslen(wPath) + wcslen(wCmd) + 2, wCwd); // Working dir
+
+  // Then convert to UTF-8, assuming worst-case explosion of characters
+  char *msg = (char *)malloc(len * 4);
+  WideCharToMultiByte(CP_UTF8, 0, wMsg, len, msg, len * 4, NULL, NULL);
+
+  // We used to set dwData to zero, when we didn't send the working dir.
+  // Now we're using it as a version number.
+  COPYDATASTRUCT cds = { 1, len, (void *)msg };
+
+  // Bring the already running Mozilla process to the foreground.
+  // nsWindow will restore the window (if minimized) and raise it.
+  // for activating the existing window on wince we need "| 0x01"
+  // see http://msdn.microsoft.com/en-us/library/ms940024.aspx for details
+  ::SetForegroundWindow((HWND)(((ULONG) wnd) | 0x01));
+  ::SendMessage(wnd, WM_COPYDATA, 0, (LPARAM)&cds);
+  free(wMsg);
+  free(msg);
+}
+#endif
+
 int
 main(int argc, char **argv)
 {
   nsresult rv;
   char *lastSlash;
 
   char iniPath[MAXPATHLEN];
   char tmpPath[MAXPATHLEN];
@@ -372,16 +409,51 @@ main(int argc, char **argv)
   
   nsINIParser parser;
   rv = parser.Init(iniPath);
   if (NS_FAILED(rv)) {
     fprintf(stderr, "Could not read application.ini\n");
     return 1;
   }
 
+#ifdef WINCE
+  // On Windows Mobile and WinCE, we can save a lot of time by not
+  // waiting for XUL and XPCOM to load up.  Let's see if we can find
+  // an existing app window to forward our command-line to now.
+
+  // Shouldn't attempt this if the -no-remote parameter has been provided.
+  bool noRemote = false;
+  for (int i = 1; i < argc; i++) {
+    if (IsArg(argv[i], "no-remote")) {
+      noRemote = true;
+      break;
+    }
+  }
+
+  if (!noRemote) {
+    char windowName[512];  // Is there a const for appname like VERSION_MAXLEN?
+    rv = parser.GetString("App", "Name", windowName, sizeof(windowName));
+    if (NS_FAILED(rv)) {
+      fprintf(stderr, "Couldn't figure out the application name\n");
+      return 1;
+    }
+
+    // Lookup the hidden message window created by nsNativeAppSupport
+    strncat(windowName, "MessageWindow", sizeof(windowName));
+    WCHAR wWindowName[512];
+    MultiByteToWideChar(CP_UTF8, 0, windowName, -1, wWindowName, sizeof(wWindowName));
+    HWND wnd = ::FindWindowW(wWindowName, NULL);
+    if (wnd) {
+      // Forward the command-line and bail out
+      ForwardToWindow(wnd);
+      return 0;
+    }
+  }
+#endif
+
   if (!greFound) {
     char minVersion[VERSION_MAXLEN];
 
     // If a gecko maxVersion is not specified, we assume that the app uses only
     // frozen APIs, and is therefore compatible with any xulrunner 1.x.
     char maxVersion[VERSION_MAXLEN] = "1.*";
 
     GREVersionRange range = {