nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult) { nsCOMPtr<nsIFile> appDir = GetAppDir(); nsAutoString appPath; nsresult rv = appDir->GetPath(appPath); NS_ENSURE_SUCCESS(rv, rv); // AppDir may be a short path. Convert to long path to make sure // the consistency of the update folder location nsString longPath; PRUnichar* buf; uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN); NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY); DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength); // Failing GetLongPathName() is not fatal. if (len <= 0 || len >= bufLength) longPath.Assign(appPath); else longPath.SetLength(len); // Use <UserLocalDataDir>\updates\<relative path to app dir from // Program Files> if app dir is under Program Files to avoid the // folder virtualization mess on Windows Vista nsAutoString programFiles; rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles); NS_ENSURE_SUCCESS(rv, rv); programFiles.AppendLiteral("\\"); uint32_t programFilesLen = programFiles.Length(); if (longPath.Length() < programFilesLen) return NS_ERROR_FAILURE; nsAutoString programName; if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) { programName = Substring(longPath, programFilesLen); } else { // We need the update root directory to live outside of the installation // directory, because otherwise the updater writing the log file can cause // the directory to be locked, which prevents it from being replaced after // background updates. programName.AssignASCII(MOZ_APP_NAME); } nsCOMPtr<nsIFile> updRoot; rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot)); NS_ENSURE_SUCCESS(rv, rv); rv = updRoot->AppendRelativePath(programName); NS_ENSURE_SUCCESS(rv, rv); NS_ADDREF(*aResult = updRoot); return NS_OK; }
nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult) { nsCOMPtr<nsIFile> appDir = GetAppDir(); nsAutoString appPath; nsresult rv = appDir->GetPath(appPath); NS_ENSURE_SUCCESS(rv, rv); // AppDir may be a short path. Convert to long path to make sure // the consistency of the update folder location nsString longPath; PRUnichar* buf; PRUint32 bufLength = longPath.GetMutableData(&buf, MAXPATHLEN); NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY); #ifdef WINCE longPath.Assign(appPath); #else DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength); // Failing GetLongPathName() is not fatal. if (len <= 0 || len >= bufLength) longPath.Assign(appPath); else longPath.SetLength(len); #endif // Use <UserLocalDataDir>\updates\<relative path to app dir from // Program Files> if app dir is under Program Files to avoid the // folder virtualization mess on Windows Vista nsAutoString programFiles; rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles); NS_ENSURE_SUCCESS(rv, rv); programFiles.AppendLiteral("\\"); PRUint32 programFilesLen = programFiles.Length(); if (longPath.Length() < programFilesLen) return NS_ERROR_FAILURE; if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) != 0) return NS_ERROR_FAILURE; nsCOMPtr<nsILocalFile> updRoot; rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot)); NS_ENSURE_SUCCESS(rv, rv); rv = updRoot->AppendRelativePath(Substring(longPath, programFilesLen)); NS_ENSURE_SUCCESS(rv, rv); NS_ADDREF(*aResult = updRoot); return NS_OK; }
nsresult nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult) { nsCOMPtr<nsIFile> updRoot; #if defined(MOZ_WIDGET_GONK) nsresult rv = NS_NewNativeLocalFile(nsDependentCString("/data/local"), true, getter_AddRefs(updRoot)); NS_ENSURE_SUCCESS(rv, rv); #else nsCOMPtr<nsIFile> appFile; bool per = false; nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile)); NS_ENSURE_SUCCESS(rv, rv); rv = appFile->GetParent(getter_AddRefs(updRoot)); NS_ENSURE_SUCCESS(rv, rv); #ifdef XP_MACOSX nsCOMPtr<nsIFile> appRootDirFile; nsCOMPtr<nsIFile> localDir; nsAutoString appDirPath; if (NS_FAILED(appFile->GetParent(getter_AddRefs(appRootDirFile))) || NS_FAILED(appRootDirFile->GetPath(appDirPath)) || NS_FAILED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true))) { return NS_ERROR_FAILURE; } int32_t dotIndex = appDirPath.RFind(".app"); if (dotIndex == kNotFound) { dotIndex = appDirPath.Length(); } appDirPath = Substring(appDirPath, 1, dotIndex - 1); bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0; if (hasVendor || gAppData->name) { if (NS_FAILED(localDir->AppendNative(nsDependentCString(hasVendor ? gAppData->vendor : gAppData->name)))) { return NS_ERROR_FAILURE; } } else if (NS_FAILED(localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla")))) { return NS_ERROR_FAILURE; } if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("updates"))) || NS_FAILED(localDir->AppendRelativePath(appDirPath))) { return NS_ERROR_FAILURE; } localDir.forget(aResult); return NS_OK; #elif XP_WIN nsAutoString pathHash; bool pathHashResult = false; bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0; nsAutoString appDirPath; if (SUCCEEDED(updRoot->GetPath(appDirPath))) { // Figure out where we should check for a cached hash value. If the // application doesn't have the nsXREAppData vendor value defined check // under SOFTWARE\Mozilla. wchar_t regPath[1024] = { L'\0' }; swprintf_s(regPath, mozilla::ArrayLength(regPath), L"SOFTWARE\\%S\\%S\\TaskBarIDs", (hasVendor ? gAppData->vendor : "Mozilla"), MOZ_APP_BASENAME); // If we pre-computed the hash, grab it from the registry. pathHashResult = GetCachedHash(HKEY_LOCAL_MACHINE, nsDependentString(regPath), appDirPath, pathHash); if (!pathHashResult) { pathHashResult = GetCachedHash(HKEY_CURRENT_USER, nsDependentString(regPath), appDirPath, pathHash); } } // Get the local app data directory and if a vendor name exists append it. // If only a product name exists, append it. If neither exist fallback to // old handling. We don't use the product name on purpose because we want a // shared update directory for different apps run from the same path. nsCOMPtr<nsIFile> localDir; if (pathHashResult && (hasVendor || gAppData->name) && NS_SUCCEEDED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true)) && NS_SUCCEEDED(localDir->AppendNative(nsDependentCString(hasVendor ? gAppData->vendor : gAppData->name))) && NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) && NS_SUCCEEDED(localDir->Append(pathHash))) { localDir.forget(aResult); return NS_OK; } nsAutoString appPath; rv = updRoot->GetPath(appPath); NS_ENSURE_SUCCESS(rv, rv); // AppDir may be a short path. Convert to long path to make sure // the consistency of the update folder location nsString longPath; wchar_t* buf; uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN); NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY); DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength); // Failing GetLongPathName() is not fatal. if (len <= 0 || len >= bufLength) longPath.Assign(appPath); else longPath.SetLength(len); // Use <UserLocalDataDir>\updates\<relative path to app dir from // Program Files> if app dir is under Program Files to avoid the // folder virtualization mess on Windows Vista nsAutoString programFiles; rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles); NS_ENSURE_SUCCESS(rv, rv); programFiles.Append('\\'); uint32_t programFilesLen = programFiles.Length(); nsAutoString programName; if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) { programName = Substring(longPath, programFilesLen); } else { // We need the update root directory to live outside of the installation // directory, because otherwise the updater writing the log file can cause // the directory to be locked, which prevents it from being replaced after // background updates. programName.AssignASCII(MOZ_APP_NAME); } rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot)); NS_ENSURE_SUCCESS(rv, rv); rv = updRoot->AppendRelativePath(programName); NS_ENSURE_SUCCESS(rv, rv); #endif // XP_WIN #endif updRoot.forget(aResult); return NS_OK; }
NS_IMETHODIMP nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent, nsIFile** aFile) { nsresult rv; bool gettingProfile = false; if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) { // If XRE_NotifyProfile hasn't been called, don't fall through to // mAppProvider on the profile keys. if (!mProfileNotified) return NS_ERROR_FAILURE; if (mProfileLocalDir) return mProfileLocalDir->Clone(aFile); if (mAppProvider) return mAppProvider->GetFile(aProperty, aPersistent, aFile); // This falls through to the case below gettingProfile = true; } if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) { if (!mProfileNotified) return NS_ERROR_FAILURE; if (mProfileDir) return mProfileDir->Clone(aFile); if (mAppProvider) return mAppProvider->GetFile(aProperty, aPersistent, aFile); // If we don't succeed here, bail early so that we aren't reentrant // through the "GetProfileDir" call below. return NS_ERROR_FAILURE; } if (mAppProvider) { rv = mAppProvider->GetFile(aProperty, aPersistent, aFile); if (NS_SUCCEEDED(rv) && *aFile) return rv; } *aPersistent = true; if (!strcmp(aProperty, NS_GRE_DIR)) { return mGREDir->Clone(aFile); } else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) || !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) { return GetAppDir()->Clone(aFile); } rv = NS_ERROR_FAILURE; nsCOMPtr<nsIFile> file; if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) || !strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR)) { return GetProfileDefaultsDir(aFile); } else if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR)) { // return the GRE default prefs directory here, and the app default prefs // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST. rv = mGREDir->Clone(getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) { rv = file->AppendNative(NS_LITERAL_CSTRING("defaults")); if (NS_SUCCEEDED(rv)) rv = file->AppendNative(NS_LITERAL_CSTRING("pref")); } } else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) || !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) { rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file)); } else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) { #if defined(XP_WIN) rv = GetUpdateRootDir(getter_AddRefs(file)); #else // Only supported on Windows, so just immediately fail. return NS_ERROR_FAILURE; #endif } else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) { rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME)); } else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) { rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) { #if !defined(XP_UNIX) || defined(XP_MACOSX) rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles")); #endif // We must create the profile directory here if it does not exist. rv |= EnsureDirectoryExists(file); } } else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) { rv = GetUserLocalDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) { #if !defined(XP_UNIX) || defined(XP_MACOSX) rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles")); #endif // We must create the profile directory here if it does not exist. rv |= EnsureDirectoryExists(file); } } else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) { nsCOMPtr<nsILocalFile> lf; rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf)); if (NS_SUCCEEDED(rv)) file = lf; } else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) { return mProfileDir->Clone(aFile); } else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) { if (mProfileLocalDir) return mProfileLocalDir->Clone(aFile); if (mProfileDir) return mProfileDir->Clone(aFile); if (mAppProvider) return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent, aFile); } #if defined(XP_UNIX) || defined(XP_MACOSX) else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) { #ifdef ENABLE_SYSTEM_EXTENSION_DIRS return GetSystemExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile); #else return NS_ERROR_FAILURE; #endif } #endif #if defined(XP_UNIX) && !defined(XP_MACOSX) else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) { #ifdef ENABLE_SYSTEM_EXTENSION_DIRS static const char *const sysLExtDir = "/usr/share/mozilla/extensions"; return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir), false, (nsILocalFile**)(nsIFile**) aFile); #else return NS_ERROR_FAILURE; #endif } #endif else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) { #ifdef ENABLE_SYSTEM_EXTENSION_DIRS return GetSysUserExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile); #else return NS_ERROR_FAILURE; #endif } else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) { rv = GetAppDir()->Clone(getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) rv = file->AppendNative(NS_LITERAL_CSTRING("distribution")); } else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) { // We need to allow component, xpt, and chrome registration to // occur prior to the profile-after-change notification. if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) { rv = file->AppendNative(NS_LITERAL_CSTRING("chrome")); } } if (NS_SUCCEEDED(rv) && file) { NS_ADDREF(*aFile = file); return NS_OK; } bool ensureFilePermissions = false; if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) { if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) { rv = NS_OK; } else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) { rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js")); } else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) { rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf")); } else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) { if (gSafeMode) { rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf")); file->Remove(false); } else { rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf")); EnsureProfileFileExists(file); ensureFilePermissions = true; } } else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) { rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf")); EnsureProfileFileExists(file); ensureFilePermissions = true; } else if (!strcmp(aProperty, NS_APP_STORAGE_50_FILE)) { rv = file->AppendNative(NS_LITERAL_CSTRING("storage.sdb")); } else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) { rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf")); } else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) { rv = mProfileDir->Clone(getter_AddRefs(file)); rv |= file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME)); rv |= EnsureDirectoryExists(file); } } if (NS_FAILED(rv) || !file) return NS_ERROR_FAILURE; if (ensureFilePermissions) { bool fileToEnsureExists; bool isWritable; if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) { PRUint32 permissions; if (NS_SUCCEEDED(file->GetPermissions(&permissions))) { rv = file->SetPermissions(permissions | 0600); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions"); } } } NS_ADDREF(*aFile = file); return NS_OK; }