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_GRE_BIN_DIR)) { return mGREBinDir->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(getter_AddRefs(file)); } else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) { rv = GetUpdateRootDir(getter_AddRefs(file)); } else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) { rv = GetUserAppDataDirectory(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 = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr); } else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) { rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr); } else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) { nsCOMPtr<nsIFile> 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(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 #if defined(__OpenBSD__) || defined(__FreeBSD__) static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions"; #else static const char *const sysLExtDir = "/usr/share/mozilla/extensions"; #endif return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir), false, aFile); #else return NS_ERROR_FAILURE; #endif } #endif else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) { #ifdef ENABLE_SYSTEM_EXTENSION_DIRS return GetSysUserExtensionsDirectory(aFile); #else return NS_ERROR_FAILURE; #endif } else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) { bool persistent = false; rv = GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) rv = file->AppendNative(NS_LITERAL_CSTRING("distribution")); } else if (!strcmp(aProperty, XRE_APP_FEATURES_DIR)) { rv = GetAppDir()->Clone(getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) rv = file->AppendNative(NS_LITERAL_CSTRING("features")); } 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) { file.forget(aFile); 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_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)); nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME)); if (NS_FAILED(tmp)) { rv = tmp; } tmp = EnsureDirectoryExists(file); if (NS_FAILED(tmp)) { rv = tmp; } } } 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) { uint32_t permissions; if (NS_SUCCEEDED(file->GetPermissions(&permissions))) { rv = file->SetPermissions(permissions | 0600); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions"); } } } file.forget(aFile); return NS_OK; }
NS_IMETHODIMP nsXREDirProvider::GetFile(const char* aProperty, PRBool* aPersistent, nsIFile** aFile) { nsresult rv; PRBool gettingProfile = PR_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 = PR_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 = PR_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)) { return GetSystemExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile); } #endif #if defined(XP_UNIX) && !defined(XP_MACOSX) else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) { static const char *const sysLExtDir = "/usr/share/mozilla/extensions"; return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir), PR_FALSE, (nsILocalFile**)(nsIFile**) aFile); } #endif else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) { return GetSysUserExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile); } 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; } PRBool ensureFilePermissions = PR_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(PR_FALSE); } else { rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf")); EnsureProfileFileExists(file); ensureFilePermissions = PR_TRUE; } } else if (!strcmp(aProperty, NS_APP_HISTORY_50_FILE)) { rv = file->AppendNative(NS_LITERAL_CSTRING("history.dat")); } else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) { rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf")); EnsureProfileFileExists(file); ensureFilePermissions = PR_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) { PRBool fileToEnsureExists; PRBool 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; }