diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in index 44c27a226c50..fa037012cefc 100644 --- a/toolkit/xre/Makefile.in +++ b/toolkit/xre/Makefile.in @@ -192,6 +192,7 @@ LOCAL_INCLUDES += \ -I$(topsrcdir)/dom/ipc \ -I$(topsrcdir)/toolkit/crashreporter \ -I$(topsrcdir)/dom/base \ + -I$(topsrcdir)/xpcom/build \ $(NULL) LOCAL_INCLUDES += \ diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index f6f491e0c150..a63545dfa3cc 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -251,6 +251,7 @@ static char **gQtOnlyArgv; #endif /* MOZ_X11 */ #include "nsGTKToolkit.h" #endif +#include "BinaryPath.h" // Save literal putenv string to environment variable. static void @@ -1435,141 +1436,10 @@ RemoteCommandLine(const char* aDesktopStartupID) } #endif // MOZ_ENABLE_XREMOTE -#ifdef XP_MACOSX -static char const *gBinaryPath; -#endif - nsresult XRE_GetBinaryPath(const char* argv0, nsILocalFile* *aResult) { - nsresult rv; - nsCOMPtr lf; - - // We need to use platform-specific hackery to find the - // path of this executable. This is copied, with some modifications, from - // nsGREDirServiceProvider.cpp - -#ifdef XP_WIN - PRUnichar exePath[MAXPATHLEN]; - - if (!::GetModuleFileNameW(0, exePath, MAXPATHLEN)) - return NS_ERROR_FAILURE; - - rv = NS_NewLocalFile(nsDependentString(exePath), PR_TRUE, - getter_AddRefs(lf)); - if (NS_FAILED(rv)) - return rv; - -#elif defined(XP_MACOSX) - if (gBinaryPath) - return NS_NewNativeLocalFile(nsDependentCString(gBinaryPath), PR_FALSE, - aResult); - - NS_NewNativeLocalFile(EmptyCString(), PR_TRUE, getter_AddRefs(lf)); - nsCOMPtr lfm (do_QueryInterface(lf)); - if (!lfm) - return NS_ERROR_FAILURE; - - // Works even if we're not bundled. - CFBundleRef appBundle = CFBundleGetMainBundle(); - if (!appBundle) - return NS_ERROR_FAILURE; - - CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle); - if (!executableURL) - return NS_ERROR_FAILURE; - rv = lfm->InitWithCFURL(executableURL); - CFRelease(executableURL); - if (NS_FAILED(rv)) - return rv; - - // Callers expect a normalized path. - lfm->Normalize(); - -#elif defined(XP_UNIX) - struct stat fileStat; - char exePath[MAXPATHLEN]; - char tmpPath[MAXPATHLEN]; - - rv = NS_ERROR_FAILURE; - - // on unix, there is no official way to get the path of the current binary. - // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to - // multiple applications, we will try a series of techniques: - // - // 1) look for /proc//exe which is a symlink to the executable on newer - // Linux kernels - // 2) use realpath() on argv[0], which works unless we're loaded from the - // PATH - // 3) manually walk through the PATH and look for ourself - // 4) give up - -// #ifdef __linux__ -// Commented out because it used to not work because it used to not deal -// with readlink not null-terminating the buffer. -#if 0 - int r = readlink("/proc/self/exe", exePath, MAXPATHLEN); - - if (r > 0 && r < MAXPATHLEN) { - exePath[r] = '\0'; - if (stat(exePath, &fileStat) == 0) { - rv = NS_OK; - } - } - -#endif - if (NS_FAILED(rv) && - realpath(argv0, exePath) && stat(exePath, &fileStat) == 0) { - rv = NS_OK; - } - - if (NS_FAILED(rv)) { - const char *path = getenv("PATH"); - if (!path) - return NS_ERROR_FAILURE; - - char *pathdup = strdup(path); - if (!pathdup) - return NS_ERROR_OUT_OF_MEMORY; - - PRBool found = PR_FALSE; - char *newStr = pathdup; - char *token; - while ( (token = nsCRT::strtok(newStr, ":", &newStr)) ) { - sprintf(tmpPath, "%s/%s", token, argv0); - if (realpath(tmpPath, exePath) && stat(exePath, &fileStat) == 0) { - found = PR_TRUE; - break; - } - } - free(pathdup); - if (!found) - return NS_ERROR_FAILURE; - } - - rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE, - getter_AddRefs(lf)); - if (NS_FAILED(rv)) - return rv; - -#elif defined(XP_OS2) - PPIB ppib; - PTIB ptib; - char exePath[MAXPATHLEN]; - - DosGetInfoBlocks( &ptib, &ppib); - DosQueryModuleName( ppib->pib_hmte, MAXPATHLEN, exePath); - rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE, - getter_AddRefs(lf)); - if (NS_FAILED(rv)) - return rv; - -#else -#error Oops, you need platform-specific code here -#endif - - NS_ADDREF(*aResult = lf); - return NS_OK; + return mozilla::BinaryPath::GetFile(argv0, aResult); } #define NS_ERROR_LAUNCHED_CHILD_PROCESS NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PROFILE, 200) @@ -2821,16 +2691,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) NS_ENSURE_TRUE(aAppData, 2); -#ifdef XP_MACOSX - // The xulrunner stub executable tricks CFBundleGetMainBundle on - // purpose into lying about the main bundle path. It will set - // XRE_BINARY_PATH to inform us of our real location. - gBinaryPath = getenv("XRE_BINARY_PATH"); - - if (gBinaryPath && !*gBinaryPath) - gBinaryPath = nsnull; -#endif - // Check for application.ini overrides const char* override = nsnull; ar = CheckArg("override", PR_TRUE, &override); @@ -3750,14 +3610,6 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD); SaveWordToEnvIfUnset("XRE_PROFILE_NAME", profileName); -#ifdef XP_MACOSX - if (gBinaryPath) { - static char kEnvVar[MAXPATHLEN]; - sprintf(kEnvVar, "XRE_BINARY_PATH=%s", gBinaryPath); - PR_SetEnv(kEnvVar); - } -#endif - #ifdef MOZ_WIDGET_GTK2 MOZ_gdk_display_close(display); #endif diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h new file mode 100644 index 000000000000..ba1e58db9249 --- /dev/null +++ b/xpcom/build/BinaryPath.h @@ -0,0 +1,178 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mike Hommey + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef mozilla_BinaryPath_h +#define mozilla_BinaryPath_h + +#include "nsXPCOMPrivate.h" // for MAXPATHLEN +#include "prtypes.h" +#ifdef XP_WIN +#include +#elif defined(XP_MACOSX) +#include +#elif defined(XP_UNIX) +#include +#endif + +namespace mozilla { + +class BinaryPath { +public: +#ifdef XP_WIN + static nsresult Get(const char *argv0, char aResult[MAXPATHLEN]) + { + PRUnichar wide_path[MAXPATHLEN]; + nsresult rv = GetW(argv0, wide_path); + if (NS_FAILED(rv)) + return rv; + WideCharToMultiByte(CP_UTF8, 0, wide_path, -1, + aResult, MAXPATHLEN, NULL, NULL); + return NS_OK; + } + +private: + static nsresult GetW(const char *argv0, PRUnichar aResult[MAXPATHLEN]) + { + if (::GetModuleFileNameW(0, aResult, MAXPATHLEN)) + return NS_OK; + return NS_ERROR_FAILURE; + } + +#elif defined(XP_MACOSX) + static nsresult Get(const char *argv0, char aResult[MAXPATHLEN]) + { + // Works even if we're not bundled. + CFBundleRef appBundle = CFBundleGetMainBundle(); + if (!appBundle) + return NS_ERROR_FAILURE; + + CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle); + if (!executableURL) + return NS_ERROR_FAILURE; + + nsresult rv; + if (CFURLGetFileSystemRepresentation(executableURL, false, (UInt8 *)aResult, MAXPATHLEN)) + rv = NS_OK; + else + rv = NS_ERROR_FAILURE; + CFRelease(executableURL); + return rv; + } + +#elif defined(XP_UNIX) + static nsresult Get(const char *argv0, char aResult[MAXPATHLEN]) + { + struct stat fileStat; + // on unix, there is no official way to get the path of the current binary. + // instead of using the MOZILLA_FIVE_HOME hack, which doesn't scale to + // multiple applications, we will try a series of techniques: + // + // 1) use realpath() on argv[0], which works unless we're loaded from the + // PATH + // 2) manually walk through the PATH and look for ourself + // 3) give up + if (realpath(argv0, aResult) && stat(aResult, &fileStat) == 0) + return NS_OK; + + const char *path = getenv("PATH"); + if (!path) + return NS_ERROR_FAILURE; + + char *pathdup = strdup(path); + if (!pathdup) + return NS_ERROR_OUT_OF_MEMORY; + + PRBool found = PR_FALSE; + char *token = strtok(pathdup, ":"); + while (token) { + char tmpPath[MAXPATHLEN]; + sprintf(tmpPath, "%s/%s", token, argv0); + if (realpath(tmpPath, aResult) && stat(aResult, &fileStat) == 0) { + found = PR_TRUE; + break; + } + token = strtok(NULL, ":"); + } + free(pathdup); + if (found) + return NS_OK; + return NS_ERROR_FAILURE; + } + +#elif defined(XP_OS2) + static nsresult Get(const char *argv0, char aResult[MAXPATHLEN]) + { + PPIB ppib; + PTIB ptib; + DosGetInfoBlocks( &ptib, &ppib); + DosQueryModuleName(ppib->pib_hmte, MAXPATHLEN, aResult); + } + +#else +#error Oops, you need platform-specific code here +#endif + +public: + static nsresult GetFile(const char *argv0, nsILocalFile* *aResult) + { + nsCOMPtr lf; +#ifdef XP_WIN + PRUnichar exePath[MAXPATHLEN]; + nsresult rv = GetW(argv0, exePath); +#else + char exePath[MAXPATHLEN]; + nsresult rv = Get(argv0, exePath); +#endif + if (NS_FAILED(rv)) + return rv; +#ifdef XP_WIN + rv = NS_NewLocalFile(nsDependentString(exePath), PR_TRUE, + getter_AddRefs(lf)); +#else + rv = NS_NewNativeLocalFile(nsDependentCString(exePath), PR_TRUE, + getter_AddRefs(lf)); +#endif + if (NS_FAILED(rv)) + return rv; + NS_ADDREF(*aResult = lf); + return NS_OK; + } +}; + +} + +#endif /* mozilla_BinaryPath_h */