Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SpecialSystemDirectory.h"
7 #include "nsString.h"
8 #include "nsDependentString.h"
9 #include "nsAutoPtr.h"
11 #if defined(XP_WIN)
13 #include <windows.h>
14 #include <shlobj.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <direct.h>
19 #include <shlobj.h>
20 #include <knownfolders.h>
21 #include <guiddef.h>
22 #include "mozilla/WindowsVersion.h"
24 using mozilla::IsWin7OrLater;
26 #elif defined(XP_UNIX)
28 #include <limits.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <sys/param.h>
32 #include "prenv.h"
34 #endif
36 #if defined(VMS)
37 #include <unixlib.h>
38 #endif
40 #ifndef MAXPATHLEN
41 #ifdef PATH_MAX
42 #define MAXPATHLEN PATH_MAX
43 #elif defined(MAX_PATH)
44 #define MAXPATHLEN MAX_PATH
45 #elif defined(_MAX_PATH)
46 #define MAXPATHLEN _MAX_PATH
47 #elif defined(CCHMAXPATH)
48 #define MAXPATHLEN CCHMAXPATH
49 #else
50 #define MAXPATHLEN 1024
51 #endif
52 #endif
54 #ifdef XP_WIN
55 typedef HRESULT (WINAPI* nsGetKnownFolderPath)(GUID& rfid,
56 DWORD dwFlags,
57 HANDLE hToken,
58 PWSTR *ppszPath);
60 static nsGetKnownFolderPath gGetKnownFolderPath = nullptr;
61 #endif
63 void StartupSpecialSystemDirectory()
64 {
65 #if defined (XP_WIN)
66 // SHGetKnownFolderPath is only available on Windows Vista
67 // so that we need to use GetProcAddress to get the pointer.
68 HMODULE hShell32DLLInst = GetModuleHandleW(L"shell32.dll");
69 if(hShell32DLLInst)
70 {
71 gGetKnownFolderPath = (nsGetKnownFolderPath)
72 GetProcAddress(hShell32DLLInst, "SHGetKnownFolderPath");
73 }
74 #endif
75 }
77 #if defined (XP_WIN)
79 static nsresult GetKnownFolder(GUID* guid, nsIFile** aFile)
80 {
81 if (!guid || !gGetKnownFolderPath)
82 return NS_ERROR_FAILURE;
84 PWSTR path = nullptr;
85 gGetKnownFolderPath(*guid, 0, nullptr, &path);
87 if (!path)
88 return NS_ERROR_FAILURE;
90 nsresult rv = NS_NewLocalFile(nsDependentString(path),
91 true,
92 aFile);
94 CoTaskMemFree(path);
95 return rv;
96 }
98 static nsresult
99 GetWindowsFolder(int folder, nsIFile** aFile)
100 {
101 WCHAR path_orig[MAX_PATH + 3];
102 WCHAR *path = path_orig+1;
103 HRESULT result = SHGetSpecialFolderPathW(nullptr, path, folder, true);
105 if (!SUCCEEDED(result))
106 return NS_ERROR_FAILURE;
108 // Append the trailing slash
109 int len = wcslen(path);
110 if (len > 1 && path[len - 1] != L'\\')
111 {
112 path[len] = L'\\';
113 path[++len] = L'\0';
114 }
116 return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
117 }
119 __inline HRESULT
120 SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId, DWORD aMode,
121 REFIID riid, void **ppv)
122 {
123 *ppv = nullptr;
124 IShellLibrary *plib;
125 HRESULT hr = CoCreateInstance(CLSID_ShellLibrary, nullptr,
126 CLSCTX_INPROC_SERVER,
127 IID_PPV_ARGS(&plib));
128 if (SUCCEEDED(hr)) {
129 hr = plib->LoadLibraryFromKnownFolder(aFolderId, aMode);
130 if (SUCCEEDED(hr)) {
131 hr = plib->QueryInterface(riid, ppv);
132 }
133 plib->Release();
134 }
135 return hr;
136 }
138 /*
139 * Check to see if we're on Win7 and up, and if so, returns the default
140 * save-to location for the Windows Library passed in through aFolderId.
141 * Otherwise falls back on pre-win7 GetWindowsFolder.
142 */
143 static nsresult
144 GetLibrarySaveToPath(int aFallbackFolderId, REFKNOWNFOLDERID aFolderId,
145 nsIFile** aFile)
146 {
147 // Skip off checking for library support if the os is Vista or lower.
148 if (!IsWin7OrLater())
149 return GetWindowsFolder(aFallbackFolderId, aFile);
151 nsRefPtr<IShellLibrary> shellLib;
152 nsRefPtr<IShellItem> savePath;
153 HRESULT hr =
154 SHLoadLibraryFromKnownFolder(aFolderId, STGM_READ,
155 IID_IShellLibrary, getter_AddRefs(shellLib));
157 if (shellLib &&
158 SUCCEEDED(shellLib->GetDefaultSaveFolder(DSFT_DETECT, IID_IShellItem,
159 getter_AddRefs(savePath)))) {
160 wchar_t* str = nullptr;
161 if (SUCCEEDED(savePath->GetDisplayName(SIGDN_FILESYSPATH, &str))) {
162 nsAutoString path;
163 path.Assign(str);
164 path.AppendLiteral("\\");
165 nsresult rv =
166 NS_NewLocalFile(path, false, aFile);
167 CoTaskMemFree(str);
168 return rv;
169 }
170 }
172 return GetWindowsFolder(aFallbackFolderId, aFile);
173 }
175 /**
176 * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
177 * querying the registry when the call to SHGetSpecialFolderPathW is unable to
178 * provide these paths (Bug 513958).
179 */
180 static nsresult GetRegWindowsAppDataFolder(bool aLocal, nsIFile** aFile)
181 {
182 HKEY key;
183 NS_NAMED_LITERAL_STRING(keyName,
184 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
185 DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
186 &key);
187 if (res != ERROR_SUCCESS)
188 return NS_ERROR_FAILURE;
190 WCHAR path[MAX_PATH + 2];
191 DWORD type, size;
192 res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
193 nullptr, &type, (LPBYTE)&path, &size);
194 ::RegCloseKey(key);
195 // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
196 // buffer size must not equal 0, and the buffer size be a multiple of 2.
197 if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0)
198 return NS_ERROR_FAILURE;
200 // Append the trailing slash
201 int len = wcslen(path);
202 if (len > 1 && path[len - 1] != L'\\')
203 {
204 path[len] = L'\\';
205 path[++len] = L'\0';
206 }
208 return NS_NewLocalFile(nsDependentString(path, len), true, aFile);
209 }
211 #endif // XP_WIN
213 #if defined(XP_UNIX)
214 static nsresult
215 GetUnixHomeDir(nsIFile** aFile)
216 {
217 #ifdef VMS
218 char *pHome;
219 pHome = getenv("HOME");
220 if (*pHome == '/') {
221 return NS_NewNativeLocalFile(nsDependentCString(pHome),
222 true,
223 aFile);
224 } else {
225 return NS_NewNativeLocalFile(nsDependentCString(decc$translate_vms(pHome)),
226 true,
227 aFile);
228 }
229 #elif defined(ANDROID)
230 // XXX no home dir on android; maybe we should return the sdcard if present?
231 return NS_ERROR_FAILURE;
232 #else
233 return NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")),
234 true, aFile);
235 #endif
236 }
238 /*
239 The following license applies to the xdg_user_dir_lookup function:
241 Copyright (c) 2007 Red Hat, Inc.
243 Permission is hereby granted, free of charge, to any person
244 obtaining a copy of this software and associated documentation files
245 (the "Software"), to deal in the Software without restriction,
246 including without limitation the rights to use, copy, modify, merge,
247 publish, distribute, sublicense, and/or sell copies of the Software,
248 and to permit persons to whom the Software is furnished to do so,
249 subject to the following conditions:
251 The above copyright notice and this permission notice shall be
252 included in all copies or substantial portions of the Software.
254 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
255 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
256 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
257 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
258 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
259 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
260 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
261 SOFTWARE.
262 */
264 static char *
265 xdg_user_dir_lookup (const char *type)
266 {
267 FILE *file;
268 char *home_dir, *config_home, *config_file;
269 char buffer[512];
270 char *user_dir;
271 char *p, *d;
272 int len;
273 int relative;
275 home_dir = getenv ("HOME");
277 if (home_dir == nullptr)
278 goto error;
280 config_home = getenv ("XDG_CONFIG_HOME");
281 if (config_home == nullptr || config_home[0] == 0)
282 {
283 config_file = (char*) malloc (strlen (home_dir) + strlen ("/.config/user-dirs.dirs") + 1);
284 if (config_file == nullptr)
285 goto error;
287 strcpy (config_file, home_dir);
288 strcat (config_file, "/.config/user-dirs.dirs");
289 }
290 else
291 {
292 config_file = (char*) malloc (strlen (config_home) + strlen ("/user-dirs.dirs") + 1);
293 if (config_file == nullptr)
294 goto error;
296 strcpy (config_file, config_home);
297 strcat (config_file, "/user-dirs.dirs");
298 }
300 file = fopen (config_file, "r");
301 free (config_file);
302 if (file == nullptr)
303 goto error;
305 user_dir = nullptr;
306 while (fgets (buffer, sizeof (buffer), file))
307 {
308 /* Remove newline at end */
309 len = strlen (buffer);
310 if (len > 0 && buffer[len-1] == '\n')
311 buffer[len-1] = 0;
313 p = buffer;
314 while (*p == ' ' || *p == '\t')
315 p++;
317 if (strncmp (p, "XDG_", 4) != 0)
318 continue;
319 p += 4;
320 if (strncmp (p, type, strlen (type)) != 0)
321 continue;
322 p += strlen (type);
323 if (strncmp (p, "_DIR", 4) != 0)
324 continue;
325 p += 4;
327 while (*p == ' ' || *p == '\t')
328 p++;
330 if (*p != '=')
331 continue;
332 p++;
334 while (*p == ' ' || *p == '\t')
335 p++;
337 if (*p != '"')
338 continue;
339 p++;
341 relative = 0;
342 if (strncmp (p, "$HOME/", 6) == 0)
343 {
344 p += 6;
345 relative = 1;
346 }
347 else if (*p != '/')
348 continue;
350 if (relative)
351 {
352 user_dir = (char*) malloc (strlen (home_dir) + 1 + strlen (p) + 1);
353 if (user_dir == nullptr)
354 goto error2;
356 strcpy (user_dir, home_dir);
357 strcat (user_dir, "/");
358 }
359 else
360 {
361 user_dir = (char*) malloc (strlen (p) + 1);
362 if (user_dir == nullptr)
363 goto error2;
365 *user_dir = 0;
366 }
368 d = user_dir + strlen (user_dir);
369 while (*p && *p != '"')
370 {
371 if ((*p == '\\') && (*(p+1) != 0))
372 p++;
373 *d++ = *p++;
374 }
375 *d = 0;
376 }
377 error2:
378 fclose (file);
380 if (user_dir)
381 return user_dir;
383 error:
384 return nullptr;
385 }
387 static const char xdg_user_dirs[] =
388 "DESKTOP\0"
389 "DOCUMENTS\0"
390 "DOWNLOAD\0"
391 "MUSIC\0"
392 "PICTURES\0"
393 "PUBLICSHARE\0"
394 "TEMPLATES\0"
395 "VIDEOS";
397 static const uint8_t xdg_user_dir_offsets[] = {
398 0,
399 8,
400 18,
401 27,
402 33,
403 42,
404 54,
405 64
406 };
408 static nsresult
409 GetUnixXDGUserDirectory(SystemDirectories aSystemDirectory,
410 nsIFile** aFile)
411 {
412 char *dir = xdg_user_dir_lookup
413 (xdg_user_dirs + xdg_user_dir_offsets[aSystemDirectory -
414 Unix_XDG_Desktop]);
416 nsresult rv;
417 nsCOMPtr<nsIFile> file;
418 if (dir) {
419 rv = NS_NewNativeLocalFile(nsDependentCString(dir), true,
420 getter_AddRefs(file));
421 free(dir);
422 } else if (Unix_XDG_Desktop == aSystemDirectory) {
423 // for the XDG desktop dir, fall back to HOME/Desktop
424 // (for historical compatibility)
425 rv = GetUnixHomeDir(getter_AddRefs(file));
426 if (NS_FAILED(rv))
427 return rv;
429 rv = file->AppendNative(NS_LITERAL_CSTRING("Desktop"));
430 }
431 else {
432 // no fallback for the other XDG dirs
433 rv = NS_ERROR_FAILURE;
434 }
436 if (NS_FAILED(rv))
437 return rv;
439 bool exists;
440 rv = file->Exists(&exists);
441 if (NS_FAILED(rv))
442 return rv;
443 if (!exists) {
444 rv = file->Create(nsIFile::DIRECTORY_TYPE, 0755);
445 if (NS_FAILED(rv))
446 return rv;
447 }
449 *aFile = nullptr;
450 file.swap(*aFile);
452 return NS_OK;
453 }
454 #endif
456 nsresult
457 GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
458 nsIFile** aFile)
459 {
460 #if defined(XP_WIN)
461 WCHAR path[MAX_PATH];
462 #else
463 char path[MAXPATHLEN];
464 #endif
466 switch (aSystemSystemDirectory)
467 {
468 case OS_CurrentWorkingDirectory:
469 #if defined(XP_WIN)
470 if (!_wgetcwd(path, MAX_PATH))
471 return NS_ERROR_FAILURE;
472 return NS_NewLocalFile(nsDependentString(path),
473 true,
474 aFile);
475 #else
476 if(!getcwd(path, MAXPATHLEN))
477 return NS_ERROR_FAILURE;
478 #endif
480 #if !defined(XP_WIN)
481 return NS_NewNativeLocalFile(nsDependentCString(path),
482 true,
483 aFile);
484 #endif
486 case OS_DriveDirectory:
487 #if defined (XP_WIN)
488 {
489 int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
490 if (len == 0)
491 break;
492 if (path[1] == char16_t(':') && path[2] == char16_t('\\'))
493 path[3] = 0;
495 return NS_NewLocalFile(nsDependentString(path),
496 true,
497 aFile);
498 }
499 #else
500 return NS_NewNativeLocalFile(nsDependentCString("/"),
501 true,
502 aFile);
504 #endif
506 case OS_TemporaryDirectory:
507 #if defined (XP_WIN)
508 {
509 DWORD len = ::GetTempPathW(MAX_PATH, path);
510 if (len == 0)
511 break;
512 return NS_NewLocalFile(nsDependentString(path, len),
513 true,
514 aFile);
515 }
516 #elif defined(MOZ_WIDGET_COCOA)
517 {
518 return GetOSXFolderType(kUserDomain, kTemporaryFolderType, aFile);
519 }
521 #elif defined(XP_UNIX)
522 {
523 static const char *tPath = nullptr;
524 if (!tPath) {
525 tPath = PR_GetEnv("TMPDIR");
526 if (!tPath || !*tPath) {
527 tPath = PR_GetEnv("TMP");
528 if (!tPath || !*tPath) {
529 tPath = PR_GetEnv("TEMP");
530 if (!tPath || !*tPath) {
531 tPath = "/tmp/";
532 }
533 }
534 }
535 }
536 return NS_NewNativeLocalFile(nsDependentCString(tPath),
537 true,
538 aFile);
539 }
540 #else
541 break;
542 #endif
543 #if defined (XP_WIN)
544 case Win_SystemDirectory:
545 {
546 int32_t len = ::GetSystemDirectoryW(path, MAX_PATH);
548 // Need enough space to add the trailing backslash
549 if (!len || len > MAX_PATH - 2)
550 break;
551 path[len] = L'\\';
552 path[++len] = L'\0';
554 return NS_NewLocalFile(nsDependentString(path, len),
555 true,
556 aFile);
557 }
559 case Win_WindowsDirectory:
560 {
561 int32_t len = ::GetWindowsDirectoryW(path, MAX_PATH);
563 // Need enough space to add the trailing backslash
564 if (!len || len > MAX_PATH - 2)
565 break;
567 path[len] = L'\\';
568 path[++len] = L'\0';
570 return NS_NewLocalFile(nsDependentString(path, len),
571 true,
572 aFile);
573 }
575 case Win_ProgramFiles:
576 {
577 return GetWindowsFolder(CSIDL_PROGRAM_FILES, aFile);
578 }
580 case Win_HomeDirectory:
581 {
582 nsresult rv = GetWindowsFolder(CSIDL_PROFILE, aFile);
583 if (NS_SUCCEEDED(rv))
584 return rv;
586 int32_t len;
587 if ((len = ::GetEnvironmentVariableW(L"HOME", path, MAX_PATH)) > 0)
588 {
589 // Need enough space to add the trailing backslash
590 if (len > MAX_PATH - 2)
591 break;
593 path[len] = L'\\';
594 path[++len] = L'\0';
596 rv = NS_NewLocalFile(nsDependentString(path, len),
597 true,
598 aFile);
599 if (NS_SUCCEEDED(rv))
600 return rv;
601 }
603 len = ::GetEnvironmentVariableW(L"HOMEDRIVE", path, MAX_PATH);
604 if (0 < len && len < MAX_PATH)
605 {
606 WCHAR temp[MAX_PATH];
607 DWORD len2 = ::GetEnvironmentVariableW(L"HOMEPATH", temp, MAX_PATH);
608 if (0 < len2 && len + len2 < MAX_PATH)
609 wcsncat(path, temp, len2);
611 len = wcslen(path);
613 // Need enough space to add the trailing backslash
614 if (len > MAX_PATH - 2)
615 break;
617 path[len] = L'\\';
618 path[++len] = L'\0';
620 return NS_NewLocalFile(nsDependentString(path, len),
621 true,
622 aFile);
623 }
624 }
625 case Win_Desktop:
626 {
627 return GetWindowsFolder(CSIDL_DESKTOP, aFile);
628 }
629 case Win_Programs:
630 {
631 return GetWindowsFolder(CSIDL_PROGRAMS, aFile);
632 }
634 case Win_Downloads:
635 {
636 // Defined in KnownFolders.h.
637 GUID folderid_downloads = {0x374de290, 0x123f, 0x4565, {0x91, 0x64,
638 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}};
639 nsresult rv = GetKnownFolder(&folderid_downloads, aFile);
640 // On WinXP, there is no downloads folder, default
641 // to 'Desktop'.
642 if(NS_ERROR_FAILURE == rv)
643 {
644 rv = GetWindowsFolder(CSIDL_DESKTOP, aFile);
645 }
646 return rv;
647 }
649 case Win_Controls:
650 {
651 return GetWindowsFolder(CSIDL_CONTROLS, aFile);
652 }
653 case Win_Printers:
654 {
655 return GetWindowsFolder(CSIDL_PRINTERS, aFile);
656 }
657 case Win_Personal:
658 {
659 return GetWindowsFolder(CSIDL_PERSONAL, aFile);
660 }
661 case Win_Favorites:
662 {
663 return GetWindowsFolder(CSIDL_FAVORITES, aFile);
664 }
665 case Win_Startup:
666 {
667 return GetWindowsFolder(CSIDL_STARTUP, aFile);
668 }
669 case Win_Recent:
670 {
671 return GetWindowsFolder(CSIDL_RECENT, aFile);
672 }
673 case Win_Sendto:
674 {
675 return GetWindowsFolder(CSIDL_SENDTO, aFile);
676 }
677 case Win_Bitbucket:
678 {
679 return GetWindowsFolder(CSIDL_BITBUCKET, aFile);
680 }
681 case Win_Startmenu:
682 {
683 return GetWindowsFolder(CSIDL_STARTMENU, aFile);
684 }
685 case Win_Desktopdirectory:
686 {
687 return GetWindowsFolder(CSIDL_DESKTOPDIRECTORY, aFile);
688 }
689 case Win_Drives:
690 {
691 return GetWindowsFolder(CSIDL_DRIVES, aFile);
692 }
693 case Win_Network:
694 {
695 return GetWindowsFolder(CSIDL_NETWORK, aFile);
696 }
697 case Win_Nethood:
698 {
699 return GetWindowsFolder(CSIDL_NETHOOD, aFile);
700 }
701 case Win_Fonts:
702 {
703 return GetWindowsFolder(CSIDL_FONTS, aFile);
704 }
705 case Win_Templates:
706 {
707 return GetWindowsFolder(CSIDL_TEMPLATES, aFile);
708 }
709 case Win_Common_Startmenu:
710 {
711 return GetWindowsFolder(CSIDL_COMMON_STARTMENU, aFile);
712 }
713 case Win_Common_Programs:
714 {
715 return GetWindowsFolder(CSIDL_COMMON_PROGRAMS, aFile);
716 }
717 case Win_Common_Startup:
718 {
719 return GetWindowsFolder(CSIDL_COMMON_STARTUP, aFile);
720 }
721 case Win_Common_Desktopdirectory:
722 {
723 return GetWindowsFolder(CSIDL_COMMON_DESKTOPDIRECTORY, aFile);
724 }
725 case Win_Common_AppData:
726 {
727 return GetWindowsFolder(CSIDL_COMMON_APPDATA, aFile);
728 }
729 case Win_Printhood:
730 {
731 return GetWindowsFolder(CSIDL_PRINTHOOD, aFile);
732 }
733 case Win_Cookies:
734 {
735 return GetWindowsFolder(CSIDL_COOKIES, aFile);
736 }
737 case Win_Appdata:
738 {
739 nsresult rv = GetWindowsFolder(CSIDL_APPDATA, aFile);
740 if (NS_FAILED(rv))
741 rv = GetRegWindowsAppDataFolder(false, aFile);
742 return rv;
743 }
744 case Win_LocalAppdata:
745 {
746 nsresult rv = GetWindowsFolder(CSIDL_LOCAL_APPDATA, aFile);
747 if (NS_FAILED(rv))
748 rv = GetRegWindowsAppDataFolder(true, aFile);
749 return rv;
750 }
751 case Win_Documents:
752 {
753 return GetLibrarySaveToPath(CSIDL_MYDOCUMENTS,
754 FOLDERID_DocumentsLibrary,
755 aFile);
756 }
757 case Win_Pictures:
758 {
759 return GetLibrarySaveToPath(CSIDL_MYPICTURES,
760 FOLDERID_PicturesLibrary,
761 aFile);
762 }
763 case Win_Music:
764 {
765 return GetLibrarySaveToPath(CSIDL_MYMUSIC,
766 FOLDERID_MusicLibrary,
767 aFile);
768 }
769 case Win_Videos:
770 {
771 return GetLibrarySaveToPath(CSIDL_MYVIDEO,
772 FOLDERID_VideosLibrary,
773 aFile);
774 }
775 #endif // XP_WIN
777 #if defined(XP_UNIX)
778 case Unix_LocalDirectory:
779 return NS_NewNativeLocalFile(nsDependentCString("/usr/local/netscape/"),
780 true,
781 aFile);
782 case Unix_LibDirectory:
783 return NS_NewNativeLocalFile(nsDependentCString("/usr/local/lib/netscape/"),
784 true,
785 aFile);
787 case Unix_HomeDirectory:
788 return GetUnixHomeDir(aFile);
790 case Unix_XDG_Desktop:
791 case Unix_XDG_Documents:
792 case Unix_XDG_Download:
793 case Unix_XDG_Music:
794 case Unix_XDG_Pictures:
795 case Unix_XDG_PublicShare:
796 case Unix_XDG_Templates:
797 case Unix_XDG_Videos:
798 return GetUnixXDGUserDirectory(aSystemSystemDirectory, aFile);
799 #endif
801 default:
802 break;
803 }
804 return NS_ERROR_NOT_AVAILABLE;
805 }
807 #if defined (MOZ_WIDGET_COCOA)
808 nsresult
809 GetOSXFolderType(short aDomain, OSType aFolderType, nsIFile **localFile)
810 {
811 OSErr err;
812 FSRef fsRef;
813 nsresult rv = NS_ERROR_FAILURE;
815 err = ::FSFindFolder(aDomain, aFolderType, kCreateFolder, &fsRef);
816 if (err == noErr)
817 {
818 NS_NewLocalFile(EmptyString(), true, localFile);
819 nsCOMPtr<nsILocalFileMac> localMacFile(do_QueryInterface(*localFile));
820 if (localMacFile)
821 rv = localMacFile->InitWithFSRef(&fsRef);
822 }
823 return rv;
824 }
825 #endif