Bug 1079220 - Modify file structure of Instantbird to match toolkit changes - make nsMain.cpp match nsMailApp.cpp and related changes, r=clokep.
authorPatrick Cloke <clokep@gmail.com>
Tue, 07 Oct 2014 09:20:05 -0400
changeset 21095 8c265f33bf17c1e8e2f2c2411559836295a8f567
parent 21094 42ccebafcb895ac53cdaecaa603bc7f5d3f41519
child 21096 14326bac575ac680afd321de2b6e87c66ce66de1
push id1274
push usermbanner@mozilla.com
push dateMon, 12 Jan 2015 19:54:49 +0000
treeherdercomm-beta@baea280adc1c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersclokep
bugs1079220
Bug 1079220 - Modify file structure of Instantbird to match toolkit changes - make nsMain.cpp match nsMailApp.cpp and related changes, r=clokep.
im/app/moz.build
im/app/nsMain.cpp
im/confvars.sh
--- a/im/app/moz.build
+++ b/im/app/moz.build
@@ -1,15 +1,19 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += ['profile']
 
+GENERATED_INCLUDES += [
+    '/build',
+]
+
 if not CONFIG['LIBXUL_SDK']:
     Program(CONFIG['MOZ_APP_NAME'])
     SOURCES += ['nsMain.cpp']
     LOCAL_INCLUDES += [
         '/mozilla/toolkit/xre',
         '/mozilla/xpcom/base',
         '/mozilla/xpcom/build',
     ]
--- a/im/app/nsMain.cpp
+++ b/im/app/nsMain.cpp
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsXULAppAPI.h"
+#include "mozilla/AppData.h"
+#include "application.ini.h"
 #include "nsXPCOMGlue.h"
-#include "nsXULAppAPI.h"
 #if defined(XP_WIN)
 #include <windows.h>
 #include <stdlib.h>
 #elif defined(XP_UNIX)
 #include <sys/time.h>
 #include <sys/resource.h>
 #endif
 
@@ -31,149 +33,267 @@
 #define strcasecmp _stricmp
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #include "mozilla/Telemetry.h"
 
+using namespace mozilla;
+
+#ifdef XP_MACOSX
+#define kOSXResourcesFolder "Resources"
+#endif
+
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
-#if defined(XP_WIN) && !MOZ_WINCONSOLE
-  char16_t msg[2048];
-  _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
-  MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
+#ifndef XP_WIN
+  vfprintf(stderr, fmt, ap);
 #else
-  vfprintf(stderr, fmt, ap);
+  char msg[2048];
+  vsnprintf_s(msg, _countof(msg), _TRUNCATE, fmt, ap);
+
+  wchar_t wide_msg[2048];
+  MultiByteToWideChar(CP_UTF8,
+                      0,
+                      msg,
+                      -1,
+                      wide_msg,
+                      _countof(wide_msg));
+#if MOZ_WINCONSOLE
+  fwprintf_s(stderr, wide_msg);
+#else
+  // Linking user32 at load-time interferes with the DLL blocklist (bug 932100).
+  // This is a rare codepath, so we can load user32 at run-time instead.
+  HMODULE user32 = LoadLibraryW(L"user32.dll");
+  if (user32) {
+    typedef int (WINAPI * MessageBoxWFn)(HWND, LPCWSTR, LPCWSTR, UINT);
+    MessageBoxWFn messageBoxW = (MessageBoxWFn)GetProcAddress(user32, "MessageBoxW");
+    if (messageBoxW) {
+      messageBoxW(nullptr, wide_msg, L"Instantbird", MB_OK
+                                                   | MB_ICONERROR
+                                                   | MB_SETFOREGROUND);
+    }
+    FreeLibrary(user32);
+  }
+#endif
 #endif
 
   va_end(ap);
 }
 
-/**
- * A helper class which calls NS_LogInit/NS_LogTerm in its scope.
- */
-class ScopedLogging
-{
-public:
-  ScopedLogging() { NS_LogInit(); }
-  ~ScopedLogging() { NS_LogTerm(); }
-};
-
 XRE_GetFileFromPathType XRE_GetFileFromPath;
 XRE_CreateAppDataType XRE_CreateAppData;
 XRE_FreeAppDataType XRE_FreeAppData;
-#ifdef XRE_HAS_DLL_BLOCKLIST
-XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
-#endif
 XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
 XRE_mainType XRE_main;
 
 static const nsDynamicFunctionLoad kXULFuncs[] = {
     { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
     { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
     { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
-#ifdef XRE_HAS_DLL_BLOCKLIST
-    { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
-#endif
     { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
     { "XRE_main", (NSFuncPtr*) &XRE_main },
     { nullptr, nullptr }
 };
 
-static int do_main(const char *exePath, int argc, char* argv[])
+static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
 {
+  NS_LogInit();
+
   nsCOMPtr<nsIFile> appini;
+  nsresult rv;
+  uint32_t mainFlags = 0;
+
+  int result;
+  {
+    ScopedAppData appData(&sAppData);
+    nsCOMPtr<nsIFile> exeFile;
+    rv = mozilla::BinaryPath::GetFile(argv[0], getter_AddRefs(exeFile));
+    if (NS_FAILED(rv)) {
+      Output("Couldn't find the application directory.\n");
+      return 255;
+    }
+
+    nsCOMPtr<nsIFile> greDir;
+    exeFile->GetParent(getter_AddRefs(greDir));
+#ifdef XP_MACOSX
+    nsCOMPtr<nsIFile> parent;
+    greDir->GetParent(getter_AddRefs(parent));
+    greDir = parent.forget();
+    greDir->AppendNative(NS_LITERAL_CSTRING(kOSXResourcesFolder));
+#endif
+    SetStrongPtr(appData.directory, static_cast<nsIFile*>(greDir.get()));
+    // xreDirectory already has a refcount from NS_NewLocalFile
+    appData.xreDirectory = xreDirectory;
+
+    result = XRE_main(argc, argv, &appData, mainFlags);
+  }
+  return result;
+}
+
+static bool
+FileExists(const char *path)
+{
 #ifdef XP_WIN
-  // exePath comes from mozilla::BinaryPath::Get, which returns a UTF-8
-  // encoded path, so it is safe to convert it
-  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
-                                getter_AddRefs(appini));
+  wchar_t wideDir[MAX_PATH];
+  MultiByteToWideChar(CP_UTF8, 0, path, -1, wideDir, MAX_PATH);
+  DWORD fileAttrs = GetFileAttributesW(wideDir);
+  return fileAttrs != INVALID_FILE_ATTRIBUTES;
+#else
+  return access(path, R_OK) == 0;
+#endif
+}
+
+#ifdef LIBXUL_SDK
+#  define XPCOM_PATH "xulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL
 #else
-  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
-                                      getter_AddRefs(appini));
+#  define XPCOM_PATH XPCOM_DLL
 #endif
+static nsresult
+InitXPCOMGlue(const char *argv0, nsIFile **xreDirectory)
+{
+  char exePath[MAXPATHLEN];
+
+  nsresult rv = mozilla::BinaryPath::Get(argv0, exePath);
   if (NS_FAILED(rv)) {
-    return 255;
+    Output("Couldn't find the application directory.\n");
+    return rv;
   }
 
-  appini->AppendNative(NS_LITERAL_CSTRING("application.ini"));
+  char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
+  if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_PATH) - 1))
+    return NS_ERROR_FAILURE;
+
+  strcpy(lastSlash + 1, XPCOM_PATH);
+  lastSlash += sizeof(XPCOM_PATH) - sizeof(XPCOM_DLL);
+
+  if (!FileExists(exePath)) {
+#if defined(LIBXUL_SDK) && defined(XP_MACOSX)
+    // Check for <bundle>/Contents/Frameworks/XUL.framework/libxpcom.dylib
+    bool greFound = false;
+    CFBundleRef appBundle = CFBundleGetMainBundle();
+    if (!appBundle)
+      return NS_ERROR_FAILURE;
+    CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle);
+    CFURLRef absfwurl = nullptr;
+    if (fwurl) {
+      absfwurl = CFURLCopyAbsoluteURL(fwurl);
+      CFRelease(fwurl);
+    }
+    if (absfwurl) {
+      CFURLRef xulurl =
+        CFURLCreateCopyAppendingPathComponent(nullptr, absfwurl,
+                                              CFSTR("XUL.framework"),
+                                              true);
 
-  nsXREAppData *appData;
-  rv = XRE_CreateAppData(appini, &appData);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't read application.ini");
-    return 255;
+      if (xulurl) {
+        CFURLRef xpcomurl =
+          CFURLCreateCopyAppendingPathComponent(nullptr, xulurl,
+                                                CFSTR("libxpcom.dylib"),
+                                                false);
+
+        if (xpcomurl) {
+          if (CFURLGetFileSystemRepresentation(xpcomurl, true,
+                                               (UInt8*) exePath,
+                                               sizeof(exePath)) &&
+              access(tbuffer, R_OK | X_OK) == 0) {
+            if (realpath(tbuffer, exePath)) {
+              greFound = true;
+            }
+          }
+          CFRelease(xpcomurl);
+        }
+        CFRelease(xulurl);
+      }
+      CFRelease(absfwurl);
+    }
+  }
+  if (!greFound) {
+#endif
+    Output("Could not find the Mozilla runtime.\n");
+    return NS_ERROR_FAILURE;
   }
 
-  int result = XRE_main(argc, argv, appData, 0);
-  XRE_FreeAppData(appData);
-  return result;
+  // We do this because of data in bug 771745
+  XPCOMGlueEnablePreload();
+
+  rv = XPCOMGlueStartup(exePath);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't load XPCOM.\n");
+    return rv;
+  }
+
+  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
+  if (NS_FAILED(rv)) {
+    Output("Couldn't load XRE functions.\n");
+    return rv;
+  }
+
+  NS_LogInit();
+
+  // chop XPCOM_DLL off exePath
+  *lastSlash = '\0';
+#ifdef XP_MACOSX
+  lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
+  strcpy(lastSlash + 1, kOSXResourcesFolder);
+#endif
+#ifdef XP_WIN
+  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
+                       xreDirectory);
+#else
+  rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
+                             xreDirectory);
+#endif
+
+  return rv;
 }
 
 int main(int argc, char* argv[])
 {
-  char exePath[MAXPATHLEN];
-
 #ifdef XP_MACOSX
   TriggerQuirks();
 #endif
 
-  nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't calculate the application directory.\n");
-    return 255;
-  }
-
-  char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
-  if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
-    return 255;
-
-  strcpy(++lastSlash, XPCOM_DLL);
-
   int gotCounters;
 #if defined(XP_UNIX)
   struct rusage initialRUsage;
   gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
 #elif defined(XP_WIN)
   // GetProcessIoCounters().ReadOperationCount seems to have little to
   // do with actual read operations. It reports 0 or 1 at this stage
   // in the program. Luckily 1 coincides with when prefetch is
   // enabled. If Windows prefetch didn't happen we can do our own
   // faster dll preloading.
   IO_COUNTERS ioCounters;
   gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
-  if (gotCounters && !ioCounters.ReadOperationCount)
 #endif
-  {
-      XPCOMGlueEnablePreload();
+
+  nsIFile *xreDirectory;
+
+#ifdef HAS_DLL_BLOCKLIST
+  DllBlocklist_Initialize();
+
+#ifdef DEBUG
+  // In order to be effective against AppInit DLLs, the blocklist must be
+  // initialized before user32.dll is loaded into the process (bug 932100).
+  if (GetModuleHandleA("user32.dll")) {
+    fprintf(stderr, "DLL blocklist was unable to intercept AppInit DLLs.\n");
   }
-
+#endif
+#endif
 
-  rv = XPCOMGlueStartup(exePath);
+  nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
   if (NS_FAILED(rv)) {
-    Output("Couldn't load XPCOM.\n");
     return 255;
   }
-  // Reset exePath so that it is the directory name and not the xpcom dll name
-  *lastSlash = 0;
-
-  rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
-  if (NS_FAILED(rv)) {
-    Output("Couldn't load XRE functions.\n");
-    return 255;
-  }
-
-#ifdef XRE_HAS_DLL_BLOCKLIST
-  XRE_SetupDllBlocklist();
-#endif
 
   if (gotCounters) {
 #if defined(XP_WIN)
     XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
                             int(ioCounters.ReadOperationCount));
     XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_TRANSFER,
                             int(ioCounters.ReadTransferCount / 1024));
     IO_COUNTERS newIoCounters;
@@ -189,16 +309,14 @@ int main(int argc, char* argv[])
     struct rusage newRUsage;
     if (!getrusage(RUSAGE_SELF, &newRUsage)) {
       XRE_TelemetryAccumulate(mozilla::Telemetry::GLUESTARTUP_HARD_FAULTS,
                               int(newRUsage.ru_majflt - initialRUsage.ru_majflt));
     }
 #endif
   }
 
-  int result;
-  {
-    ScopedLogging log;
-    result = do_main(exePath, argc, argv);
-  }
+  int result = do_main(argc, argv, xreDirectory);
+
+  NS_LogTerm();
 
   return result;
 }
--- a/im/confvars.sh
+++ b/im/confvars.sh
@@ -1,14 +1,16 @@
 #! /bin/sh
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+MOZ_APP_BASENAME=Instantbird
 MOZ_APP_NAME=instantbird
+MOZ_APP_STATIC_INI=1
 MOZ_XUL_APP=1
 MOZ_ENABLE_LIBXUL=1
 MOZ_CHROME_FILE_FORMAT=omni
 MOZ_DISABLE_EXPORT_JS=1
 MOZ_UPDATER=1
 MOZ_MATHML=
 MOZ_MEDIA_NAVIGATOR=1