1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2002
20 * the Initial Developer. All Rights Reserved.
23 * Brian Ryner <bryner@brianryner.com>
24 * Benjamin Smedberg <bsmedberg@covad.net>
25 * Ben Goodger <ben@mozilla.org>
26 * Jens Bannmann <jens.b@web.de>
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 #include "nsAppRunner.h"
43 #include "nsXREDirProvider.h"
47 #include "nsIJSContextStack.h"
48 #include "nsIDirectoryEnumerator.h"
49 #include "nsILocalFile.h"
50 #include "nsIObserver.h"
51 #include "nsIObserverService.h"
52 #include "nsIProfileChangeStatus.h"
53 #include "nsISimpleEnumerator.h"
54 #include "nsIToolkitChromeRegistry.h"
56 #include "nsAppDirectoryServiceDefs.h"
57 #include "nsDirectoryServiceDefs.h"
58 #include "nsDirectoryServiceUtils.h"
59 #include "nsXULAppAPI.h"
60 #include "nsCategoryManagerUtils.h"
62 #include "nsINIParser.h"
63 #include "nsDependentString.h"
64 #include "nsCOMArray.h"
65 #include "nsArrayEnumerator.h"
66 #include "nsEnumeratorUtils.h"
67 #include "nsReadableUtils.h"
68 #include "mozilla/Services.h"
69 #include "mozilla/Omnijar.h"
76 // This is not defined by VC6.
77 #ifndef CSIDL_LOCAL_APPDATA
78 #define CSIDL_LOCAL_APPDATA 0x001C
82 #include "nsILocalFileMac.h"
85 #include <be/kernel/image.h>
86 #include <FindDirectory.h>
96 #if defined(XP_MACOSX)
97 #define APP_REGISTRY_NAME "Application Registry"
98 #elif defined(XP_WIN) || defined(XP_OS2)
99 #define APP_REGISTRY_NAME "registry.dat"
101 #define APP_REGISTRY_NAME "appreg"
104 #define PREF_OVERRIDE_DIRNAME "preferences"
106 static already_AddRefed
<nsILocalFile
>
107 CloneAndAppend(nsIFile
* aFile
, const char* name
)
109 nsCOMPtr
<nsIFile
> file
;
110 aFile
->Clone(getter_AddRefs(file
));
111 nsCOMPtr
<nsILocalFile
> lfile
= do_QueryInterface(file
);
112 lfile
->AppendNative(nsDependentCString(name
));
113 return lfile
.forget();
116 nsXREDirProvider
* gDirServiceProvider
= nsnull
;
118 nsXREDirProvider::nsXREDirProvider() :
119 mProfileNotified(PR_FALSE
)
121 gDirServiceProvider
= this;
124 nsXREDirProvider::~nsXREDirProvider()
126 gDirServiceProvider
= nsnull
;
130 nsXREDirProvider::Initialize(nsIFile
*aXULAppDir
,
131 nsILocalFile
*aGREDir
,
132 nsIDirectoryServiceProvider
* aAppProvider
)
134 NS_ENSURE_ARG(aXULAppDir
);
135 NS_ENSURE_ARG(aGREDir
);
137 mAppProvider
= aAppProvider
;
138 mXULAppDir
= aXULAppDir
;
142 nsCOMPtr
<nsIDirectoryServiceProvider
> app(do_QueryInterface(mAppProvider
));
144 PRBool per
= PR_FALSE
;
145 app
->GetFile(NS_APP_USER_PROFILE_50_DIR
, &per
, getter_AddRefs(mProfileDir
));
146 NS_ASSERTION(per
, "NS_APP_USER_PROFILE_50_DIR must be persistent!");
147 NS_ASSERTION(mProfileDir
, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!");
156 nsXREDirProvider::SetProfile(nsIFile
* aDir
, nsIFile
* aLocalDir
)
158 NS_ASSERTION(aDir
&& aLocalDir
, "We don't support no-profile apps yet!");
162 rv
= EnsureDirectoryExists(aDir
);
166 rv
= EnsureDirectoryExists(aLocalDir
);
171 mProfileLocalDir
= aLocalDir
;
175 NS_IMPL_QUERY_INTERFACE3(nsXREDirProvider
,
176 nsIDirectoryServiceProvider
,
177 nsIDirectoryServiceProvider2
,
180 NS_IMETHODIMP_(nsrefcnt
)
181 nsXREDirProvider::AddRef()
186 NS_IMETHODIMP_(nsrefcnt
)
187 nsXREDirProvider::Release()
193 nsXREDirProvider::GetFile(const char* aProperty
, PRBool
* aPersistent
,
198 PRBool gettingProfile
= PR_FALSE
;
200 if (!strcmp(aProperty
, NS_APP_USER_PROFILE_LOCAL_50_DIR
)) {
201 // If XRE_NotifyProfile hasn't been called, don't fall through to
202 // mAppProvider on the profile keys.
203 if (!mProfileNotified
)
204 return NS_ERROR_FAILURE
;
206 if (mProfileLocalDir
)
207 return mProfileLocalDir
->Clone(aFile
);
210 return mAppProvider
->GetFile(aProperty
, aPersistent
, aFile
);
212 // This falls through to the case below
213 gettingProfile
= PR_TRUE
;
215 if (!strcmp(aProperty
, NS_APP_USER_PROFILE_50_DIR
) || gettingProfile
) {
216 if (!mProfileNotified
)
217 return NS_ERROR_FAILURE
;
220 return mProfileDir
->Clone(aFile
);
223 return mAppProvider
->GetFile(aProperty
, aPersistent
, aFile
);
225 // If we don't succeed here, bail early so that we aren't reentrant
226 // through the "GetProfileDir" call below.
227 return NS_ERROR_FAILURE
;
231 rv
= mAppProvider
->GetFile(aProperty
, aPersistent
, aFile
);
232 if (NS_SUCCEEDED(rv
) && *aFile
)
236 *aPersistent
= PR_TRUE
;
238 if (!strcmp(aProperty
, NS_GRE_DIR
)) {
239 return mGREDir
->Clone(aFile
);
241 else if (!strcmp(aProperty
, NS_OS_CURRENT_PROCESS_DIR
) ||
242 !strcmp(aProperty
, NS_APP_INSTALL_CLEANUP_DIR
)) {
243 return GetAppDir()->Clone(aFile
);
246 rv
= NS_ERROR_FAILURE
;
247 nsCOMPtr
<nsIFile
> file
;
249 if (!strcmp(aProperty
, NS_APP_PROFILE_DEFAULTS_50_DIR
) ||
250 !strcmp(aProperty
, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR
)) {
251 return GetProfileDefaultsDir(aFile
);
253 else if (!strcmp(aProperty
, NS_APP_PREF_DEFAULTS_50_DIR
))
255 // return the GRE default prefs directory here, and the app default prefs
256 // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
257 rv
= mGREDir
->Clone(getter_AddRefs(file
));
258 if (NS_SUCCEEDED(rv
)) {
259 rv
= file
->AppendNative(NS_LITERAL_CSTRING("defaults"));
260 if (NS_SUCCEEDED(rv
))
261 rv
= file
->AppendNative(NS_LITERAL_CSTRING("pref"));
264 else if (!strcmp(aProperty
, NS_APP_APPLICATION_REGISTRY_DIR
) ||
265 !strcmp(aProperty
, XRE_USER_APP_DATA_DIR
)) {
266 rv
= GetUserAppDataDirectory((nsILocalFile
**)(nsIFile
**) getter_AddRefs(file
));
268 else if (!strcmp(aProperty
, XRE_UPDATE_ROOT_DIR
)) {
269 #if defined(XP_WIN) && !defined(WINCE)
270 rv
= GetUpdateRootDir(getter_AddRefs(file
));
272 // Only supported on Windows other than WINCE, so just immediately fail.
273 return NS_ERROR_FAILURE
;
276 else if (!strcmp(aProperty
, NS_APP_APPLICATION_REGISTRY_FILE
)) {
277 rv
= GetUserAppDataDirectory((nsILocalFile
**)(nsIFile
**) getter_AddRefs(file
));
278 if (NS_SUCCEEDED(rv
))
279 rv
= file
->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME
));
281 else if (!strcmp(aProperty
, NS_APP_USER_PROFILES_ROOT_DIR
)) {
282 rv
= GetUserAppDataDirectory((nsILocalFile
**)(nsIFile
**) getter_AddRefs(file
));
284 if (NS_SUCCEEDED(rv
)) {
285 #if !defined(XP_UNIX) || defined(XP_MACOSX)
286 rv
= file
->AppendNative(NS_LITERAL_CSTRING("Profiles"));
289 // We must create the profile directory here if it does not exist.
290 rv
|= EnsureDirectoryExists(file
);
293 else if (!strcmp(aProperty
, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR
)) {
294 rv
= GetUserLocalDataDirectory((nsILocalFile
**)(nsIFile
**) getter_AddRefs(file
));
296 if (NS_SUCCEEDED(rv
)) {
297 #if !defined(XP_UNIX) || defined(XP_MACOSX)
298 rv
= file
->AppendNative(NS_LITERAL_CSTRING("Profiles"));
301 // We must create the profile directory here if it does not exist.
302 rv
|= EnsureDirectoryExists(file
);
305 else if (!strcmp(aProperty
, XRE_EXECUTABLE_FILE
) && gArgv
[0]) {
306 nsCOMPtr
<nsILocalFile
> lf
;
307 rv
= XRE_GetBinaryPath(gArgv
[0], getter_AddRefs(lf
));
308 if (NS_SUCCEEDED(rv
))
311 else if (!strcmp(aProperty
, "resource:app")) {
312 rv
= GetAppDir()->Clone(getter_AddRefs(file
));
315 else if (!strcmp(aProperty
, NS_APP_PROFILE_DIR_STARTUP
) && mProfileDir
) {
316 return mProfileDir
->Clone(aFile
);
318 else if (!strcmp(aProperty
, NS_APP_PROFILE_LOCAL_DIR_STARTUP
)) {
319 if (mProfileLocalDir
)
320 return mProfileLocalDir
->Clone(aFile
);
323 return mProfileDir
->Clone(aFile
);
326 return mAppProvider
->GetFile(NS_APP_PROFILE_DIR_STARTUP
, aPersistent
,
329 #if defined(XP_UNIX) || defined(XP_MACOSX)
330 else if (!strcmp(aProperty
, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR
)) {
331 return GetSystemExtensionsDirectory((nsILocalFile
**)(nsIFile
**) aFile
);
334 #if defined(XP_UNIX) && !defined(XP_MACOSX)
335 else if (!strcmp(aProperty
, XRE_SYS_SHARE_EXTENSION_PARENT_DIR
)) {
336 static const char *const sysLExtDir
= "/usr/share/mozilla/extensions";
337 return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir
),
338 PR_FALSE
, (nsILocalFile
**)(nsIFile
**) aFile
);
341 else if (!strcmp(aProperty
, XRE_USER_SYS_EXTENSION_DIR
)) {
342 return GetSysUserExtensionsDirectory((nsILocalFile
**)(nsIFile
**) aFile
);
344 else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file
)))) {
345 // We need to allow component, xpt, and chrome registration to
346 // occur prior to the profile-after-change notification.
347 if (!strcmp(aProperty
, NS_APP_USER_CHROME_DIR
)) {
348 rv
= file
->AppendNative(NS_LITERAL_CSTRING("chrome"));
352 if (NS_SUCCEEDED(rv
) && file
) {
353 NS_ADDREF(*aFile
= file
);
357 PRBool ensureFilePermissions
= PR_FALSE
;
359 if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file
)))) {
360 if (!strcmp(aProperty
, NS_APP_PREFS_50_DIR
)) {
363 else if (!strcmp(aProperty
, NS_APP_PREFS_50_FILE
)) {
364 rv
= file
->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
366 else if (!strcmp(aProperty
, NS_LOCALSTORE_UNSAFE_FILE
)) {
367 rv
= file
->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
369 else if (!strcmp(aProperty
, NS_APP_LOCALSTORE_50_FILE
)) {
371 rv
= file
->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
372 file
->Remove(PR_FALSE
);
375 rv
= file
->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
376 EnsureProfileFileExists(file
);
377 ensureFilePermissions
= PR_TRUE
;
380 else if (!strcmp(aProperty
, NS_APP_HISTORY_50_FILE
)) {
381 rv
= file
->AppendNative(NS_LITERAL_CSTRING("history.dat"));
383 else if (!strcmp(aProperty
, NS_APP_USER_MIMETYPES_50_FILE
)) {
384 rv
= file
->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
385 EnsureProfileFileExists(file
);
386 ensureFilePermissions
= PR_TRUE
;
388 else if (!strcmp(aProperty
, NS_APP_STORAGE_50_FILE
)) {
389 rv
= file
->AppendNative(NS_LITERAL_CSTRING("storage.sdb"));
391 else if (!strcmp(aProperty
, NS_APP_DOWNLOADS_50_FILE
)) {
392 rv
= file
->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
394 else if (!strcmp(aProperty
, NS_APP_PREFS_OVERRIDE_DIR
)) {
395 rv
= mProfileDir
->Clone(getter_AddRefs(file
));
396 rv
|= file
->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME
));
397 rv
|= EnsureDirectoryExists(file
);
400 if (NS_FAILED(rv
) || !file
)
401 return NS_ERROR_FAILURE
;
403 if (ensureFilePermissions
) {
404 PRBool fileToEnsureExists
;
406 if (NS_SUCCEEDED(file
->Exists(&fileToEnsureExists
)) && fileToEnsureExists
407 && NS_SUCCEEDED(file
->IsWritable(&isWritable
)) && !isWritable
) {
408 PRUint32 permissions
;
409 if (NS_SUCCEEDED(file
->GetPermissions(&permissions
))) {
410 rv
= file
->SetPermissions(permissions
| 0600);
411 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to ensure file permissions");
416 NS_ADDREF(*aFile
= file
);
421 LoadAppDirIntoArray(nsIFile
* aXULAppDir
,
422 const char *const *aAppendList
,
423 nsCOMArray
<nsIFile
>& aDirectories
)
428 nsCOMPtr
<nsIFile
> subdir
;
429 aXULAppDir
->Clone(getter_AddRefs(subdir
));
433 for (; *aAppendList
; ++aAppendList
)
434 subdir
->AppendNative(nsDependentCString(*aAppendList
));
437 if (NS_SUCCEEDED(subdir
->Exists(&exists
)) && exists
)
438 aDirectories
.AppendObject(subdir
);
442 LoadDirsIntoArray(nsCOMArray
<nsIFile
>& aSourceDirs
,
443 const char *const* aAppendList
,
444 nsCOMArray
<nsIFile
>& aDirectories
)
446 nsCOMPtr
<nsIFile
> appended
;
449 for (PRInt32 i
= 0; i
< aSourceDirs
.Count(); ++i
) {
450 aSourceDirs
[i
]->Clone(getter_AddRefs(appended
));
454 for (const char *const *a
= aAppendList
; *a
; ++a
)
455 appended
->AppendNative(nsDependentCString(*a
));
457 if (NS_SUCCEEDED(appended
->Exists(&exists
)) && exists
)
458 aDirectories
.AppendObject(appended
);
462 static const char *const kAppendChromeManifests
[] =
463 { "chrome.manifest", nsnull
};
466 nsXREDirProvider::GetFiles(const char* aProperty
, nsISimpleEnumerator
** aResult
)
470 nsCOMPtr
<nsISimpleEnumerator
> appEnum
;
471 nsCOMPtr
<nsIDirectoryServiceProvider2
>
472 appP2(do_QueryInterface(mAppProvider
));
474 rv
= appP2
->GetFiles(aProperty
, getter_AddRefs(appEnum
));
478 else if (rv
!= NS_SUCCESS_AGGREGATE_RESULT
) {
479 NS_ADDREF(*aResult
= appEnum
);
484 nsCOMPtr
<nsISimpleEnumerator
> xreEnum
;
485 rv
= GetFilesInternal(aProperty
, getter_AddRefs(xreEnum
));
488 NS_ADDREF(*aResult
= appEnum
);
489 return NS_SUCCESS_AGGREGATE_RESULT
;
495 rv
= NS_NewUnionEnumerator(aResult
, appEnum
, xreEnum
);
499 return NS_SUCCESS_AGGREGATE_RESULT
;
503 LoadExtensionDirectories(nsINIParser
&parser
,
504 const char *aSection
,
505 nsCOMArray
<nsIFile
> &aDirectories
,
506 NSLocationType aType
)
511 nsCAutoString
buf("Extension");
515 rv
= parser
.GetString(aSection
, buf
.get(), path
);
519 nsCOMPtr
<nsILocalFile
> dir
= do_CreateInstance("@mozilla.org/file/local;1", &rv
);
523 rv
= dir
->SetPersistentDescriptor(path
);
527 aDirectories
.AppendObject(dir
);
529 nsCOMPtr
<nsILocalFile
> manifest
=
530 CloneAndAppend(dir
, "chrome.manifest");
531 XRE_AddManifestLocation(aType
, manifest
);
537 nsXREDirProvider::LoadExtensionBundleDirectories()
539 if (mProfileDir
&& !gSafeMode
) {
540 nsCOMPtr
<nsIFile
> extensionsINI
;
541 mProfileDir
->Clone(getter_AddRefs(extensionsINI
));
545 extensionsINI
->AppendNative(NS_LITERAL_CSTRING("extensions.ini"));
547 nsCOMPtr
<nsILocalFile
> extensionsINILF
=
548 do_QueryInterface(extensionsINI
);
549 if (!extensionsINILF
)
553 nsresult rv
= parser
.Init(extensionsINILF
);
557 LoadExtensionDirectories(parser
, "ExtensionDirs", mExtensionDirectories
,
558 NS_COMPONENT_LOCATION
);
559 LoadExtensionDirectories(parser
, "ThemeDirs", mThemeDirectories
,
565 nsXREDirProvider::LoadAppBundleDirs()
567 nsCOMPtr
<nsIFile
> dir
;
568 nsresult rv
= mXULAppDir
->Clone(getter_AddRefs(dir
));
572 dir
->AppendNative(NS_LITERAL_CSTRING("distribution"));
573 dir
->AppendNative(NS_LITERAL_CSTRING("bundles"));
575 nsCOMPtr
<nsISimpleEnumerator
> e
;
576 rv
= dir
->GetDirectoryEntries(getter_AddRefs(e
));
580 nsCOMPtr
<nsIDirectoryEnumerator
> files
= do_QueryInterface(e
);
584 nsCOMPtr
<nsIFile
> subdir
;
585 while (NS_SUCCEEDED(files
->GetNextFile(getter_AddRefs(subdir
))) && subdir
) {
586 mAppBundleDirectories
.AppendObject(subdir
);
588 nsCOMPtr
<nsILocalFile
> manifest
=
589 CloneAndAppend(subdir
, "chrome.manifest");
590 XRE_AddManifestLocation(NS_COMPONENT_LOCATION
, manifest
);
594 static const char *const kAppendPrefDir
[] = { "defaults", "preferences", nsnull
};
596 #ifdef DEBUG_bsmedberg
598 DumpFileArray(const char *key
,
599 nsCOMArray
<nsIFile
> dirs
)
601 fprintf(stderr
, "nsXREDirProvider::GetFilesInternal(%s)\n", key
);
604 for (PRInt32 i
= 0; i
< dirs
.Count(); ++i
) {
605 dirs
[i
]->GetNativePath(path
);
606 fprintf(stderr
, " %s\n", path
.get());
609 #endif // DEBUG_bsmedberg
612 nsXREDirProvider::GetFilesInternal(const char* aProperty
,
613 nsISimpleEnumerator
** aResult
)
618 if (!strcmp(aProperty
, XRE_EXTENSIONS_DIR_LIST
)) {
619 nsCOMArray
<nsIFile
> directories
;
621 static const char *const kAppendNothing
[] = { nsnull
};
623 LoadDirsIntoArray(mAppBundleDirectories
,
624 kAppendNothing
, directories
);
625 LoadDirsIntoArray(mExtensionDirectories
,
626 kAppendNothing
, directories
);
628 rv
= NS_NewArrayEnumerator(aResult
, directories
);
630 else if (!strcmp(aProperty
, NS_APP_PREFS_DEFAULTS_DIR_LIST
)) {
631 nsCOMArray
<nsIFile
> directories
;
633 LoadAppDirIntoArray(mXULAppDir
, kAppendPrefDir
, directories
);
634 LoadDirsIntoArray(mAppBundleDirectories
,
635 kAppendPrefDir
, directories
);
637 rv
= NS_NewArrayEnumerator(aResult
, directories
);
639 else if (!strcmp(aProperty
, NS_EXT_PREFS_DEFAULTS_DIR_LIST
)) {
640 nsCOMArray
<nsIFile
> directories
;
642 LoadDirsIntoArray(mExtensionDirectories
,
643 kAppendPrefDir
, directories
);
646 nsCOMPtr
<nsIFile
> overrideFile
;
647 mProfileDir
->Clone(getter_AddRefs(overrideFile
));
648 overrideFile
->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME
));
651 if (NS_SUCCEEDED(overrideFile
->Exists(&exists
)) && exists
)
652 directories
.AppendObject(overrideFile
);
655 rv
= NS_NewArrayEnumerator(aResult
, directories
);
657 else if (!strcmp(aProperty
, NS_APP_CHROME_DIR_LIST
)) {
658 // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
659 // for OS window decoration.
661 static const char *const kAppendChromeDir
[] = { "chrome", nsnull
};
662 nsCOMArray
<nsIFile
> directories
;
663 LoadAppDirIntoArray(mXULAppDir
,
666 LoadDirsIntoArray(mAppBundleDirectories
,
669 LoadDirsIntoArray(mExtensionDirectories
,
673 rv
= NS_NewArrayEnumerator(aResult
, directories
);
675 else if (!strcmp(aProperty
, NS_APP_PLUGINS_DIR_LIST
)) {
676 static const char *const kAppendPlugins
[] = { "plugins", nsnull
};
677 nsCOMArray
<nsIFile
> directories
;
679 // The root dirserviceprovider does quite a bit for us: we're mainly
680 // interested in xulapp and extension-provided plugins.
681 LoadDirsIntoArray(mAppBundleDirectories
,
684 LoadDirsIntoArray(mExtensionDirectories
,
689 nsCOMArray
<nsIFile
> profileDir
;
690 profileDir
.AppendObject(mProfileDir
);
691 LoadDirsIntoArray(profileDir
,
696 rv
= NS_NewArrayEnumerator(aResult
, directories
);
697 NS_ENSURE_SUCCESS(rv
, rv
);
699 rv
= NS_SUCCESS_AGGREGATE_RESULT
;
702 rv
= NS_ERROR_FAILURE
;
708 nsXREDirProvider::GetDirectory(nsIFile
* *aResult
)
710 NS_ENSURE_TRUE(mProfileDir
, NS_ERROR_NOT_INITIALIZED
);
712 return mProfileDir
->Clone(aResult
);
716 nsXREDirProvider::DoStartup()
718 if (!mProfileNotified
) {
719 nsCOMPtr
<nsIObserverService
> obsSvc
=
720 mozilla::services::GetObserverService();
721 if (!obsSvc
) return NS_ERROR_FAILURE
;
723 mProfileNotified
= PR_TRUE
;
725 static const PRUnichar kStartup
[] = {'s','t','a','r','t','u','p','\0'};
726 obsSvc
->NotifyObservers(nsnull
, "profile-do-change", kStartup
);
727 // Init the Extension Manager
728 nsCOMPtr
<nsIObserver
> em
= do_GetService("@mozilla.org/addons/integration;1");
730 em
->Observe(nsnull
, "addons-startup", nsnull
);
732 NS_WARNING("Failed to create Addons Manager.");
735 LoadExtensionBundleDirectories();
737 obsSvc
->NotifyObservers(nsnull
, "load-extension-defaults", nsnull
);
738 obsSvc
->NotifyObservers(nsnull
, "profile-after-change", kStartup
);
740 // Any component that has registered for the profile-after-change category
741 // should also be created at this time.
742 (void)NS_CreateServicesFromCategory("profile-after-change", nsnull
,
743 "profile-after-change");
745 obsSvc
->NotifyObservers(nsnull
, "profile-initial-state", nsnull
);
750 class ProfileChangeStatusImpl
: public nsIProfileChangeStatus
754 NS_DECL_NSIPROFILECHANGESTATUS
755 ProfileChangeStatusImpl() { }
757 ~ProfileChangeStatusImpl() { }
760 NS_IMPL_ISUPPORTS1(ProfileChangeStatusImpl
, nsIProfileChangeStatus
)
763 ProfileChangeStatusImpl::VetoChange()
765 NS_ERROR("Can't veto change!");
766 return NS_ERROR_FAILURE
;
770 ProfileChangeStatusImpl::ChangeFailed()
772 NS_ERROR("Profile change cancellation.");
773 return NS_ERROR_FAILURE
;
777 nsXREDirProvider::DoShutdown()
779 if (mProfileNotified
) {
780 nsCOMPtr
<nsIObserverService
> obsSvc
=
781 mozilla::services::GetObserverService();
782 NS_ASSERTION(obsSvc
, "No observer service?");
784 nsCOMPtr
<nsIProfileChangeStatus
> cs
= new ProfileChangeStatusImpl();
785 static const PRUnichar kShutdownPersist
[] =
786 {'s','h','u','t','d','o','w','n','-','p','e','r','s','i','s','t','\0'};
787 obsSvc
->NotifyObservers(cs
, "profile-change-net-teardown", kShutdownPersist
);
788 obsSvc
->NotifyObservers(cs
, "profile-change-teardown", kShutdownPersist
);
790 // Phase 2c: Now that things are torn down, force JS GC so that things which depend on
791 // resources which are about to go away in "profile-before-change" are destroyed first.
792 nsCOMPtr
<nsIThreadJSContextStack
> stack
793 (do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
796 JSContext
*cx
= nsnull
;
797 stack
->GetSafeJSContext(&cx
);
802 // Phase 3: Notify observers of a profile change
803 obsSvc
->NotifyObservers(cs
, "profile-before-change", kShutdownPersist
);
805 mProfileNotified
= PR_FALSE
;
811 GetShellFolderPath(int folder
, nsAString
& _retval
)
814 PRUint32 bufLength
= _retval
.GetMutableData(&buf
, MAXPATHLEN
+ 3);
815 NS_ENSURE_TRUE(bufLength
>= (MAXPATHLEN
+ 3), NS_ERROR_OUT_OF_MEMORY
);
819 #if defined(WINCE) && !defined(WINCE_WINDOWS_MOBILE)
820 if (folder
== CSIDL_APPDATA
|| folder
== CSIDL_LOCAL_APPDATA
)
821 folder
= CSIDL_PROFILE
;
823 BOOL ok
= SHGetSpecialFolderPath(NULL
, buf
, folder
, true);
825 _retval
.SetLength(0);
826 return NS_ERROR_FAILURE
;
829 buf
[bufLength
- 1] = L
'\0';
830 _retval
.SetLength(wcslen(buf
));
832 // sometimes CSIDL_PROFILE shows up without a root slash
833 if (folder
== CSIDL_PROFILE
&& buf
[0] != '\\') {
834 _retval
.Insert('\\', 0);
837 LPITEMIDLIST pItemIDList
= NULL
;
839 if (SUCCEEDED(SHGetSpecialFolderLocation(NULL
, folder
, &pItemIDList
)) &&
840 SHGetPathFromIDListW(pItemIDList
, buf
)) {
841 // We're going to use wcslen (wcsnlen not available in msvc7.1) so make
842 // sure to null terminate.
843 buf
[bufLength
- 1] = L
'\0';
844 _retval
.SetLength(wcslen(buf
));
846 _retval
.SetLength(0);
847 rv
= NS_ERROR_NOT_AVAILABLE
;
850 CoTaskMemFree(pItemIDList
);
858 * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
859 * querying the registry when the call to SHGetSpecialFolderLocation or
860 * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
863 GetRegWindowsAppDataFolder(PRBool aLocal
, nsAString
& _retval
)
866 NS_NAMED_LITERAL_STRING(keyName
,
867 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
868 DWORD res
= ::RegOpenKeyExW(HKEY_CURRENT_USER
, keyName
.get(), 0, KEY_READ
,
870 if (res
!= ERROR_SUCCESS
) {
871 _retval
.SetLength(0);
872 return NS_ERROR_NOT_AVAILABLE
;
876 res
= RegQueryValueExW(key
, (aLocal
? L
"Local AppData" : L
"AppData"), NULL
,
878 // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
879 // buffer size must not equal 0, and the buffer size be a multiple of 2.
880 if (res
!= ERROR_SUCCESS
|| type
!= REG_SZ
|| size
== 0 || size
% 2 != 0) {
882 _retval
.SetLength(0);
883 return NS_ERROR_NOT_AVAILABLE
;
886 // |size| includes room for the terminating null character
887 DWORD resultLen
= size
/ 2 - 1;
889 _retval
.SetLength(resultLen
);
890 nsAString::iterator begin
;
891 _retval
.BeginWriting(begin
);
892 if (begin
.size_forward() != resultLen
) {
894 _retval
.SetLength(0);
895 return NS_ERROR_NOT_AVAILABLE
;
898 res
= RegQueryValueExW(key
, (aLocal
? L
"Local AppData" : L
"AppData"), NULL
,
899 NULL
, (LPBYTE
) begin
.get(), &size
);
901 if (res
!= ERROR_SUCCESS
) {
902 _retval
.SetLength(0);
903 return NS_ERROR_NOT_AVAILABLE
;
911 nsXREDirProvider::GetUpdateRootDir(nsIFile
* *aResult
)
913 nsCOMPtr
<nsIFile
> appDir
= GetAppDir();
915 nsAutoString appPath
;
916 nsresult rv
= appDir
->GetPath(appPath
);
917 NS_ENSURE_SUCCESS(rv
, rv
);
919 // AppDir may be a short path. Convert to long path to make sure
920 // the consistency of the update folder location
924 PRUint32 bufLength
= longPath
.GetMutableData(&buf
, MAXPATHLEN
);
925 NS_ENSURE_TRUE(bufLength
>= MAXPATHLEN
, NS_ERROR_OUT_OF_MEMORY
);
928 longPath
.Assign(appPath
);
930 DWORD len
= GetLongPathNameW(appPath
.get(), buf
, bufLength
);
932 // Failing GetLongPathName() is not fatal.
933 if (len
<= 0 || len
>= bufLength
)
934 longPath
.Assign(appPath
);
936 longPath
.SetLength(len
);
938 // Use <UserLocalDataDir>\updates\<relative path to app dir from
939 // Program Files> if app dir is under Program Files to avoid the
940 // folder virtualization mess on Windows Vista
941 nsAutoString programFiles
;
942 rv
= GetShellFolderPath(CSIDL_PROGRAM_FILES
, programFiles
);
943 NS_ENSURE_SUCCESS(rv
, rv
);
945 programFiles
.AppendLiteral("\\");
946 PRUint32 programFilesLen
= programFiles
.Length();
948 if (longPath
.Length() < programFilesLen
)
949 return NS_ERROR_FAILURE
;
951 if (_wcsnicmp(programFiles
.get(), longPath
.get(), programFilesLen
) != 0)
952 return NS_ERROR_FAILURE
;
954 nsCOMPtr
<nsILocalFile
> updRoot
;
955 rv
= GetUserLocalDataDirectory(getter_AddRefs(updRoot
));
956 NS_ENSURE_SUCCESS(rv
, rv
);
958 rv
= updRoot
->AppendRelativePath(Substring(longPath
, programFilesLen
));
959 NS_ENSURE_SUCCESS(rv
, rv
);
961 NS_ADDREF(*aResult
= updRoot
);
967 nsXREDirProvider::GetProfileStartupDir(nsIFile
* *aResult
)
970 return mProfileDir
->Clone(aResult
);
973 nsCOMPtr
<nsIFile
> needsclone
;
975 nsresult rv
= mAppProvider
->GetFile(NS_APP_PROFILE_DIR_STARTUP
,
977 getter_AddRefs(needsclone
));
978 if (NS_SUCCEEDED(rv
))
979 return needsclone
->Clone(aResult
);
982 return NS_ERROR_FAILURE
;
986 nsXREDirProvider::GetProfileDir(nsIFile
* *aResult
)
989 if (!mProfileNotified
)
990 return NS_ERROR_FAILURE
;
992 return mProfileDir
->Clone(aResult
);
996 nsCOMPtr
<nsIFile
> needsclone
;
998 nsresult rv
= mAppProvider
->GetFile(NS_APP_USER_PROFILE_50_DIR
,
1000 getter_AddRefs(needsclone
));
1001 if (NS_SUCCEEDED(rv
))
1002 return needsclone
->Clone(aResult
);
1005 return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR
, aResult
);
1009 nsXREDirProvider::GetUserDataDirectoryHome(nsILocalFile
** aFile
, PRBool aLocal
)
1011 // Copied from nsAppFileLocationProvider (more or less)
1013 nsCOMPtr
<nsILocalFile
> localDir
;
1015 #if defined(XP_MACOSX)
1019 folderType
= kCachedDataFolderType
;
1021 #ifdef MOZ_THUNDERBIRD
1022 folderType
= kDomainLibraryFolderType
;
1024 folderType
= kApplicationSupportFolderType
;
1027 OSErr err
= ::FSFindFolder(kUserDomain
, folderType
, kCreateFolder
, &fsRef
);
1028 NS_ENSURE_FALSE(err
, NS_ERROR_FAILURE
);
1030 rv
= NS_NewNativeLocalFile(EmptyCString(), PR_TRUE
, getter_AddRefs(localDir
));
1031 NS_ENSURE_SUCCESS(rv
, rv
);
1033 nsCOMPtr
<nsILocalFileMac
> dirFileMac
= do_QueryInterface(localDir
);
1034 NS_ENSURE_TRUE(dirFileMac
, NS_ERROR_UNEXPECTED
);
1036 rv
= dirFileMac
->InitWithFSRef(&fsRef
);
1037 NS_ENSURE_SUCCESS(rv
, rv
);
1039 localDir
= do_QueryInterface(dirFileMac
, &rv
);
1040 #elif defined(XP_WIN)
1043 rv
= GetShellFolderPath(CSIDL_LOCAL_APPDATA
, path
);
1046 rv
= GetRegWindowsAppDataFolder(aLocal
, path
);
1049 if (!aLocal
|| NS_FAILED(rv
)) {
1050 rv
= GetShellFolderPath(CSIDL_APPDATA
, path
);
1052 if (NS_FAILED(rv
)) {
1054 rv
= GetRegWindowsAppDataFolder(aLocal
, path
);
1059 NS_ENSURE_SUCCESS(rv
, rv
);
1061 rv
= NS_NewLocalFile(path
, PR_TRUE
, getter_AddRefs(localDir
));
1062 #elif defined(XP_OS2)
1063 #if 0 /* For OS/2 we want to always use MOZILLA_HOME */
1064 // we want an environment variable of the form
1065 // FIREFOX_HOME, etc
1067 return NS_ERROR_FAILURE
;
1068 nsDependentCString
envVar(nsDependentCString(gAppData
->name
));
1069 envVar
.Append("_HOME");
1070 char *pHome
= getenv(envVar
.get());
1072 char *pHome
= getenv("MOZILLA_HOME");
1073 if (pHome
&& *pHome
) {
1074 rv
= NS_NewNativeLocalFile(nsDependentCString(pHome
), PR_TRUE
,
1075 getter_AddRefs(localDir
));
1079 char appDir
[CCHMAXPATH
];
1081 DosGetInfoBlocks(&ptib
, &ppib
);
1082 DosQueryModuleName(ppib
->pib_hmte
, CCHMAXPATH
, appDir
);
1083 *strrchr(appDir
, '\\') = '\0';
1084 rv
= NS_NewNativeLocalFile(nsDependentCString(appDir
), PR_TRUE
, getter_AddRefs(localDir
));
1086 #elif defined(XP_BEOS)
1087 char appDir
[MAXPATHLEN
];
1088 if (find_directory(B_USER_SETTINGS_DIRECTORY
, NULL
, true, appDir
, MAXPATHLEN
))
1089 return NS_ERROR_FAILURE
;
1091 int len
= strlen(appDir
);
1093 appDir
[len
+1] = '\0';
1095 rv
= NS_NewNativeLocalFile(nsDependentCString(appDir
), PR_TRUE
,
1096 getter_AddRefs(localDir
));
1097 #elif defined(ANDROID)
1098 // used for setting the patch to our profile
1099 // XXX: investigate putting the profile somewhere else
1100 const char* homeDir
= "/data/data/org.mozilla." MOZ_APP_NAME
;
1102 rv
= NS_NewNativeLocalFile(nsDependentCString(homeDir
), PR_TRUE
,
1103 getter_AddRefs(localDir
));
1104 #elif defined(XP_UNIX)
1105 const char* homeDir
= getenv("HOME");
1106 if (!homeDir
|| !*homeDir
)
1107 return NS_ERROR_FAILURE
;
1109 rv
= NS_NewNativeLocalFile(nsDependentCString(homeDir
), PR_TRUE
,
1110 getter_AddRefs(localDir
));
1112 #error "Don't know how to get product dir on your platform"
1115 NS_IF_ADDREF(*aFile
= localDir
);
1120 nsXREDirProvider::GetSysUserExtensionsDirectory(nsILocalFile
** aFile
)
1122 nsCOMPtr
<nsILocalFile
> localDir
;
1123 nsresult rv
= GetUserDataDirectoryHome(getter_AddRefs(localDir
), PR_FALSE
);
1124 NS_ENSURE_SUCCESS(rv
, rv
);
1126 rv
= AppendSysUserExtensionPath(localDir
);
1127 NS_ENSURE_SUCCESS(rv
, rv
);
1129 rv
= EnsureDirectoryExists(localDir
);
1130 NS_ENSURE_SUCCESS(rv
, rv
);
1132 NS_ADDREF(*aFile
= localDir
);
1136 #if defined(XP_UNIX) || defined(XP_MACOSX)
1138 nsXREDirProvider::GetSystemExtensionsDirectory(nsILocalFile
** aFile
)
1141 nsCOMPtr
<nsILocalFile
> localDir
;
1142 #if defined(XP_MACOSX)
1144 OSErr err
= ::FSFindFolder(kOnSystemDisk
, kApplicationSupportFolderType
, kCreateFolder
, &fsRef
);
1145 NS_ENSURE_FALSE(err
, NS_ERROR_FAILURE
);
1147 rv
= NS_NewNativeLocalFile(EmptyCString(), PR_TRUE
, getter_AddRefs(localDir
));
1148 NS_ENSURE_SUCCESS(rv
, rv
);
1150 nsCOMPtr
<nsILocalFileMac
> dirFileMac
= do_QueryInterface(localDir
);
1151 NS_ENSURE_TRUE(dirFileMac
, NS_ERROR_UNEXPECTED
);
1153 rv
= dirFileMac
->InitWithFSRef(&fsRef
);
1154 NS_ENSURE_SUCCESS(rv
, rv
);
1156 localDir
= do_QueryInterface(dirFileMac
, &rv
);
1158 static const char* const sXR
= "Mozilla";
1159 rv
= localDir
->AppendNative(nsDependentCString(sXR
));
1160 NS_ENSURE_SUCCESS(rv
, rv
);
1162 static const char* const sExtensions
= "Extensions";
1163 rv
= localDir
->AppendNative(nsDependentCString(sExtensions
));
1164 NS_ENSURE_SUCCESS(rv
, rv
);
1165 #elif defined(XP_UNIX)
1166 static const char *const sysSExtDir
=
1167 #ifdef HAVE_USR_LIB64_DIR
1168 "/usr/lib64/mozilla/extensions";
1170 "/usr/lib/mozilla/extensions";
1173 rv
= NS_NewNativeLocalFile(nsDependentCString(sysSExtDir
), PR_FALSE
,
1174 getter_AddRefs(localDir
));
1175 NS_ENSURE_SUCCESS(rv
, rv
);
1178 NS_ADDREF(*aFile
= localDir
);
1184 nsXREDirProvider::GetUserDataDirectory(nsILocalFile
** aFile
, PRBool aLocal
)
1186 nsCOMPtr
<nsILocalFile
> localDir
;
1187 nsresult rv
= GetUserDataDirectoryHome(getter_AddRefs(localDir
), aLocal
);
1188 NS_ENSURE_SUCCESS(rv
, rv
);
1190 rv
= AppendProfilePath(localDir
);
1191 NS_ENSURE_SUCCESS(rv
, rv
);
1193 #ifdef DEBUG_jungshik
1195 localDir
->GetNativePath(cwd
);
1196 printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd
.get());
1198 rv
= EnsureDirectoryExists(localDir
);
1199 NS_ENSURE_SUCCESS(rv
, rv
);
1201 NS_ADDREF(*aFile
= localDir
);
1206 nsXREDirProvider::EnsureDirectoryExists(nsIFile
* aDirectory
)
1209 nsresult rv
= aDirectory
->Exists(&exists
);
1210 NS_ENSURE_SUCCESS(rv
, rv
);
1211 #ifdef DEBUG_jungshik
1214 aDirectory
->GetNativePath(cwd
);
1215 printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd
.get());
1219 rv
= aDirectory
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
1220 #ifdef DEBUG_jungshik
1222 NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
1229 nsXREDirProvider::EnsureProfileFileExists(nsIFile
*aFile
)
1234 rv
= aFile
->Exists(&exists
);
1235 if (NS_FAILED(rv
) || exists
) return;
1237 nsCAutoString leafName
;
1238 rv
= aFile
->GetNativeLeafName(leafName
);
1239 if (NS_FAILED(rv
)) return;
1241 nsCOMPtr
<nsIFile
> defaultsFile
;
1242 rv
= GetProfileDefaultsDir(getter_AddRefs(defaultsFile
));
1243 if (NS_FAILED(rv
)) return;
1245 rv
= defaultsFile
->AppendNative(leafName
);
1246 if (NS_FAILED(rv
)) return;
1248 defaultsFile
->CopyToNative(mProfileDir
, EmptyCString());
1252 nsXREDirProvider::GetProfileDefaultsDir(nsIFile
* *aResult
)
1254 NS_ASSERTION(mGREDir
, "nsXREDirProvider not initialized.");
1255 NS_PRECONDITION(aResult
, "Null out-param");
1258 nsCOMPtr
<nsIFile
> defaultsDir
;
1260 rv
= GetAppDir()->Clone(getter_AddRefs(defaultsDir
));
1261 NS_ENSURE_SUCCESS(rv
, rv
);
1263 rv
= defaultsDir
->AppendNative(NS_LITERAL_CSTRING("defaults"));
1264 NS_ENSURE_SUCCESS(rv
, rv
);
1266 rv
= defaultsDir
->AppendNative(NS_LITERAL_CSTRING("profile"));
1267 NS_ENSURE_SUCCESS(rv
, rv
);
1269 NS_ADDREF(*aResult
= defaultsDir
);
1274 nsXREDirProvider::AppendSysUserExtensionPath(nsIFile
* aFile
)
1276 NS_ASSERTION(aFile
, "Null pointer!");
1280 #if defined (XP_MACOSX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS)
1282 static const char* const sXR
= "Mozilla";
1283 rv
= aFile
->AppendNative(nsDependentCString(sXR
));
1284 NS_ENSURE_SUCCESS(rv
, rv
);
1286 static const char* const sExtensions
= "Extensions";
1287 rv
= aFile
->AppendNative(nsDependentCString(sExtensions
));
1288 NS_ENSURE_SUCCESS(rv
, rv
);
1290 #elif defined(XP_UNIX)
1292 static const char* const sXR
= ".mozilla";
1293 rv
= aFile
->AppendNative(nsDependentCString(sXR
));
1294 NS_ENSURE_SUCCESS(rv
, rv
);
1296 static const char* const sExtensions
= "extensions";
1297 rv
= aFile
->AppendNative(nsDependentCString(sExtensions
));
1298 NS_ENSURE_SUCCESS(rv
, rv
);
1301 #error "Don't know how to get XRE user extension path on your platform"
1308 nsXREDirProvider::AppendProfilePath(nsIFile
* aFile
)
1310 NS_ASSERTION(aFile
, "Null pointer!");
1315 return NS_ERROR_FAILURE
;
1317 #if defined (XP_MACOSX)
1318 if (gAppData
->profile
) {
1319 rv
= AppendProfileString(aFile
, gAppData
->profile
);
1322 // Note that MacOS ignores the vendor when creating the profile hierarchy -
1323 // all application preferences directories live alongside one another in
1324 // ~/Library/Application Support/
1325 rv
= aFile
->AppendNative(nsDependentCString(gAppData
->name
));
1327 NS_ENSURE_SUCCESS(rv
, rv
);
1329 #elif defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS)
1330 if (gAppData
->profile
) {
1331 rv
= AppendProfileString(aFile
, gAppData
->profile
);
1334 if (gAppData
->vendor
) {
1335 rv
= aFile
->AppendNative(nsDependentCString(gAppData
->vendor
));
1336 NS_ENSURE_SUCCESS(rv
, rv
);
1338 rv
= aFile
->AppendNative(nsDependentCString(gAppData
->name
));
1340 NS_ENSURE_SUCCESS(rv
, rv
);
1342 #elif defined(ANDROID)
1343 // The directory used for storing profiles
1344 // The parent of this directory is set in GetUserDataDirectoryHome
1345 // XXX: handle gAppData->profile properly
1346 rv
= aFile
->AppendNative(nsDependentCString("mozilla"));
1347 NS_ENSURE_SUCCESS(rv
, rv
);
1348 #elif defined(XP_UNIX)
1349 // Make it hidden (i.e. using the ".")
1350 nsCAutoString
folder(".");
1352 if (gAppData
->profile
) {
1353 // Skip any leading path characters
1354 const char* profileStart
= gAppData
->profile
;
1355 while (*profileStart
== '/' || *profileStart
== '\\')
1358 // On the off chance that someone wanted their folder to be hidden don't
1359 // let it become ".."
1360 if (*profileStart
== '.')
1363 folder
.Append(profileStart
);
1364 ToLowerCase(folder
);
1366 rv
= AppendProfileString(aFile
, folder
.BeginReading());
1369 if (gAppData
->vendor
) {
1370 folder
.Append(gAppData
->vendor
);
1371 ToLowerCase(folder
);
1373 rv
= aFile
->AppendNative(folder
);
1374 NS_ENSURE_SUCCESS(rv
, rv
);
1379 folder
.Append(gAppData
->name
);
1380 ToLowerCase(folder
);
1382 rv
= aFile
->AppendNative(folder
);
1384 NS_ENSURE_SUCCESS(rv
, rv
);
1387 #error "Don't know how to get profile path on your platform"
1393 nsXREDirProvider::AppendProfileString(nsIFile
* aFile
, const char* aPath
)
1395 NS_ASSERTION(aFile
, "Null file!");
1396 NS_ASSERTION(aPath
, "Null path!");
1398 nsCAutoString
pathDup(aPath
);
1400 char* path
= pathDup
.BeginWriting();
1404 while ((subdir
= NS_strtok("/\\", &path
))) {
1405 rv
= aFile
->AppendNative(nsDependentCString(subdir
));
1406 NS_ENSURE_SUCCESS(rv
, rv
);