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 * Conrad Carlen <ccarlen@netscape.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsProfileDirServiceProvider.h"
40 #include "nsProfileStringTypes.h"
41 #include "nsProfileLock.h"
42 #include "nsILocalFile.h"
43 #include "nsDirectoryServiceDefs.h"
44 #include "nsAppDirectoryServiceDefs.h"
45 #include "nsISupportsUtils.h"
46 #include "nsISimpleEnumerator.h"
47 #include "nsIObserverService.h"
49 #ifdef MOZ_PROFILESHARING
50 #include "nsIProfileSharingSetup.h"
51 #include "ipcITransactionService.h"
56 #define PREFS_FILE_50_NAME NS_LITERAL_CSTRING("prefs.js")
57 #define USER_CHROME_DIR_50_NAME NS_LITERAL_CSTRING("chrome")
58 #define LOCAL_STORE_FILE_50_NAME NS_LITERAL_CSTRING("localstore.rdf")
59 #define HISTORY_FILE_50_NAME NS_LITERAL_CSTRING("history.dat")
60 #define PANELS_FILE_50_NAME NS_LITERAL_CSTRING("panels.rdf")
61 #define MIME_TYPES_FILE_50_NAME NS_LITERAL_CSTRING("mimeTypes.rdf")
62 #define BOOKMARKS_FILE_50_NAME NS_LITERAL_CSTRING("bookmarks.html")
63 #define DOWNLOADS_FILE_50_NAME NS_LITERAL_CSTRING("downloads.rdf")
64 #define SEARCH_FILE_50_NAME NS_LITERAL_CSTRING("search.rdf" )
65 #define STORAGE_FILE_50_NAME NS_LITERAL_CSTRING("storage.sdb")
67 //*****************************************************************************
68 // nsProfileDirServiceProvider::nsProfileDirServiceProvider
69 //*****************************************************************************
71 nsProfileDirServiceProvider::nsProfileDirServiceProvider(PRBool aNotifyObservers
) :
72 #ifdef MOZ_PROFILELOCKING
73 mProfileDirLock(nsnull
),
75 mNotifyObservers(aNotifyObservers
),
76 mSharingEnabled(PR_FALSE
)
81 nsProfileDirServiceProvider::~nsProfileDirServiceProvider()
83 #ifdef MOZ_PROFILELOCKING
84 delete mProfileDirLock
;
89 nsProfileDirServiceProvider::SetProfileDir(nsIFile
* aProfileDir
,
90 nsIFile
* aLocalProfileDir
)
92 if (!aLocalProfileDir
)
93 aLocalProfileDir
= aProfileDir
;
97 NS_SUCCEEDED(aProfileDir
->Equals(mProfileDir
, &isEqual
)) && isEqual
) {
98 NS_WARNING("Setting profile dir to same as current");
101 #ifdef MOZ_PROFILELOCKING
102 mProfileDirLock
->Unlock();
104 UndefineFileLocations();
106 mProfileDir
= aProfileDir
;
107 mLocalProfileDir
= aLocalProfileDir
;
111 nsresult rv
= InitProfileDir(mProfileDir
);
115 // Make sure that the local profile dir exists
116 // we just try to create it - if it exists already, that'll fail; ignore
118 mLocalProfileDir
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
120 #ifdef MOZ_PROFILESHARING
121 if (mSharingEnabled
) {
122 nsCOMPtr
<ipcITransactionService
> transServ
=
123 do_GetService(IPC_TRANSACTIONSERVICE_CONTRACTID
, &rv
);
124 if (NS_SUCCEEDED(rv
)) {
125 nsCAutoString nativePath
;
126 rv
= mProfileDir
->GetNativePath(nativePath
);
127 if (NS_SUCCEEDED(rv
))
128 rv
= transServ
->Init(nativePath
);
131 NS_WARNING("Unable to initialize transaction service");
136 #ifdef MOZ_PROFILELOCKING
137 // Lock the non-shared sub-dir if we are sharing,
138 // the whole profile dir if we are not.
139 nsCOMPtr
<nsILocalFile
> dirToLock
;
141 dirToLock
= do_QueryInterface(mNonSharedProfileDir
);
143 dirToLock
= do_QueryInterface(mProfileDir
);
144 rv
= mProfileDirLock
->Lock(dirToLock
, nsnull
);
149 if (mNotifyObservers
) {
150 nsCOMPtr
<nsIObserverService
> observerService
=
151 do_GetService("@mozilla.org/observer-service;1");
152 if (!observerService
)
153 return NS_ERROR_FAILURE
;
155 NS_NAMED_LITERAL_STRING(context
, "startup");
156 // Notify observers that the profile has changed - Here they respond to new profile
157 observerService
->NotifyObservers(nsnull
, "profile-do-change", context
.get());
158 // Now observers can respond to something another observer did on "profile-do-change"
159 observerService
->NotifyObservers(nsnull
, "profile-after-change", context
.get());
166 nsProfileDirServiceProvider::Register()
168 nsCOMPtr
<nsIDirectoryService
> directoryService
=
169 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
);
170 if (!directoryService
)
171 return NS_ERROR_FAILURE
;
172 return directoryService
->RegisterProvider(this);
176 nsProfileDirServiceProvider::Shutdown()
178 if (!mNotifyObservers
)
181 nsCOMPtr
<nsIObserverService
> observerService
=
182 do_GetService("@mozilla.org/observer-service;1");
183 if (!observerService
)
184 return NS_ERROR_FAILURE
;
186 NS_NAMED_LITERAL_STRING(context
, "shutdown-persist");
187 observerService
->NotifyObservers(nsnull
, "profile-before-change", context
.get());
191 //*****************************************************************************
192 // nsProfileDirServiceProvider::nsISupports
193 //*****************************************************************************
195 NS_IMPL_ISUPPORTS1(nsProfileDirServiceProvider
,
196 nsIDirectoryServiceProvider
)
198 //*****************************************************************************
199 // nsProfileDirServiceProvider::nsIDirectoryServiceProvider
200 //*****************************************************************************
203 nsProfileDirServiceProvider::GetFile(const char *prop
, PRBool
*persistant
, nsIFile
**_retval
)
206 NS_ENSURE_ARG_POINTER(persistant
);
207 NS_ENSURE_ARG_POINTER(_retval
);
209 // Don't assert - we can be called many times before SetProfileDir() has been called.
211 return NS_ERROR_FAILURE
;
213 *persistant
= PR_TRUE
;
214 nsIFile
* domainDir
= mProfileDir
;
216 #ifdef MOZ_PROFILESHARING
217 // If the prop is prefixed with NS_SHARED,
218 // the location is in the shared domain.
219 PRBool bUseShared
= PR_FALSE
;
220 if (strncmp(prop
, NS_SHARED
, sizeof(NS_SHARED
)-1) == 0) {
221 prop
+= (sizeof(NS_SHARED
)-1);
222 bUseShared
= PR_TRUE
;
224 if (!bUseShared
&& mNonSharedProfileDir
)
225 domainDir
= mNonSharedProfileDir
;
228 nsCOMPtr
<nsIFile
> localFile
;
229 nsresult rv
= NS_ERROR_FAILURE
;
231 if (strcmp(prop
, NS_APP_PREFS_50_DIR
) == 0) {
232 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
234 else if (strcmp(prop
, NS_APP_PREFS_50_FILE
) == 0) {
235 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
236 if (NS_SUCCEEDED(rv
))
237 rv
= localFile
->AppendNative(PREFS_FILE_50_NAME
);
239 else if (strcmp(prop
, NS_APP_USER_PROFILE_50_DIR
) == 0) {
240 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
242 else if (strcmp(prop
, NS_APP_USER_PROFILE_LOCAL_50_DIR
) == 0) {
243 rv
= mLocalProfileDir
->Clone(getter_AddRefs(localFile
));
245 else if (strcmp(prop
, NS_APP_USER_CHROME_DIR
) == 0) {
246 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
247 if (NS_SUCCEEDED(rv
))
248 rv
= localFile
->AppendNative(USER_CHROME_DIR_50_NAME
);
250 else if (strcmp(prop
, NS_APP_LOCALSTORE_50_FILE
) == 0) {
251 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
252 if (NS_SUCCEEDED(rv
)) {
253 rv
= localFile
->AppendNative(LOCAL_STORE_FILE_50_NAME
);
254 if (NS_SUCCEEDED(rv
)) {
255 // it's OK if we can't copy the file... it will be created
257 (void) EnsureProfileFileExists(localFile
, domainDir
);
261 else if (strcmp(prop
, NS_APP_HISTORY_50_FILE
) == 0) {
262 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
263 if (NS_SUCCEEDED(rv
))
264 rv
= localFile
->AppendNative(HISTORY_FILE_50_NAME
);
266 else if (strcmp(prop
, NS_APP_USER_PANELS_50_FILE
) == 0) {
267 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
268 if (NS_SUCCEEDED(rv
)) {
269 rv
= localFile
->AppendNative(PANELS_FILE_50_NAME
);
270 if (NS_SUCCEEDED(rv
))
271 rv
= EnsureProfileFileExists(localFile
, domainDir
);
274 else if (strcmp(prop
, NS_APP_USER_MIMETYPES_50_FILE
) == 0) {
275 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
276 if (NS_SUCCEEDED(rv
)) {
277 rv
= localFile
->AppendNative(MIME_TYPES_FILE_50_NAME
);
278 if (NS_SUCCEEDED(rv
))
279 rv
= EnsureProfileFileExists(localFile
, domainDir
);
282 else if (strcmp(prop
, NS_APP_BOOKMARKS_50_FILE
) == 0) {
283 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
284 if (NS_SUCCEEDED(rv
))
285 rv
= localFile
->AppendNative(BOOKMARKS_FILE_50_NAME
);
287 else if (strcmp(prop
, NS_APP_DOWNLOADS_50_FILE
) == 0) {
288 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
289 if (NS_SUCCEEDED(rv
))
290 rv
= localFile
->AppendNative(DOWNLOADS_FILE_50_NAME
);
292 else if (strcmp(prop
, NS_APP_SEARCH_50_FILE
) == 0) {
293 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
294 if (NS_SUCCEEDED(rv
)) {
295 rv
= localFile
->AppendNative(SEARCH_FILE_50_NAME
);
296 if (NS_SUCCEEDED(rv
))
297 rv
= EnsureProfileFileExists(localFile
, domainDir
);
300 else if (strcmp(prop
, NS_APP_STORAGE_50_FILE
) == 0) {
301 rv
= domainDir
->Clone(getter_AddRefs(localFile
));
302 if (NS_SUCCEEDED(rv
))
303 rv
= localFile
->AppendNative(STORAGE_FILE_50_NAME
);
307 if (localFile
&& NS_SUCCEEDED(rv
))
308 return CallQueryInterface(localFile
, _retval
);
313 //*****************************************************************************
315 //*****************************************************************************
318 nsProfileDirServiceProvider::Initialize()
320 #ifdef MOZ_PROFILELOCKING
321 mProfileDirLock
= new nsProfileLock
;
322 if (!mProfileDirLock
)
323 return NS_ERROR_OUT_OF_MEMORY
;
326 #ifdef MOZ_PROFILESHARING
327 nsCOMPtr
<nsIProfileSharingSetup
> sharingSetup
=
328 do_GetService("@mozilla.org/embedcomp/profile-sharing-setup;1");
331 if (NS_SUCCEEDED(sharingSetup
->GetIsSharingEnabled(&tempBool
)))
332 mSharingEnabled
= tempBool
;
334 sharingSetup
->GetClientName(mNonSharedDirName
);
342 nsProfileDirServiceProvider::InitProfileDir(nsIFile
*profileDir
)
344 // Make sure our "Profile" folder exists.
345 // If it does not, copy the profile defaults to its location.
349 rv
= profileDir
->Exists(&exists
);
354 nsCOMPtr
<nsIFile
> profileDefaultsDir
;
355 nsCOMPtr
<nsIFile
> profileDirParent
;
356 nsCAutoString profileDirName
;
358 (void)profileDir
->GetParent(getter_AddRefs(profileDirParent
));
359 if (!profileDirParent
)
360 return NS_ERROR_FAILURE
;
361 rv
= profileDir
->GetNativeLeafName(profileDirName
);
365 rv
= NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR
, getter_AddRefs(profileDefaultsDir
));
367 rv
= NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR
, getter_AddRefs(profileDefaultsDir
));
371 rv
= profileDefaultsDir
->CopyToNative(profileDirParent
, profileDirName
);
373 // if copying failed, lets just ensure that the profile directory exists.
374 profileDirParent
->AppendNative(profileDirName
);
375 rv
= profileDirParent
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
381 rv
= profileDir
->SetPermissions(0700);
389 rv
= profileDir
->IsDirectory(&isDir
);
394 return NS_ERROR_FILE_NOT_DIRECTORY
;
397 if (mNonSharedDirName
.Length())
398 rv
= InitNonSharedProfileDir();
404 nsProfileDirServiceProvider::InitNonSharedProfileDir()
408 NS_ENSURE_STATE(mProfileDir
);
409 NS_ENSURE_STATE(mNonSharedDirName
.Length());
411 nsCOMPtr
<nsIFile
> localDir
;
412 rv
= mProfileDir
->Clone(getter_AddRefs(localDir
));
413 if (NS_SUCCEEDED(rv
)) {
414 rv
= localDir
->Append(mNonSharedDirName
);
415 if (NS_SUCCEEDED(rv
)) {
417 rv
= localDir
->Exists(&exists
);
418 if (NS_SUCCEEDED(rv
)) {
420 rv
= localDir
->Create(nsIFile::DIRECTORY_TYPE
, 0700);
424 rv
= localDir
->IsDirectory(&isDir
);
425 if (NS_SUCCEEDED(rv
)) {
427 rv
= NS_ERROR_FILE_NOT_DIRECTORY
;
430 if (NS_SUCCEEDED(rv
))
431 mNonSharedProfileDir
= localDir
;
439 nsProfileDirServiceProvider::EnsureProfileFileExists(nsIFile
*aFile
, nsIFile
*destDir
)
444 rv
= aFile
->Exists(&exists
);
450 nsCOMPtr
<nsIFile
> defaultsFile
;
452 // Attempt first to get the localized subdir of the defaults
453 rv
= NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR
, getter_AddRefs(defaultsFile
));
455 // If that has not been defined, use the top level of the defaults
456 rv
= NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR
, getter_AddRefs(defaultsFile
));
461 nsCAutoString leafName
;
462 rv
= aFile
->GetNativeLeafName(leafName
);
465 rv
= defaultsFile
->AppendNative(leafName
);
469 return defaultsFile
->CopyTo(destDir
, EmptyString());
473 nsProfileDirServiceProvider::UndefineFileLocations()
477 nsCOMPtr
<nsIProperties
> directoryService
=
478 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
);
479 NS_ENSURE_TRUE(directoryService
, NS_ERROR_FAILURE
);
481 (void) directoryService
->Undefine(NS_APP_PREFS_50_DIR
);
482 (void) directoryService
->Undefine(NS_APP_PREFS_50_FILE
);
483 (void) directoryService
->Undefine(NS_APP_USER_PROFILE_50_DIR
);
484 (void) directoryService
->Undefine(NS_APP_USER_CHROME_DIR
);
485 (void) directoryService
->Undefine(NS_APP_LOCALSTORE_50_FILE
);
486 (void) directoryService
->Undefine(NS_APP_HISTORY_50_FILE
);
487 (void) directoryService
->Undefine(NS_APP_USER_PANELS_50_FILE
);
488 (void) directoryService
->Undefine(NS_APP_USER_MIMETYPES_50_FILE
);
489 (void) directoryService
->Undefine(NS_APP_BOOKMARKS_50_FILE
);
490 (void) directoryService
->Undefine(NS_APP_DOWNLOADS_50_FILE
);
491 (void) directoryService
->Undefine(NS_APP_SEARCH_50_FILE
);
496 //*****************************************************************************
497 // Global creation function
498 //*****************************************************************************
500 nsresult
NS_NewProfileDirServiceProvider(PRBool aNotifyObservers
,
501 nsProfileDirServiceProvider
** aProvider
)
503 NS_ENSURE_ARG_POINTER(aProvider
);
506 nsProfileDirServiceProvider
*prov
= new nsProfileDirServiceProvider(aNotifyObservers
);
508 return NS_ERROR_OUT_OF_MEMORY
;
509 nsresult rv
= prov
->Initialize();
514 NS_ADDREF(*aProvider
= prov
);