summaryrefslogtreecommitdiffstats
path: root/xpcom/io/SpecialSystemDirectory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/io/SpecialSystemDirectory.cpp')
-rw-r--r--xpcom/io/SpecialSystemDirectory.cpp748
1 files changed, 748 insertions, 0 deletions
diff --git a/xpcom/io/SpecialSystemDirectory.cpp b/xpcom/io/SpecialSystemDirectory.cpp
new file mode 100644
index 0000000000..fcb366aede
--- /dev/null
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -0,0 +1,748 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SpecialSystemDirectory.h"
+#include "nsString.h"
+#include "nsDependentString.h"
+#include "nsIXULAppInfo.h"
+
+#if defined(XP_WIN)
+
+# include <windows.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+# include <direct.h>
+# include <shlobj.h>
+# include <knownfolders.h>
+# include <guiddef.h>
+
+#elif defined(XP_UNIX)
+
+# include <limits.h>
+# include <unistd.h>
+# include <stdlib.h>
+# include <sys/param.h>
+# include "prenv.h"
+# if defined(MOZ_WIDGET_COCOA)
+# include "CFTypeRefPtr.h"
+# include "CocoaFileUtils.h"
+# endif
+# if defined(MOZ_WIDGET_GTK)
+# include "mozilla/WidgetUtilsGtk.h"
+# endif
+
+#endif
+
+#ifndef MAXPATHLEN
+# ifdef PATH_MAX
+# define MAXPATHLEN PATH_MAX
+# elif defined(MAX_PATH)
+# define MAXPATHLEN MAX_PATH
+# elif defined(_MAX_PATH)
+# define MAXPATHLEN _MAX_PATH
+# elif defined(CCHMAXPATH)
+# define MAXPATHLEN CCHMAXPATH
+# else
+# define MAXPATHLEN 1024
+# endif
+#endif
+
+#if defined(XP_WIN)
+
+static nsresult GetKnownFolder(GUID* aGuid, nsIFile** aFile) {
+ if (!aGuid) {
+ return NS_ERROR_FAILURE;
+ }
+
+ PWSTR path = nullptr;
+ SHGetKnownFolderPath(*aGuid, 0, nullptr, &path);
+
+ if (!path) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsresult rv = NS_NewLocalFile(nsDependentString(path), true, aFile);
+
+ CoTaskMemFree(path);
+ return rv;
+}
+
+static nsresult GetWindowsFolder(int aFolder, nsIFile** aFile) {
+ WCHAR path_orig[MAX_PATH + 3];
+ WCHAR* path = path_orig + 1;
+ BOOL result = SHGetSpecialFolderPathW(nullptr, path, aFolder, true);
+
+ if (!result) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Append the trailing slash
+ int len = wcslen(path);
+ if (len == 0) {
+ return NS_ERROR_FILE_UNRECOGNIZED_PATH;
+ }
+ if (len > 1 && path[len - 1] != L'\\') {
+ path[len] = L'\\';
+ path[++len] = L'\0';
+ }
+
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+}
+
+# if WINVER < 0x0601
+__inline HRESULT SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId,
+ DWORD aMode, REFIID riid,
+ void** ppv) {
+ *ppv = nullptr;
+ IShellLibrary* plib;
+ HRESULT hr = CoCreateInstance(CLSID_ShellLibrary, nullptr,
+ CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&plib));
+ if (SUCCEEDED(hr)) {
+ hr = plib->LoadLibraryFromKnownFolder(aFolderId, aMode);
+ if (SUCCEEDED(hr)) {
+ hr = plib->QueryInterface(riid, ppv);
+ }
+ plib->Release();
+ }
+ return hr;
+}
+# endif
+
+# if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+/*
+ * Return the default save-to location for the Windows Library passed in
+ * through aFolderId.
+ */
+static nsresult GetLibrarySaveToPath(int aFallbackFolderId,
+ REFKNOWNFOLDERID aFolderId,
+ nsIFile** aFile) {
+ RefPtr<IShellLibrary> shellLib;
+ RefPtr<IShellItem> savePath;
+ SHLoadLibraryFromKnownFolder(aFolderId, STGM_READ, IID_IShellLibrary,
+ getter_AddRefs(shellLib));
+
+ if (shellLib && SUCCEEDED(shellLib->GetDefaultSaveFolder(
+ DSFT_DETECT, IID_IShellItem, getter_AddRefs(savePath)))) {
+ wchar_t* str = nullptr;
+ if (SUCCEEDED(savePath->GetDisplayName(SIGDN_FILESYSPATH, &str))) {
+ nsAutoString path;
+ path.Assign(str);
+ path.Append('\\');
+ nsresult rv = NS_NewLocalFile(path, false, aFile);
+ CoTaskMemFree(str);
+ return rv;
+ }
+ }
+
+ return GetWindowsFolder(aFallbackFolderId, aFile);
+}
+# endif
+
+/**
+ * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
+ * querying the registry when the call to SHGetSpecialFolderPathW is unable to
+ * provide these paths (Bug 513958).
+ */
+static nsresult GetRegWindowsAppDataFolder(bool aLocal, nsIFile** aFile) {
+ HKEY key;
+ LPCWSTR keyName =
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
+ DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName, 0, KEY_READ, &key);
+ if (res != ERROR_SUCCESS) {
+ return NS_ERROR_FAILURE;
+ }
+
+ WCHAR path[MAX_PATH + 2];
+ DWORD type, size;
+ res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"), nullptr,
+ &type, (LPBYTE)&path, &size);
+ ::RegCloseKey(key);
+ // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
+ // buffer size must not equal 0, and the buffer size be a multiple of 2.
+ if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Append the trailing slash
+ int len = wcslen(path);
+ if (len > 1 && path[len - 1] != L'\\') {
+ path[len] = L'\\';
+ path[++len] = L'\0';
+ }
+
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+}
+
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+static nsresult GetUnixHomeDir(nsIFile** aFile) {
+# if defined(ANDROID)
+ // XXX no home dir on android; maybe we should return the sdcard if present?
+ return NS_ERROR_FAILURE;
+# else
+ return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), true,
+ aFile);
+# endif
+}
+
+static nsresult GetUnixSystemConfigDir(nsIFile** aFile) {
+# if defined(ANDROID)
+ return NS_ERROR_FAILURE;
+# else
+ nsAutoCString appName;
+ if (nsCOMPtr<nsIXULAppInfo> appInfo =
+ do_GetService("@mozilla.org/xre/app-info;1")) {
+ MOZ_TRY(appInfo->GetName(appName));
+ } else {
+ appName.AssignLiteral(MOZ_APP_BASENAME);
+ }
+
+ ToLowerCase(appName);
+
+ nsDependentCString sysConfigDir;
+ if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
+ const char* mozSystemConfigDir = PR_GetEnv("MOZ_SYSTEM_CONFIG_DIR");
+ if (mozSystemConfigDir) {
+ sysConfigDir.Assign(nsDependentCString(mozSystemConfigDir));
+ }
+ }
+# if defined(MOZ_WIDGET_GTK)
+ if (sysConfigDir.IsEmpty() && mozilla::widget::IsRunningUnderFlatpak()) {
+ sysConfigDir.Assign(nsLiteralCString("/app/etc"));
+ }
+# endif
+ if (sysConfigDir.IsEmpty()) {
+ sysConfigDir.Assign(nsLiteralCString("/etc"));
+ }
+ MOZ_TRY(NS_NewNativeLocalFile(sysConfigDir, true, aFile));
+ MOZ_TRY((*aFile)->AppendNative(appName));
+ return NS_OK;
+# endif
+}
+
+/*
+ The following license applies to the xdg_user_dir_lookup function:
+
+ Copyright (c) 2007 Red Hat, Inc.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+static char* xdg_user_dir_lookup(const char* aType) {
+ FILE* file;
+ char* home_dir;
+ char* config_home;
+ char* config_file;
+ char buffer[512];
+ char* user_dir;
+ char* p;
+ char* d;
+ int len;
+ int relative;
+
+ home_dir = getenv("HOME");
+
+ if (!home_dir) {
+ goto error;
+ }
+
+ config_home = getenv("XDG_CONFIG_HOME");
+ if (!config_home || config_home[0] == 0) {
+ config_file =
+ (char*)malloc(strlen(home_dir) + strlen("/.config/user-dirs.dirs") + 1);
+ if (!config_file) {
+ goto error;
+ }
+
+ strcpy(config_file, home_dir);
+ strcat(config_file, "/.config/user-dirs.dirs");
+ } else {
+ config_file =
+ (char*)malloc(strlen(config_home) + strlen("/user-dirs.dirs") + 1);
+ if (!config_file) {
+ goto error;
+ }
+
+ strcpy(config_file, config_home);
+ strcat(config_file, "/user-dirs.dirs");
+ }
+
+ file = fopen(config_file, "r");
+ free(config_file);
+ if (!file) {
+ goto error;
+ }
+
+ user_dir = nullptr;
+ while (fgets(buffer, sizeof(buffer), file)) {
+ /* Remove newline at end */
+ len = strlen(buffer);
+ if (len > 0 && buffer[len - 1] == '\n') {
+ buffer[len - 1] = 0;
+ }
+
+ p = buffer;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+
+ if (strncmp(p, "XDG_", 4) != 0) {
+ continue;
+ }
+ p += 4;
+ if (strncmp(p, aType, strlen(aType)) != 0) {
+ continue;
+ }
+ p += strlen(aType);
+ if (strncmp(p, "_DIR", 4) != 0) {
+ continue;
+ }
+ p += 4;
+
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+
+ if (*p != '=') {
+ continue;
+ }
+ p++;
+
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+
+ if (*p != '"') {
+ continue;
+ }
+ p++;
+
+ relative = 0;
+ if (strncmp(p, "$HOME/", 6) == 0) {
+ p += 6;
+ relative = 1;
+ } else if (*p != '/') {
+ continue;
+ }
+
+ if (relative) {
+ user_dir = (char*)malloc(strlen(home_dir) + 1 + strlen(p) + 1);
+ if (!user_dir) {
+ goto error2;
+ }
+
+ strcpy(user_dir, home_dir);
+ strcat(user_dir, "/");
+ } else {
+ user_dir = (char*)malloc(strlen(p) + 1);
+ if (!user_dir) {
+ goto error2;
+ }
+
+ *user_dir = 0;
+ }
+
+ d = user_dir + strlen(user_dir);
+ while (*p && *p != '"') {
+ if ((*p == '\\') && (*(p + 1) != 0)) {
+ p++;
+ }
+ *d++ = *p++;
+ }
+ *d = 0;
+ }
+error2:
+ fclose(file);
+
+ if (user_dir) {
+ return user_dir;
+ }
+
+error:
+ return nullptr;
+}
+
+static const char xdg_user_dirs[] =
+ "DESKTOP\0"
+ "DOCUMENTS\0"
+ "DOWNLOAD\0"
+ "MUSIC\0"
+ "PICTURES\0"
+ "PUBLICSHARE\0"
+ "TEMPLATES\0"
+ "VIDEOS";
+
+static const uint8_t xdg_user_dir_offsets[] = {0, 8, 18, 27, 33, 42, 54, 64};
+
+static nsresult GetUnixXDGUserDirectory(SystemDirectories aSystemDirectory,
+ nsIFile** aFile) {
+ char* dir = xdg_user_dir_lookup(
+ xdg_user_dirs +
+ xdg_user_dir_offsets[aSystemDirectory - Unix_XDG_Desktop]);
+
+ nsresult rv;
+ nsCOMPtr<nsIFile> file;
+ bool exists;
+ if (dir) {
+ rv = NS_NewNativeLocalFile(nsDependentCString(dir), true,
+ getter_AddRefs(file));
+ free(dir);
+
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (!exists) {
+ rv = file->Create(nsIFile::DIRECTORY_TYPE, 0755);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ } else if (Unix_XDG_Desktop == aSystemDirectory) {
+ // for the XDG desktop dir, fall back to HOME/Desktop
+ // (for historical compatibility)
+ nsCOMPtr<nsIFile> home;
+ rv = GetUnixHomeDir(getter_AddRefs(home));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = home->Clone(getter_AddRefs(file));
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = file->AppendNative("Desktop"_ns);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ rv = file->Exists(&exists);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ // fallback to HOME only if HOME/Desktop doesn't exist
+ if (!exists) {
+ file = home;
+ }
+ } else {
+ // no fallback for the other XDG dirs
+ return NS_ERROR_FAILURE;
+ }
+
+ *aFile = nullptr;
+ file.swap(*aFile);
+
+ return NS_OK;
+}
+#endif
+
+nsresult GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
+ nsIFile** aFile) {
+#if defined(XP_WIN)
+ WCHAR path[MAX_PATH];
+#else
+ char path[MAXPATHLEN];
+#endif
+
+ switch (aSystemSystemDirectory) {
+ case OS_CurrentWorkingDirectory:
+#if defined(XP_WIN)
+ if (!_wgetcwd(path, MAX_PATH)) {
+ return NS_ERROR_FAILURE;
+ }
+ return NS_NewLocalFile(nsDependentString(path), true, aFile);
+#else
+ if (!getcwd(path, MAXPATHLEN)) {
+ return NS_ERROR_FAILURE;
+ }
+#endif
+
+#if !defined(XP_WIN)
+ return NS_NewNativeLocalFile(nsDependentCString(path), true, aFile);
+#endif
+
+ case OS_TemporaryDirectory:
+#if defined(XP_WIN)
+ {
+ DWORD len = ::GetTempPathW(MAX_PATH, path);
+ if (len == 0) {
+ break;
+ }
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+ }
+#elif defined(MOZ_WIDGET_COCOA)
+ {
+ return GetOSXFolderType(kUserDomain, kTemporaryFolderType, aFile);
+ }
+
+#elif defined(XP_UNIX)
+ {
+ static const char* tPath = nullptr;
+ if (!tPath) {
+ tPath = PR_GetEnv("TMPDIR");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TMP");
+ if (!tPath || !*tPath) {
+ tPath = PR_GetEnv("TEMP");
+ if (!tPath || !*tPath) {
+ tPath = "/tmp/";
+ }
+ }
+ }
+ }
+ return NS_NewNativeLocalFile(nsDependentCString(tPath), true, aFile);
+ }
+#else
+ break;
+#endif
+#if defined(MOZ_WIDGET_COCOA)
+ case Mac_SystemDirectory: {
+ return GetOSXFolderType(kClassicDomain, kSystemFolderType, aFile);
+ }
+ case Mac_UserLibDirectory: {
+ return GetOSXFolderType(kUserDomain, kDomainLibraryFolderType, aFile);
+ }
+ case Mac_HomeDirectory: {
+ return GetOSXFolderType(kUserDomain, kDomainTopLevelFolderType, aFile);
+ }
+ case Mac_DefaultDownloadDirectory: {
+ nsresult rv = GetOSXFolderType(kUserDomain, kDownloadsFolderType, aFile);
+ if (NS_FAILED(rv)) {
+ return GetOSXFolderType(kUserDomain, kDesktopFolderType, aFile);
+ }
+ return NS_OK;
+ }
+ case Mac_UserDesktopDirectory: {
+ return GetOSXFolderType(kUserDomain, kDesktopFolderType, aFile);
+ }
+ case Mac_LocalApplicationsDirectory: {
+ return GetOSXFolderType(kLocalDomain, kApplicationsFolderType, aFile);
+ }
+ case Mac_UserPreferencesDirectory: {
+ return GetOSXFolderType(kUserDomain, kPreferencesFolderType, aFile);
+ }
+ case Mac_PictureDocumentsDirectory: {
+ return GetOSXFolderType(kUserDomain, kPictureDocumentsFolderType, aFile);
+ }
+ case Mac_DefaultScreenshotDirectory: {
+ auto prefValue = CFTypeRefPtr<CFPropertyListRef>::WrapUnderCreateRule(
+ CFPreferencesCopyAppValue(CFSTR("location"),
+ CFSTR("com.apple.screencapture")));
+
+ if (!prefValue || CFGetTypeID(prefValue.get()) != CFStringGetTypeID()) {
+ return GetOSXFolderType(kUserDomain, kPictureDocumentsFolderType,
+ aFile);
+ }
+
+ nsAutoString path;
+ mozilla::Span<char16_t> data =
+ path.GetMutableData(CFStringGetLength((CFStringRef)prefValue.get()));
+ CFStringGetCharacters((CFStringRef)prefValue.get(),
+ CFRangeMake(0, data.Length()),
+ reinterpret_cast<UniChar*>(data.Elements()));
+
+ return NS_NewLocalFile(path, true, aFile);
+ }
+#elif defined(XP_WIN)
+ case Win_SystemDirectory: {
+ int32_t len = ::GetSystemDirectoryW(path, MAX_PATH);
+
+ // Need enough space to add the trailing backslash
+ if (!len || len > MAX_PATH - 2) {
+ break;
+ }
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+ }
+
+ case Win_WindowsDirectory: {
+ int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
+
+ // Need enough space to add the trailing backslash
+ if (!len || len > MAX_PATH - 2) {
+ break;
+ }
+
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+ }
+
+ case Win_ProgramFiles: {
+ return GetWindowsFolder(CSIDL_PROGRAM_FILES, aFile);
+ }
+
+ case Win_HomeDirectory: {
+ nsresult rv = GetWindowsFolder(CSIDL_PROFILE, aFile);
+ if (NS_SUCCEEDED(rv)) {
+ return rv;
+ }
+
+ int32_t len;
+ if ((len = ::GetEnvironmentVariableW(L"HOME", path, MAX_PATH)) > 0) {
+ // Need enough space to add the trailing backslash
+ if (len > MAX_PATH - 2) {
+ break;
+ }
+
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ rv = NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+ if (NS_SUCCEEDED(rv)) {
+ return rv;
+ }
+ }
+
+ len = ::GetEnvironmentVariableW(L"HOMEDRIVE", path, MAX_PATH);
+ if (0 < len && len < MAX_PATH) {
+ WCHAR temp[MAX_PATH];
+ DWORD len2 = ::GetEnvironmentVariableW(L"HOMEPATH", temp, MAX_PATH);
+ if (0 < len2 && len + len2 < MAX_PATH) {
+ wcsncat(path, temp, len2);
+ }
+
+ len = wcslen(path);
+
+ // Need enough space to add the trailing backslash
+ if (len > MAX_PATH - 2) {
+ break;
+ }
+
+ path[len] = L'\\';
+ path[++len] = L'\0';
+
+ return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
+ }
+ break;
+ }
+ case Win_Programs: {
+ return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
+ }
+
+ case Win_Downloads: {
+ // Defined in KnownFolders.h.
+ GUID folderid_downloads = {
+ 0x374de290,
+ 0x123f,
+ 0x4565,
+ {0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}};
+ nsresult rv = GetKnownFolder(&folderid_downloads, aFile);
+ // On WinXP, there is no downloads folder, default
+ // to 'Desktop'.
+ if (NS_ERROR_FAILURE == rv) {
+ rv = GetWindowsFolder(CSIDL_DESKTOP, aFile);
+ }
+ return rv;
+ }
+
+ case Win_Favorites: {
+ return GetWindowsFolder(CSIDL_FAVORITES, aFile);
+ }
+ case Win_Desktopdirectory: {
+ return GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, aFile);
+ }
+ case Win_Cookies: {
+ return GetWindowsFolder(CSIDL_COOKIES, aFile);
+ }
+ case Win_Appdata: {
+ nsresult rv = GetWindowsFolder(CSIDL_APPDATA, aFile);
+ if (NS_FAILED(rv)) {
+ rv = GetRegWindowsAppDataFolder(false, aFile);
+ }
+ return rv;
+ }
+ case Win_LocalAppdata: {
+ nsresult rv = GetWindowsFolder(CSIDL_LOCAL_APPDATA, aFile);
+ if (NS_FAILED(rv)) {
+ rv = GetRegWindowsAppDataFolder(true, aFile);
+ }
+ return rv;
+ }
+# if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+ case Win_Documents: {
+ return GetLibrarySaveToPath(CSIDL_MYDOCUMENTS, FOLDERID_DocumentsLibrary,
+ aFile);
+ }
+# endif
+#endif // XP_WIN
+
+#if defined(XP_UNIX)
+ case Unix_HomeDirectory:
+ return GetUnixHomeDir(aFile);
+
+ case Unix_XDG_Desktop:
+ case Unix_XDG_Download:
+ return GetUnixXDGUserDirectory(aSystemSystemDirectory, aFile);
+
+ case Unix_SystemConfigDirectory:
+ return GetUnixSystemConfigDir(aFile);
+#endif
+
+ default:
+ break;
+ }
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+#if defined(MOZ_WIDGET_COCOA)
+nsresult GetOSXFolderType(short aDomain, OSType aFolderType,
+ nsIFile** aLocalFile) {
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (aFolderType == kTemporaryFolderType) {
+ NS_NewLocalFile(u""_ns, true, aLocalFile);
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*aLocalFile));
+ if (localMacFile) {
+ rv = localMacFile->InitWithCFURL(
+ CocoaFileUtils::GetTemporaryFolderCFURLRef());
+ }
+ return rv;
+ }
+
+ OSErr err;
+ FSRef fsRef;
+ err = ::FSFindFolder(aDomain, aFolderType, kCreateFolder, &fsRef);
+ if (err == noErr) {
+ NS_NewLocalFile(u""_ns, true, aLocalFile);
+ nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*aLocalFile));
+ if (localMacFile) {
+ rv = localMacFile->InitWithFSRef(&fsRef);
+ }
+ }
+ return rv;
+}
+#endif