xulrunner/stub/nsXULStub.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "nsXPCOMGlue.h"
     6 #include "nsINIParser.h"
     7 #include "nsXPCOMPrivate.h" // for XP MAXPATHLEN
     8 #include "nsXULAppAPI.h"
     9 #include "nsIFile.h"
    11 #include <stdarg.h>
    13 #ifdef XP_WIN
    14 #include <windows.h>
    15 #include <io.h>
    16 #define snprintf _snprintf
    17 #define vsnprintf _vsnprintf
    18 #define strcasecmp _stricmp
    19 #define PATH_SEPARATOR_CHAR '\\'
    20 #define R_OK 04
    21 #elif defined(XP_MACOSX)
    22 #include <unistd.h>
    23 #include <sys/stat.h>
    24 #include <CoreFoundation/CoreFoundation.h>
    25 #define PATH_SEPARATOR_CHAR '/'
    26 #else
    27 #include <unistd.h>
    28 #include <sys/types.h>
    29 #include <sys/stat.h>
    30 #define PATH_SEPARATOR_CHAR '/'
    31 #endif
    33 #ifdef XP_WIN
    34 #define XRE_DONT_PROTECT_DLL_LOAD
    35 #include "nsWindowsWMain.cpp"
    36 #endif
    38 #define VERSION_MAXLEN 128
    40 static void Output(bool isError, const char *fmt, ... )
    41 {
    42   va_list ap;
    43   va_start(ap, fmt);
    45 #if (defined(XP_WIN) && !MOZ_WINCONSOLE)
    46   char msg[2048];
    48   vsnprintf(msg, sizeof(msg), fmt, ap);
    50   UINT flags = MB_OK;
    51   if (isError)
    52     flags |= MB_ICONERROR;
    53   else
    54     flags |= MB_ICONINFORMATION;
    56   wchar_t wide_msg[1024];
    57   MultiByteToWideChar(CP_ACP,
    58 		      0,
    59 		      msg,
    60 		      -1,
    61 		      wide_msg,
    62 		      sizeof(wide_msg) / sizeof(wchar_t));
    64   MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
    65 #else
    66   vfprintf(stderr, fmt, ap);
    67 #endif
    69   va_end(ap);
    70 }
    72 /**
    73  * Return true if |arg| matches the given argument name.
    74  */
    75 static bool IsArg(const char* arg, const char* s)
    76 {
    77   if (*arg == '-')
    78   {
    79     if (*++arg == '-')
    80       ++arg;
    81     return !strcasecmp(arg, s);
    82   }
    84 #if defined(XP_WIN)
    85   if (*arg == '/')
    86     return !strcasecmp(++arg, s);
    87 #endif
    89   return false;
    90 }
    92 /**
    93  * Return true if |aDir| is a valid file/directory.
    94  */
    95 static bool FolderExists(const char* aDir)
    96 {
    97 #ifdef XP_WIN
    98   wchar_t wideDir[MAX_PATH];
    99   MultiByteToWideChar(CP_UTF8, 0, aDir, -1, wideDir, MAX_PATH);
   100   DWORD fileAttrs = GetFileAttributesW(wideDir);
   101   return fileAttrs != INVALID_FILE_ATTRIBUTES;
   102 #else
   103   return access(aDir, R_OK) == 0;
   104 #endif
   105 }
   107 static nsresult GetRealPath(const char* appDataFile, char* *aResult)
   108 {
   109 #ifdef XP_WIN
   110   wchar_t wAppDataFile[MAX_PATH];
   111   wchar_t wIniPath[MAX_PATH];
   112   MultiByteToWideChar(CP_UTF8, 0, appDataFile, -1, wAppDataFile, MAX_PATH);
   113   _wfullpath(wIniPath, wAppDataFile, MAX_PATH);
   114   WideCharToMultiByte(CP_UTF8, 0, wIniPath, -1, *aResult, MAX_PATH, 0, 0);
   115 #else
   116   struct stat fileStat;
   117   if (!realpath(appDataFile, *aResult) || stat(*aResult, &fileStat))
   118     return NS_ERROR_FAILURE;
   119 #endif
   120   if (!*aResult || !**aResult)
   121     return NS_ERROR_FAILURE;
   123   return NS_OK;
   124 }
   126 class AutoAppData
   127 {
   128 public:
   129   AutoAppData(nsIFile* aINIFile) : mAppData(nullptr) {
   130     nsresult rv = XRE_CreateAppData(aINIFile, &mAppData);
   131     if (NS_FAILED(rv))
   132       mAppData = nullptr;
   133   }
   134   ~AutoAppData() {
   135     if (mAppData)
   136       XRE_FreeAppData(mAppData);
   137   }
   139   operator nsXREAppData*() const { return mAppData; }
   140   nsXREAppData* operator -> () const { return mAppData; }
   142 private:
   143   nsXREAppData* mAppData;
   144 };
   146 XRE_CreateAppDataType XRE_CreateAppData;
   147 XRE_FreeAppDataType XRE_FreeAppData;
   148 XRE_mainType XRE_main;
   150 int
   151 main(int argc, char **argv)
   152 {
   153   nsresult rv;
   154   char *lastSlash;
   156   char iniPath[MAXPATHLEN];
   157   char tmpPath[MAXPATHLEN];
   158   char greDir[MAXPATHLEN];
   159   bool greFound = false;
   161 #if defined(XP_MACOSX)
   162   CFBundleRef appBundle = CFBundleGetMainBundle();
   163   if (!appBundle)
   164     return 1;
   166   CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(appBundle);
   167   if (!resourcesURL)
   168     return 1;
   170   CFURLRef absResourcesURL = CFURLCopyAbsoluteURL(resourcesURL);
   171   CFRelease(resourcesURL);
   172   if (!absResourcesURL)
   173     return 1;
   175   CFURLRef iniFileURL =
   176     CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
   177                                           absResourcesURL,
   178                                           CFSTR("application.ini"),
   179                                           false);
   180   CFRelease(absResourcesURL);
   181   if (!iniFileURL)
   182     return 1;
   184   CFStringRef iniPathStr =
   185     CFURLCopyFileSystemPath(iniFileURL, kCFURLPOSIXPathStyle);
   186   CFRelease(iniFileURL);
   187   if (!iniPathStr)
   188     return 1;
   190   CFStringGetCString(iniPathStr, iniPath, sizeof(iniPath),
   191                      kCFStringEncodingUTF8);
   192   CFRelease(iniPathStr);
   194 #else
   196 #ifdef XP_WIN
   197   wchar_t wide_path[MAX_PATH];
   198   if (!::GetModuleFileNameW(nullptr, wide_path, MAX_PATH))
   199     return 1;
   201   WideCharToMultiByte(CP_UTF8, 0, wide_path,-1,
   202 		      iniPath, MAX_PATH, nullptr, nullptr);
   204 #else
   205   // on unix, there is no official way to get the path of the current binary.
   206   // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to
   207   // multiple applications, we will try a series of techniques:
   208   //
   209   // 1) use realpath() on argv[0], which works unless we're loaded from the
   210   //    PATH
   211   // 2) manually walk through the PATH and look for ourself
   212   // 3) give up
   214   struct stat fileStat;
   215   strncpy(tmpPath, argv[0], sizeof(tmpPath));
   216   lastSlash = strrchr(tmpPath, '/');
   217   if (lastSlash) {
   218     *lastSlash = 0;
   219     realpath(tmpPath, iniPath);
   220   } else {
   221     const char *path = getenv("PATH");
   222     if (!path)
   223       return 1;
   225     char *pathdup = strdup(path);
   226     if (!pathdup)
   227       return 1;
   229     bool found = false;
   230     char *token = strtok(pathdup, ":");
   231     while (token) {
   232       sprintf(tmpPath, "%s/%s", token, argv[0]);
   233       if (stat(tmpPath, &fileStat) == 0) {
   234         found = true;
   235         lastSlash = strrchr(tmpPath, '/');
   236         *lastSlash = 0;
   237         realpath(tmpPath, iniPath);
   238         break;
   239       }
   240       token = strtok(nullptr, ":");
   241     }
   242     free (pathdup);
   243     if (!found)
   244       return 1;
   245   }
   246   lastSlash = iniPath + strlen(iniPath);
   247   *lastSlash = '/';
   248 #endif
   250 #ifndef XP_UNIX
   251   lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
   252   if (!lastSlash)
   253     return 1;
   254 #endif
   256   *(++lastSlash) = '\0';
   258   // On Linux/Win, look for XULRunner in appdir/xulrunner
   260   snprintf(greDir, sizeof(greDir),
   261            "%sxulrunner" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL,
   262            iniPath);
   264   greFound = FolderExists(greDir);
   266 #ifdef XP_UNIX
   267   if (greFound) {
   268     char resolved_greDir[MAXPATHLEN] = "";
   269     if (realpath(greDir, resolved_greDir) && *resolved_greDir) {
   270       strncpy(greDir, resolved_greDir, MAXPATHLEN);
   271     }
   272   }
   273 #endif
   275   strncpy(lastSlash, "application.ini", sizeof(iniPath) - (lastSlash - iniPath));
   277 #endif
   279   // If -app parameter was passed in, it is now time to take it under 
   280   // consideration.
   281   const char *appDataFile;
   282   appDataFile = getenv("XUL_APP_FILE");
   283   if (!appDataFile || !*appDataFile) 
   284     if (argc > 1 && IsArg(argv[1], "app")) {
   285       if (argc == 2) {
   286         Output(false, "specify APP-FILE (optional)\n");
   287         return 1;
   288       }
   289       argv[1] = argv[0];
   290       ++argv;
   291       --argc;
   293       appDataFile = argv[1];
   294       argv[1] = argv[0];
   295       ++argv;
   296       --argc;
   298       char kAppEnv[MAXPATHLEN];
   299       snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile);
   300       if (putenv(kAppEnv)) 
   301         Output(false, "Couldn't set %s.\n", kAppEnv);
   303       char *result = (char*) calloc(sizeof(char), MAXPATHLEN);
   304       if (NS_FAILED(GetRealPath(appDataFile, &result))) {
   305         Output(true, "Invalid application.ini path.\n");
   306         return 1;
   307       }
   309       // We have a valid application.ini path passed in to the -app parameter 
   310       // but not yet a valid greDir, so lets look for it also on the same folder
   311       // as the stub.
   312       if (!greFound) {
   313         lastSlash = strrchr(iniPath, PATH_SEPARATOR_CHAR);
   314         if (!lastSlash)
   315           return 1;
   317         *(++lastSlash) = '\0';
   319         snprintf(greDir, sizeof(greDir), "%s" XPCOM_DLL, iniPath);
   320         greFound = FolderExists(greDir);
   321       }
   323       // copy it back.
   324       strcpy(iniPath, result);
   325     }
   327   nsINIParser parser;
   328   rv = parser.Init(iniPath);
   329   if (NS_FAILED(rv)) {
   330     fprintf(stderr, "Could not read application.ini\n");
   331     return 1;
   332   }
   334   if (!greFound) {
   335 #ifdef XP_MACOSX
   336     // Check for <bundle>/Contents/Frameworks/XUL.framework/Versions/Current/libmozglue.dylib
   337     CFURLRef fwurl = CFBundleCopyPrivateFrameworksURL(appBundle);
   338     CFURLRef absfwurl = nullptr;
   339     if (fwurl) {
   340       absfwurl = CFURLCopyAbsoluteURL(fwurl);
   341       CFRelease(fwurl);
   342     }
   344     if (absfwurl) {
   345       CFURLRef xulurl =
   346         CFURLCreateCopyAppendingPathComponent(nullptr, absfwurl,
   347                                               CFSTR("XUL.framework/Versions/Current"),
   348                                               true);
   350       if (xulurl) {
   351         CFURLRef xpcomurl =
   352           CFURLCreateCopyAppendingPathComponent(nullptr, xulurl,
   353                                                 CFSTR("libmozglue.dylib"),
   354                                                 false);
   356         if (xpcomurl) {
   357           char tbuffer[MAXPATHLEN];
   359           if (CFURLGetFileSystemRepresentation(xpcomurl, true,
   360                                                (UInt8*) tbuffer,
   361                                                sizeof(tbuffer)) &&
   362               access(tbuffer, R_OK | X_OK) == 0) {
   363             if (realpath(tbuffer, greDir)) {
   364               greFound = true;
   365             }
   366             else {
   367               greDir[0] = '\0';
   368             }
   369           }
   371           CFRelease(xpcomurl);
   372         }
   374         CFRelease(xulurl);
   375       }
   377       CFRelease(absfwurl);
   378     }
   379 #endif
   380     if (!greFound) {
   381       Output(false, "Could not find the Mozilla runtime.\n");
   382       return 1;
   383     }
   384   }
   386   rv = XPCOMGlueStartup(greDir);
   387   if (NS_FAILED(rv)) {
   388     if (rv == NS_ERROR_OUT_OF_MEMORY) {
   389       char applicationName[2000] = "this application";
   390       parser.GetString("App", "Name", applicationName, sizeof(applicationName));
   391       Output(true, "Not enough memory available to start %s.\n",
   392              applicationName);
   393     } else {
   394       Output(true, "Couldn't load XPCOM.\n");
   395     }
   396     return 1;
   397   }
   399   static const nsDynamicFunctionLoad kXULFuncs[] = {
   400     { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
   401     { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
   402     { "XRE_main", (NSFuncPtr*) &XRE_main },
   403     { nullptr, nullptr }
   404   };
   406   rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
   407   if (NS_FAILED(rv)) {
   408     Output(true, "Couldn't load XRE functions.\n");
   409     return 1;
   410   }
   412   NS_LogInit();
   414   int retval;
   416   { // Scope COMPtr and AutoAppData
   417     nsCOMPtr<nsIFile> iniFile;
   418 #ifdef XP_WIN
   419     // On Windows iniPath is UTF-8 encoded so we need to convert it.
   420     rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(iniPath), false,
   421                          getter_AddRefs(iniFile));
   422 #else
   423     rv = NS_NewNativeLocalFile(nsDependentCString(iniPath), false,
   424                                getter_AddRefs(iniFile));
   425 #endif
   426     if (NS_FAILED(rv)) {
   427       Output(true, "Couldn't find application.ini file.\n");
   428       return 1;
   429     }
   431     AutoAppData appData(iniFile);
   432     if (!appData) {
   433       Output(true, "Error: couldn't parse application.ini.\n");
   434       return 1;
   435     }
   437     NS_ASSERTION(appData->directory, "Failed to get app directory.");
   439     if (!appData->xreDirectory) {
   440       // chop "libxul.so" off the GRE path
   441       lastSlash = strrchr(greDir, PATH_SEPARATOR_CHAR);
   442       if (lastSlash) {
   443         *lastSlash = '\0';
   444       }
   445 #ifdef XP_WIN
   446       // same as iniPath.
   447       NS_NewLocalFile(NS_ConvertUTF8toUTF16(greDir), false,
   448                       &appData->xreDirectory);
   449 #else
   450       NS_NewNativeLocalFile(nsDependentCString(greDir), false,
   451                             &appData->xreDirectory);
   452 #endif
   453     }
   455     retval = XRE_main(argc, argv, appData, 0);
   456   }
   458   NS_LogTerm();
   460   return retval;
   461 }

mercurial