toolkit/xre/nsXREDirProvider.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsAppRunner.h"
michael@0 7 #include "nsToolkitCompsCID.h"
michael@0 8 #include "nsXREDirProvider.h"
michael@0 9
michael@0 10 #include "jsapi.h"
michael@0 11
michael@0 12 #include "nsIJSRuntimeService.h"
michael@0 13 #include "nsIAppStartup.h"
michael@0 14 #include "nsIDirectoryEnumerator.h"
michael@0 15 #include "nsIFile.h"
michael@0 16 #include "nsIObserver.h"
michael@0 17 #include "nsIObserverService.h"
michael@0 18 #include "nsISimpleEnumerator.h"
michael@0 19 #include "nsIToolkitChromeRegistry.h"
michael@0 20
michael@0 21 #include "nsAppDirectoryServiceDefs.h"
michael@0 22 #include "nsDirectoryServiceDefs.h"
michael@0 23 #include "nsDirectoryServiceUtils.h"
michael@0 24 #include "nsXULAppAPI.h"
michael@0 25 #include "nsCategoryManagerUtils.h"
michael@0 26
michael@0 27 #include "nsINIParser.h"
michael@0 28 #include "nsDependentString.h"
michael@0 29 #include "nsCOMArray.h"
michael@0 30 #include "nsArrayEnumerator.h"
michael@0 31 #include "nsEnumeratorUtils.h"
michael@0 32 #include "nsReadableUtils.h"
michael@0 33 #include "nsXPCOMPrivate.h" // for XPCOM_FILE_PATH_SEPARATOR
michael@0 34 #include "mozilla/Services.h"
michael@0 35 #include "mozilla/Omnijar.h"
michael@0 36 #include "mozilla/Preferences.h"
michael@0 37 #include "mozilla/Telemetry.h"
michael@0 38
michael@0 39 #include <stdlib.h>
michael@0 40
michael@0 41 #ifdef XP_WIN
michael@0 42 #include <windows.h>
michael@0 43 #include <shlobj.h>
michael@0 44 #endif
michael@0 45 #ifdef XP_MACOSX
michael@0 46 #include "nsILocalFileMac.h"
michael@0 47 // for chflags()
michael@0 48 #include <sys/stat.h>
michael@0 49 #include <unistd.h>
michael@0 50 #endif
michael@0 51 #ifdef XP_UNIX
michael@0 52 #include <ctype.h>
michael@0 53 #endif
michael@0 54
michael@0 55 #if defined(XP_MACOSX)
michael@0 56 #define APP_REGISTRY_NAME "Application Registry"
michael@0 57 #elif defined(XP_WIN)
michael@0 58 #define APP_REGISTRY_NAME "registry.dat"
michael@0 59 #else
michael@0 60 #define APP_REGISTRY_NAME "appreg"
michael@0 61 #endif
michael@0 62
michael@0 63 #define PREF_OVERRIDE_DIRNAME "preferences"
michael@0 64
michael@0 65 static already_AddRefed<nsIFile>
michael@0 66 CloneAndAppend(nsIFile* aFile, const char* name)
michael@0 67 {
michael@0 68 nsCOMPtr<nsIFile> file;
michael@0 69 aFile->Clone(getter_AddRefs(file));
michael@0 70 file->AppendNative(nsDependentCString(name));
michael@0 71 return file.forget();
michael@0 72 }
michael@0 73
michael@0 74 nsXREDirProvider* gDirServiceProvider = nullptr;
michael@0 75
michael@0 76 nsXREDirProvider::nsXREDirProvider() :
michael@0 77 mProfileNotified(false)
michael@0 78 {
michael@0 79 gDirServiceProvider = this;
michael@0 80 }
michael@0 81
michael@0 82 nsXREDirProvider::~nsXREDirProvider()
michael@0 83 {
michael@0 84 gDirServiceProvider = nullptr;
michael@0 85 }
michael@0 86
michael@0 87 nsXREDirProvider*
michael@0 88 nsXREDirProvider::GetSingleton()
michael@0 89 {
michael@0 90 return gDirServiceProvider;
michael@0 91 }
michael@0 92
michael@0 93 nsresult
michael@0 94 nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
michael@0 95 nsIFile *aGREDir,
michael@0 96 nsIDirectoryServiceProvider* aAppProvider)
michael@0 97 {
michael@0 98 NS_ENSURE_ARG(aXULAppDir);
michael@0 99 NS_ENSURE_ARG(aGREDir);
michael@0 100
michael@0 101 mAppProvider = aAppProvider;
michael@0 102 mXULAppDir = aXULAppDir;
michael@0 103 mGREDir = aGREDir;
michael@0 104
michael@0 105 if (!mProfileDir) {
michael@0 106 nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
michael@0 107 if (app) {
michael@0 108 bool per = false;
michael@0 109 app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir));
michael@0 110 NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!");
michael@0 111 NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!");
michael@0 112 }
michael@0 113 }
michael@0 114
michael@0 115 LoadAppBundleDirs();
michael@0 116 return NS_OK;
michael@0 117 }
michael@0 118
michael@0 119 nsresult
michael@0 120 nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
michael@0 121 {
michael@0 122 NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
michael@0 123
michael@0 124 nsresult rv;
michael@0 125
michael@0 126 rv = EnsureDirectoryExists(aDir);
michael@0 127 if (NS_FAILED(rv))
michael@0 128 return rv;
michael@0 129
michael@0 130 rv = EnsureDirectoryExists(aLocalDir);
michael@0 131 if (NS_FAILED(rv))
michael@0 132 return rv;
michael@0 133
michael@0 134 #ifdef XP_MACOSX
michael@0 135 bool same;
michael@0 136 if (NS_SUCCEEDED(aDir->Equals(aLocalDir, &same)) && !same) {
michael@0 137 // Ensure that the cache directory is not indexed by Spotlight
michael@0 138 // (bug 718910). At least on OS X, the cache directory (under
michael@0 139 // ~/Library/Caches/) is always the "local" user profile
michael@0 140 // directory. This is confusing, since *both* user profile
michael@0 141 // directories are "local" (they both exist under the user's
michael@0 142 // home directory). But this usage dates back at least as far
michael@0 143 // as the patch for bug 291033, where "local" seems to mean
michael@0 144 // "suitable for temporary storage". Don't hide the cache
michael@0 145 // directory if by some chance it and the "non-local" profile
michael@0 146 // directory are the same -- there are bad side effects from
michael@0 147 // hiding a profile directory under /Library/Application Support/
michael@0 148 // (see bug 801883).
michael@0 149 nsAutoCString cacheDir;
michael@0 150 if (NS_SUCCEEDED(aLocalDir->GetNativePath(cacheDir))) {
michael@0 151 if (chflags(cacheDir.get(), UF_HIDDEN)) {
michael@0 152 NS_WARNING("Failed to set Cache directory to HIDDEN.");
michael@0 153 }
michael@0 154 }
michael@0 155 }
michael@0 156 #endif
michael@0 157
michael@0 158 mProfileDir = aDir;
michael@0 159 mProfileLocalDir = aLocalDir;
michael@0 160 return NS_OK;
michael@0 161 }
michael@0 162
michael@0 163 NS_IMPL_QUERY_INTERFACE(nsXREDirProvider,
michael@0 164 nsIDirectoryServiceProvider,
michael@0 165 nsIDirectoryServiceProvider2,
michael@0 166 nsIProfileStartup)
michael@0 167
michael@0 168 NS_IMETHODIMP_(MozExternalRefCountType)
michael@0 169 nsXREDirProvider::AddRef()
michael@0 170 {
michael@0 171 return 1;
michael@0 172 }
michael@0 173
michael@0 174 NS_IMETHODIMP_(MozExternalRefCountType)
michael@0 175 nsXREDirProvider::Release()
michael@0 176 {
michael@0 177 return 0;
michael@0 178 }
michael@0 179
michael@0 180 nsresult
michael@0 181 nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult,
michael@0 182 const nsACString* aProfileName,
michael@0 183 const nsACString* aAppName,
michael@0 184 const nsACString* aVendorName)
michael@0 185 {
michael@0 186 nsCOMPtr<nsIFile> file;
michael@0 187 nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
michael@0 188 false,
michael@0 189 aProfileName, aAppName, aVendorName);
michael@0 190
michael@0 191 if (NS_SUCCEEDED(rv)) {
michael@0 192 // We must create the profile directory here if it does not exist.
michael@0 193 nsresult tmp = EnsureDirectoryExists(file);
michael@0 194 if (NS_FAILED(tmp)) {
michael@0 195 rv = tmp;
michael@0 196 }
michael@0 197 }
michael@0 198 file.swap(*aResult);
michael@0 199 return rv;
michael@0 200 }
michael@0 201
michael@0 202 nsresult
michael@0 203 nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
michael@0 204 const nsACString* aProfileName,
michael@0 205 const nsACString* aAppName,
michael@0 206 const nsACString* aVendorName)
michael@0 207 {
michael@0 208 nsCOMPtr<nsIFile> file;
michael@0 209 nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
michael@0 210 true,
michael@0 211 aProfileName, aAppName, aVendorName);
michael@0 212
michael@0 213 if (NS_SUCCEEDED(rv)) {
michael@0 214 // We must create the profile directory here if it does not exist.
michael@0 215 nsresult tmp = EnsureDirectoryExists(file);
michael@0 216 if (NS_FAILED(tmp)) {
michael@0 217 rv = tmp;
michael@0 218 }
michael@0 219 }
michael@0 220 file.swap(*aResult);
michael@0 221 return NS_OK;
michael@0 222 }
michael@0 223
michael@0 224 NS_IMETHODIMP
michael@0 225 nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
michael@0 226 nsIFile** aFile)
michael@0 227 {
michael@0 228 nsresult rv;
michael@0 229
michael@0 230 bool gettingProfile = false;
michael@0 231
michael@0 232 if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
michael@0 233 // If XRE_NotifyProfile hasn't been called, don't fall through to
michael@0 234 // mAppProvider on the profile keys.
michael@0 235 if (!mProfileNotified)
michael@0 236 return NS_ERROR_FAILURE;
michael@0 237
michael@0 238 if (mProfileLocalDir)
michael@0 239 return mProfileLocalDir->Clone(aFile);
michael@0 240
michael@0 241 if (mAppProvider)
michael@0 242 return mAppProvider->GetFile(aProperty, aPersistent, aFile);
michael@0 243
michael@0 244 // This falls through to the case below
michael@0 245 gettingProfile = true;
michael@0 246 }
michael@0 247 if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
michael@0 248 if (!mProfileNotified)
michael@0 249 return NS_ERROR_FAILURE;
michael@0 250
michael@0 251 if (mProfileDir)
michael@0 252 return mProfileDir->Clone(aFile);
michael@0 253
michael@0 254 if (mAppProvider)
michael@0 255 return mAppProvider->GetFile(aProperty, aPersistent, aFile);
michael@0 256
michael@0 257 // If we don't succeed here, bail early so that we aren't reentrant
michael@0 258 // through the "GetProfileDir" call below.
michael@0 259 return NS_ERROR_FAILURE;
michael@0 260 }
michael@0 261
michael@0 262 if (mAppProvider) {
michael@0 263 rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
michael@0 264 if (NS_SUCCEEDED(rv) && *aFile)
michael@0 265 return rv;
michael@0 266 }
michael@0 267
michael@0 268 *aPersistent = true;
michael@0 269
michael@0 270 if (!strcmp(aProperty, NS_GRE_DIR)) {
michael@0 271 return mGREDir->Clone(aFile);
michael@0 272 }
michael@0 273 else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
michael@0 274 !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
michael@0 275 return GetAppDir()->Clone(aFile);
michael@0 276 }
michael@0 277
michael@0 278 rv = NS_ERROR_FAILURE;
michael@0 279 nsCOMPtr<nsIFile> file;
michael@0 280
michael@0 281 if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) ||
michael@0 282 !strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR)) {
michael@0 283 return GetProfileDefaultsDir(aFile);
michael@0 284 }
michael@0 285 else if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
michael@0 286 {
michael@0 287 // return the GRE default prefs directory here, and the app default prefs
michael@0 288 // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
michael@0 289 rv = mGREDir->Clone(getter_AddRefs(file));
michael@0 290 if (NS_SUCCEEDED(rv)) {
michael@0 291 rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
michael@0 292 if (NS_SUCCEEDED(rv))
michael@0 293 rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
michael@0 294 }
michael@0 295 }
michael@0 296 else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
michael@0 297 !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
michael@0 298 rv = GetUserAppDataDirectory(getter_AddRefs(file));
michael@0 299 }
michael@0 300 else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
michael@0 301 rv = GetUpdateRootDir(getter_AddRefs(file));
michael@0 302 }
michael@0 303 else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
michael@0 304 rv = GetUserAppDataDirectory(getter_AddRefs(file));
michael@0 305 if (NS_SUCCEEDED(rv))
michael@0 306 rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
michael@0 307 }
michael@0 308 else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
michael@0 309 rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
michael@0 310 }
michael@0 311 else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
michael@0 312 rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
michael@0 313 }
michael@0 314 else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
michael@0 315 nsCOMPtr<nsIFile> lf;
michael@0 316 rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
michael@0 317 if (NS_SUCCEEDED(rv))
michael@0 318 file = lf;
michael@0 319 }
michael@0 320
michael@0 321 else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
michael@0 322 return mProfileDir->Clone(aFile);
michael@0 323 }
michael@0 324 else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
michael@0 325 if (mProfileLocalDir)
michael@0 326 return mProfileLocalDir->Clone(aFile);
michael@0 327
michael@0 328 if (mProfileDir)
michael@0 329 return mProfileDir->Clone(aFile);
michael@0 330
michael@0 331 if (mAppProvider)
michael@0 332 return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
michael@0 333 aFile);
michael@0 334 }
michael@0 335 #if defined(XP_UNIX) || defined(XP_MACOSX)
michael@0 336 else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
michael@0 337 #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
michael@0 338 return GetSystemExtensionsDirectory(aFile);
michael@0 339 #else
michael@0 340 return NS_ERROR_FAILURE;
michael@0 341 #endif
michael@0 342 }
michael@0 343 #endif
michael@0 344 #if defined(XP_UNIX) && !defined(XP_MACOSX)
michael@0 345 else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
michael@0 346 #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
michael@0 347 #if defined(__OpenBSD__) || defined(__FreeBSD__)
michael@0 348 static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions";
michael@0 349 #else
michael@0 350 static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
michael@0 351 #endif
michael@0 352 return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
michael@0 353 false, aFile);
michael@0 354 #else
michael@0 355 return NS_ERROR_FAILURE;
michael@0 356 #endif
michael@0 357 }
michael@0 358 #endif
michael@0 359 else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
michael@0 360 #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
michael@0 361 return GetSysUserExtensionsDirectory(aFile);
michael@0 362 #else
michael@0 363 return NS_ERROR_FAILURE;
michael@0 364 #endif
michael@0 365 }
michael@0 366 else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
michael@0 367 bool persistent = false;
michael@0 368 rv = GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(file));
michael@0 369 if (NS_SUCCEEDED(rv))
michael@0 370 rv = file->SetNativeLeafName(NS_LITERAL_CSTRING("distribution"));
michael@0 371 }
michael@0 372 else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
michael@0 373 // We need to allow component, xpt, and chrome registration to
michael@0 374 // occur prior to the profile-after-change notification.
michael@0 375 if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
michael@0 376 rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
michael@0 377 }
michael@0 378 }
michael@0 379
michael@0 380 if (NS_SUCCEEDED(rv) && file) {
michael@0 381 NS_ADDREF(*aFile = file);
michael@0 382 return NS_OK;
michael@0 383 }
michael@0 384
michael@0 385 bool ensureFilePermissions = false;
michael@0 386
michael@0 387 if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
michael@0 388 if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
michael@0 389 rv = NS_OK;
michael@0 390 }
michael@0 391 else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
michael@0 392 rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
michael@0 393 }
michael@0 394 else if (!strcmp(aProperty, NS_METRO_APP_PREFS_50_FILE)) {
michael@0 395 rv = file->AppendNative(NS_LITERAL_CSTRING("metro-prefs.js"));
michael@0 396 }
michael@0 397 else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
michael@0 398 rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
michael@0 399 }
michael@0 400 else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
michael@0 401 if (gSafeMode) {
michael@0 402 rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
michael@0 403 file->Remove(false);
michael@0 404 }
michael@0 405 else {
michael@0 406 rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
michael@0 407 EnsureProfileFileExists(file);
michael@0 408 ensureFilePermissions = true;
michael@0 409 }
michael@0 410 }
michael@0 411 else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
michael@0 412 rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
michael@0 413 EnsureProfileFileExists(file);
michael@0 414 ensureFilePermissions = true;
michael@0 415 }
michael@0 416 else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
michael@0 417 rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
michael@0 418 }
michael@0 419 else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
michael@0 420 rv = mProfileDir->Clone(getter_AddRefs(file));
michael@0 421 nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
michael@0 422 if (NS_FAILED(tmp)) {
michael@0 423 rv = tmp;
michael@0 424 }
michael@0 425 tmp = EnsureDirectoryExists(file);
michael@0 426 if (NS_FAILED(tmp)) {
michael@0 427 rv = tmp;
michael@0 428 }
michael@0 429 }
michael@0 430 }
michael@0 431 if (NS_FAILED(rv) || !file)
michael@0 432 return NS_ERROR_FAILURE;
michael@0 433
michael@0 434 if (ensureFilePermissions) {
michael@0 435 bool fileToEnsureExists;
michael@0 436 bool isWritable;
michael@0 437 if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
michael@0 438 && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
michael@0 439 uint32_t permissions;
michael@0 440 if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
michael@0 441 rv = file->SetPermissions(permissions | 0600);
michael@0 442 NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
michael@0 443 }
michael@0 444 }
michael@0 445 }
michael@0 446
michael@0 447 NS_ADDREF(*aFile = file);
michael@0 448 return NS_OK;
michael@0 449 }
michael@0 450
michael@0 451 static void
michael@0 452 LoadDirIntoArray(nsIFile* dir,
michael@0 453 const char *const *aAppendList,
michael@0 454 nsCOMArray<nsIFile>& aDirectories)
michael@0 455 {
michael@0 456 if (!dir)
michael@0 457 return;
michael@0 458
michael@0 459 nsCOMPtr<nsIFile> subdir;
michael@0 460 dir->Clone(getter_AddRefs(subdir));
michael@0 461 if (!subdir)
michael@0 462 return;
michael@0 463
michael@0 464 for (const char *const *a = aAppendList; *a; ++a) {
michael@0 465 subdir->AppendNative(nsDependentCString(*a));
michael@0 466 }
michael@0 467
michael@0 468 bool exists;
michael@0 469 if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) {
michael@0 470 aDirectories.AppendObject(subdir);
michael@0 471 }
michael@0 472 }
michael@0 473
michael@0 474 static void
michael@0 475 LoadDirsIntoArray(nsCOMArray<nsIFile>& aSourceDirs,
michael@0 476 const char *const* aAppendList,
michael@0 477 nsCOMArray<nsIFile>& aDirectories)
michael@0 478 {
michael@0 479 nsCOMPtr<nsIFile> appended;
michael@0 480 bool exists;
michael@0 481
michael@0 482 for (int32_t i = 0; i < aSourceDirs.Count(); ++i) {
michael@0 483 aSourceDirs[i]->Clone(getter_AddRefs(appended));
michael@0 484 if (!appended)
michael@0 485 continue;
michael@0 486
michael@0 487 nsAutoCString leaf;
michael@0 488 appended->GetNativeLeafName(leaf);
michael@0 489 if (!Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) {
michael@0 490 LoadDirIntoArray(appended,
michael@0 491 aAppendList,
michael@0 492 aDirectories);
michael@0 493 }
michael@0 494 else if (NS_SUCCEEDED(appended->Exists(&exists)) && exists)
michael@0 495 aDirectories.AppendObject(appended);
michael@0 496 }
michael@0 497 }
michael@0 498
michael@0 499 NS_IMETHODIMP
michael@0 500 nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
michael@0 501 {
michael@0 502 nsresult rv;
michael@0 503
michael@0 504 nsCOMPtr<nsISimpleEnumerator> appEnum;
michael@0 505 nsCOMPtr<nsIDirectoryServiceProvider2>
michael@0 506 appP2(do_QueryInterface(mAppProvider));
michael@0 507 if (appP2) {
michael@0 508 rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
michael@0 509 if (NS_FAILED(rv)) {
michael@0 510 appEnum = nullptr;
michael@0 511 }
michael@0 512 else if (rv != NS_SUCCESS_AGGREGATE_RESULT) {
michael@0 513 NS_ADDREF(*aResult = appEnum);
michael@0 514 return NS_OK;
michael@0 515 }
michael@0 516 }
michael@0 517
michael@0 518 nsCOMPtr<nsISimpleEnumerator> xreEnum;
michael@0 519 rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum));
michael@0 520 if (NS_FAILED(rv)) {
michael@0 521 if (appEnum) {
michael@0 522 NS_ADDREF(*aResult = appEnum);
michael@0 523 return NS_SUCCESS_AGGREGATE_RESULT;
michael@0 524 }
michael@0 525
michael@0 526 return rv;
michael@0 527 }
michael@0 528
michael@0 529 rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum);
michael@0 530 if (NS_FAILED(rv))
michael@0 531 return rv;
michael@0 532
michael@0 533 return NS_SUCCESS_AGGREGATE_RESULT;
michael@0 534 }
michael@0 535
michael@0 536 static void
michael@0 537 LoadExtensionDirectories(nsINIParser &parser,
michael@0 538 const char *aSection,
michael@0 539 nsCOMArray<nsIFile> &aDirectories,
michael@0 540 NSLocationType aType)
michael@0 541 {
michael@0 542 nsresult rv;
michael@0 543 int32_t i = 0;
michael@0 544 do {
michael@0 545 nsAutoCString buf("Extension");
michael@0 546 buf.AppendInt(i++);
michael@0 547
michael@0 548 nsAutoCString path;
michael@0 549 rv = parser.GetString(aSection, buf.get(), path);
michael@0 550 if (NS_FAILED(rv))
michael@0 551 return;
michael@0 552
michael@0 553 nsCOMPtr<nsIFile> dir = do_CreateInstance("@mozilla.org/file/local;1", &rv);
michael@0 554 if (NS_FAILED(rv))
michael@0 555 continue;
michael@0 556
michael@0 557 rv = dir->SetPersistentDescriptor(path);
michael@0 558 if (NS_FAILED(rv))
michael@0 559 continue;
michael@0 560
michael@0 561 aDirectories.AppendObject(dir);
michael@0 562 if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) {
michael@0 563 XRE_AddJarManifestLocation(aType, dir);
michael@0 564 }
michael@0 565 else {
michael@0 566 nsCOMPtr<nsIFile> manifest =
michael@0 567 CloneAndAppend(dir, "chrome.manifest");
michael@0 568 XRE_AddManifestLocation(aType, manifest);
michael@0 569 }
michael@0 570 }
michael@0 571 while (true);
michael@0 572 }
michael@0 573
michael@0 574 void
michael@0 575 nsXREDirProvider::LoadExtensionBundleDirectories()
michael@0 576 {
michael@0 577 if (!mozilla::Preferences::GetBool("extensions.defaultProviders.enabled", true))
michael@0 578 return;
michael@0 579
michael@0 580 if (mProfileDir && !gSafeMode) {
michael@0 581 nsCOMPtr<nsIFile> extensionsINI;
michael@0 582 mProfileDir->Clone(getter_AddRefs(extensionsINI));
michael@0 583 if (!extensionsINI)
michael@0 584 return;
michael@0 585
michael@0 586 extensionsINI->AppendNative(NS_LITERAL_CSTRING("extensions.ini"));
michael@0 587
michael@0 588 nsCOMPtr<nsIFile> extensionsINILF =
michael@0 589 do_QueryInterface(extensionsINI);
michael@0 590 if (!extensionsINILF)
michael@0 591 return;
michael@0 592
michael@0 593 nsINIParser parser;
michael@0 594 nsresult rv = parser.Init(extensionsINILF);
michael@0 595 if (NS_FAILED(rv))
michael@0 596 return;
michael@0 597
michael@0 598 LoadExtensionDirectories(parser, "ExtensionDirs", mExtensionDirectories,
michael@0 599 NS_COMPONENT_LOCATION);
michael@0 600 LoadExtensionDirectories(parser, "ThemeDirs", mThemeDirectories,
michael@0 601 NS_SKIN_LOCATION);
michael@0 602 }
michael@0 603 }
michael@0 604
michael@0 605 void
michael@0 606 nsXREDirProvider::LoadAppBundleDirs()
michael@0 607 {
michael@0 608 nsCOMPtr<nsIFile> dir;
michael@0 609 bool persistent = false;
michael@0 610 nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(dir));
michael@0 611 if (NS_FAILED(rv))
michael@0 612 return;
michael@0 613
michael@0 614 dir->SetNativeLeafName(NS_LITERAL_CSTRING("distribution"));
michael@0 615 dir->AppendNative(NS_LITERAL_CSTRING("bundles"));
michael@0 616
michael@0 617 nsCOMPtr<nsISimpleEnumerator> e;
michael@0 618 rv = dir->GetDirectoryEntries(getter_AddRefs(e));
michael@0 619 if (NS_FAILED(rv))
michael@0 620 return;
michael@0 621
michael@0 622 nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
michael@0 623 if (!files)
michael@0 624 return;
michael@0 625
michael@0 626 nsCOMPtr<nsIFile> subdir;
michael@0 627 while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(subdir))) && subdir) {
michael@0 628 mAppBundleDirectories.AppendObject(subdir);
michael@0 629
michael@0 630 nsCOMPtr<nsIFile> manifest =
michael@0 631 CloneAndAppend(subdir, "chrome.manifest");
michael@0 632 XRE_AddManifestLocation(NS_COMPONENT_LOCATION, manifest);
michael@0 633 }
michael@0 634 }
michael@0 635
michael@0 636 static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr };
michael@0 637
michael@0 638 #ifdef DEBUG_bsmedberg
michael@0 639 static void
michael@0 640 DumpFileArray(const char *key,
michael@0 641 nsCOMArray<nsIFile> dirs)
michael@0 642 {
michael@0 643 fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key);
michael@0 644
michael@0 645 nsAutoCString path;
michael@0 646 for (int32_t i = 0; i < dirs.Count(); ++i) {
michael@0 647 dirs[i]->GetNativePath(path);
michael@0 648 fprintf(stderr, " %s\n", path.get());
michael@0 649 }
michael@0 650 }
michael@0 651 #endif // DEBUG_bsmedberg
michael@0 652
michael@0 653 nsresult
michael@0 654 nsXREDirProvider::GetFilesInternal(const char* aProperty,
michael@0 655 nsISimpleEnumerator** aResult)
michael@0 656 {
michael@0 657 nsresult rv = NS_OK;
michael@0 658 *aResult = nullptr;
michael@0 659
michael@0 660 if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
michael@0 661 nsCOMArray<nsIFile> directories;
michael@0 662
michael@0 663 static const char *const kAppendNothing[] = { nullptr };
michael@0 664
michael@0 665 LoadDirsIntoArray(mAppBundleDirectories,
michael@0 666 kAppendNothing, directories);
michael@0 667 LoadDirsIntoArray(mExtensionDirectories,
michael@0 668 kAppendNothing, directories);
michael@0 669
michael@0 670 rv = NS_NewArrayEnumerator(aResult, directories);
michael@0 671 }
michael@0 672 else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
michael@0 673 nsCOMArray<nsIFile> directories;
michael@0 674
michael@0 675 LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
michael@0 676 LoadDirsIntoArray(mAppBundleDirectories,
michael@0 677 kAppendPrefDir, directories);
michael@0 678
michael@0 679 rv = NS_NewArrayEnumerator(aResult, directories);
michael@0 680 }
michael@0 681 else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
michael@0 682 nsCOMArray<nsIFile> directories;
michael@0 683
michael@0 684 LoadDirsIntoArray(mExtensionDirectories,
michael@0 685 kAppendPrefDir, directories);
michael@0 686
michael@0 687 if (mProfileDir) {
michael@0 688 nsCOMPtr<nsIFile> overrideFile;
michael@0 689 mProfileDir->Clone(getter_AddRefs(overrideFile));
michael@0 690 overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
michael@0 691
michael@0 692 bool exists;
michael@0 693 if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists)
michael@0 694 directories.AppendObject(overrideFile);
michael@0 695 }
michael@0 696
michael@0 697 rv = NS_NewArrayEnumerator(aResult, directories);
michael@0 698 }
michael@0 699 else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
michael@0 700 // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
michael@0 701 // for OS window decoration.
michael@0 702
michael@0 703 static const char *const kAppendChromeDir[] = { "chrome", nullptr };
michael@0 704 nsCOMArray<nsIFile> directories;
michael@0 705 LoadDirIntoArray(mXULAppDir,
michael@0 706 kAppendChromeDir,
michael@0 707 directories);
michael@0 708 LoadDirsIntoArray(mAppBundleDirectories,
michael@0 709 kAppendChromeDir,
michael@0 710 directories);
michael@0 711 LoadDirsIntoArray(mExtensionDirectories,
michael@0 712 kAppendChromeDir,
michael@0 713 directories);
michael@0 714
michael@0 715 rv = NS_NewArrayEnumerator(aResult, directories);
michael@0 716 }
michael@0 717 else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
michael@0 718 nsCOMArray<nsIFile> directories;
michael@0 719
michael@0 720 if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
michael@0 721 nsCOMPtr<nsIFile> appdir;
michael@0 722 rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir));
michael@0 723 if (NS_SUCCEEDED(rv)) {
michael@0 724 appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
michael@0 725 directories.AppendObject(appdir);
michael@0 726 }
michael@0 727 }
michael@0 728
michael@0 729 static const char *const kAppendPlugins[] = { "plugins", nullptr };
michael@0 730
michael@0 731 // The root dirserviceprovider does quite a bit for us: we're mainly
michael@0 732 // interested in xulapp and extension-provided plugins.
michael@0 733 LoadDirsIntoArray(mAppBundleDirectories,
michael@0 734 kAppendPlugins,
michael@0 735 directories);
michael@0 736 LoadDirsIntoArray(mExtensionDirectories,
michael@0 737 kAppendPlugins,
michael@0 738 directories);
michael@0 739
michael@0 740 if (mProfileDir) {
michael@0 741 nsCOMArray<nsIFile> profileDir;
michael@0 742 profileDir.AppendObject(mProfileDir);
michael@0 743 LoadDirsIntoArray(profileDir,
michael@0 744 kAppendPlugins,
michael@0 745 directories);
michael@0 746 }
michael@0 747
michael@0 748 rv = NS_NewArrayEnumerator(aResult, directories);
michael@0 749 NS_ENSURE_SUCCESS(rv, rv);
michael@0 750
michael@0 751 rv = NS_SUCCESS_AGGREGATE_RESULT;
michael@0 752 }
michael@0 753 else
michael@0 754 rv = NS_ERROR_FAILURE;
michael@0 755
michael@0 756 return rv;
michael@0 757 }
michael@0 758
michael@0 759 NS_IMETHODIMP
michael@0 760 nsXREDirProvider::GetDirectory(nsIFile* *aResult)
michael@0 761 {
michael@0 762 NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
michael@0 763
michael@0 764 return mProfileDir->Clone(aResult);
michael@0 765 }
michael@0 766
michael@0 767 NS_IMETHODIMP
michael@0 768 nsXREDirProvider::DoStartup()
michael@0 769 {
michael@0 770 if (!mProfileNotified) {
michael@0 771 nsCOMPtr<nsIObserverService> obsSvc =
michael@0 772 mozilla::services::GetObserverService();
michael@0 773 if (!obsSvc) return NS_ERROR_FAILURE;
michael@0 774
michael@0 775 mProfileNotified = true;
michael@0 776
michael@0 777 /*
michael@0 778 Setup prefs before profile-do-change to be able to use them to track
michael@0 779 crashes and because we want to begin crash tracking before other code run
michael@0 780 from this notification since they may cause crashes.
michael@0 781 */
michael@0 782 nsresult rv = mozilla::Preferences::ResetAndReadUserPrefs();
michael@0 783 if (NS_FAILED(rv)) NS_WARNING("Failed to setup pref service.");
michael@0 784
michael@0 785 bool safeModeNecessary = false;
michael@0 786 nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
michael@0 787 if (appStartup) {
michael@0 788 rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary);
michael@0 789 if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
michael@0 790 NS_WARNING("Error while beginning startup crash tracking");
michael@0 791
michael@0 792 if (!gSafeMode && safeModeNecessary) {
michael@0 793 appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit);
michael@0 794 return NS_OK;
michael@0 795 }
michael@0 796 }
michael@0 797
michael@0 798 static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
michael@0 799 obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
michael@0 800 // Init the Extension Manager
michael@0 801 nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
michael@0 802 if (em) {
michael@0 803 em->Observe(nullptr, "addons-startup", nullptr);
michael@0 804 } else {
michael@0 805 NS_WARNING("Failed to create Addons Manager.");
michael@0 806 }
michael@0 807
michael@0 808 LoadExtensionBundleDirectories();
michael@0 809
michael@0 810 obsSvc->NotifyObservers(nullptr, "load-extension-defaults", nullptr);
michael@0 811 obsSvc->NotifyObservers(nullptr, "profile-after-change", kStartup);
michael@0 812
michael@0 813 // Any component that has registered for the profile-after-change category
michael@0 814 // should also be created at this time.
michael@0 815 (void)NS_CreateServicesFromCategory("profile-after-change", nullptr,
michael@0 816 "profile-after-change");
michael@0 817
michael@0 818 if (gSafeMode && safeModeNecessary) {
michael@0 819 static const char16_t kCrashed[] = {'c','r','a','s','h','e','d','\0'};
michael@0 820 obsSvc->NotifyObservers(nullptr, "safemode-forced", kCrashed);
michael@0 821 }
michael@0 822
michael@0 823 // 1 = Regular mode, 2 = Safe mode, 3 = Safe mode forced
michael@0 824 int mode = 1;
michael@0 825 if (gSafeMode) {
michael@0 826 if (safeModeNecessary)
michael@0 827 mode = 3;
michael@0 828 else
michael@0 829 mode = 2;
michael@0 830 }
michael@0 831 mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode);
michael@0 832
michael@0 833 obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr);
michael@0 834 }
michael@0 835 return NS_OK;
michael@0 836 }
michael@0 837
michael@0 838 void
michael@0 839 nsXREDirProvider::DoShutdown()
michael@0 840 {
michael@0 841 if (mProfileNotified) {
michael@0 842 nsCOMPtr<nsIObserverService> obsSvc =
michael@0 843 mozilla::services::GetObserverService();
michael@0 844 NS_ASSERTION(obsSvc, "No observer service?");
michael@0 845 if (obsSvc) {
michael@0 846 static const char16_t kShutdownPersist[] =
michael@0 847 {'s','h','u','t','d','o','w','n','-','p','e','r','s','i','s','t','\0'};
michael@0 848 obsSvc->NotifyObservers(nullptr, "profile-change-net-teardown", kShutdownPersist);
michael@0 849 obsSvc->NotifyObservers(nullptr, "profile-change-teardown", kShutdownPersist);
michael@0 850
michael@0 851 // Phase 2c: Now that things are torn down, force JS GC so that things which depend on
michael@0 852 // resources which are about to go away in "profile-before-change" are destroyed first.
michael@0 853
michael@0 854 nsCOMPtr<nsIJSRuntimeService> rtsvc
michael@0 855 (do_GetService("@mozilla.org/js/xpc/RuntimeService;1"));
michael@0 856 if (rtsvc)
michael@0 857 {
michael@0 858 JSRuntime *rt = nullptr;
michael@0 859 rtsvc->GetRuntime(&rt);
michael@0 860 if (rt)
michael@0 861 ::JS_GC(rt);
michael@0 862 }
michael@0 863
michael@0 864 // Phase 3: Notify observers of a profile change
michael@0 865 obsSvc->NotifyObservers(nullptr, "profile-before-change", kShutdownPersist);
michael@0 866 obsSvc->NotifyObservers(nullptr, "profile-before-change2", kShutdownPersist);
michael@0 867 }
michael@0 868 mProfileNotified = false;
michael@0 869 }
michael@0 870 }
michael@0 871
michael@0 872 #ifdef XP_WIN
michael@0 873 static nsresult
michael@0 874 GetShellFolderPath(int folder, nsAString& _retval)
michael@0 875 {
michael@0 876 wchar_t* buf;
michael@0 877 uint32_t bufLength = _retval.GetMutableData(&buf, MAXPATHLEN + 3);
michael@0 878 NS_ENSURE_TRUE(bufLength >= (MAXPATHLEN + 3), NS_ERROR_OUT_OF_MEMORY);
michael@0 879
michael@0 880 nsresult rv = NS_OK;
michael@0 881
michael@0 882 LPITEMIDLIST pItemIDList = nullptr;
michael@0 883
michael@0 884 if (SUCCEEDED(SHGetSpecialFolderLocation(nullptr, folder, &pItemIDList)) &&
michael@0 885 SHGetPathFromIDListW(pItemIDList, buf)) {
michael@0 886 // We're going to use wcslen (wcsnlen not available in msvc7.1) so make
michael@0 887 // sure to null terminate.
michael@0 888 buf[bufLength - 1] = L'\0';
michael@0 889 _retval.SetLength(wcslen(buf));
michael@0 890 } else {
michael@0 891 _retval.SetLength(0);
michael@0 892 rv = NS_ERROR_NOT_AVAILABLE;
michael@0 893 }
michael@0 894
michael@0 895 CoTaskMemFree(pItemIDList);
michael@0 896
michael@0 897 return rv;
michael@0 898 }
michael@0 899
michael@0 900 /**
michael@0 901 * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
michael@0 902 * querying the registry when the call to SHGetSpecialFolderLocation or
michael@0 903 * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
michael@0 904 */
michael@0 905 static nsresult
michael@0 906 GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval)
michael@0 907 {
michael@0 908 HKEY key;
michael@0 909 NS_NAMED_LITERAL_STRING(keyName,
michael@0 910 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
michael@0 911 DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
michael@0 912 &key);
michael@0 913 if (res != ERROR_SUCCESS) {
michael@0 914 _retval.SetLength(0);
michael@0 915 return NS_ERROR_NOT_AVAILABLE;
michael@0 916 }
michael@0 917
michael@0 918 DWORD type, size;
michael@0 919 res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
michael@0 920 nullptr, &type, nullptr, &size);
michael@0 921 // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
michael@0 922 // buffer size must not equal 0, and the buffer size be a multiple of 2.
michael@0 923 if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
michael@0 924 ::RegCloseKey(key);
michael@0 925 _retval.SetLength(0);
michael@0 926 return NS_ERROR_NOT_AVAILABLE;
michael@0 927 }
michael@0 928
michael@0 929 // |size| may or may not include room for the terminating null character
michael@0 930 DWORD resultLen = size / 2;
michael@0 931
michael@0 932 _retval.SetLength(resultLen);
michael@0 933 nsAString::iterator begin;
michael@0 934 _retval.BeginWriting(begin);
michael@0 935 if (begin.size_forward() != resultLen) {
michael@0 936 ::RegCloseKey(key);
michael@0 937 _retval.SetLength(0);
michael@0 938 return NS_ERROR_NOT_AVAILABLE;
michael@0 939 }
michael@0 940
michael@0 941 res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
michael@0 942 nullptr, nullptr, (LPBYTE) begin.get(), &size);
michael@0 943 ::RegCloseKey(key);
michael@0 944 if (res != ERROR_SUCCESS) {
michael@0 945 _retval.SetLength(0);
michael@0 946 return NS_ERROR_NOT_AVAILABLE;
michael@0 947 }
michael@0 948
michael@0 949 if (!_retval.CharAt(resultLen - 1)) {
michael@0 950 // It was already null terminated.
michael@0 951 _retval.Truncate(resultLen - 1);
michael@0 952 }
michael@0 953
michael@0 954 return NS_OK;
michael@0 955 }
michael@0 956
michael@0 957 static bool
michael@0 958 GetCachedHash(HKEY rootKey, const nsAString &regPath, const nsAString &path,
michael@0 959 nsAString &cachedHash)
michael@0 960 {
michael@0 961 HKEY baseKey;
michael@0 962 if (RegOpenKeyExW(rootKey, reinterpret_cast<const wchar_t*>(regPath.BeginReading()), 0, KEY_READ, &baseKey) !=
michael@0 963 ERROR_SUCCESS) {
michael@0 964 return false;
michael@0 965 }
michael@0 966
michael@0 967 wchar_t cachedHashRaw[512];
michael@0 968 DWORD bufferSize = sizeof(cachedHashRaw);
michael@0 969 LONG result = RegQueryValueExW(baseKey, reinterpret_cast<const wchar_t*>(path.BeginReading()), 0, nullptr,
michael@0 970 (LPBYTE)cachedHashRaw, &bufferSize);
michael@0 971 RegCloseKey(baseKey);
michael@0 972 if (result == ERROR_SUCCESS) {
michael@0 973 cachedHash.Assign(cachedHashRaw);
michael@0 974 }
michael@0 975 return ERROR_SUCCESS == result;
michael@0 976 }
michael@0 977
michael@0 978 #endif
michael@0 979
michael@0 980 nsresult
michael@0 981 nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
michael@0 982 {
michael@0 983 nsCOMPtr<nsIFile> updRoot;
michael@0 984 #if defined(MOZ_WIDGET_GONK)
michael@0 985
michael@0 986 nsresult rv = NS_NewNativeLocalFile(nsDependentCString("/data/local"),
michael@0 987 true,
michael@0 988 getter_AddRefs(updRoot));
michael@0 989 NS_ENSURE_SUCCESS(rv, rv);
michael@0 990
michael@0 991 #else
michael@0 992 nsCOMPtr<nsIFile> appFile;
michael@0 993 bool per = false;
michael@0 994 nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile));
michael@0 995 NS_ENSURE_SUCCESS(rv, rv);
michael@0 996 rv = appFile->GetParent(getter_AddRefs(updRoot));
michael@0 997 NS_ENSURE_SUCCESS(rv, rv);
michael@0 998
michael@0 999 #ifdef XP_WIN
michael@0 1000
michael@0 1001 nsAutoString pathHash;
michael@0 1002 bool pathHashResult = false;
michael@0 1003 bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
michael@0 1004
michael@0 1005 nsAutoString appDirPath;
michael@0 1006 if (SUCCEEDED(updRoot->GetPath(appDirPath))) {
michael@0 1007
michael@0 1008 // Figure out where we should check for a cached hash value. If the
michael@0 1009 // application doesn't have the nsXREAppData vendor value defined check
michael@0 1010 // under SOFTWARE\Mozilla.
michael@0 1011 wchar_t regPath[1024] = { L'\0' };
michael@0 1012 swprintf_s(regPath, mozilla::ArrayLength(regPath), L"SOFTWARE\\%S\\%S\\TaskBarIDs",
michael@0 1013 (hasVendor ? gAppData->vendor : "Mozilla"), MOZ_APP_BASENAME);
michael@0 1014
michael@0 1015 // If we pre-computed the hash, grab it from the registry.
michael@0 1016 pathHashResult = GetCachedHash(HKEY_LOCAL_MACHINE,
michael@0 1017 nsDependentString(regPath), appDirPath,
michael@0 1018 pathHash);
michael@0 1019 if (!pathHashResult) {
michael@0 1020 pathHashResult = GetCachedHash(HKEY_CURRENT_USER,
michael@0 1021 nsDependentString(regPath), appDirPath,
michael@0 1022 pathHash);
michael@0 1023 }
michael@0 1024 }
michael@0 1025
michael@0 1026 // Get the local app data directory and if a vendor name exists append it.
michael@0 1027 // If only a product name exists, append it. If neither exist fallback to
michael@0 1028 // old handling. We don't use the product name on purpose because we want a
michael@0 1029 // shared update directory for different apps run from the same path (like
michael@0 1030 // Metro & Desktop).
michael@0 1031 nsCOMPtr<nsIFile> localDir;
michael@0 1032 if (pathHashResult && (hasVendor || gAppData->name) &&
michael@0 1033 NS_SUCCEEDED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true)) &&
michael@0 1034 NS_SUCCEEDED(localDir->AppendNative(nsDependentCString(hasVendor ?
michael@0 1035 gAppData->vendor : gAppData->name))) &&
michael@0 1036 NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) &&
michael@0 1037 NS_SUCCEEDED(localDir->Append(pathHash))) {
michael@0 1038 NS_ADDREF(*aResult = localDir);
michael@0 1039 return NS_OK;
michael@0 1040 }
michael@0 1041
michael@0 1042 nsAutoString appPath;
michael@0 1043 rv = updRoot->GetPath(appPath);
michael@0 1044 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1045
michael@0 1046 // AppDir may be a short path. Convert to long path to make sure
michael@0 1047 // the consistency of the update folder location
michael@0 1048 nsString longPath;
michael@0 1049 wchar_t* buf;
michael@0 1050
michael@0 1051 uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN);
michael@0 1052 NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
michael@0 1053
michael@0 1054 DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength);
michael@0 1055
michael@0 1056 // Failing GetLongPathName() is not fatal.
michael@0 1057 if (len <= 0 || len >= bufLength)
michael@0 1058 longPath.Assign(appPath);
michael@0 1059 else
michael@0 1060 longPath.SetLength(len);
michael@0 1061
michael@0 1062 // Use <UserLocalDataDir>\updates\<relative path to app dir from
michael@0 1063 // Program Files> if app dir is under Program Files to avoid the
michael@0 1064 // folder virtualization mess on Windows Vista
michael@0 1065 nsAutoString programFiles;
michael@0 1066 rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles);
michael@0 1067 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1068
michael@0 1069 programFiles.AppendLiteral("\\");
michael@0 1070 uint32_t programFilesLen = programFiles.Length();
michael@0 1071
michael@0 1072 nsAutoString programName;
michael@0 1073 if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) {
michael@0 1074 programName = Substring(longPath, programFilesLen);
michael@0 1075 } else {
michael@0 1076 // We need the update root directory to live outside of the installation
michael@0 1077 // directory, because otherwise the updater writing the log file can cause
michael@0 1078 // the directory to be locked, which prevents it from being replaced after
michael@0 1079 // background updates.
michael@0 1080 programName.AssignASCII(MOZ_APP_NAME);
michael@0 1081 }
michael@0 1082
michael@0 1083 rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
michael@0 1084 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1085
michael@0 1086 rv = updRoot->AppendRelativePath(programName);
michael@0 1087 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1088
michael@0 1089 #endif
michael@0 1090 #endif
michael@0 1091 NS_ADDREF(*aResult = updRoot);
michael@0 1092 return NS_OK;
michael@0 1093 }
michael@0 1094
michael@0 1095 nsresult
michael@0 1096 nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult)
michael@0 1097 {
michael@0 1098 if (mProfileDir)
michael@0 1099 return mProfileDir->Clone(aResult);
michael@0 1100
michael@0 1101 if (mAppProvider) {
michael@0 1102 nsCOMPtr<nsIFile> needsclone;
michael@0 1103 bool dummy;
michael@0 1104 nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP,
michael@0 1105 &dummy,
michael@0 1106 getter_AddRefs(needsclone));
michael@0 1107 if (NS_SUCCEEDED(rv))
michael@0 1108 return needsclone->Clone(aResult);
michael@0 1109 }
michael@0 1110
michael@0 1111 return NS_ERROR_FAILURE;
michael@0 1112 }
michael@0 1113
michael@0 1114 nsresult
michael@0 1115 nsXREDirProvider::GetProfileDir(nsIFile* *aResult)
michael@0 1116 {
michael@0 1117 if (mProfileDir) {
michael@0 1118 if (!mProfileNotified)
michael@0 1119 return NS_ERROR_FAILURE;
michael@0 1120
michael@0 1121 return mProfileDir->Clone(aResult);
michael@0 1122 }
michael@0 1123
michael@0 1124 if (mAppProvider) {
michael@0 1125 nsCOMPtr<nsIFile> needsclone;
michael@0 1126 bool dummy;
michael@0 1127 nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR,
michael@0 1128 &dummy,
michael@0 1129 getter_AddRefs(needsclone));
michael@0 1130 if (NS_SUCCEEDED(rv))
michael@0 1131 return needsclone->Clone(aResult);
michael@0 1132 }
michael@0 1133
michael@0 1134 return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
michael@0 1135 }
michael@0 1136
michael@0 1137 nsresult
michael@0 1138 nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
michael@0 1139 {
michael@0 1140 // Copied from nsAppFileLocationProvider (more or less)
michael@0 1141 NS_ENSURE_ARG_POINTER(aFile);
michael@0 1142 nsCOMPtr<nsIFile> localDir;
michael@0 1143
michael@0 1144 nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir));
michael@0 1145 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1146
michael@0 1147 int levelsToRemove = 1; // In FF21+, appDir points to browser subdirectory.
michael@0 1148 #if defined(XP_MACOSX)
michael@0 1149 levelsToRemove += 2;
michael@0 1150 #endif
michael@0 1151 while (localDir && (levelsToRemove > 0)) {
michael@0 1152 // When crawling up the hierarchy, components named "." do not count.
michael@0 1153 nsAutoCString removedName;
michael@0 1154 rv = localDir->GetNativeLeafName(removedName);
michael@0 1155 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1156 bool didRemove = !removedName.Equals(".");
michael@0 1157
michael@0 1158 // Remove a directory component.
michael@0 1159 nsCOMPtr<nsIFile> parentDir;
michael@0 1160 rv = localDir->GetParent(getter_AddRefs(parentDir));
michael@0 1161 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1162 localDir = parentDir;
michael@0 1163
michael@0 1164 if (didRemove)
michael@0 1165 --levelsToRemove;
michael@0 1166 }
michael@0 1167
michael@0 1168 if (!localDir)
michael@0 1169 return NS_ERROR_FAILURE;
michael@0 1170
michael@0 1171 rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("TorBrowser"
michael@0 1172 XPCOM_FILE_PATH_SEPARATOR "Data"
michael@0 1173 XPCOM_FILE_PATH_SEPARATOR "Browser"));
michael@0 1174 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1175
michael@0 1176 if (aLocal) {
michael@0 1177 rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
michael@0 1178 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1179 }
michael@0 1180
michael@0 1181 NS_IF_ADDREF(*aFile = localDir);
michael@0 1182 return rv;
michael@0 1183 }
michael@0 1184
michael@0 1185 nsresult
michael@0 1186 nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile)
michael@0 1187 {
michael@0 1188 nsCOMPtr<nsIFile> localDir;
michael@0 1189 nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
michael@0 1190 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1191
michael@0 1192 rv = AppendSysUserExtensionPath(localDir);
michael@0 1193 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1194
michael@0 1195 rv = EnsureDirectoryExists(localDir);
michael@0 1196 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1197
michael@0 1198 NS_ADDREF(*aFile = localDir);
michael@0 1199 return NS_OK;
michael@0 1200 }
michael@0 1201
michael@0 1202 #if defined(XP_UNIX) || defined(XP_MACOSX)
michael@0 1203 nsresult
michael@0 1204 nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile)
michael@0 1205 {
michael@0 1206 nsresult rv;
michael@0 1207 nsCOMPtr<nsIFile> localDir;
michael@0 1208 #if defined(XP_MACOSX)
michael@0 1209 FSRef fsRef;
michael@0 1210 OSErr err = ::FSFindFolder(kOnSystemDisk, kApplicationSupportFolderType, kCreateFolder, &fsRef);
michael@0 1211 NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
michael@0 1212
michael@0 1213 rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
michael@0 1214 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1215
michael@0 1216 nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
michael@0 1217 NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
michael@0 1218
michael@0 1219 rv = dirFileMac->InitWithFSRef(&fsRef);
michael@0 1220 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1221
michael@0 1222 localDir = do_QueryInterface(dirFileMac, &rv);
michael@0 1223
michael@0 1224 static const char* const sXR = "Mozilla";
michael@0 1225 rv = localDir->AppendNative(nsDependentCString(sXR));
michael@0 1226 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1227
michael@0 1228 static const char* const sExtensions = "Extensions";
michael@0 1229 rv = localDir->AppendNative(nsDependentCString(sExtensions));
michael@0 1230 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1231 #elif defined(XP_UNIX)
michael@0 1232 static const char *const sysSExtDir =
michael@0 1233 #ifdef HAVE_USR_LIB64_DIR
michael@0 1234 "/usr/lib64/mozilla/extensions";
michael@0 1235 #elif defined(__OpenBSD__) || defined(__FreeBSD__)
michael@0 1236 "/usr/local/lib/mozilla/extensions";
michael@0 1237 #else
michael@0 1238 "/usr/lib/mozilla/extensions";
michael@0 1239 #endif
michael@0 1240
michael@0 1241 rv = NS_NewNativeLocalFile(nsDependentCString(sysSExtDir), false,
michael@0 1242 getter_AddRefs(localDir));
michael@0 1243 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1244 #endif
michael@0 1245
michael@0 1246 NS_ADDREF(*aFile = localDir);
michael@0 1247 return NS_OK;
michael@0 1248 }
michael@0 1249 #endif
michael@0 1250
michael@0 1251 nsresult
michael@0 1252 nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal,
michael@0 1253 const nsACString* aProfileName,
michael@0 1254 const nsACString* aAppName,
michael@0 1255 const nsACString* aVendorName)
michael@0 1256 {
michael@0 1257 nsCOMPtr<nsIFile> localDir;
michael@0 1258 nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal);
michael@0 1259 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1260
michael@0 1261 rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName, aLocal);
michael@0 1262 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1263
michael@0 1264 #ifdef DEBUG_jungshik
michael@0 1265 nsAutoCString cwd;
michael@0 1266 localDir->GetNativePath(cwd);
michael@0 1267 printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
michael@0 1268 #endif
michael@0 1269 rv = EnsureDirectoryExists(localDir);
michael@0 1270 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1271
michael@0 1272 NS_ADDREF(*aFile = localDir);
michael@0 1273 return NS_OK;
michael@0 1274 }
michael@0 1275
michael@0 1276 nsresult
michael@0 1277 nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
michael@0 1278 {
michael@0 1279 bool exists;
michael@0 1280 nsresult rv = aDirectory->Exists(&exists);
michael@0 1281 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1282 #ifdef DEBUG_jungshik
michael@0 1283 if (!exists) {
michael@0 1284 nsAutoCString cwd;
michael@0 1285 aDirectory->GetNativePath(cwd);
michael@0 1286 printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get());
michael@0 1287 }
michael@0 1288 #endif
michael@0 1289 if (!exists)
michael@0 1290 rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
michael@0 1291 #ifdef DEBUG_jungshik
michael@0 1292 if (NS_FAILED(rv))
michael@0 1293 NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
michael@0 1294 #endif
michael@0 1295
michael@0 1296 return rv;
michael@0 1297 }
michael@0 1298
michael@0 1299 void
michael@0 1300 nsXREDirProvider::EnsureProfileFileExists(nsIFile *aFile)
michael@0 1301 {
michael@0 1302 nsresult rv;
michael@0 1303 bool exists;
michael@0 1304
michael@0 1305 rv = aFile->Exists(&exists);
michael@0 1306 if (NS_FAILED(rv) || exists) return;
michael@0 1307
michael@0 1308 nsAutoCString leafName;
michael@0 1309 rv = aFile->GetNativeLeafName(leafName);
michael@0 1310 if (NS_FAILED(rv)) return;
michael@0 1311
michael@0 1312 nsCOMPtr<nsIFile> defaultsFile;
michael@0 1313 rv = GetProfileDefaultsDir(getter_AddRefs(defaultsFile));
michael@0 1314 if (NS_FAILED(rv)) return;
michael@0 1315
michael@0 1316 rv = defaultsFile->AppendNative(leafName);
michael@0 1317 if (NS_FAILED(rv)) return;
michael@0 1318
michael@0 1319 defaultsFile->CopyToNative(mProfileDir, EmptyCString());
michael@0 1320 }
michael@0 1321
michael@0 1322 nsresult
michael@0 1323 nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult)
michael@0 1324 {
michael@0 1325 NS_ASSERTION(mGREDir, "nsXREDirProvider not initialized.");
michael@0 1326 NS_PRECONDITION(aResult, "Null out-param");
michael@0 1327
michael@0 1328 nsresult rv;
michael@0 1329 nsCOMPtr<nsIFile> defaultsDir;
michael@0 1330
michael@0 1331 rv = GetAppDir()->Clone(getter_AddRefs(defaultsDir));
michael@0 1332 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1333
michael@0 1334 rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("defaults"));
michael@0 1335 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1336
michael@0 1337 rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile"));
michael@0 1338 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1339
michael@0 1340 NS_ADDREF(*aResult = defaultsDir);
michael@0 1341 return NS_OK;
michael@0 1342 }
michael@0 1343
michael@0 1344 nsresult
michael@0 1345 nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile)
michael@0 1346 {
michael@0 1347 NS_ASSERTION(aFile, "Null pointer!");
michael@0 1348
michael@0 1349 nsresult rv;
michael@0 1350
michael@0 1351 #if defined (XP_MACOSX) || defined(XP_WIN)
michael@0 1352
michael@0 1353 static const char* const sXR = "Mozilla";
michael@0 1354 rv = aFile->AppendNative(nsDependentCString(sXR));
michael@0 1355 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1356
michael@0 1357 static const char* const sExtensions = "Extensions";
michael@0 1358 rv = aFile->AppendNative(nsDependentCString(sExtensions));
michael@0 1359 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1360
michael@0 1361 #elif defined(XP_UNIX)
michael@0 1362
michael@0 1363 static const char* const sXR = ".mozilla";
michael@0 1364 rv = aFile->AppendNative(nsDependentCString(sXR));
michael@0 1365 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1366
michael@0 1367 static const char* const sExtensions = "extensions";
michael@0 1368 rv = aFile->AppendNative(nsDependentCString(sExtensions));
michael@0 1369 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1370
michael@0 1371 #else
michael@0 1372 #error "Don't know how to get XRE user extension path on your platform"
michael@0 1373 #endif
michael@0 1374 return NS_OK;
michael@0 1375 }
michael@0 1376
michael@0 1377
michael@0 1378 nsresult
michael@0 1379 nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
michael@0 1380 const nsACString* aProfileName,
michael@0 1381 const nsACString* aAppName,
michael@0 1382 const nsACString* aVendorName,
michael@0 1383 bool aLocal)
michael@0 1384 {
michael@0 1385 NS_ASSERTION(aFile, "Null pointer!");
michael@0 1386
michael@0 1387 if (!gAppData) {
michael@0 1388 return NS_ERROR_FAILURE;
michael@0 1389 }
michael@0 1390
michael@0 1391 nsAutoCString profile;
michael@0 1392 if (aProfileName && !aProfileName->IsEmpty()) {
michael@0 1393 profile = *aProfileName;
michael@0 1394 } else if (gAppData->profile) {
michael@0 1395 profile = gAppData->profile;
michael@0 1396 }
michael@0 1397
michael@0 1398 nsresult rv = NS_ERROR_FAILURE;
michael@0 1399
michael@0 1400 #if defined (XP_MACOSX)
michael@0 1401 if (!profile.IsEmpty()) {
michael@0 1402 rv = AppendProfileString(aFile, profile.get());
michael@0 1403 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1404 }
michael@0 1405
michael@0 1406 #elif defined(XP_WIN)
michael@0 1407 if (!profile.IsEmpty()) {
michael@0 1408 rv = AppendProfileString(aFile, profile.get());
michael@0 1409 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1410 }
michael@0 1411
michael@0 1412 #elif defined(ANDROID)
michael@0 1413 // The directory used for storing profiles
michael@0 1414 // The parent of this directory is set in GetUserDataDirectoryHome
michael@0 1415 // XXX: handle gAppData->profile properly
michael@0 1416 // XXXsmaug ...and the rest of the profile creation!
michael@0 1417 MOZ_ASSERT(!aAppName,
michael@0 1418 "Profile creation for external applications is not implemented!");
michael@0 1419 rv = aFile->AppendNative(nsDependentCString("mozilla"));
michael@0 1420 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1421 #elif defined(XP_UNIX)
michael@0 1422 if (!profile.IsEmpty()) {
michael@0 1423 // Skip any leading path characters
michael@0 1424 const char* profileStart = profile.get();
michael@0 1425 while (*profileStart == '/' || *profileStart == '\\')
michael@0 1426 profileStart++;
michael@0 1427
michael@0 1428 // On the off chance that someone wanted their folder to be hidden don't
michael@0 1429 // let it become ".."
michael@0 1430 if (*profileStart == '.')
michael@0 1431 profileStart++;
michael@0 1432
michael@0 1433 // Make it hidden (by starting with ".").
michael@0 1434 nsAutoCString folder(".");
michael@0 1435 folder.Append(profileStart);
michael@0 1436 ToLowerCase(folder);
michael@0 1437
michael@0 1438 rv = AppendProfileString(aFile, folder.BeginReading());
michael@0 1439 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1440 }
michael@0 1441
michael@0 1442 #else
michael@0 1443 #error "Don't know how to get profile path on your platform"
michael@0 1444 #endif
michael@0 1445 return NS_OK;
michael@0 1446 }
michael@0 1447
michael@0 1448 nsresult
michael@0 1449 nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath)
michael@0 1450 {
michael@0 1451 NS_ASSERTION(aFile, "Null file!");
michael@0 1452 NS_ASSERTION(aPath, "Null path!");
michael@0 1453
michael@0 1454 nsAutoCString pathDup(aPath);
michael@0 1455
michael@0 1456 char* path = pathDup.BeginWriting();
michael@0 1457
michael@0 1458 nsresult rv;
michael@0 1459 char* subdir;
michael@0 1460 while ((subdir = NS_strtok("/\\", &path))) {
michael@0 1461 rv = aFile->AppendNative(nsDependentCString(subdir));
michael@0 1462 NS_ENSURE_SUCCESS(rv, rv);
michael@0 1463 }
michael@0 1464
michael@0 1465 return NS_OK;
michael@0 1466 }

mercurial