Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 5 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | // System headers (alphabetical) |
michael@0 | 8 | #include <fcntl.h> |
michael@0 | 9 | #include <io.h> |
michael@0 | 10 | #include <share.h> |
michael@0 | 11 | #include <sys/stat.h> |
michael@0 | 12 | #include <windows.h> |
michael@0 | 13 | |
michael@0 | 14 | // Mozilla headers (alphabetical) |
michael@0 | 15 | #include "nsIFile.h" |
michael@0 | 16 | #include "nsINIParser.h" |
michael@0 | 17 | #include "nsWindowsWMain.cpp" // we want a wmain entry point |
michael@0 | 18 | #include "nsXPCOMGlue.h" |
michael@0 | 19 | #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL |
michael@0 | 20 | #include "nsXULAppAPI.h" |
michael@0 | 21 | #include "mozilla/AppData.h" |
michael@0 | 22 | |
michael@0 | 23 | using namespace mozilla; |
michael@0 | 24 | |
michael@0 | 25 | XRE_GetFileFromPathType XRE_GetFileFromPath; |
michael@0 | 26 | XRE_CreateAppDataType XRE_CreateAppData; |
michael@0 | 27 | XRE_FreeAppDataType XRE_FreeAppData; |
michael@0 | 28 | XRE_mainType XRE_main; |
michael@0 | 29 | |
michael@0 | 30 | namespace { |
michael@0 | 31 | const char kAPP_INI[] = "application.ini"; |
michael@0 | 32 | const char kWEBAPP_INI[] = "webapp.ini"; |
michael@0 | 33 | const char kWEBAPPRT_INI[] = "webapprt.ini"; |
michael@0 | 34 | const char kWEBAPPRT_PATH[] = "webapprt"; |
michael@0 | 35 | const char kAPP_ENV_PREFIX[] = "XUL_APP_FILE="; |
michael@0 | 36 | const char kAPP_RT[] = "webapprt-stub.exe"; |
michael@0 | 37 | |
michael@0 | 38 | const wchar_t kAPP_RT_BACKUP[] = L"webapprt.old"; |
michael@0 | 39 | |
michael@0 | 40 | wchar_t curExePath[MAXPATHLEN]; |
michael@0 | 41 | wchar_t backupFilePath[MAXPATHLEN]; |
michael@0 | 42 | wchar_t iconPath[MAXPATHLEN]; |
michael@0 | 43 | char profile[MAXPATHLEN]; |
michael@0 | 44 | bool isProfileOverridden = false; |
michael@0 | 45 | int* pargc; |
michael@0 | 46 | char*** pargv; |
michael@0 | 47 | |
michael@0 | 48 | nsresult |
michael@0 | 49 | joinPath(char* const dest, |
michael@0 | 50 | char const* const dir, |
michael@0 | 51 | char const* const leaf, |
michael@0 | 52 | size_t bufferSize) |
michael@0 | 53 | { |
michael@0 | 54 | size_t dirLen = strlen(dir); |
michael@0 | 55 | size_t leafLen = strlen(leaf); |
michael@0 | 56 | bool needsSeparator = (dirLen != 0 |
michael@0 | 57 | && dir[dirLen-1] != '\\' |
michael@0 | 58 | && leafLen != 0 |
michael@0 | 59 | && leaf[0] != '\\'); |
michael@0 | 60 | |
michael@0 | 61 | if (dirLen + (needsSeparator? 1 : 0) + leafLen >= bufferSize) { |
michael@0 | 62 | return NS_ERROR_FAILURE; |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | strncpy(dest, dir, bufferSize); |
michael@0 | 66 | char* destEnd = dest + dirLen; |
michael@0 | 67 | if (needsSeparator) { |
michael@0 | 68 | *(destEnd++) = '\\'; |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | strncpy(destEnd, leaf, leafLen); |
michael@0 | 72 | return NS_OK; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | /** |
michael@0 | 76 | * A helper class which calls NS_LogInit/NS_LogTerm in its scope. |
michael@0 | 77 | */ |
michael@0 | 78 | class ScopedLogging |
michael@0 | 79 | { |
michael@0 | 80 | public: |
michael@0 | 81 | ScopedLogging() { NS_LogInit(); } |
michael@0 | 82 | ~ScopedLogging() { NS_LogTerm(); } |
michael@0 | 83 | }; |
michael@0 | 84 | |
michael@0 | 85 | /** |
michael@0 | 86 | * A helper class for scope-guarding nsXREAppData. |
michael@0 | 87 | */ |
michael@0 | 88 | class ScopedXREAppData |
michael@0 | 89 | { |
michael@0 | 90 | public: |
michael@0 | 91 | ScopedXREAppData() |
michael@0 | 92 | : mAppData(nullptr) { } |
michael@0 | 93 | |
michael@0 | 94 | nsresult |
michael@0 | 95 | create(nsIFile* aINIFile) |
michael@0 | 96 | { |
michael@0 | 97 | return XRE_CreateAppData(aINIFile, &mAppData); |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | ~ScopedXREAppData() |
michael@0 | 101 | { |
michael@0 | 102 | if (nullptr != mAppData) { |
michael@0 | 103 | XRE_FreeAppData(mAppData); |
michael@0 | 104 | } |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | nsXREAppData* const |
michael@0 | 108 | operator->() |
michael@0 | 109 | { |
michael@0 | 110 | return get(); |
michael@0 | 111 | } |
michael@0 | 112 | |
michael@0 | 113 | nsXREAppData |
michael@0 | 114 | operator*() |
michael@0 | 115 | { |
michael@0 | 116 | return *get(); |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | operator |
michael@0 | 120 | nsXREAppData*() |
michael@0 | 121 | { |
michael@0 | 122 | return get(); |
michael@0 | 123 | } |
michael@0 | 124 | private: |
michael@0 | 125 | nsXREAppData* mAppData; |
michael@0 | 126 | nsXREAppData* const get() { return mAppData; } |
michael@0 | 127 | }; |
michael@0 | 128 | |
michael@0 | 129 | void |
michael@0 | 130 | Output(const wchar_t *fmt, ... ) |
michael@0 | 131 | { |
michael@0 | 132 | va_list ap; |
michael@0 | 133 | va_start(ap, fmt); |
michael@0 | 134 | |
michael@0 | 135 | wchar_t msg[1024]; |
michael@0 | 136 | _vsnwprintf_s(msg, _countof(msg), _countof(msg), fmt, ap); |
michael@0 | 137 | |
michael@0 | 138 | MessageBoxW(nullptr, msg, L"Web Runtime", MB_OK); |
michael@0 | 139 | |
michael@0 | 140 | va_end(ap); |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | void |
michael@0 | 144 | Output(const char *fmt, ... ) |
michael@0 | 145 | { |
michael@0 | 146 | va_list ap; |
michael@0 | 147 | va_start(ap, fmt); |
michael@0 | 148 | |
michael@0 | 149 | char msg[1024]; |
michael@0 | 150 | vsnprintf(msg, sizeof(msg), fmt, ap); |
michael@0 | 151 | |
michael@0 | 152 | wchar_t wide_msg[1024]; |
michael@0 | 153 | MultiByteToWideChar(CP_UTF8, |
michael@0 | 154 | 0, |
michael@0 | 155 | msg, |
michael@0 | 156 | -1, |
michael@0 | 157 | wide_msg, |
michael@0 | 158 | _countof(wide_msg)); |
michael@0 | 159 | Output(wide_msg); |
michael@0 | 160 | |
michael@0 | 161 | va_end(ap); |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | const nsDynamicFunctionLoad kXULFuncs[] = { |
michael@0 | 165 | { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, |
michael@0 | 166 | { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData }, |
michael@0 | 167 | { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData }, |
michael@0 | 168 | { "XRE_main", (NSFuncPtr*) &XRE_main }, |
michael@0 | 169 | { nullptr, nullptr } |
michael@0 | 170 | }; |
michael@0 | 171 | |
michael@0 | 172 | bool |
michael@0 | 173 | AttemptCopyAndLaunch(wchar_t* src) |
michael@0 | 174 | { |
michael@0 | 175 | // Rename the old app executable |
michael@0 | 176 | if (FALSE == ::MoveFileExW(curExePath, |
michael@0 | 177 | backupFilePath, |
michael@0 | 178 | MOVEFILE_REPLACE_EXISTING)) { |
michael@0 | 179 | return false; |
michael@0 | 180 | } |
michael@0 | 181 | |
michael@0 | 182 | // Copy webapprt-stub.exe from the Firefox dir to the app's dir |
michael@0 | 183 | if (FALSE == ::CopyFileW(src, |
michael@0 | 184 | curExePath, |
michael@0 | 185 | TRUE)) { |
michael@0 | 186 | // Try to move the old file back to its original location |
michael@0 | 187 | ::MoveFileW(backupFilePath, |
michael@0 | 188 | curExePath); |
michael@0 | 189 | return false; |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | // XXX: We will soon embed the app's icon in the EXE here |
michael@0 | 193 | |
michael@0 | 194 | STARTUPINFOW si; |
michael@0 | 195 | PROCESS_INFORMATION pi; |
michael@0 | 196 | |
michael@0 | 197 | ::ZeroMemory(&si, sizeof(si)); |
michael@0 | 198 | si.cb = sizeof(si); |
michael@0 | 199 | ::ZeroMemory(&pi, sizeof(pi)); |
michael@0 | 200 | |
michael@0 | 201 | if (!CreateProcessW(curExePath, // Module name |
michael@0 | 202 | nullptr, // Command line |
michael@0 | 203 | nullptr, // Process handle not inheritable |
michael@0 | 204 | nullptr, // Thread handle not inheritable |
michael@0 | 205 | FALSE, // Set handle inheritance to FALSE |
michael@0 | 206 | 0, // No creation flags |
michael@0 | 207 | nullptr, // Use parent's environment block |
michael@0 | 208 | nullptr, // Use parent's starting directory |
michael@0 | 209 | &si, |
michael@0 | 210 | &pi)) { |
michael@0 | 211 | return false; |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | // Close process and thread handles. |
michael@0 | 215 | CloseHandle( pi.hProcess ); |
michael@0 | 216 | CloseHandle( pi.hThread ); |
michael@0 | 217 | |
michael@0 | 218 | return true; |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | bool |
michael@0 | 222 | AttemptCopyAndLaunch(char* srcUtf8) |
michael@0 | 223 | { |
michael@0 | 224 | wchar_t src[MAXPATHLEN]; |
michael@0 | 225 | if (0 == MultiByteToWideChar(CP_UTF8, |
michael@0 | 226 | 0, |
michael@0 | 227 | srcUtf8, |
michael@0 | 228 | -1, |
michael@0 | 229 | src, |
michael@0 | 230 | MAXPATHLEN)) { |
michael@0 | 231 | return false; |
michael@0 | 232 | } |
michael@0 | 233 | |
michael@0 | 234 | return AttemptCopyAndLaunch(src); |
michael@0 | 235 | } |
michael@0 | 236 | |
michael@0 | 237 | bool |
michael@0 | 238 | AttemptGRELoadAndLaunch(char* greDir) |
michael@0 | 239 | { |
michael@0 | 240 | nsresult rv; |
michael@0 | 241 | |
michael@0 | 242 | char xpcomDllPath[MAXPATHLEN]; |
michael@0 | 243 | rv = joinPath(xpcomDllPath, greDir, XPCOM_DLL, MAXPATHLEN); |
michael@0 | 244 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 245 | |
michael@0 | 246 | rv = XPCOMGlueStartup(xpcomDllPath); |
michael@0 | 247 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 248 | |
michael@0 | 249 | rv = XPCOMGlueLoadXULFunctions(kXULFuncs); |
michael@0 | 250 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 251 | |
michael@0 | 252 | // NOTE: The GRE has successfully loaded, so we can use XPCOM now |
michael@0 | 253 | { // Scope for any XPCOM stuff we create |
michael@0 | 254 | |
michael@0 | 255 | ScopedLogging log; |
michael@0 | 256 | |
michael@0 | 257 | // Get the path to the runtime. |
michael@0 | 258 | char rtPath[MAXPATHLEN]; |
michael@0 | 259 | rv = joinPath(rtPath, greDir, kWEBAPPRT_PATH, MAXPATHLEN); |
michael@0 | 260 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 261 | |
michael@0 | 262 | // Get the path to the runtime's INI file. |
michael@0 | 263 | char rtIniPath[MAXPATHLEN]; |
michael@0 | 264 | rv = joinPath(rtIniPath, rtPath, kWEBAPPRT_INI, MAXPATHLEN); |
michael@0 | 265 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 266 | |
michael@0 | 267 | // Load the runtime's INI from its path. |
michael@0 | 268 | nsCOMPtr<nsIFile> rtINI; |
michael@0 | 269 | rv = XRE_GetFileFromPath(rtIniPath, getter_AddRefs(rtINI)); |
michael@0 | 270 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 271 | |
michael@0 | 272 | bool exists; |
michael@0 | 273 | rv = rtINI->Exists(&exists); |
michael@0 | 274 | if (NS_FAILED(rv) || !exists) |
michael@0 | 275 | return false; |
michael@0 | 276 | |
michael@0 | 277 | ScopedXREAppData webShellAppData; |
michael@0 | 278 | rv = webShellAppData.create(rtINI); |
michael@0 | 279 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 280 | |
michael@0 | 281 | if (!isProfileOverridden) { |
michael@0 | 282 | SetAllocatedString(webShellAppData->profile, profile); |
michael@0 | 283 | SetAllocatedString(webShellAppData->name, profile); |
michael@0 | 284 | } |
michael@0 | 285 | |
michael@0 | 286 | nsCOMPtr<nsIFile> directory; |
michael@0 | 287 | rv = XRE_GetFileFromPath(rtPath, getter_AddRefs(directory)); |
michael@0 | 288 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 289 | |
michael@0 | 290 | nsCOMPtr<nsIFile> xreDir; |
michael@0 | 291 | rv = XRE_GetFileFromPath(greDir, getter_AddRefs(xreDir)); |
michael@0 | 292 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 293 | |
michael@0 | 294 | xreDir.forget(&webShellAppData->xreDirectory); |
michael@0 | 295 | NS_IF_RELEASE(webShellAppData->directory); |
michael@0 | 296 | directory.forget(&webShellAppData->directory); |
michael@0 | 297 | |
michael@0 | 298 | // There is only XUL. |
michael@0 | 299 | XRE_main(*pargc, *pargv, webShellAppData, 0); |
michael@0 | 300 | } |
michael@0 | 301 | |
michael@0 | 302 | return true; |
michael@0 | 303 | } |
michael@0 | 304 | |
michael@0 | 305 | bool |
michael@0 | 306 | AttemptLoadFromDir(char* firefoxDir) |
michael@0 | 307 | { |
michael@0 | 308 | nsresult rv; |
michael@0 | 309 | |
michael@0 | 310 | // Here we're going to open Firefox's application.ini |
michael@0 | 311 | char appIniPath[MAXPATHLEN]; |
michael@0 | 312 | rv = joinPath(appIniPath, firefoxDir, kAPP_INI, MAXPATHLEN); |
michael@0 | 313 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 314 | |
michael@0 | 315 | nsINIParser parser; |
michael@0 | 316 | rv = parser.Init(appIniPath); |
michael@0 | 317 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 318 | |
michael@0 | 319 | // Get buildid of FF we're trying to load |
michael@0 | 320 | char buildid[MAXPATHLEN]; // This isn't a path, so MAXPATHLEN doesn't |
michael@0 | 321 | // necessarily make sense, but it's a |
michael@0 | 322 | // convenient number to use. |
michael@0 | 323 | rv = parser.GetString("App", |
michael@0 | 324 | "BuildID", |
michael@0 | 325 | buildid, |
michael@0 | 326 | MAXPATHLEN); |
michael@0 | 327 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 328 | |
michael@0 | 329 | if (0 == strcmp(buildid, NS_STRINGIFY(GRE_BUILDID))) { |
michael@0 | 330 | return AttemptGRELoadAndLaunch(firefoxDir); |
michael@0 | 331 | } |
michael@0 | 332 | |
michael@0 | 333 | char webAppRTExe[MAXPATHLEN]; |
michael@0 | 334 | rv = joinPath(webAppRTExe, firefoxDir, kAPP_RT, MAXPATHLEN); |
michael@0 | 335 | NS_ENSURE_SUCCESS(rv, false); |
michael@0 | 336 | |
michael@0 | 337 | return AttemptCopyAndLaunch(webAppRTExe); |
michael@0 | 338 | } |
michael@0 | 339 | |
michael@0 | 340 | bool |
michael@0 | 341 | GetFirefoxDirFromRegistry(char* firefoxDir) |
michael@0 | 342 | { |
michael@0 | 343 | HKEY key; |
michael@0 | 344 | wchar_t wideGreDir[MAXPATHLEN]; |
michael@0 | 345 | |
michael@0 | 346 | if (ERROR_SUCCESS != |
michael@0 | 347 | RegOpenKeyExW(HKEY_LOCAL_MACHINE, |
michael@0 | 348 | L"SOFTWARE\\Microsoft\\Windows" |
michael@0 | 349 | L"\\CurrentVersion\\App paths\\firefox.exe", |
michael@0 | 350 | 0, |
michael@0 | 351 | KEY_READ, |
michael@0 | 352 | &key)) { |
michael@0 | 353 | return false; |
michael@0 | 354 | } |
michael@0 | 355 | |
michael@0 | 356 | DWORD length = MAXPATHLEN * sizeof(wchar_t); |
michael@0 | 357 | // XXX: When Vista/XP64 become our minimum supported client, we can use |
michael@0 | 358 | // RegGetValue instead |
michael@0 | 359 | if (ERROR_SUCCESS != RegQueryValueExW(key, |
michael@0 | 360 | L"Path", |
michael@0 | 361 | nullptr, |
michael@0 | 362 | nullptr, |
michael@0 | 363 | reinterpret_cast<BYTE*>(wideGreDir), |
michael@0 | 364 | &length)) { |
michael@0 | 365 | RegCloseKey(key); |
michael@0 | 366 | return false; |
michael@0 | 367 | }; |
michael@0 | 368 | RegCloseKey(key); |
michael@0 | 369 | |
michael@0 | 370 | // According to this article, we need to write our own null terminator: |
michael@0 | 371 | // http://msdn.microsoft.com/en-us/library/ms724911%28v=vs.85%29.aspx |
michael@0 | 372 | length = length / sizeof(wchar_t); |
michael@0 | 373 | if (wideGreDir[length] != L'\0') { |
michael@0 | 374 | if (length >= MAXPATHLEN) { |
michael@0 | 375 | return false; |
michael@0 | 376 | } |
michael@0 | 377 | wideGreDir[length] = L'\0'; |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | if (0 == WideCharToMultiByte(CP_UTF8, |
michael@0 | 381 | 0, |
michael@0 | 382 | wideGreDir, |
michael@0 | 383 | -1, |
michael@0 | 384 | firefoxDir, |
michael@0 | 385 | MAXPATHLEN, |
michael@0 | 386 | nullptr, |
michael@0 | 387 | nullptr)) { |
michael@0 | 388 | return false; |
michael@0 | 389 | } |
michael@0 | 390 | |
michael@0 | 391 | return true; |
michael@0 | 392 | } |
michael@0 | 393 | }; |
michael@0 | 394 | |
michael@0 | 395 | |
michael@0 | 396 | |
michael@0 | 397 | ////////////////////////////////////////////////////////////////////////////// |
michael@0 | 398 | // main |
michael@0 | 399 | // |
michael@0 | 400 | // Note: XPCOM cannot be used until AttemptGRELoad has returned successfully. |
michael@0 | 401 | int |
michael@0 | 402 | main(int argc, char* argv[]) |
michael@0 | 403 | { |
michael@0 | 404 | pargc = &argc; |
michael@0 | 405 | pargv = &argv; |
michael@0 | 406 | nsresult rv; |
michael@0 | 407 | char buffer[MAXPATHLEN]; |
michael@0 | 408 | wchar_t wbuffer[MAXPATHLEN]; |
michael@0 | 409 | |
michael@0 | 410 | // Set up curEXEPath |
michael@0 | 411 | if (!GetModuleFileNameW(0, wbuffer, MAXPATHLEN)) { |
michael@0 | 412 | Output("Couldn't calculate the application directory."); |
michael@0 | 413 | return 255; |
michael@0 | 414 | } |
michael@0 | 415 | wcsncpy(curExePath, wbuffer, MAXPATHLEN); |
michael@0 | 416 | |
michael@0 | 417 | // Get the current directory into wbuffer |
michael@0 | 418 | wchar_t* lastSlash = wcsrchr(wbuffer, L'\\'); |
michael@0 | 419 | if (!lastSlash) { |
michael@0 | 420 | Output("Application directory format not understood."); |
michael@0 | 421 | return 255; |
michael@0 | 422 | } |
michael@0 | 423 | *(++lastSlash) = L'\0'; |
michael@0 | 424 | |
michael@0 | 425 | // Set up backup file path |
michael@0 | 426 | if (wcslen(wbuffer) + _countof(kAPP_RT_BACKUP) >= MAXPATHLEN) { |
michael@0 | 427 | Output("Application directory path is too long (couldn't set up backup file path)."); |
michael@0 | 428 | } |
michael@0 | 429 | wcsncpy(lastSlash, kAPP_RT_BACKUP, _countof(kAPP_RT_BACKUP)); |
michael@0 | 430 | wcsncpy(backupFilePath, wbuffer, MAXPATHLEN); |
michael@0 | 431 | |
michael@0 | 432 | *lastSlash = L'\0'; |
michael@0 | 433 | |
michael@0 | 434 | // Convert current directory to utf8 and stuff it in buffer |
michael@0 | 435 | if (0 == WideCharToMultiByte(CP_UTF8, |
michael@0 | 436 | 0, |
michael@0 | 437 | wbuffer, |
michael@0 | 438 | -1, |
michael@0 | 439 | buffer, |
michael@0 | 440 | MAXPATHLEN, |
michael@0 | 441 | nullptr, |
michael@0 | 442 | nullptr)) { |
michael@0 | 443 | Output("Application directory could not be processed."); |
michael@0 | 444 | return 255; |
michael@0 | 445 | } |
michael@0 | 446 | |
michael@0 | 447 | // Check if the runtime was executed with the "-profile" argument |
michael@0 | 448 | for (int i = 1; i < argc; i++) { |
michael@0 | 449 | if (!strcmp(argv[i], "-profile")) { |
michael@0 | 450 | isProfileOverridden = true; |
michael@0 | 451 | break; |
michael@0 | 452 | } |
michael@0 | 453 | } |
michael@0 | 454 | |
michael@0 | 455 | // First attempt at loading Firefox binaries: |
michael@0 | 456 | // Check if the webapprt is in the same directory as the Firefox binary. |
michael@0 | 457 | // This is the case during WebappRT chrome and content tests. |
michael@0 | 458 | if (AttemptLoadFromDir(buffer)) { |
michael@0 | 459 | return 0; |
michael@0 | 460 | } |
michael@0 | 461 | |
michael@0 | 462 | // Set up appIniPath with path to webapp.ini. |
michael@0 | 463 | // This should be in the same directory as the running executable. |
michael@0 | 464 | char appIniPath[MAXPATHLEN]; |
michael@0 | 465 | if (NS_FAILED(joinPath(appIniPath, buffer, kWEBAPP_INI, MAXPATHLEN))) { |
michael@0 | 466 | Output("Path to webapp.ini could not be processed."); |
michael@0 | 467 | return 255; |
michael@0 | 468 | } |
michael@0 | 469 | |
michael@0 | 470 | // Open webapp.ini as an INI file (as opposed to using the |
michael@0 | 471 | // XRE webapp.ini-specific processing we do later) |
michael@0 | 472 | nsINIParser parser; |
michael@0 | 473 | if (NS_FAILED(parser.Init(appIniPath))) { |
michael@0 | 474 | Output("Could not open webapp.ini"); |
michael@0 | 475 | return 255; |
michael@0 | 476 | } |
michael@0 | 477 | |
michael@0 | 478 | // Set up our environment to know where webapp.ini was loaded from. |
michael@0 | 479 | char appEnv[MAXPATHLEN + _countof(kAPP_ENV_PREFIX)]; |
michael@0 | 480 | strcpy(appEnv, kAPP_ENV_PREFIX); |
michael@0 | 481 | strcpy(appEnv + _countof(kAPP_ENV_PREFIX) - 1, appIniPath); |
michael@0 | 482 | if (putenv(appEnv)) { |
michael@0 | 483 | Output("Couldn't set up app environment"); |
michael@0 | 484 | return 255; |
michael@0 | 485 | } |
michael@0 | 486 | |
michael@0 | 487 | if (!isProfileOverridden) { |
michael@0 | 488 | // Get profile dir from webapp.ini |
michael@0 | 489 | if (NS_FAILED(parser.GetString("Webapp", |
michael@0 | 490 | "Profile", |
michael@0 | 491 | profile, |
michael@0 | 492 | MAXPATHLEN))) { |
michael@0 | 493 | Output("Unable to retrieve profile from web app INI file"); |
michael@0 | 494 | return 255; |
michael@0 | 495 | } |
michael@0 | 496 | } |
michael@0 | 497 | |
michael@0 | 498 | char firefoxDir[MAXPATHLEN]; |
michael@0 | 499 | |
michael@0 | 500 | // Second attempt at loading Firefox binaries: |
michael@0 | 501 | // Get the location of Firefox from our webapp.ini |
michael@0 | 502 | |
michael@0 | 503 | // XXX: This string better be UTF-8... |
michael@0 | 504 | rv = parser.GetString("WebappRT", |
michael@0 | 505 | "InstallDir", |
michael@0 | 506 | firefoxDir, |
michael@0 | 507 | MAXPATHLEN); |
michael@0 | 508 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 509 | if (AttemptLoadFromDir(firefoxDir)) { |
michael@0 | 510 | return 0; |
michael@0 | 511 | } |
michael@0 | 512 | } |
michael@0 | 513 | |
michael@0 | 514 | // Third attempt at loading Firefox binaries: |
michael@0 | 515 | // Get the location of Firefox from the registry |
michael@0 | 516 | if (GetFirefoxDirFromRegistry(firefoxDir)) { |
michael@0 | 517 | if (AttemptLoadFromDir(firefoxDir)) { |
michael@0 | 518 | // XXX: Write gre dir location to webapp.ini |
michael@0 | 519 | return 0; |
michael@0 | 520 | } |
michael@0 | 521 | } |
michael@0 | 522 | |
michael@0 | 523 | // We've done all we know how to do to try to find and launch FF |
michael@0 | 524 | Output("This app requires that Firefox version 16 or above is installed." |
michael@0 | 525 | " Firefox 16+ has not been detected."); |
michael@0 | 526 | return 255; |
michael@0 | 527 | } |