1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "mozilla/ArrayUtils.h"
8 
9 #include "nsCOMPtr.h"
10 #include "nsAutoPtr.h"
11 #include "nsDirectoryService.h"
12 #include "nsDirectoryServiceDefs.h"
13 #include "nsLocalFile.h"
14 #include "nsDebug.h"
15 #include "nsStaticAtom.h"
16 #include "nsEnumeratorUtils.h"
17 
18 #include "nsICategoryManager.h"
19 #include "nsISimpleEnumerator.h"
20 #include "nsIStringEnumerator.h"
21 
22 #if defined(XP_WIN)
23 #include <windows.h>
24 #include <shlobj.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #elif defined(XP_UNIX)
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <sys/param.h>
31 #include "prenv.h"
32 #ifdef MOZ_WIDGET_COCOA
33 #include <CoreServices/CoreServices.h>
34 #include <Carbon/Carbon.h>
35 #endif
36 #endif
37 
38 #include "SpecialSystemDirectory.h"
39 #include "nsAppFileLocationProvider.h"
40 
41 using namespace mozilla;
42 
43 // define home directory
44 // For Windows platform, We are choosing Appdata folder as HOME
45 #if defined (XP_WIN)
46 #define HOME_DIR NS_WIN_APPDATA_DIR
47 #elif defined (MOZ_WIDGET_COCOA)
48 #define HOME_DIR NS_OSX_HOME_DIR
49 #elif defined (XP_UNIX)
50 #define HOME_DIR NS_UNIX_HOME_DIR
51 #endif
52 
53 //----------------------------------------------------------------------------------------
54 nsresult
GetCurrentProcessDirectory(nsIFile ** aFile)55 nsDirectoryService::GetCurrentProcessDirectory(nsIFile** aFile)
56 //----------------------------------------------------------------------------------------
57 {
58   if (NS_WARN_IF(!aFile)) {
59     return NS_ERROR_INVALID_ARG;
60   }
61   *aFile = nullptr;
62 
63   //  Set the component registry location:
64   if (!gService) {
65     return NS_ERROR_FAILURE;
66   }
67 
68   nsresult rv;
69 
70   nsCOMPtr<nsIProperties> dirService;
71   rv = nsDirectoryService::Create(nullptr,
72                                   NS_GET_IID(nsIProperties),
73                                   getter_AddRefs(dirService));  // needs to be around for life of product
74   if (NS_FAILED(rv)) {
75     return rv;
76   }
77 
78   if (dirService) {
79     nsCOMPtr<nsIFile> localFile;
80     dirService->Get(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile),
81                     getter_AddRefs(localFile));
82     if (localFile) {
83       localFile.forget(aFile);
84       return NS_OK;
85     }
86   }
87 
88   RefPtr<nsLocalFile> localFile = new nsLocalFile;
89 
90 #ifdef XP_WIN
91   wchar_t buf[MAX_PATH + 1];
92   SetLastError(ERROR_SUCCESS);
93   if (GetModuleFileNameW(0, buf, mozilla::ArrayLength(buf)) &&
94       GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
95     // chop off the executable name by finding the rightmost backslash
96     wchar_t* lastSlash = wcsrchr(buf, L'\\');
97     if (lastSlash) {
98       *(lastSlash + 1) = L'\0';
99     }
100 
101     localFile->InitWithPath(nsDependentString(buf));
102     localFile.forget(aFile);
103     return NS_OK;
104   }
105 
106 #elif defined(MOZ_WIDGET_COCOA)
107   // Works even if we're not bundled.
108   CFBundleRef appBundle = CFBundleGetMainBundle();
109   if (appBundle) {
110     CFURLRef bundleURL = CFBundleCopyExecutableURL(appBundle);
111     if (bundleURL) {
112       CFURLRef parentURL = CFURLCreateCopyDeletingLastPathComponent(
113         kCFAllocatorDefault, bundleURL);
114       if (parentURL) {
115         // Pass true for the "resolveAgainstBase" arg to CFURLGetFileSystemRepresentation.
116         // This will resolve the relative portion of the CFURL against it base, giving a full
117         // path, which CFURLCopyFileSystemPath doesn't do.
118         char buffer[PATH_MAX];
119         if (CFURLGetFileSystemRepresentation(parentURL, true,
120                                              (UInt8*)buffer, sizeof(buffer))) {
121 #ifdef DEBUG_conrad
122           printf("nsDirectoryService - CurrentProcessDir is: %s\n", buffer);
123 #endif
124           rv = localFile->InitWithNativePath(nsDependentCString(buffer));
125           if (NS_SUCCEEDED(rv)) {
126             localFile.forget(aFile);
127           }
128         }
129         CFRelease(parentURL);
130       }
131       CFRelease(bundleURL);
132     }
133   }
134 
135   NS_ASSERTION(*aFile, "nsDirectoryService - Could not determine CurrentProcessDir.\n");
136   if (*aFile) {
137     return NS_OK;
138   }
139 
140 #elif defined(XP_UNIX)
141 
142   // In the absence of a good way to get the executable directory let
143   // us try this for unix:
144   //    - if MOZILLA_FIVE_HOME is defined, that is it
145   //    - else give the current directory
146   char buf[MAXPATHLEN];
147 
148   // The MOZ_DEFAULT_MOZILLA_FIVE_HOME variable can be set at configure time with
149   // a --with-default-mozilla-five-home=foo autoconf flag.
150   //
151   // The idea here is to allow for builds that have a default MOZILLA_FIVE_HOME
152   // regardless of the environment.  This makes it easier to write apps that
153   // embed mozilla without having to worry about setting up the environment
154   //
155   // We do this by putenv()ing the default value into the environment.  Note that
156   // we only do this if it is not already set.
157 #ifdef MOZ_DEFAULT_MOZILLA_FIVE_HOME
158   const char* home = PR_GetEnv("MOZILLA_FIVE_HOME");
159   if (!home || !*home) {
160     putenv("MOZILLA_FIVE_HOME=" MOZ_DEFAULT_MOZILLA_FIVE_HOME);
161   }
162 #endif
163 
164   char* moz5 = PR_GetEnv("MOZILLA_FIVE_HOME");
165   if (moz5 && *moz5) {
166     if (realpath(moz5, buf)) {
167       localFile->InitWithNativePath(nsDependentCString(buf));
168       localFile.forget(aFile);
169       return NS_OK;
170     }
171   }
172 #if defined(DEBUG)
173   static bool firstWarning = true;
174 
175   if ((!moz5 || !*moz5) && firstWarning) {
176     // Warn that MOZILLA_FIVE_HOME not set, once.
177     printf("Warning: MOZILLA_FIVE_HOME not set.\n");
178     firstWarning = false;
179   }
180 #endif /* DEBUG */
181 
182   // Fall back to current directory.
183   if (getcwd(buf, sizeof(buf))) {
184     localFile->InitWithNativePath(nsDependentCString(buf));
185     localFile.forget(aFile);
186     return NS_OK;
187   }
188 
189 #endif
190 
191   NS_ERROR("unable to get current process directory");
192   return NS_ERROR_FAILURE;
193 } // GetCurrentProcessDirectory()
194 
195 StaticRefPtr<nsDirectoryService> nsDirectoryService::gService;
196 
nsDirectoryService()197 nsDirectoryService::nsDirectoryService()
198   : mHashtable(128)
199 {
200 }
201 
202 nsresult
Create(nsISupports * aOuter,REFNSIID aIID,void ** aResult)203 nsDirectoryService::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
204 {
205   if (NS_WARN_IF(!aResult)) {
206     return NS_ERROR_INVALID_ARG;
207   }
208   if (NS_WARN_IF(aOuter)) {
209     return NS_ERROR_NO_AGGREGATION;
210   }
211 
212   if (!gService) {
213     return NS_ERROR_NOT_INITIALIZED;
214   }
215 
216   return gService->QueryInterface(aIID, aResult);
217 }
218 
219 #define DIR_ATOM(name_, value_) nsIAtom* nsDirectoryService::name_ = nullptr;
220 #include "nsDirectoryServiceAtomList.h"
221 #undef DIR_ATOM
222 
223 #define DIR_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
224 #include "nsDirectoryServiceAtomList.h"
225 #undef DIR_ATOM
226 
227 static const nsStaticAtom directory_atoms[] = {
228 #define DIR_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsDirectoryService::name_),
229 #include "nsDirectoryServiceAtomList.h"
230 #undef DIR_ATOM
231 };
232 
233 NS_IMETHODIMP
Init()234 nsDirectoryService::Init()
235 {
236   NS_NOTREACHED("nsDirectoryService::Init() for internal use only!");
237   return NS_OK;
238 }
239 
240 void
RealInit()241 nsDirectoryService::RealInit()
242 {
243   NS_ASSERTION(!gService,
244                "nsDirectoryService::RealInit Mustn't initialize twice!");
245 
246   gService = new nsDirectoryService();
247 
248   NS_RegisterStaticAtoms(directory_atoms);
249 
250   // Let the list hold the only reference to the provider.
251   nsAppFileLocationProvider* defaultProvider = new nsAppFileLocationProvider;
252   gService->mProviders.AppendElement(defaultProvider);
253 }
254 
~nsDirectoryService()255 nsDirectoryService::~nsDirectoryService()
256 {
257 }
258 
NS_IMPL_ISUPPORTS(nsDirectoryService,nsIProperties,nsIDirectoryService,nsIDirectoryServiceProvider,nsIDirectoryServiceProvider2)259 NS_IMPL_ISUPPORTS(nsDirectoryService,
260                   nsIProperties,
261                   nsIDirectoryService,
262                   nsIDirectoryServiceProvider,
263                   nsIDirectoryServiceProvider2)
264 
265 
266 NS_IMETHODIMP
267 nsDirectoryService::Undefine(const char* aProp)
268 {
269   if (NS_WARN_IF(!aProp)) {
270     return NS_ERROR_INVALID_ARG;
271   }
272 
273   nsDependentCString key(aProp);
274   if (!mHashtable.Get(key, nullptr)) {
275     return NS_ERROR_FAILURE;
276   }
277 
278   mHashtable.Remove(key);
279   return NS_OK;
280 }
281 
282 NS_IMETHODIMP
GetKeys(uint32_t * aCount,char *** aKeys)283 nsDirectoryService::GetKeys(uint32_t* aCount, char*** aKeys)
284 {
285   return NS_ERROR_NOT_IMPLEMENTED;
286 }
287 
288 struct MOZ_STACK_CLASS FileData
289 {
FileDataFileData290   FileData(const char* aProperty, const nsIID& aUUID)
291     : property(aProperty)
292     , data(nullptr)
293     , persistent(true)
294     , uuid(aUUID)
295   {
296   }
297 
298   const char*   property;
299   nsCOMPtr<nsISupports> data;
300   bool          persistent;
301   const nsIID&  uuid;
302 };
303 
304 static bool
FindProviderFile(nsIDirectoryServiceProvider * aElement,FileData * aData)305 FindProviderFile(nsIDirectoryServiceProvider* aElement, FileData* aData)
306 {
307   nsresult rv;
308   if (aData->uuid.Equals(NS_GET_IID(nsISimpleEnumerator))) {
309     // Not all providers implement this iface
310     nsCOMPtr<nsIDirectoryServiceProvider2> prov2 = do_QueryInterface(aElement);
311     if (prov2) {
312       nsCOMPtr<nsISimpleEnumerator> newFiles;
313       rv = prov2->GetFiles(aData->property, getter_AddRefs(newFiles));
314       if (NS_SUCCEEDED(rv) && newFiles) {
315         if (aData->data) {
316           nsCOMPtr<nsISimpleEnumerator> unionFiles;
317 
318           NS_NewUnionEnumerator(getter_AddRefs(unionFiles),
319                                 (nsISimpleEnumerator*)aData->data.get(), newFiles);
320 
321           if (unionFiles) {
322             unionFiles.swap(*(nsISimpleEnumerator**)&aData->data);
323           }
324         } else {
325           aData->data = newFiles;
326         }
327 
328         aData->persistent = false; // Enumerators can never be persistent
329         return rv == NS_SUCCESS_AGGREGATE_RESULT;
330       }
331     }
332   } else {
333     rv = aElement->GetFile(aData->property, &aData->persistent,
334                            (nsIFile**)&aData->data);
335     if (NS_SUCCEEDED(rv) && aData->data) {
336       return false;
337     }
338   }
339 
340   return true;
341 }
342 
343 NS_IMETHODIMP
Get(const char * aProp,const nsIID & aUuid,void ** aResult)344 nsDirectoryService::Get(const char* aProp, const nsIID& aUuid, void** aResult)
345 {
346   if (NS_WARN_IF(!aProp)) {
347     return NS_ERROR_INVALID_ARG;
348   }
349 
350   nsDependentCString key(aProp);
351 
352   nsCOMPtr<nsIFile> cachedFile = mHashtable.Get(key);
353 
354   if (cachedFile) {
355     nsCOMPtr<nsIFile> cloneFile;
356     cachedFile->Clone(getter_AddRefs(cloneFile));
357     return cloneFile->QueryInterface(aUuid, aResult);
358   }
359 
360   // it is not one of our defaults, lets check any providers
361   FileData fileData(aProp, aUuid);
362 
363   for (int32_t i = mProviders.Length() - 1; i >= 0; i--) {
364     if (!FindProviderFile(mProviders[i], &fileData)) {
365       break;
366     }
367   }
368   if (fileData.data) {
369     if (fileData.persistent) {
370       Set(aProp, static_cast<nsIFile*>(fileData.data.get()));
371     }
372     nsresult rv = (fileData.data)->QueryInterface(aUuid, aResult);
373     fileData.data = nullptr; // AddRef occurs in FindProviderFile()
374     return rv;
375   }
376 
377   FindProviderFile(static_cast<nsIDirectoryServiceProvider*>(this), &fileData);
378   if (fileData.data) {
379     if (fileData.persistent) {
380       Set(aProp, static_cast<nsIFile*>(fileData.data.get()));
381     }
382     nsresult rv = (fileData.data)->QueryInterface(aUuid, aResult);
383     fileData.data = nullptr; // AddRef occurs in FindProviderFile()
384     return rv;
385   }
386 
387   return NS_ERROR_FAILURE;
388 }
389 
390 NS_IMETHODIMP
Set(const char * aProp,nsISupports * aValue)391 nsDirectoryService::Set(const char* aProp, nsISupports* aValue)
392 {
393   if (NS_WARN_IF(!aProp)) {
394     return NS_ERROR_INVALID_ARG;
395   }
396 
397   nsDependentCString key(aProp);
398   if (mHashtable.Get(key, nullptr) || !aValue) {
399     return NS_ERROR_FAILURE;
400   }
401 
402   nsCOMPtr<nsIFile> ourFile = do_QueryInterface(aValue);
403   if (ourFile) {
404     nsCOMPtr<nsIFile> cloneFile;
405     ourFile->Clone(getter_AddRefs(cloneFile));
406     mHashtable.Put(key, cloneFile);
407 
408     return NS_OK;
409   }
410 
411   return NS_ERROR_FAILURE;
412 }
413 
414 NS_IMETHODIMP
Has(const char * aProp,bool * aResult)415 nsDirectoryService::Has(const char* aProp, bool* aResult)
416 {
417   if (NS_WARN_IF(!aProp)) {
418     return NS_ERROR_INVALID_ARG;
419   }
420 
421   *aResult = false;
422   nsCOMPtr<nsIFile> value;
423   nsresult rv = Get(aProp, NS_GET_IID(nsIFile), getter_AddRefs(value));
424   if (NS_FAILED(rv)) {
425     return NS_OK;
426   }
427 
428   if (value) {
429     *aResult = true;
430   }
431 
432   return rv;
433 }
434 
435 NS_IMETHODIMP
RegisterProvider(nsIDirectoryServiceProvider * aProv)436 nsDirectoryService::RegisterProvider(nsIDirectoryServiceProvider* aProv)
437 {
438   if (!aProv) {
439     return NS_ERROR_FAILURE;
440   }
441 
442   mProviders.AppendElement(aProv);
443   return NS_OK;
444 }
445 
446 void
RegisterCategoryProviders()447 nsDirectoryService::RegisterCategoryProviders()
448 {
449   nsCOMPtr<nsICategoryManager> catman
450   (do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
451   if (!catman) {
452     return;
453   }
454 
455   nsCOMPtr<nsISimpleEnumerator> entries;
456   catman->EnumerateCategory(XPCOM_DIRECTORY_PROVIDER_CATEGORY,
457                             getter_AddRefs(entries));
458 
459   nsCOMPtr<nsIUTF8StringEnumerator> strings(do_QueryInterface(entries));
460   if (!strings) {
461     return;
462   }
463 
464   bool more;
465   while (NS_SUCCEEDED(strings->HasMore(&more)) && more) {
466     nsAutoCString entry;
467     strings->GetNext(entry);
468 
469     nsXPIDLCString contractID;
470     catman->GetCategoryEntry(XPCOM_DIRECTORY_PROVIDER_CATEGORY, entry.get(),
471                              getter_Copies(contractID));
472 
473     if (contractID) {
474       nsCOMPtr<nsIDirectoryServiceProvider> provider = do_GetService(contractID.get());
475       if (provider) {
476         RegisterProvider(provider);
477       }
478     }
479   }
480 }
481 
482 NS_IMETHODIMP
UnregisterProvider(nsIDirectoryServiceProvider * aProv)483 nsDirectoryService::UnregisterProvider(nsIDirectoryServiceProvider* aProv)
484 {
485   if (!aProv) {
486     return NS_ERROR_FAILURE;
487   }
488 
489   mProviders.RemoveElement(aProv);
490   return NS_OK;
491 }
492 
493 #if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN)
494 static nsresult
GetLowIntegrityTempBase(nsIFile ** aLowIntegrityTempBase)495 GetLowIntegrityTempBase(nsIFile** aLowIntegrityTempBase)
496 {
497   nsCOMPtr<nsIFile> localFile;
498   nsresult rv = GetSpecialSystemDirectory(Win_LocalAppdataLow,
499                                           getter_AddRefs(localFile));
500   if (NS_WARN_IF(NS_FAILED(rv))) {
501     return rv;
502   }
503 
504   rv = localFile->Append(NS_LITERAL_STRING(MOZ_USER_DIR));
505   if (NS_WARN_IF(NS_FAILED(rv))) {
506     return rv;
507   }
508 
509   localFile.forget(aLowIntegrityTempBase);
510   return rv;
511 }
512 #endif
513 
514 // DO NOT ADD ANY LOCATIONS TO THIS FUNCTION UNTIL YOU TALK TO: dougt@netscape.com.
515 // This is meant to be a place of xpcom or system specific file locations, not
516 // application specific locations.  If you need the later, register a callback for
517 // your application.
518 
519 NS_IMETHODIMP
GetFile(const char * aProp,bool * aPersistent,nsIFile ** aResult)520 nsDirectoryService::GetFile(const char* aProp, bool* aPersistent,
521                             nsIFile** aResult)
522 {
523   nsCOMPtr<nsIFile> localFile;
524   nsresult rv = NS_ERROR_FAILURE;
525 
526   *aResult = nullptr;
527   *aPersistent = true;
528 
529   nsCOMPtr<nsIAtom> inAtom = NS_Atomize(aProp);
530 
531   // check to see if it is one of our defaults
532 
533   if (inAtom == nsDirectoryService::sCurrentProcess ||
534       inAtom == nsDirectoryService::sOS_CurrentProcessDirectory) {
535     rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
536   }
537 
538   // Unless otherwise set, the core pieces of the GRE exist
539   // in the current process directory.
540   else if (inAtom == nsDirectoryService::sGRE_Directory ||
541            inAtom == nsDirectoryService::sGRE_BinDirectory) {
542     rv = GetCurrentProcessDirectory(getter_AddRefs(localFile));
543   } else if (inAtom == nsDirectoryService::sOS_DriveDirectory) {
544     rv = GetSpecialSystemDirectory(OS_DriveDirectory, getter_AddRefs(localFile));
545   } else if (inAtom == nsDirectoryService::sOS_TemporaryDirectory) {
546     rv = GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(localFile));
547   } else if (inAtom == nsDirectoryService::sOS_CurrentProcessDirectory) {
548     rv = GetSpecialSystemDirectory(OS_CurrentProcessDirectory, getter_AddRefs(localFile));
549   } else if (inAtom == nsDirectoryService::sOS_CurrentWorkingDirectory) {
550     rv = GetSpecialSystemDirectory(OS_CurrentWorkingDirectory, getter_AddRefs(localFile));
551   }
552 
553 #if defined(MOZ_WIDGET_COCOA)
554   else if (inAtom == nsDirectoryService::sDirectory) {
555     rv = GetOSXFolderType(kClassicDomain, kSystemFolderType, getter_AddRefs(localFile));
556   } else if (inAtom == nsDirectoryService::sTrashDirectory) {
557     rv = GetOSXFolderType(kClassicDomain, kTrashFolderType, getter_AddRefs(localFile));
558   } else if (inAtom == nsDirectoryService::sStartupDirectory) {
559     rv = GetOSXFolderType(kClassicDomain, kStartupFolderType, getter_AddRefs(localFile));
560   } else if (inAtom == nsDirectoryService::sShutdownDirectory) {
561     rv = GetOSXFolderType(kClassicDomain, kShutdownFolderType, getter_AddRefs(localFile));
562   } else if (inAtom == nsDirectoryService::sAppleMenuDirectory) {
563     rv = GetOSXFolderType(kClassicDomain, kAppleMenuFolderType, getter_AddRefs(localFile));
564   } else if (inAtom == nsDirectoryService::sControlPanelDirectory) {
565     rv = GetOSXFolderType(kClassicDomain, kControlPanelFolderType, getter_AddRefs(localFile));
566   } else if (inAtom == nsDirectoryService::sExtensionDirectory) {
567     rv = GetOSXFolderType(kClassicDomain, kExtensionFolderType, getter_AddRefs(localFile));
568   } else if (inAtom == nsDirectoryService::sFontsDirectory) {
569     rv = GetOSXFolderType(kClassicDomain, kFontsFolderType, getter_AddRefs(localFile));
570   } else if (inAtom == nsDirectoryService::sPreferencesDirectory) {
571     rv = GetOSXFolderType(kClassicDomain, kPreferencesFolderType, getter_AddRefs(localFile));
572   } else if (inAtom == nsDirectoryService::sDocumentsDirectory) {
573     rv = GetOSXFolderType(kClassicDomain, kDocumentsFolderType, getter_AddRefs(localFile));
574   } else if (inAtom == nsDirectoryService::sInternetSearchDirectory) {
575     rv = GetOSXFolderType(kClassicDomain, kInternetSearchSitesFolderType, getter_AddRefs(localFile));
576   } else if (inAtom == nsDirectoryService::sUserLibDirectory) {
577     rv = GetOSXFolderType(kUserDomain, kDomainLibraryFolderType, getter_AddRefs(localFile));
578   } else if (inAtom == nsDirectoryService::sOS_HomeDirectory) {
579     rv = GetOSXFolderType(kUserDomain, kDomainTopLevelFolderType, getter_AddRefs(localFile));
580   } else if (inAtom == nsDirectoryService::sDefaultDownloadDirectory) {
581     // 10.5 and later, we can use kDownloadsFolderType which is defined in
582     // Folders.h as "down".  However, in order to support 10.4 still, we
583     // cannot use the named constant.  We'll use it's value, and if it
584     // fails, fall back to the desktop.
585 #ifndef kDownloadsFolderType
586 #define kDownloadsFolderType 'down'
587 #endif
588 
589     rv = GetOSXFolderType(kUserDomain, kDownloadsFolderType,
590                           getter_AddRefs(localFile));
591     if (NS_FAILED(rv)) {
592       rv = GetOSXFolderType(kUserDomain, kDesktopFolderType,
593                             getter_AddRefs(localFile));
594     }
595   } else if (inAtom == nsDirectoryService::sUserDesktopDirectory ||
596              inAtom == nsDirectoryService::sOS_DesktopDirectory) {
597     rv = GetOSXFolderType(kUserDomain, kDesktopFolderType, getter_AddRefs(localFile));
598   } else if (inAtom == nsDirectoryService::sLocalDesktopDirectory) {
599     rv = GetOSXFolderType(kLocalDomain, kDesktopFolderType, getter_AddRefs(localFile));
600   } else if (inAtom == nsDirectoryService::sUserApplicationsDirectory) {
601     rv = GetOSXFolderType(kUserDomain, kApplicationsFolderType, getter_AddRefs(localFile));
602   } else if (inAtom == nsDirectoryService::sLocalApplicationsDirectory) {
603     rv = GetOSXFolderType(kLocalDomain, kApplicationsFolderType, getter_AddRefs(localFile));
604   } else if (inAtom == nsDirectoryService::sUserDocumentsDirectory) {
605     rv = GetOSXFolderType(kUserDomain, kDocumentsFolderType, getter_AddRefs(localFile));
606   } else if (inAtom == nsDirectoryService::sLocalDocumentsDirectory) {
607     rv = GetOSXFolderType(kLocalDomain, kDocumentsFolderType, getter_AddRefs(localFile));
608   } else if (inAtom == nsDirectoryService::sUserInternetPlugInDirectory) {
609     rv = GetOSXFolderType(kUserDomain, kInternetPlugInFolderType, getter_AddRefs(localFile));
610   } else if (inAtom == nsDirectoryService::sLocalInternetPlugInDirectory) {
611     rv = GetOSXFolderType(kLocalDomain, kInternetPlugInFolderType, getter_AddRefs(localFile));
612   } else if (inAtom == nsDirectoryService::sUserFrameworksDirectory) {
613     rv = GetOSXFolderType(kUserDomain, kFrameworksFolderType, getter_AddRefs(localFile));
614   } else if (inAtom == nsDirectoryService::sLocalFrameworksDirectory) {
615     rv = GetOSXFolderType(kLocalDomain, kFrameworksFolderType, getter_AddRefs(localFile));
616   } else if (inAtom == nsDirectoryService::sUserPreferencesDirectory) {
617     rv = GetOSXFolderType(kUserDomain, kPreferencesFolderType, getter_AddRefs(localFile));
618   } else if (inAtom == nsDirectoryService::sLocalPreferencesDirectory) {
619     rv = GetOSXFolderType(kLocalDomain, kPreferencesFolderType, getter_AddRefs(localFile));
620   } else if (inAtom == nsDirectoryService::sPictureDocumentsDirectory) {
621     rv = GetOSXFolderType(kUserDomain, kPictureDocumentsFolderType, getter_AddRefs(localFile));
622   } else if (inAtom == nsDirectoryService::sMovieDocumentsDirectory) {
623     rv = GetOSXFolderType(kUserDomain, kMovieDocumentsFolderType, getter_AddRefs(localFile));
624   } else if (inAtom == nsDirectoryService::sMusicDocumentsDirectory) {
625     rv = GetOSXFolderType(kUserDomain, kMusicDocumentsFolderType, getter_AddRefs(localFile));
626   } else if (inAtom == nsDirectoryService::sInternetSitesDirectory) {
627     rv = GetOSXFolderType(kUserDomain, kInternetSitesFolderType, getter_AddRefs(localFile));
628   }
629 #elif defined (XP_WIN)
630   else if (inAtom == nsDirectoryService::sSystemDirectory) {
631     rv = GetSpecialSystemDirectory(Win_SystemDirectory, getter_AddRefs(localFile));
632   } else if (inAtom == nsDirectoryService::sWindowsDirectory) {
633     rv = GetSpecialSystemDirectory(Win_WindowsDirectory, getter_AddRefs(localFile));
634   } else if (inAtom == nsDirectoryService::sWindowsProgramFiles) {
635     rv = GetSpecialSystemDirectory(Win_ProgramFiles, getter_AddRefs(localFile));
636   } else if (inAtom == nsDirectoryService::sOS_HomeDirectory) {
637     rv = GetSpecialSystemDirectory(Win_HomeDirectory, getter_AddRefs(localFile));
638   } else if (inAtom == nsDirectoryService::sDesktop) {
639     rv = GetSpecialSystemDirectory(Win_Desktop, getter_AddRefs(localFile));
640   } else if (inAtom == nsDirectoryService::sPrograms) {
641     rv = GetSpecialSystemDirectory(Win_Programs, getter_AddRefs(localFile));
642   } else if (inAtom == nsDirectoryService::sControls) {
643     rv = GetSpecialSystemDirectory(Win_Controls, getter_AddRefs(localFile));
644   } else if (inAtom == nsDirectoryService::sPrinters) {
645     rv = GetSpecialSystemDirectory(Win_Printers, getter_AddRefs(localFile));
646   } else if (inAtom == nsDirectoryService::sPersonal) {
647     rv = GetSpecialSystemDirectory(Win_Personal, getter_AddRefs(localFile));
648   } else if (inAtom == nsDirectoryService::sFavorites) {
649     rv = GetSpecialSystemDirectory(Win_Favorites, getter_AddRefs(localFile));
650   } else if (inAtom == nsDirectoryService::sStartup) {
651     rv = GetSpecialSystemDirectory(Win_Startup, getter_AddRefs(localFile));
652   } else if (inAtom == nsDirectoryService::sRecent) {
653     rv = GetSpecialSystemDirectory(Win_Recent, getter_AddRefs(localFile));
654   } else if (inAtom == nsDirectoryService::sSendto) {
655     rv = GetSpecialSystemDirectory(Win_Sendto, getter_AddRefs(localFile));
656   } else if (inAtom == nsDirectoryService::sBitbucket) {
657     rv = GetSpecialSystemDirectory(Win_Bitbucket, getter_AddRefs(localFile));
658   } else if (inAtom == nsDirectoryService::sStartmenu) {
659     rv = GetSpecialSystemDirectory(Win_Startmenu, getter_AddRefs(localFile));
660   } else if (inAtom == nsDirectoryService::sDesktopdirectory ||
661              inAtom == nsDirectoryService::sOS_DesktopDirectory) {
662     rv = GetSpecialSystemDirectory(Win_Desktopdirectory, getter_AddRefs(localFile));
663   } else if (inAtom == nsDirectoryService::sDrives) {
664     rv = GetSpecialSystemDirectory(Win_Drives, getter_AddRefs(localFile));
665   } else if (inAtom == nsDirectoryService::sNetwork) {
666     rv = GetSpecialSystemDirectory(Win_Network, getter_AddRefs(localFile));
667   } else if (inAtom == nsDirectoryService::sNethood) {
668     rv = GetSpecialSystemDirectory(Win_Nethood, getter_AddRefs(localFile));
669   } else if (inAtom == nsDirectoryService::sFonts) {
670     rv = GetSpecialSystemDirectory(Win_Fonts, getter_AddRefs(localFile));
671   } else if (inAtom == nsDirectoryService::sTemplates) {
672     rv = GetSpecialSystemDirectory(Win_Templates, getter_AddRefs(localFile));
673   } else if (inAtom == nsDirectoryService::sCommon_Startmenu) {
674     rv = GetSpecialSystemDirectory(Win_Common_Startmenu, getter_AddRefs(localFile));
675   } else if (inAtom == nsDirectoryService::sCommon_Programs) {
676     rv = GetSpecialSystemDirectory(Win_Common_Programs, getter_AddRefs(localFile));
677   } else if (inAtom == nsDirectoryService::sCommon_Startup) {
678     rv = GetSpecialSystemDirectory(Win_Common_Startup, getter_AddRefs(localFile));
679   } else if (inAtom == nsDirectoryService::sCommon_Desktopdirectory) {
680     rv = GetSpecialSystemDirectory(Win_Common_Desktopdirectory, getter_AddRefs(localFile));
681   } else if (inAtom == nsDirectoryService::sCommon_AppData) {
682     rv = GetSpecialSystemDirectory(Win_Common_AppData, getter_AddRefs(localFile));
683   } else if (inAtom == nsDirectoryService::sAppdata) {
684     rv = GetSpecialSystemDirectory(Win_Appdata, getter_AddRefs(localFile));
685   } else if (inAtom == nsDirectoryService::sLocalAppdata) {
686     rv = GetSpecialSystemDirectory(Win_LocalAppdata, getter_AddRefs(localFile));
687 #if defined(MOZ_CONTENT_SANDBOX)
688   } else if (inAtom == nsDirectoryService::sLocalAppdataLow) {
689     rv = GetSpecialSystemDirectory(Win_LocalAppdataLow, getter_AddRefs(localFile));
690   } else if (inAtom == nsDirectoryService::sLowIntegrityTempBase) {
691     rv = GetLowIntegrityTempBase(getter_AddRefs(localFile));
692 #endif
693   } else if (inAtom == nsDirectoryService::sPrinthood) {
694     rv = GetSpecialSystemDirectory(Win_Printhood, getter_AddRefs(localFile));
695   } else if (inAtom == nsDirectoryService::sWinCookiesDirectory) {
696     rv = GetSpecialSystemDirectory(Win_Cookies, getter_AddRefs(localFile));
697   } else if (inAtom == nsDirectoryService::sDefaultDownloadDirectory) {
698     rv = GetSpecialSystemDirectory(Win_Downloads, getter_AddRefs(localFile));
699   } else if (inAtom == nsDirectoryService::sDocs) {
700     rv = GetSpecialSystemDirectory(Win_Documents, getter_AddRefs(localFile));
701   } else if (inAtom == nsDirectoryService::sPictures) {
702     rv = GetSpecialSystemDirectory(Win_Pictures, getter_AddRefs(localFile));
703   } else if (inAtom == nsDirectoryService::sMusic) {
704     rv = GetSpecialSystemDirectory(Win_Music, getter_AddRefs(localFile));
705   } else if (inAtom == nsDirectoryService::sVideos) {
706     rv = GetSpecialSystemDirectory(Win_Videos, getter_AddRefs(localFile));
707   }
708 #elif defined (XP_UNIX)
709 
710   else if (inAtom == nsDirectoryService::sLocalDirectory) {
711     rv = GetSpecialSystemDirectory(Unix_LocalDirectory, getter_AddRefs(localFile));
712   } else if (inAtom == nsDirectoryService::sLibDirectory) {
713     rv = GetSpecialSystemDirectory(Unix_LibDirectory, getter_AddRefs(localFile));
714   } else if (inAtom == nsDirectoryService::sOS_HomeDirectory) {
715     rv = GetSpecialSystemDirectory(Unix_HomeDirectory, getter_AddRefs(localFile));
716   } else if (inAtom == nsDirectoryService::sXDGDesktop ||
717              inAtom == nsDirectoryService::sOS_DesktopDirectory) {
718     rv = GetSpecialSystemDirectory(Unix_XDG_Desktop, getter_AddRefs(localFile));
719     *aPersistent = false;
720   } else if (inAtom == nsDirectoryService::sXDGDocuments) {
721     rv = GetSpecialSystemDirectory(Unix_XDG_Documents, getter_AddRefs(localFile));
722     *aPersistent = false;
723   } else if (inAtom == nsDirectoryService::sXDGDownload ||
724              inAtom == nsDirectoryService::sDefaultDownloadDirectory) {
725     rv = GetSpecialSystemDirectory(Unix_XDG_Download, getter_AddRefs(localFile));
726     *aPersistent = false;
727   } else if (inAtom == nsDirectoryService::sXDGMusic) {
728     rv = GetSpecialSystemDirectory(Unix_XDG_Music, getter_AddRefs(localFile));
729     *aPersistent = false;
730   } else if (inAtom == nsDirectoryService::sXDGPictures) {
731     rv = GetSpecialSystemDirectory(Unix_XDG_Pictures, getter_AddRefs(localFile));
732     *aPersistent = false;
733   } else if (inAtom == nsDirectoryService::sXDGPublicShare) {
734     rv = GetSpecialSystemDirectory(Unix_XDG_PublicShare, getter_AddRefs(localFile));
735     *aPersistent = false;
736   } else if (inAtom == nsDirectoryService::sXDGTemplates) {
737     rv = GetSpecialSystemDirectory(Unix_XDG_Templates, getter_AddRefs(localFile));
738     *aPersistent = false;
739   } else if (inAtom == nsDirectoryService::sXDGVideos) {
740     rv = GetSpecialSystemDirectory(Unix_XDG_Videos, getter_AddRefs(localFile));
741     *aPersistent = false;
742   }
743 #endif
744 
745   if (NS_FAILED(rv)) {
746     return rv;
747   }
748 
749   if (!localFile) {
750     return NS_ERROR_FAILURE;
751   }
752 
753   localFile.forget(aResult);
754   return NS_OK;
755 }
756 
757 NS_IMETHODIMP
GetFiles(const char * aProp,nsISimpleEnumerator ** aResult)758 nsDirectoryService::GetFiles(const char* aProp, nsISimpleEnumerator** aResult)
759 {
760   if (NS_WARN_IF(!aResult)) {
761     return NS_ERROR_INVALID_ARG;
762   }
763   *aResult = nullptr;
764 
765   return NS_ERROR_FAILURE;
766 }
767