1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xulrunner/app/nsXULRunnerApp.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,303 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsXULAppAPI.h" 1.9 +#include "nsXPCOMGlue.h" 1.10 +#include <stdio.h> 1.11 +#include <stdlib.h> 1.12 +#ifdef XP_WIN 1.13 +#include <windows.h> 1.14 +#define snprintf _snprintf 1.15 +#define strcasecmp _stricmp 1.16 +#endif 1.17 + 1.18 +#include "nsAppRunner.h" 1.19 +#include "nsIFile.h" 1.20 +#include "nsCOMPtr.h" 1.21 +#include "nsMemory.h" 1.22 +#include "nsCRTGlue.h" 1.23 +#include "nsStringAPI.h" 1.24 +#include "nsServiceManagerUtils.h" 1.25 +#include "plstr.h" 1.26 +#include "prprf.h" 1.27 +#include "prenv.h" 1.28 +#include "nsINIParser.h" 1.29 + 1.30 +#ifdef XP_WIN 1.31 +#include "nsWindowsWMain.cpp" 1.32 +#endif 1.33 + 1.34 +#include "BinaryPath.h" 1.35 + 1.36 +#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL 1.37 + 1.38 +using namespace mozilla; 1.39 + 1.40 +/** 1.41 + * Output a string to the user. This method is really only meant to be used to 1.42 + * output last-ditch error messages designed for developers NOT END USERS. 1.43 + * 1.44 + * @param isError 1.45 + * Pass true to indicate severe errors. 1.46 + * @param fmt 1.47 + * printf-style format string followed by arguments. 1.48 + */ 1.49 +static void Output(bool isError, const char *fmt, ... ) 1.50 +{ 1.51 + va_list ap; 1.52 + va_start(ap, fmt); 1.53 + 1.54 +#if (defined(XP_WIN) && !MOZ_WINCONSOLE) 1.55 + char16_t msg[2048]; 1.56 + _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap); 1.57 + 1.58 + UINT flags = MB_OK; 1.59 + if (isError) 1.60 + flags |= MB_ICONERROR; 1.61 + else 1.62 + flags |= MB_ICONINFORMATION; 1.63 + 1.64 + MessageBoxW(nullptr, msg, L"XULRunner", flags); 1.65 +#else 1.66 + vfprintf(stderr, fmt, ap); 1.67 +#endif 1.68 + 1.69 + va_end(ap); 1.70 +} 1.71 + 1.72 +/** 1.73 + * Return true if |arg| matches the given argument name. 1.74 + */ 1.75 +static bool IsArg(const char* arg, const char* s) 1.76 +{ 1.77 + if (*arg == '-') 1.78 + { 1.79 + if (*++arg == '-') 1.80 + ++arg; 1.81 + return !strcasecmp(arg, s); 1.82 + } 1.83 + 1.84 +#if defined(XP_WIN) 1.85 + if (*arg == '/') 1.86 + return !strcasecmp(++arg, s); 1.87 +#endif 1.88 + 1.89 + return false; 1.90 +} 1.91 + 1.92 +static nsresult 1.93 +GetGREVersion(const char *argv0, 1.94 + nsACString *aMilestone, 1.95 + nsACString *aVersion) 1.96 +{ 1.97 + if (aMilestone) 1.98 + aMilestone->Assign("<Error>"); 1.99 + if (aVersion) 1.100 + aVersion->Assign("<Error>"); 1.101 + 1.102 + nsCOMPtr<nsIFile> iniFile; 1.103 + nsresult rv = BinaryPath::GetFile(argv0, getter_AddRefs(iniFile)); 1.104 + if (NS_FAILED(rv)) 1.105 + return rv; 1.106 + 1.107 + iniFile->SetNativeLeafName(NS_LITERAL_CSTRING("platform.ini")); 1.108 + 1.109 + nsINIParser parser; 1.110 + rv = parser.Init(iniFile); 1.111 + if (NS_FAILED(rv)) 1.112 + return rv; 1.113 + 1.114 + if (aMilestone) { 1.115 + rv = parser.GetString("Build", "Milestone", *aMilestone); 1.116 + if (NS_FAILED(rv)) 1.117 + return rv; 1.118 + } 1.119 + if (aVersion) { 1.120 + rv = parser.GetString("Build", "BuildID", *aVersion); 1.121 + if (NS_FAILED(rv)) 1.122 + return rv; 1.123 + } 1.124 + return NS_OK; 1.125 +} 1.126 + 1.127 +/** 1.128 + * A helper class which calls NS_LogInit/NS_LogTerm in its scope. 1.129 + */ 1.130 +class ScopedLogging 1.131 +{ 1.132 +public: 1.133 + ScopedLogging() { NS_LogInit(); } 1.134 + ~ScopedLogging() { NS_LogTerm(); } 1.135 +}; 1.136 + 1.137 +static void Usage(const char *argv0) 1.138 +{ 1.139 + nsAutoCString milestone; 1.140 + GetGREVersion(argv0, &milestone, nullptr); 1.141 + 1.142 + // display additional information (XXX make localizable?) 1.143 + Output(false, 1.144 + "Mozilla XULRunner %s\n\n" 1.145 + "Usage: " XULRUNNER_PROGNAME " [OPTIONS]\n" 1.146 + " " XULRUNNER_PROGNAME " APP-FILE [APP-OPTIONS...]\n" 1.147 + "\n" 1.148 + "OPTIONS\n" 1.149 + " --app specify APP-FILE (optional)\n" 1.150 + " -h, --help show this message\n" 1.151 + " -v, --version show version\n" 1.152 + " --gre-version print the GRE version string on stdout\n" 1.153 + "\n" 1.154 + "APP-FILE\n" 1.155 + " Application initialization file.\n" 1.156 + "\n" 1.157 + "APP-OPTIONS\n" 1.158 + " Application specific options.\n", 1.159 + milestone.get()); 1.160 +} 1.161 + 1.162 +XRE_GetFileFromPathType XRE_GetFileFromPath; 1.163 +XRE_CreateAppDataType XRE_CreateAppData; 1.164 +XRE_FreeAppDataType XRE_FreeAppData; 1.165 +XRE_mainType XRE_main; 1.166 + 1.167 +static const nsDynamicFunctionLoad kXULFuncs[] = { 1.168 + { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, 1.169 + { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData }, 1.170 + { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData }, 1.171 + { "XRE_main", (NSFuncPtr*) &XRE_main }, 1.172 + { nullptr, nullptr } 1.173 +}; 1.174 + 1.175 +class AutoAppData 1.176 +{ 1.177 +public: 1.178 + AutoAppData(nsIFile* aINIFile) : mAppData(nullptr) { 1.179 + nsresult rv = XRE_CreateAppData(aINIFile, &mAppData); 1.180 + if (NS_FAILED(rv)) 1.181 + mAppData = nullptr; 1.182 + } 1.183 + ~AutoAppData() { 1.184 + if (mAppData) 1.185 + XRE_FreeAppData(mAppData); 1.186 + } 1.187 + 1.188 + operator nsXREAppData*() const { return mAppData; } 1.189 + nsXREAppData* operator -> () const { return mAppData; } 1.190 + 1.191 +private: 1.192 + nsXREAppData* mAppData; 1.193 +}; 1.194 + 1.195 +int main(int argc, char* argv[]) 1.196 +{ 1.197 + char exePath[MAXPATHLEN]; 1.198 + nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath); 1.199 + if (NS_FAILED(rv)) { 1.200 + Output(true, "Couldn't calculate the application directory.\n"); 1.201 + return 255; 1.202 + } 1.203 + 1.204 + char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); 1.205 + if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1)) 1.206 + return 255; 1.207 + 1.208 + strcpy(++lastSlash, XPCOM_DLL); 1.209 + 1.210 + rv = XPCOMGlueStartup(exePath); 1.211 + if (NS_FAILED(rv)) { 1.212 + Output(true, "Couldn't load XPCOM.\n"); 1.213 + return 255; 1.214 + } 1.215 + 1.216 + ScopedLogging log; 1.217 + 1.218 + if (argc > 1 && (IsArg(argv[1], "h") || 1.219 + IsArg(argv[1], "help") || 1.220 + IsArg(argv[1], "?"))) 1.221 + { 1.222 + Usage(argv[0]); 1.223 + return 0; 1.224 + } 1.225 + 1.226 + if (argc == 2 && (IsArg(argv[1], "v") || IsArg(argv[1], "version"))) 1.227 + { 1.228 + nsAutoCString milestone; 1.229 + nsAutoCString version; 1.230 + GetGREVersion(argv[0], &milestone, &version); 1.231 + Output(false, "Mozilla XULRunner %s - %s\n", 1.232 + milestone.get(), version.get()); 1.233 + return 0; 1.234 + } 1.235 + 1.236 + rv = XPCOMGlueLoadXULFunctions(kXULFuncs); 1.237 + if (NS_FAILED(rv)) { 1.238 + Output(true, "Couldn't load XRE functions.\n"); 1.239 + return 255; 1.240 + } 1.241 + 1.242 + if (argc > 1) { 1.243 + nsAutoCString milestone; 1.244 + rv = GetGREVersion(argv[0], &milestone, nullptr); 1.245 + if (NS_FAILED(rv)) 1.246 + return 2; 1.247 + 1.248 + if (IsArg(argv[1], "gre-version")) { 1.249 + if (argc != 2) { 1.250 + Usage(argv[0]); 1.251 + return 1; 1.252 + } 1.253 + 1.254 + printf("%s\n", milestone.get()); 1.255 + return 0; 1.256 + } 1.257 + 1.258 + if (IsArg(argv[1], "install-app")) { 1.259 + Output(true, "--install-app support has been removed. Use 'python install-app.py' instead.\n"); 1.260 + return 1; 1.261 + } 1.262 + } 1.263 + 1.264 + const char *appDataFile = getenv("XUL_APP_FILE"); 1.265 + 1.266 + if (!(appDataFile && *appDataFile)) { 1.267 + if (argc < 2) { 1.268 + Usage(argv[0]); 1.269 + return 1; 1.270 + } 1.271 + 1.272 + if (IsArg(argv[1], "app")) { 1.273 + if (argc == 2) { 1.274 + Usage(argv[0]); 1.275 + return 1; 1.276 + } 1.277 + argv[1] = argv[0]; 1.278 + ++argv; 1.279 + --argc; 1.280 + } 1.281 + 1.282 + appDataFile = argv[1]; 1.283 + argv[1] = argv[0]; 1.284 + ++argv; 1.285 + --argc; 1.286 + 1.287 + static char kAppEnv[MAXPATHLEN]; 1.288 + snprintf(kAppEnv, MAXPATHLEN, "XUL_APP_FILE=%s", appDataFile); 1.289 + putenv(kAppEnv); 1.290 + } 1.291 + 1.292 + nsCOMPtr<nsIFile> appDataLF; 1.293 + rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appDataLF)); 1.294 + if (NS_FAILED(rv)) { 1.295 + Output(true, "Error: unrecognized application.ini path.\n"); 1.296 + return 2; 1.297 + } 1.298 + 1.299 + AutoAppData appData(appDataLF); 1.300 + if (!appData) { 1.301 + Output(true, "Error: couldn't parse application.ini.\n"); 1.302 + return 2; 1.303 + } 1.304 + 1.305 + return XRE_main(argc, argv, appData, 0); 1.306 +}