1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/xre/nsXREDirProvider.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1466 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsAppRunner.h" 1.10 +#include "nsToolkitCompsCID.h" 1.11 +#include "nsXREDirProvider.h" 1.12 + 1.13 +#include "jsapi.h" 1.14 + 1.15 +#include "nsIJSRuntimeService.h" 1.16 +#include "nsIAppStartup.h" 1.17 +#include "nsIDirectoryEnumerator.h" 1.18 +#include "nsIFile.h" 1.19 +#include "nsIObserver.h" 1.20 +#include "nsIObserverService.h" 1.21 +#include "nsISimpleEnumerator.h" 1.22 +#include "nsIToolkitChromeRegistry.h" 1.23 + 1.24 +#include "nsAppDirectoryServiceDefs.h" 1.25 +#include "nsDirectoryServiceDefs.h" 1.26 +#include "nsDirectoryServiceUtils.h" 1.27 +#include "nsXULAppAPI.h" 1.28 +#include "nsCategoryManagerUtils.h" 1.29 + 1.30 +#include "nsINIParser.h" 1.31 +#include "nsDependentString.h" 1.32 +#include "nsCOMArray.h" 1.33 +#include "nsArrayEnumerator.h" 1.34 +#include "nsEnumeratorUtils.h" 1.35 +#include "nsReadableUtils.h" 1.36 +#include "nsXPCOMPrivate.h" // for XPCOM_FILE_PATH_SEPARATOR 1.37 +#include "mozilla/Services.h" 1.38 +#include "mozilla/Omnijar.h" 1.39 +#include "mozilla/Preferences.h" 1.40 +#include "mozilla/Telemetry.h" 1.41 + 1.42 +#include <stdlib.h> 1.43 + 1.44 +#ifdef XP_WIN 1.45 +#include <windows.h> 1.46 +#include <shlobj.h> 1.47 +#endif 1.48 +#ifdef XP_MACOSX 1.49 +#include "nsILocalFileMac.h" 1.50 +// for chflags() 1.51 +#include <sys/stat.h> 1.52 +#include <unistd.h> 1.53 +#endif 1.54 +#ifdef XP_UNIX 1.55 +#include <ctype.h> 1.56 +#endif 1.57 + 1.58 +#if defined(XP_MACOSX) 1.59 +#define APP_REGISTRY_NAME "Application Registry" 1.60 +#elif defined(XP_WIN) 1.61 +#define APP_REGISTRY_NAME "registry.dat" 1.62 +#else 1.63 +#define APP_REGISTRY_NAME "appreg" 1.64 +#endif 1.65 + 1.66 +#define PREF_OVERRIDE_DIRNAME "preferences" 1.67 + 1.68 +static already_AddRefed<nsIFile> 1.69 +CloneAndAppend(nsIFile* aFile, const char* name) 1.70 +{ 1.71 + nsCOMPtr<nsIFile> file; 1.72 + aFile->Clone(getter_AddRefs(file)); 1.73 + file->AppendNative(nsDependentCString(name)); 1.74 + return file.forget(); 1.75 +} 1.76 + 1.77 +nsXREDirProvider* gDirServiceProvider = nullptr; 1.78 + 1.79 +nsXREDirProvider::nsXREDirProvider() : 1.80 + mProfileNotified(false) 1.81 +{ 1.82 + gDirServiceProvider = this; 1.83 +} 1.84 + 1.85 +nsXREDirProvider::~nsXREDirProvider() 1.86 +{ 1.87 + gDirServiceProvider = nullptr; 1.88 +} 1.89 + 1.90 +nsXREDirProvider* 1.91 +nsXREDirProvider::GetSingleton() 1.92 +{ 1.93 + return gDirServiceProvider; 1.94 +} 1.95 + 1.96 +nsresult 1.97 +nsXREDirProvider::Initialize(nsIFile *aXULAppDir, 1.98 + nsIFile *aGREDir, 1.99 + nsIDirectoryServiceProvider* aAppProvider) 1.100 +{ 1.101 + NS_ENSURE_ARG(aXULAppDir); 1.102 + NS_ENSURE_ARG(aGREDir); 1.103 + 1.104 + mAppProvider = aAppProvider; 1.105 + mXULAppDir = aXULAppDir; 1.106 + mGREDir = aGREDir; 1.107 + 1.108 + if (!mProfileDir) { 1.109 + nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider)); 1.110 + if (app) { 1.111 + bool per = false; 1.112 + app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir)); 1.113 + NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!"); 1.114 + NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!"); 1.115 + } 1.116 + } 1.117 + 1.118 + LoadAppBundleDirs(); 1.119 + return NS_OK; 1.120 +} 1.121 + 1.122 +nsresult 1.123 +nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir) 1.124 +{ 1.125 + NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!"); 1.126 + 1.127 + nsresult rv; 1.128 + 1.129 + rv = EnsureDirectoryExists(aDir); 1.130 + if (NS_FAILED(rv)) 1.131 + return rv; 1.132 + 1.133 + rv = EnsureDirectoryExists(aLocalDir); 1.134 + if (NS_FAILED(rv)) 1.135 + return rv; 1.136 + 1.137 +#ifdef XP_MACOSX 1.138 + bool same; 1.139 + if (NS_SUCCEEDED(aDir->Equals(aLocalDir, &same)) && !same) { 1.140 + // Ensure that the cache directory is not indexed by Spotlight 1.141 + // (bug 718910). At least on OS X, the cache directory (under 1.142 + // ~/Library/Caches/) is always the "local" user profile 1.143 + // directory. This is confusing, since *both* user profile 1.144 + // directories are "local" (they both exist under the user's 1.145 + // home directory). But this usage dates back at least as far 1.146 + // as the patch for bug 291033, where "local" seems to mean 1.147 + // "suitable for temporary storage". Don't hide the cache 1.148 + // directory if by some chance it and the "non-local" profile 1.149 + // directory are the same -- there are bad side effects from 1.150 + // hiding a profile directory under /Library/Application Support/ 1.151 + // (see bug 801883). 1.152 + nsAutoCString cacheDir; 1.153 + if (NS_SUCCEEDED(aLocalDir->GetNativePath(cacheDir))) { 1.154 + if (chflags(cacheDir.get(), UF_HIDDEN)) { 1.155 + NS_WARNING("Failed to set Cache directory to HIDDEN."); 1.156 + } 1.157 + } 1.158 + } 1.159 +#endif 1.160 + 1.161 + mProfileDir = aDir; 1.162 + mProfileLocalDir = aLocalDir; 1.163 + return NS_OK; 1.164 +} 1.165 + 1.166 +NS_IMPL_QUERY_INTERFACE(nsXREDirProvider, 1.167 + nsIDirectoryServiceProvider, 1.168 + nsIDirectoryServiceProvider2, 1.169 + nsIProfileStartup) 1.170 + 1.171 +NS_IMETHODIMP_(MozExternalRefCountType) 1.172 +nsXREDirProvider::AddRef() 1.173 +{ 1.174 + return 1; 1.175 +} 1.176 + 1.177 +NS_IMETHODIMP_(MozExternalRefCountType) 1.178 +nsXREDirProvider::Release() 1.179 +{ 1.180 + return 0; 1.181 +} 1.182 + 1.183 +nsresult 1.184 +nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult, 1.185 + const nsACString* aProfileName, 1.186 + const nsACString* aAppName, 1.187 + const nsACString* aVendorName) 1.188 +{ 1.189 + nsCOMPtr<nsIFile> file; 1.190 + nsresult rv = GetUserDataDirectory(getter_AddRefs(file), 1.191 + false, 1.192 + aProfileName, aAppName, aVendorName); 1.193 + 1.194 + if (NS_SUCCEEDED(rv)) { 1.195 + // We must create the profile directory here if it does not exist. 1.196 + nsresult tmp = EnsureDirectoryExists(file); 1.197 + if (NS_FAILED(tmp)) { 1.198 + rv = tmp; 1.199 + } 1.200 + } 1.201 + file.swap(*aResult); 1.202 + return rv; 1.203 +} 1.204 + 1.205 +nsresult 1.206 +nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult, 1.207 + const nsACString* aProfileName, 1.208 + const nsACString* aAppName, 1.209 + const nsACString* aVendorName) 1.210 +{ 1.211 + nsCOMPtr<nsIFile> file; 1.212 + nsresult rv = GetUserDataDirectory(getter_AddRefs(file), 1.213 + true, 1.214 + aProfileName, aAppName, aVendorName); 1.215 + 1.216 + if (NS_SUCCEEDED(rv)) { 1.217 + // We must create the profile directory here if it does not exist. 1.218 + nsresult tmp = EnsureDirectoryExists(file); 1.219 + if (NS_FAILED(tmp)) { 1.220 + rv = tmp; 1.221 + } 1.222 + } 1.223 + file.swap(*aResult); 1.224 + return NS_OK; 1.225 +} 1.226 + 1.227 +NS_IMETHODIMP 1.228 +nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent, 1.229 + nsIFile** aFile) 1.230 +{ 1.231 + nsresult rv; 1.232 + 1.233 + bool gettingProfile = false; 1.234 + 1.235 + if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) { 1.236 + // If XRE_NotifyProfile hasn't been called, don't fall through to 1.237 + // mAppProvider on the profile keys. 1.238 + if (!mProfileNotified) 1.239 + return NS_ERROR_FAILURE; 1.240 + 1.241 + if (mProfileLocalDir) 1.242 + return mProfileLocalDir->Clone(aFile); 1.243 + 1.244 + if (mAppProvider) 1.245 + return mAppProvider->GetFile(aProperty, aPersistent, aFile); 1.246 + 1.247 + // This falls through to the case below 1.248 + gettingProfile = true; 1.249 + } 1.250 + if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) { 1.251 + if (!mProfileNotified) 1.252 + return NS_ERROR_FAILURE; 1.253 + 1.254 + if (mProfileDir) 1.255 + return mProfileDir->Clone(aFile); 1.256 + 1.257 + if (mAppProvider) 1.258 + return mAppProvider->GetFile(aProperty, aPersistent, aFile); 1.259 + 1.260 + // If we don't succeed here, bail early so that we aren't reentrant 1.261 + // through the "GetProfileDir" call below. 1.262 + return NS_ERROR_FAILURE; 1.263 + } 1.264 + 1.265 + if (mAppProvider) { 1.266 + rv = mAppProvider->GetFile(aProperty, aPersistent, aFile); 1.267 + if (NS_SUCCEEDED(rv) && *aFile) 1.268 + return rv; 1.269 + } 1.270 + 1.271 + *aPersistent = true; 1.272 + 1.273 + if (!strcmp(aProperty, NS_GRE_DIR)) { 1.274 + return mGREDir->Clone(aFile); 1.275 + } 1.276 + else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) || 1.277 + !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) { 1.278 + return GetAppDir()->Clone(aFile); 1.279 + } 1.280 + 1.281 + rv = NS_ERROR_FAILURE; 1.282 + nsCOMPtr<nsIFile> file; 1.283 + 1.284 + if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) || 1.285 + !strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR)) { 1.286 + return GetProfileDefaultsDir(aFile); 1.287 + } 1.288 + else if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR)) 1.289 + { 1.290 + // return the GRE default prefs directory here, and the app default prefs 1.291 + // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST. 1.292 + rv = mGREDir->Clone(getter_AddRefs(file)); 1.293 + if (NS_SUCCEEDED(rv)) { 1.294 + rv = file->AppendNative(NS_LITERAL_CSTRING("defaults")); 1.295 + if (NS_SUCCEEDED(rv)) 1.296 + rv = file->AppendNative(NS_LITERAL_CSTRING("pref")); 1.297 + } 1.298 + } 1.299 + else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) || 1.300 + !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) { 1.301 + rv = GetUserAppDataDirectory(getter_AddRefs(file)); 1.302 + } 1.303 + else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) { 1.304 + rv = GetUpdateRootDir(getter_AddRefs(file)); 1.305 + } 1.306 + else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) { 1.307 + rv = GetUserAppDataDirectory(getter_AddRefs(file)); 1.308 + if (NS_SUCCEEDED(rv)) 1.309 + rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME)); 1.310 + } 1.311 + else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) { 1.312 + rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr); 1.313 + } 1.314 + else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) { 1.315 + rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr); 1.316 + } 1.317 + else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) { 1.318 + nsCOMPtr<nsIFile> lf; 1.319 + rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf)); 1.320 + if (NS_SUCCEEDED(rv)) 1.321 + file = lf; 1.322 + } 1.323 + 1.324 + else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) { 1.325 + return mProfileDir->Clone(aFile); 1.326 + } 1.327 + else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) { 1.328 + if (mProfileLocalDir) 1.329 + return mProfileLocalDir->Clone(aFile); 1.330 + 1.331 + if (mProfileDir) 1.332 + return mProfileDir->Clone(aFile); 1.333 + 1.334 + if (mAppProvider) 1.335 + return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent, 1.336 + aFile); 1.337 + } 1.338 +#if defined(XP_UNIX) || defined(XP_MACOSX) 1.339 + else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) { 1.340 +#ifdef ENABLE_SYSTEM_EXTENSION_DIRS 1.341 + return GetSystemExtensionsDirectory(aFile); 1.342 +#else 1.343 + return NS_ERROR_FAILURE; 1.344 +#endif 1.345 + } 1.346 +#endif 1.347 +#if defined(XP_UNIX) && !defined(XP_MACOSX) 1.348 + else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) { 1.349 +#ifdef ENABLE_SYSTEM_EXTENSION_DIRS 1.350 +#if defined(__OpenBSD__) || defined(__FreeBSD__) 1.351 + static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions"; 1.352 +#else 1.353 + static const char *const sysLExtDir = "/usr/share/mozilla/extensions"; 1.354 +#endif 1.355 + return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir), 1.356 + false, aFile); 1.357 +#else 1.358 + return NS_ERROR_FAILURE; 1.359 +#endif 1.360 + } 1.361 +#endif 1.362 + else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) { 1.363 +#ifdef ENABLE_SYSTEM_EXTENSION_DIRS 1.364 + return GetSysUserExtensionsDirectory(aFile); 1.365 +#else 1.366 + return NS_ERROR_FAILURE; 1.367 +#endif 1.368 + } 1.369 + else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) { 1.370 + bool persistent = false; 1.371 + rv = GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(file)); 1.372 + if (NS_SUCCEEDED(rv)) 1.373 + rv = file->SetNativeLeafName(NS_LITERAL_CSTRING("distribution")); 1.374 + } 1.375 + else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) { 1.376 + // We need to allow component, xpt, and chrome registration to 1.377 + // occur prior to the profile-after-change notification. 1.378 + if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) { 1.379 + rv = file->AppendNative(NS_LITERAL_CSTRING("chrome")); 1.380 + } 1.381 + } 1.382 + 1.383 + if (NS_SUCCEEDED(rv) && file) { 1.384 + NS_ADDREF(*aFile = file); 1.385 + return NS_OK; 1.386 + } 1.387 + 1.388 + bool ensureFilePermissions = false; 1.389 + 1.390 + if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) { 1.391 + if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) { 1.392 + rv = NS_OK; 1.393 + } 1.394 + else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) { 1.395 + rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js")); 1.396 + } 1.397 + else if (!strcmp(aProperty, NS_METRO_APP_PREFS_50_FILE)) { 1.398 + rv = file->AppendNative(NS_LITERAL_CSTRING("metro-prefs.js")); 1.399 + } 1.400 + else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) { 1.401 + rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf")); 1.402 + } 1.403 + else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) { 1.404 + if (gSafeMode) { 1.405 + rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf")); 1.406 + file->Remove(false); 1.407 + } 1.408 + else { 1.409 + rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf")); 1.410 + EnsureProfileFileExists(file); 1.411 + ensureFilePermissions = true; 1.412 + } 1.413 + } 1.414 + else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) { 1.415 + rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf")); 1.416 + EnsureProfileFileExists(file); 1.417 + ensureFilePermissions = true; 1.418 + } 1.419 + else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) { 1.420 + rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf")); 1.421 + } 1.422 + else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) { 1.423 + rv = mProfileDir->Clone(getter_AddRefs(file)); 1.424 + nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME)); 1.425 + if (NS_FAILED(tmp)) { 1.426 + rv = tmp; 1.427 + } 1.428 + tmp = EnsureDirectoryExists(file); 1.429 + if (NS_FAILED(tmp)) { 1.430 + rv = tmp; 1.431 + } 1.432 + } 1.433 + } 1.434 + if (NS_FAILED(rv) || !file) 1.435 + return NS_ERROR_FAILURE; 1.436 + 1.437 + if (ensureFilePermissions) { 1.438 + bool fileToEnsureExists; 1.439 + bool isWritable; 1.440 + if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists 1.441 + && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) { 1.442 + uint32_t permissions; 1.443 + if (NS_SUCCEEDED(file->GetPermissions(&permissions))) { 1.444 + rv = file->SetPermissions(permissions | 0600); 1.445 + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions"); 1.446 + } 1.447 + } 1.448 + } 1.449 + 1.450 + NS_ADDREF(*aFile = file); 1.451 + return NS_OK; 1.452 +} 1.453 + 1.454 +static void 1.455 +LoadDirIntoArray(nsIFile* dir, 1.456 + const char *const *aAppendList, 1.457 + nsCOMArray<nsIFile>& aDirectories) 1.458 +{ 1.459 + if (!dir) 1.460 + return; 1.461 + 1.462 + nsCOMPtr<nsIFile> subdir; 1.463 + dir->Clone(getter_AddRefs(subdir)); 1.464 + if (!subdir) 1.465 + return; 1.466 + 1.467 + for (const char *const *a = aAppendList; *a; ++a) { 1.468 + subdir->AppendNative(nsDependentCString(*a)); 1.469 + } 1.470 + 1.471 + bool exists; 1.472 + if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) { 1.473 + aDirectories.AppendObject(subdir); 1.474 + } 1.475 +} 1.476 + 1.477 +static void 1.478 +LoadDirsIntoArray(nsCOMArray<nsIFile>& aSourceDirs, 1.479 + const char *const* aAppendList, 1.480 + nsCOMArray<nsIFile>& aDirectories) 1.481 +{ 1.482 + nsCOMPtr<nsIFile> appended; 1.483 + bool exists; 1.484 + 1.485 + for (int32_t i = 0; i < aSourceDirs.Count(); ++i) { 1.486 + aSourceDirs[i]->Clone(getter_AddRefs(appended)); 1.487 + if (!appended) 1.488 + continue; 1.489 + 1.490 + nsAutoCString leaf; 1.491 + appended->GetNativeLeafName(leaf); 1.492 + if (!Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) { 1.493 + LoadDirIntoArray(appended, 1.494 + aAppendList, 1.495 + aDirectories); 1.496 + } 1.497 + else if (NS_SUCCEEDED(appended->Exists(&exists)) && exists) 1.498 + aDirectories.AppendObject(appended); 1.499 + } 1.500 +} 1.501 + 1.502 +NS_IMETHODIMP 1.503 +nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult) 1.504 +{ 1.505 + nsresult rv; 1.506 + 1.507 + nsCOMPtr<nsISimpleEnumerator> appEnum; 1.508 + nsCOMPtr<nsIDirectoryServiceProvider2> 1.509 + appP2(do_QueryInterface(mAppProvider)); 1.510 + if (appP2) { 1.511 + rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum)); 1.512 + if (NS_FAILED(rv)) { 1.513 + appEnum = nullptr; 1.514 + } 1.515 + else if (rv != NS_SUCCESS_AGGREGATE_RESULT) { 1.516 + NS_ADDREF(*aResult = appEnum); 1.517 + return NS_OK; 1.518 + } 1.519 + } 1.520 + 1.521 + nsCOMPtr<nsISimpleEnumerator> xreEnum; 1.522 + rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum)); 1.523 + if (NS_FAILED(rv)) { 1.524 + if (appEnum) { 1.525 + NS_ADDREF(*aResult = appEnum); 1.526 + return NS_SUCCESS_AGGREGATE_RESULT; 1.527 + } 1.528 + 1.529 + return rv; 1.530 + } 1.531 + 1.532 + rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum); 1.533 + if (NS_FAILED(rv)) 1.534 + return rv; 1.535 + 1.536 + return NS_SUCCESS_AGGREGATE_RESULT; 1.537 +} 1.538 + 1.539 +static void 1.540 +LoadExtensionDirectories(nsINIParser &parser, 1.541 + const char *aSection, 1.542 + nsCOMArray<nsIFile> &aDirectories, 1.543 + NSLocationType aType) 1.544 +{ 1.545 + nsresult rv; 1.546 + int32_t i = 0; 1.547 + do { 1.548 + nsAutoCString buf("Extension"); 1.549 + buf.AppendInt(i++); 1.550 + 1.551 + nsAutoCString path; 1.552 + rv = parser.GetString(aSection, buf.get(), path); 1.553 + if (NS_FAILED(rv)) 1.554 + return; 1.555 + 1.556 + nsCOMPtr<nsIFile> dir = do_CreateInstance("@mozilla.org/file/local;1", &rv); 1.557 + if (NS_FAILED(rv)) 1.558 + continue; 1.559 + 1.560 + rv = dir->SetPersistentDescriptor(path); 1.561 + if (NS_FAILED(rv)) 1.562 + continue; 1.563 + 1.564 + aDirectories.AppendObject(dir); 1.565 + if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) { 1.566 + XRE_AddJarManifestLocation(aType, dir); 1.567 + } 1.568 + else { 1.569 + nsCOMPtr<nsIFile> manifest = 1.570 + CloneAndAppend(dir, "chrome.manifest"); 1.571 + XRE_AddManifestLocation(aType, manifest); 1.572 + } 1.573 + } 1.574 + while (true); 1.575 +} 1.576 + 1.577 +void 1.578 +nsXREDirProvider::LoadExtensionBundleDirectories() 1.579 +{ 1.580 + if (!mozilla::Preferences::GetBool("extensions.defaultProviders.enabled", true)) 1.581 + return; 1.582 + 1.583 + if (mProfileDir && !gSafeMode) { 1.584 + nsCOMPtr<nsIFile> extensionsINI; 1.585 + mProfileDir->Clone(getter_AddRefs(extensionsINI)); 1.586 + if (!extensionsINI) 1.587 + return; 1.588 + 1.589 + extensionsINI->AppendNative(NS_LITERAL_CSTRING("extensions.ini")); 1.590 + 1.591 + nsCOMPtr<nsIFile> extensionsINILF = 1.592 + do_QueryInterface(extensionsINI); 1.593 + if (!extensionsINILF) 1.594 + return; 1.595 + 1.596 + nsINIParser parser; 1.597 + nsresult rv = parser.Init(extensionsINILF); 1.598 + if (NS_FAILED(rv)) 1.599 + return; 1.600 + 1.601 + LoadExtensionDirectories(parser, "ExtensionDirs", mExtensionDirectories, 1.602 + NS_COMPONENT_LOCATION); 1.603 + LoadExtensionDirectories(parser, "ThemeDirs", mThemeDirectories, 1.604 + NS_SKIN_LOCATION); 1.605 + } 1.606 +} 1.607 + 1.608 +void 1.609 +nsXREDirProvider::LoadAppBundleDirs() 1.610 +{ 1.611 + nsCOMPtr<nsIFile> dir; 1.612 + bool persistent = false; 1.613 + nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(dir)); 1.614 + if (NS_FAILED(rv)) 1.615 + return; 1.616 + 1.617 + dir->SetNativeLeafName(NS_LITERAL_CSTRING("distribution")); 1.618 + dir->AppendNative(NS_LITERAL_CSTRING("bundles")); 1.619 + 1.620 + nsCOMPtr<nsISimpleEnumerator> e; 1.621 + rv = dir->GetDirectoryEntries(getter_AddRefs(e)); 1.622 + if (NS_FAILED(rv)) 1.623 + return; 1.624 + 1.625 + nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e); 1.626 + if (!files) 1.627 + return; 1.628 + 1.629 + nsCOMPtr<nsIFile> subdir; 1.630 + while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(subdir))) && subdir) { 1.631 + mAppBundleDirectories.AppendObject(subdir); 1.632 + 1.633 + nsCOMPtr<nsIFile> manifest = 1.634 + CloneAndAppend(subdir, "chrome.manifest"); 1.635 + XRE_AddManifestLocation(NS_COMPONENT_LOCATION, manifest); 1.636 + } 1.637 +} 1.638 + 1.639 +static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr }; 1.640 + 1.641 +#ifdef DEBUG_bsmedberg 1.642 +static void 1.643 +DumpFileArray(const char *key, 1.644 + nsCOMArray<nsIFile> dirs) 1.645 +{ 1.646 + fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key); 1.647 + 1.648 + nsAutoCString path; 1.649 + for (int32_t i = 0; i < dirs.Count(); ++i) { 1.650 + dirs[i]->GetNativePath(path); 1.651 + fprintf(stderr, " %s\n", path.get()); 1.652 + } 1.653 +} 1.654 +#endif // DEBUG_bsmedberg 1.655 + 1.656 +nsresult 1.657 +nsXREDirProvider::GetFilesInternal(const char* aProperty, 1.658 + nsISimpleEnumerator** aResult) 1.659 +{ 1.660 + nsresult rv = NS_OK; 1.661 + *aResult = nullptr; 1.662 + 1.663 + if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) { 1.664 + nsCOMArray<nsIFile> directories; 1.665 + 1.666 + static const char *const kAppendNothing[] = { nullptr }; 1.667 + 1.668 + LoadDirsIntoArray(mAppBundleDirectories, 1.669 + kAppendNothing, directories); 1.670 + LoadDirsIntoArray(mExtensionDirectories, 1.671 + kAppendNothing, directories); 1.672 + 1.673 + rv = NS_NewArrayEnumerator(aResult, directories); 1.674 + } 1.675 + else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) { 1.676 + nsCOMArray<nsIFile> directories; 1.677 + 1.678 + LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories); 1.679 + LoadDirsIntoArray(mAppBundleDirectories, 1.680 + kAppendPrefDir, directories); 1.681 + 1.682 + rv = NS_NewArrayEnumerator(aResult, directories); 1.683 + } 1.684 + else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) { 1.685 + nsCOMArray<nsIFile> directories; 1.686 + 1.687 + LoadDirsIntoArray(mExtensionDirectories, 1.688 + kAppendPrefDir, directories); 1.689 + 1.690 + if (mProfileDir) { 1.691 + nsCOMPtr<nsIFile> overrideFile; 1.692 + mProfileDir->Clone(getter_AddRefs(overrideFile)); 1.693 + overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME)); 1.694 + 1.695 + bool exists; 1.696 + if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists) 1.697 + directories.AppendObject(overrideFile); 1.698 + } 1.699 + 1.700 + rv = NS_NewArrayEnumerator(aResult, directories); 1.701 + } 1.702 + else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) { 1.703 + // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons 1.704 + // for OS window decoration. 1.705 + 1.706 + static const char *const kAppendChromeDir[] = { "chrome", nullptr }; 1.707 + nsCOMArray<nsIFile> directories; 1.708 + LoadDirIntoArray(mXULAppDir, 1.709 + kAppendChromeDir, 1.710 + directories); 1.711 + LoadDirsIntoArray(mAppBundleDirectories, 1.712 + kAppendChromeDir, 1.713 + directories); 1.714 + LoadDirsIntoArray(mExtensionDirectories, 1.715 + kAppendChromeDir, 1.716 + directories); 1.717 + 1.718 + rv = NS_NewArrayEnumerator(aResult, directories); 1.719 + } 1.720 + else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) { 1.721 + nsCOMArray<nsIFile> directories; 1.722 + 1.723 + if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) { 1.724 + nsCOMPtr<nsIFile> appdir; 1.725 + rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir)); 1.726 + if (NS_SUCCEEDED(rv)) { 1.727 + appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins")); 1.728 + directories.AppendObject(appdir); 1.729 + } 1.730 + } 1.731 + 1.732 + static const char *const kAppendPlugins[] = { "plugins", nullptr }; 1.733 + 1.734 + // The root dirserviceprovider does quite a bit for us: we're mainly 1.735 + // interested in xulapp and extension-provided plugins. 1.736 + LoadDirsIntoArray(mAppBundleDirectories, 1.737 + kAppendPlugins, 1.738 + directories); 1.739 + LoadDirsIntoArray(mExtensionDirectories, 1.740 + kAppendPlugins, 1.741 + directories); 1.742 + 1.743 + if (mProfileDir) { 1.744 + nsCOMArray<nsIFile> profileDir; 1.745 + profileDir.AppendObject(mProfileDir); 1.746 + LoadDirsIntoArray(profileDir, 1.747 + kAppendPlugins, 1.748 + directories); 1.749 + } 1.750 + 1.751 + rv = NS_NewArrayEnumerator(aResult, directories); 1.752 + NS_ENSURE_SUCCESS(rv, rv); 1.753 + 1.754 + rv = NS_SUCCESS_AGGREGATE_RESULT; 1.755 + } 1.756 + else 1.757 + rv = NS_ERROR_FAILURE; 1.758 + 1.759 + return rv; 1.760 +} 1.761 + 1.762 +NS_IMETHODIMP 1.763 +nsXREDirProvider::GetDirectory(nsIFile* *aResult) 1.764 +{ 1.765 + NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED); 1.766 + 1.767 + return mProfileDir->Clone(aResult); 1.768 +} 1.769 + 1.770 +NS_IMETHODIMP 1.771 +nsXREDirProvider::DoStartup() 1.772 +{ 1.773 + if (!mProfileNotified) { 1.774 + nsCOMPtr<nsIObserverService> obsSvc = 1.775 + mozilla::services::GetObserverService(); 1.776 + if (!obsSvc) return NS_ERROR_FAILURE; 1.777 + 1.778 + mProfileNotified = true; 1.779 + 1.780 + /* 1.781 + Setup prefs before profile-do-change to be able to use them to track 1.782 + crashes and because we want to begin crash tracking before other code run 1.783 + from this notification since they may cause crashes. 1.784 + */ 1.785 + nsresult rv = mozilla::Preferences::ResetAndReadUserPrefs(); 1.786 + if (NS_FAILED(rv)) NS_WARNING("Failed to setup pref service."); 1.787 + 1.788 + bool safeModeNecessary = false; 1.789 + nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID)); 1.790 + if (appStartup) { 1.791 + rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary); 1.792 + if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE) 1.793 + NS_WARNING("Error while beginning startup crash tracking"); 1.794 + 1.795 + if (!gSafeMode && safeModeNecessary) { 1.796 + appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit); 1.797 + return NS_OK; 1.798 + } 1.799 + } 1.800 + 1.801 + static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'}; 1.802 + obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup); 1.803 + // Init the Extension Manager 1.804 + nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1"); 1.805 + if (em) { 1.806 + em->Observe(nullptr, "addons-startup", nullptr); 1.807 + } else { 1.808 + NS_WARNING("Failed to create Addons Manager."); 1.809 + } 1.810 + 1.811 + LoadExtensionBundleDirectories(); 1.812 + 1.813 + obsSvc->NotifyObservers(nullptr, "load-extension-defaults", nullptr); 1.814 + obsSvc->NotifyObservers(nullptr, "profile-after-change", kStartup); 1.815 + 1.816 + // Any component that has registered for the profile-after-change category 1.817 + // should also be created at this time. 1.818 + (void)NS_CreateServicesFromCategory("profile-after-change", nullptr, 1.819 + "profile-after-change"); 1.820 + 1.821 + if (gSafeMode && safeModeNecessary) { 1.822 + static const char16_t kCrashed[] = {'c','r','a','s','h','e','d','\0'}; 1.823 + obsSvc->NotifyObservers(nullptr, "safemode-forced", kCrashed); 1.824 + } 1.825 + 1.826 + // 1 = Regular mode, 2 = Safe mode, 3 = Safe mode forced 1.827 + int mode = 1; 1.828 + if (gSafeMode) { 1.829 + if (safeModeNecessary) 1.830 + mode = 3; 1.831 + else 1.832 + mode = 2; 1.833 + } 1.834 + mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode); 1.835 + 1.836 + obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr); 1.837 + } 1.838 + return NS_OK; 1.839 +} 1.840 + 1.841 +void 1.842 +nsXREDirProvider::DoShutdown() 1.843 +{ 1.844 + if (mProfileNotified) { 1.845 + nsCOMPtr<nsIObserverService> obsSvc = 1.846 + mozilla::services::GetObserverService(); 1.847 + NS_ASSERTION(obsSvc, "No observer service?"); 1.848 + if (obsSvc) { 1.849 + static const char16_t kShutdownPersist[] = 1.850 + {'s','h','u','t','d','o','w','n','-','p','e','r','s','i','s','t','\0'}; 1.851 + obsSvc->NotifyObservers(nullptr, "profile-change-net-teardown", kShutdownPersist); 1.852 + obsSvc->NotifyObservers(nullptr, "profile-change-teardown", kShutdownPersist); 1.853 + 1.854 + // Phase 2c: Now that things are torn down, force JS GC so that things which depend on 1.855 + // resources which are about to go away in "profile-before-change" are destroyed first. 1.856 + 1.857 + nsCOMPtr<nsIJSRuntimeService> rtsvc 1.858 + (do_GetService("@mozilla.org/js/xpc/RuntimeService;1")); 1.859 + if (rtsvc) 1.860 + { 1.861 + JSRuntime *rt = nullptr; 1.862 + rtsvc->GetRuntime(&rt); 1.863 + if (rt) 1.864 + ::JS_GC(rt); 1.865 + } 1.866 + 1.867 + // Phase 3: Notify observers of a profile change 1.868 + obsSvc->NotifyObservers(nullptr, "profile-before-change", kShutdownPersist); 1.869 + obsSvc->NotifyObservers(nullptr, "profile-before-change2", kShutdownPersist); 1.870 + } 1.871 + mProfileNotified = false; 1.872 + } 1.873 +} 1.874 + 1.875 +#ifdef XP_WIN 1.876 +static nsresult 1.877 +GetShellFolderPath(int folder, nsAString& _retval) 1.878 +{ 1.879 + wchar_t* buf; 1.880 + uint32_t bufLength = _retval.GetMutableData(&buf, MAXPATHLEN + 3); 1.881 + NS_ENSURE_TRUE(bufLength >= (MAXPATHLEN + 3), NS_ERROR_OUT_OF_MEMORY); 1.882 + 1.883 + nsresult rv = NS_OK; 1.884 + 1.885 + LPITEMIDLIST pItemIDList = nullptr; 1.886 + 1.887 + if (SUCCEEDED(SHGetSpecialFolderLocation(nullptr, folder, &pItemIDList)) && 1.888 + SHGetPathFromIDListW(pItemIDList, buf)) { 1.889 + // We're going to use wcslen (wcsnlen not available in msvc7.1) so make 1.890 + // sure to null terminate. 1.891 + buf[bufLength - 1] = L'\0'; 1.892 + _retval.SetLength(wcslen(buf)); 1.893 + } else { 1.894 + _retval.SetLength(0); 1.895 + rv = NS_ERROR_NOT_AVAILABLE; 1.896 + } 1.897 + 1.898 + CoTaskMemFree(pItemIDList); 1.899 + 1.900 + return rv; 1.901 +} 1.902 + 1.903 +/** 1.904 + * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by 1.905 + * querying the registry when the call to SHGetSpecialFolderLocation or 1.906 + * SHGetPathFromIDListW is unable to provide these paths (Bug 513958). 1.907 + */ 1.908 +static nsresult 1.909 +GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval) 1.910 +{ 1.911 + HKEY key; 1.912 + NS_NAMED_LITERAL_STRING(keyName, 1.913 + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"); 1.914 + DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ, 1.915 + &key); 1.916 + if (res != ERROR_SUCCESS) { 1.917 + _retval.SetLength(0); 1.918 + return NS_ERROR_NOT_AVAILABLE; 1.919 + } 1.920 + 1.921 + DWORD type, size; 1.922 + res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"), 1.923 + nullptr, &type, nullptr, &size); 1.924 + // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the 1.925 + // buffer size must not equal 0, and the buffer size be a multiple of 2. 1.926 + if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) { 1.927 + ::RegCloseKey(key); 1.928 + _retval.SetLength(0); 1.929 + return NS_ERROR_NOT_AVAILABLE; 1.930 + } 1.931 + 1.932 + // |size| may or may not include room for the terminating null character 1.933 + DWORD resultLen = size / 2; 1.934 + 1.935 + _retval.SetLength(resultLen); 1.936 + nsAString::iterator begin; 1.937 + _retval.BeginWriting(begin); 1.938 + if (begin.size_forward() != resultLen) { 1.939 + ::RegCloseKey(key); 1.940 + _retval.SetLength(0); 1.941 + return NS_ERROR_NOT_AVAILABLE; 1.942 + } 1.943 + 1.944 + res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"), 1.945 + nullptr, nullptr, (LPBYTE) begin.get(), &size); 1.946 + ::RegCloseKey(key); 1.947 + if (res != ERROR_SUCCESS) { 1.948 + _retval.SetLength(0); 1.949 + return NS_ERROR_NOT_AVAILABLE; 1.950 + } 1.951 + 1.952 + if (!_retval.CharAt(resultLen - 1)) { 1.953 + // It was already null terminated. 1.954 + _retval.Truncate(resultLen - 1); 1.955 + } 1.956 + 1.957 + return NS_OK; 1.958 +} 1.959 + 1.960 +static bool 1.961 +GetCachedHash(HKEY rootKey, const nsAString ®Path, const nsAString &path, 1.962 + nsAString &cachedHash) 1.963 +{ 1.964 + HKEY baseKey; 1.965 + if (RegOpenKeyExW(rootKey, reinterpret_cast<const wchar_t*>(regPath.BeginReading()), 0, KEY_READ, &baseKey) != 1.966 + ERROR_SUCCESS) { 1.967 + return false; 1.968 + } 1.969 + 1.970 + wchar_t cachedHashRaw[512]; 1.971 + DWORD bufferSize = sizeof(cachedHashRaw); 1.972 + LONG result = RegQueryValueExW(baseKey, reinterpret_cast<const wchar_t*>(path.BeginReading()), 0, nullptr, 1.973 + (LPBYTE)cachedHashRaw, &bufferSize); 1.974 + RegCloseKey(baseKey); 1.975 + if (result == ERROR_SUCCESS) { 1.976 + cachedHash.Assign(cachedHashRaw); 1.977 + } 1.978 + return ERROR_SUCCESS == result; 1.979 +} 1.980 + 1.981 +#endif 1.982 + 1.983 +nsresult 1.984 +nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult) 1.985 +{ 1.986 + nsCOMPtr<nsIFile> updRoot; 1.987 +#if defined(MOZ_WIDGET_GONK) 1.988 + 1.989 + nsresult rv = NS_NewNativeLocalFile(nsDependentCString("/data/local"), 1.990 + true, 1.991 + getter_AddRefs(updRoot)); 1.992 + NS_ENSURE_SUCCESS(rv, rv); 1.993 + 1.994 +#else 1.995 + nsCOMPtr<nsIFile> appFile; 1.996 + bool per = false; 1.997 + nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile)); 1.998 + NS_ENSURE_SUCCESS(rv, rv); 1.999 + rv = appFile->GetParent(getter_AddRefs(updRoot)); 1.1000 + NS_ENSURE_SUCCESS(rv, rv); 1.1001 + 1.1002 +#ifdef XP_WIN 1.1003 + 1.1004 + nsAutoString pathHash; 1.1005 + bool pathHashResult = false; 1.1006 + bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0; 1.1007 + 1.1008 + nsAutoString appDirPath; 1.1009 + if (SUCCEEDED(updRoot->GetPath(appDirPath))) { 1.1010 + 1.1011 + // Figure out where we should check for a cached hash value. If the 1.1012 + // application doesn't have the nsXREAppData vendor value defined check 1.1013 + // under SOFTWARE\Mozilla. 1.1014 + wchar_t regPath[1024] = { L'\0' }; 1.1015 + swprintf_s(regPath, mozilla::ArrayLength(regPath), L"SOFTWARE\\%S\\%S\\TaskBarIDs", 1.1016 + (hasVendor ? gAppData->vendor : "Mozilla"), MOZ_APP_BASENAME); 1.1017 + 1.1018 + // If we pre-computed the hash, grab it from the registry. 1.1019 + pathHashResult = GetCachedHash(HKEY_LOCAL_MACHINE, 1.1020 + nsDependentString(regPath), appDirPath, 1.1021 + pathHash); 1.1022 + if (!pathHashResult) { 1.1023 + pathHashResult = GetCachedHash(HKEY_CURRENT_USER, 1.1024 + nsDependentString(regPath), appDirPath, 1.1025 + pathHash); 1.1026 + } 1.1027 + } 1.1028 + 1.1029 + // Get the local app data directory and if a vendor name exists append it. 1.1030 + // If only a product name exists, append it. If neither exist fallback to 1.1031 + // old handling. We don't use the product name on purpose because we want a 1.1032 + // shared update directory for different apps run from the same path (like 1.1033 + // Metro & Desktop). 1.1034 + nsCOMPtr<nsIFile> localDir; 1.1035 + if (pathHashResult && (hasVendor || gAppData->name) && 1.1036 + NS_SUCCEEDED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true)) && 1.1037 + NS_SUCCEEDED(localDir->AppendNative(nsDependentCString(hasVendor ? 1.1038 + gAppData->vendor : gAppData->name))) && 1.1039 + NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) && 1.1040 + NS_SUCCEEDED(localDir->Append(pathHash))) { 1.1041 + NS_ADDREF(*aResult = localDir); 1.1042 + return NS_OK; 1.1043 + } 1.1044 + 1.1045 + nsAutoString appPath; 1.1046 + rv = updRoot->GetPath(appPath); 1.1047 + NS_ENSURE_SUCCESS(rv, rv); 1.1048 + 1.1049 + // AppDir may be a short path. Convert to long path to make sure 1.1050 + // the consistency of the update folder location 1.1051 + nsString longPath; 1.1052 + wchar_t* buf; 1.1053 + 1.1054 + uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN); 1.1055 + NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY); 1.1056 + 1.1057 + DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength); 1.1058 + 1.1059 + // Failing GetLongPathName() is not fatal. 1.1060 + if (len <= 0 || len >= bufLength) 1.1061 + longPath.Assign(appPath); 1.1062 + else 1.1063 + longPath.SetLength(len); 1.1064 + 1.1065 + // Use <UserLocalDataDir>\updates\<relative path to app dir from 1.1066 + // Program Files> if app dir is under Program Files to avoid the 1.1067 + // folder virtualization mess on Windows Vista 1.1068 + nsAutoString programFiles; 1.1069 + rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles); 1.1070 + NS_ENSURE_SUCCESS(rv, rv); 1.1071 + 1.1072 + programFiles.AppendLiteral("\\"); 1.1073 + uint32_t programFilesLen = programFiles.Length(); 1.1074 + 1.1075 + nsAutoString programName; 1.1076 + if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) { 1.1077 + programName = Substring(longPath, programFilesLen); 1.1078 + } else { 1.1079 + // We need the update root directory to live outside of the installation 1.1080 + // directory, because otherwise the updater writing the log file can cause 1.1081 + // the directory to be locked, which prevents it from being replaced after 1.1082 + // background updates. 1.1083 + programName.AssignASCII(MOZ_APP_NAME); 1.1084 + } 1.1085 + 1.1086 + rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot)); 1.1087 + NS_ENSURE_SUCCESS(rv, rv); 1.1088 + 1.1089 + rv = updRoot->AppendRelativePath(programName); 1.1090 + NS_ENSURE_SUCCESS(rv, rv); 1.1091 + 1.1092 +#endif 1.1093 +#endif 1.1094 + NS_ADDREF(*aResult = updRoot); 1.1095 + return NS_OK; 1.1096 +} 1.1097 + 1.1098 +nsresult 1.1099 +nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult) 1.1100 +{ 1.1101 + if (mProfileDir) 1.1102 + return mProfileDir->Clone(aResult); 1.1103 + 1.1104 + if (mAppProvider) { 1.1105 + nsCOMPtr<nsIFile> needsclone; 1.1106 + bool dummy; 1.1107 + nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, 1.1108 + &dummy, 1.1109 + getter_AddRefs(needsclone)); 1.1110 + if (NS_SUCCEEDED(rv)) 1.1111 + return needsclone->Clone(aResult); 1.1112 + } 1.1113 + 1.1114 + return NS_ERROR_FAILURE; 1.1115 +} 1.1116 + 1.1117 +nsresult 1.1118 +nsXREDirProvider::GetProfileDir(nsIFile* *aResult) 1.1119 +{ 1.1120 + if (mProfileDir) { 1.1121 + if (!mProfileNotified) 1.1122 + return NS_ERROR_FAILURE; 1.1123 + 1.1124 + return mProfileDir->Clone(aResult); 1.1125 + } 1.1126 + 1.1127 + if (mAppProvider) { 1.1128 + nsCOMPtr<nsIFile> needsclone; 1.1129 + bool dummy; 1.1130 + nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR, 1.1131 + &dummy, 1.1132 + getter_AddRefs(needsclone)); 1.1133 + if (NS_SUCCEEDED(rv)) 1.1134 + return needsclone->Clone(aResult); 1.1135 + } 1.1136 + 1.1137 + return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult); 1.1138 +} 1.1139 + 1.1140 +nsresult 1.1141 +nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal) 1.1142 +{ 1.1143 + // Copied from nsAppFileLocationProvider (more or less) 1.1144 + NS_ENSURE_ARG_POINTER(aFile); 1.1145 + nsCOMPtr<nsIFile> localDir; 1.1146 + 1.1147 + nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir)); 1.1148 + NS_ENSURE_SUCCESS(rv, rv); 1.1149 + 1.1150 + int levelsToRemove = 1; // In FF21+, appDir points to browser subdirectory. 1.1151 +#if defined(XP_MACOSX) 1.1152 + levelsToRemove += 2; 1.1153 +#endif 1.1154 + while (localDir && (levelsToRemove > 0)) { 1.1155 + // When crawling up the hierarchy, components named "." do not count. 1.1156 + nsAutoCString removedName; 1.1157 + rv = localDir->GetNativeLeafName(removedName); 1.1158 + NS_ENSURE_SUCCESS(rv, rv); 1.1159 + bool didRemove = !removedName.Equals("."); 1.1160 + 1.1161 + // Remove a directory component. 1.1162 + nsCOMPtr<nsIFile> parentDir; 1.1163 + rv = localDir->GetParent(getter_AddRefs(parentDir)); 1.1164 + NS_ENSURE_SUCCESS(rv, rv); 1.1165 + localDir = parentDir; 1.1166 + 1.1167 + if (didRemove) 1.1168 + --levelsToRemove; 1.1169 + } 1.1170 + 1.1171 + if (!localDir) 1.1172 + return NS_ERROR_FAILURE; 1.1173 + 1.1174 + rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("TorBrowser" 1.1175 + XPCOM_FILE_PATH_SEPARATOR "Data" 1.1176 + XPCOM_FILE_PATH_SEPARATOR "Browser")); 1.1177 + NS_ENSURE_SUCCESS(rv, rv); 1.1178 + 1.1179 + if (aLocal) { 1.1180 + rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches")); 1.1181 + NS_ENSURE_SUCCESS(rv, rv); 1.1182 + } 1.1183 + 1.1184 + NS_IF_ADDREF(*aFile = localDir); 1.1185 + return rv; 1.1186 +} 1.1187 + 1.1188 +nsresult 1.1189 +nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile) 1.1190 +{ 1.1191 + nsCOMPtr<nsIFile> localDir; 1.1192 + nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false); 1.1193 + NS_ENSURE_SUCCESS(rv, rv); 1.1194 + 1.1195 + rv = AppendSysUserExtensionPath(localDir); 1.1196 + NS_ENSURE_SUCCESS(rv, rv); 1.1197 + 1.1198 + rv = EnsureDirectoryExists(localDir); 1.1199 + NS_ENSURE_SUCCESS(rv, rv); 1.1200 + 1.1201 + NS_ADDREF(*aFile = localDir); 1.1202 + return NS_OK; 1.1203 +} 1.1204 + 1.1205 +#if defined(XP_UNIX) || defined(XP_MACOSX) 1.1206 +nsresult 1.1207 +nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile) 1.1208 +{ 1.1209 + nsresult rv; 1.1210 + nsCOMPtr<nsIFile> localDir; 1.1211 +#if defined(XP_MACOSX) 1.1212 + FSRef fsRef; 1.1213 + OSErr err = ::FSFindFolder(kOnSystemDisk, kApplicationSupportFolderType, kCreateFolder, &fsRef); 1.1214 + NS_ENSURE_FALSE(err, NS_ERROR_FAILURE); 1.1215 + 1.1216 + rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir)); 1.1217 + NS_ENSURE_SUCCESS(rv, rv); 1.1218 + 1.1219 + nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir); 1.1220 + NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED); 1.1221 + 1.1222 + rv = dirFileMac->InitWithFSRef(&fsRef); 1.1223 + NS_ENSURE_SUCCESS(rv, rv); 1.1224 + 1.1225 + localDir = do_QueryInterface(dirFileMac, &rv); 1.1226 + 1.1227 + static const char* const sXR = "Mozilla"; 1.1228 + rv = localDir->AppendNative(nsDependentCString(sXR)); 1.1229 + NS_ENSURE_SUCCESS(rv, rv); 1.1230 + 1.1231 + static const char* const sExtensions = "Extensions"; 1.1232 + rv = localDir->AppendNative(nsDependentCString(sExtensions)); 1.1233 + NS_ENSURE_SUCCESS(rv, rv); 1.1234 +#elif defined(XP_UNIX) 1.1235 + static const char *const sysSExtDir = 1.1236 +#ifdef HAVE_USR_LIB64_DIR 1.1237 + "/usr/lib64/mozilla/extensions"; 1.1238 +#elif defined(__OpenBSD__) || defined(__FreeBSD__) 1.1239 + "/usr/local/lib/mozilla/extensions"; 1.1240 +#else 1.1241 + "/usr/lib/mozilla/extensions"; 1.1242 +#endif 1.1243 + 1.1244 + rv = NS_NewNativeLocalFile(nsDependentCString(sysSExtDir), false, 1.1245 + getter_AddRefs(localDir)); 1.1246 + NS_ENSURE_SUCCESS(rv, rv); 1.1247 +#endif 1.1248 + 1.1249 + NS_ADDREF(*aFile = localDir); 1.1250 + return NS_OK; 1.1251 +} 1.1252 +#endif 1.1253 + 1.1254 +nsresult 1.1255 +nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal, 1.1256 + const nsACString* aProfileName, 1.1257 + const nsACString* aAppName, 1.1258 + const nsACString* aVendorName) 1.1259 +{ 1.1260 + nsCOMPtr<nsIFile> localDir; 1.1261 + nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal); 1.1262 + NS_ENSURE_SUCCESS(rv, rv); 1.1263 + 1.1264 + rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName, aLocal); 1.1265 + NS_ENSURE_SUCCESS(rv, rv); 1.1266 + 1.1267 +#ifdef DEBUG_jungshik 1.1268 + nsAutoCString cwd; 1.1269 + localDir->GetNativePath(cwd); 1.1270 + printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get()); 1.1271 +#endif 1.1272 + rv = EnsureDirectoryExists(localDir); 1.1273 + NS_ENSURE_SUCCESS(rv, rv); 1.1274 + 1.1275 + NS_ADDREF(*aFile = localDir); 1.1276 + return NS_OK; 1.1277 +} 1.1278 + 1.1279 +nsresult 1.1280 +nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory) 1.1281 +{ 1.1282 + bool exists; 1.1283 + nsresult rv = aDirectory->Exists(&exists); 1.1284 + NS_ENSURE_SUCCESS(rv, rv); 1.1285 +#ifdef DEBUG_jungshik 1.1286 + if (!exists) { 1.1287 + nsAutoCString cwd; 1.1288 + aDirectory->GetNativePath(cwd); 1.1289 + printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get()); 1.1290 + } 1.1291 +#endif 1.1292 + if (!exists) 1.1293 + rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700); 1.1294 +#ifdef DEBUG_jungshik 1.1295 + if (NS_FAILED(rv)) 1.1296 + NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed"); 1.1297 +#endif 1.1298 + 1.1299 + return rv; 1.1300 +} 1.1301 + 1.1302 +void 1.1303 +nsXREDirProvider::EnsureProfileFileExists(nsIFile *aFile) 1.1304 +{ 1.1305 + nsresult rv; 1.1306 + bool exists; 1.1307 + 1.1308 + rv = aFile->Exists(&exists); 1.1309 + if (NS_FAILED(rv) || exists) return; 1.1310 + 1.1311 + nsAutoCString leafName; 1.1312 + rv = aFile->GetNativeLeafName(leafName); 1.1313 + if (NS_FAILED(rv)) return; 1.1314 + 1.1315 + nsCOMPtr<nsIFile> defaultsFile; 1.1316 + rv = GetProfileDefaultsDir(getter_AddRefs(defaultsFile)); 1.1317 + if (NS_FAILED(rv)) return; 1.1318 + 1.1319 + rv = defaultsFile->AppendNative(leafName); 1.1320 + if (NS_FAILED(rv)) return; 1.1321 + 1.1322 + defaultsFile->CopyToNative(mProfileDir, EmptyCString()); 1.1323 +} 1.1324 + 1.1325 +nsresult 1.1326 +nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult) 1.1327 +{ 1.1328 + NS_ASSERTION(mGREDir, "nsXREDirProvider not initialized."); 1.1329 + NS_PRECONDITION(aResult, "Null out-param"); 1.1330 + 1.1331 + nsresult rv; 1.1332 + nsCOMPtr<nsIFile> defaultsDir; 1.1333 + 1.1334 + rv = GetAppDir()->Clone(getter_AddRefs(defaultsDir)); 1.1335 + NS_ENSURE_SUCCESS(rv, rv); 1.1336 + 1.1337 + rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("defaults")); 1.1338 + NS_ENSURE_SUCCESS(rv, rv); 1.1339 + 1.1340 + rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile")); 1.1341 + NS_ENSURE_SUCCESS(rv, rv); 1.1342 + 1.1343 + NS_ADDREF(*aResult = defaultsDir); 1.1344 + return NS_OK; 1.1345 +} 1.1346 + 1.1347 +nsresult 1.1348 +nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile) 1.1349 +{ 1.1350 + NS_ASSERTION(aFile, "Null pointer!"); 1.1351 + 1.1352 + nsresult rv; 1.1353 + 1.1354 +#if defined (XP_MACOSX) || defined(XP_WIN) 1.1355 + 1.1356 + static const char* const sXR = "Mozilla"; 1.1357 + rv = aFile->AppendNative(nsDependentCString(sXR)); 1.1358 + NS_ENSURE_SUCCESS(rv, rv); 1.1359 + 1.1360 + static const char* const sExtensions = "Extensions"; 1.1361 + rv = aFile->AppendNative(nsDependentCString(sExtensions)); 1.1362 + NS_ENSURE_SUCCESS(rv, rv); 1.1363 + 1.1364 +#elif defined(XP_UNIX) 1.1365 + 1.1366 + static const char* const sXR = ".mozilla"; 1.1367 + rv = aFile->AppendNative(nsDependentCString(sXR)); 1.1368 + NS_ENSURE_SUCCESS(rv, rv); 1.1369 + 1.1370 + static const char* const sExtensions = "extensions"; 1.1371 + rv = aFile->AppendNative(nsDependentCString(sExtensions)); 1.1372 + NS_ENSURE_SUCCESS(rv, rv); 1.1373 + 1.1374 +#else 1.1375 +#error "Don't know how to get XRE user extension path on your platform" 1.1376 +#endif 1.1377 + return NS_OK; 1.1378 +} 1.1379 + 1.1380 + 1.1381 +nsresult 1.1382 +nsXREDirProvider::AppendProfilePath(nsIFile* aFile, 1.1383 + const nsACString* aProfileName, 1.1384 + const nsACString* aAppName, 1.1385 + const nsACString* aVendorName, 1.1386 + bool aLocal) 1.1387 +{ 1.1388 + NS_ASSERTION(aFile, "Null pointer!"); 1.1389 + 1.1390 + if (!gAppData) { 1.1391 + return NS_ERROR_FAILURE; 1.1392 + } 1.1393 + 1.1394 + nsAutoCString profile; 1.1395 + if (aProfileName && !aProfileName->IsEmpty()) { 1.1396 + profile = *aProfileName; 1.1397 + } else if (gAppData->profile) { 1.1398 + profile = gAppData->profile; 1.1399 + } 1.1400 + 1.1401 + nsresult rv = NS_ERROR_FAILURE; 1.1402 + 1.1403 +#if defined (XP_MACOSX) 1.1404 + if (!profile.IsEmpty()) { 1.1405 + rv = AppendProfileString(aFile, profile.get()); 1.1406 + NS_ENSURE_SUCCESS(rv, rv); 1.1407 + } 1.1408 + 1.1409 +#elif defined(XP_WIN) 1.1410 + if (!profile.IsEmpty()) { 1.1411 + rv = AppendProfileString(aFile, profile.get()); 1.1412 + NS_ENSURE_SUCCESS(rv, rv); 1.1413 + } 1.1414 + 1.1415 +#elif defined(ANDROID) 1.1416 + // The directory used for storing profiles 1.1417 + // The parent of this directory is set in GetUserDataDirectoryHome 1.1418 + // XXX: handle gAppData->profile properly 1.1419 + // XXXsmaug ...and the rest of the profile creation! 1.1420 + MOZ_ASSERT(!aAppName, 1.1421 + "Profile creation for external applications is not implemented!"); 1.1422 + rv = aFile->AppendNative(nsDependentCString("mozilla")); 1.1423 + NS_ENSURE_SUCCESS(rv, rv); 1.1424 +#elif defined(XP_UNIX) 1.1425 + if (!profile.IsEmpty()) { 1.1426 + // Skip any leading path characters 1.1427 + const char* profileStart = profile.get(); 1.1428 + while (*profileStart == '/' || *profileStart == '\\') 1.1429 + profileStart++; 1.1430 + 1.1431 + // On the off chance that someone wanted their folder to be hidden don't 1.1432 + // let it become ".." 1.1433 + if (*profileStart == '.') 1.1434 + profileStart++; 1.1435 + 1.1436 + // Make it hidden (by starting with "."). 1.1437 + nsAutoCString folder("."); 1.1438 + folder.Append(profileStart); 1.1439 + ToLowerCase(folder); 1.1440 + 1.1441 + rv = AppendProfileString(aFile, folder.BeginReading()); 1.1442 + NS_ENSURE_SUCCESS(rv, rv); 1.1443 + } 1.1444 + 1.1445 +#else 1.1446 +#error "Don't know how to get profile path on your platform" 1.1447 +#endif 1.1448 + return NS_OK; 1.1449 +} 1.1450 + 1.1451 +nsresult 1.1452 +nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath) 1.1453 +{ 1.1454 + NS_ASSERTION(aFile, "Null file!"); 1.1455 + NS_ASSERTION(aPath, "Null path!"); 1.1456 + 1.1457 + nsAutoCString pathDup(aPath); 1.1458 + 1.1459 + char* path = pathDup.BeginWriting(); 1.1460 + 1.1461 + nsresult rv; 1.1462 + char* subdir; 1.1463 + while ((subdir = NS_strtok("/\\", &path))) { 1.1464 + rv = aFile->AppendNative(nsDependentCString(subdir)); 1.1465 + NS_ENSURE_SUCCESS(rv, rv); 1.1466 + } 1.1467 + 1.1468 + return NS_OK; 1.1469 +}