Backed out changeset fa432b23baa5. (Backing out bug 454781 to investigate mochitest...
[wine-gecko.git] / profile / dirserviceprovider / src / nsProfileDirServiceProvider.cpp
blobb05942e640fac78741a375c9ff816b2addadd120
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
13 * License.
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.
22 * Contributor(s):
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"
52 #endif
54 // File Name Defines
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),
74 #endif
75 mNotifyObservers(aNotifyObservers),
76 mSharingEnabled(PR_FALSE)
81 nsProfileDirServiceProvider::~nsProfileDirServiceProvider()
83 #ifdef MOZ_PROFILELOCKING
84 delete mProfileDirLock;
85 #endif
88 nsresult
89 nsProfileDirServiceProvider::SetProfileDir(nsIFile* aProfileDir,
90 nsIFile* aLocalProfileDir)
92 if (!aLocalProfileDir)
93 aLocalProfileDir = aProfileDir;
94 if (mProfileDir) {
95 PRBool isEqual;
96 if (aProfileDir &&
97 NS_SUCCEEDED(aProfileDir->Equals(mProfileDir, &isEqual)) && isEqual) {
98 NS_WARNING("Setting profile dir to same as current");
99 return NS_OK;
101 #ifdef MOZ_PROFILELOCKING
102 mProfileDirLock->Unlock();
103 #endif
104 UndefineFileLocations();
106 mProfileDir = aProfileDir;
107 mLocalProfileDir = aLocalProfileDir;
108 if (!mProfileDir)
109 return NS_OK;
111 nsresult rv = InitProfileDir(mProfileDir);
112 if (NS_FAILED(rv))
113 return rv;
115 // Make sure that the local profile dir exists
116 // we just try to create it - if it exists already, that'll fail; ignore
117 // errors
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);
130 if (NS_FAILED(rv)) {
131 NS_WARNING("Unable to initialize transaction service");
134 #endif
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;
140 if (mSharingEnabled)
141 dirToLock = do_QueryInterface(mNonSharedProfileDir);
142 else
143 dirToLock = do_QueryInterface(mProfileDir);
144 rv = mProfileDirLock->Lock(dirToLock, nsnull);
145 if (NS_FAILED(rv))
146 return rv;
147 #endif
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());
162 return NS_OK;
165 nsresult
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);
175 nsresult
176 nsProfileDirServiceProvider::Shutdown()
178 if (!mNotifyObservers)
179 return NS_OK;
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());
188 return NS_OK;
191 //*****************************************************************************
192 // nsProfileDirServiceProvider::nsISupports
193 //*****************************************************************************
195 NS_IMPL_ISUPPORTS1(nsProfileDirServiceProvider,
196 nsIDirectoryServiceProvider)
198 //*****************************************************************************
199 // nsProfileDirServiceProvider::nsIDirectoryServiceProvider
200 //*****************************************************************************
202 NS_IMETHODIMP
203 nsProfileDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
205 NS_ENSURE_ARG(prop);
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.
210 if (!mProfileDir)
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;
226 #endif
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
256 // by client code.
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);
310 return rv;
313 //*****************************************************************************
314 // Protected methods
315 //*****************************************************************************
317 nsresult
318 nsProfileDirServiceProvider::Initialize()
320 #ifdef MOZ_PROFILELOCKING
321 mProfileDirLock = new nsProfileLock;
322 if (!mProfileDirLock)
323 return NS_ERROR_OUT_OF_MEMORY;
324 #endif
326 #ifdef MOZ_PROFILESHARING
327 nsCOMPtr<nsIProfileSharingSetup> sharingSetup =
328 do_GetService("@mozilla.org/embedcomp/profile-sharing-setup;1");
329 if (sharingSetup) {
330 PRBool tempBool;
331 if (NS_SUCCEEDED(sharingSetup->GetIsSharingEnabled(&tempBool)))
332 mSharingEnabled = tempBool;
333 if (mSharingEnabled)
334 sharingSetup->GetClientName(mNonSharedDirName);
336 #endif
338 return NS_OK;
341 nsresult
342 nsProfileDirServiceProvider::InitProfileDir(nsIFile *profileDir)
344 // Make sure our "Profile" folder exists.
345 // If it does not, copy the profile defaults to its location.
347 nsresult rv;
348 PRBool exists;
349 rv = profileDir->Exists(&exists);
350 if (NS_FAILED(rv))
351 return rv;
353 if (!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);
362 if (NS_FAILED(rv))
363 return rv;
365 rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_50_DIR, getter_AddRefs(profileDefaultsDir));
366 if (NS_FAILED(rv)) {
367 rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR, getter_AddRefs(profileDefaultsDir));
368 if (NS_FAILED(rv))
369 return rv;
371 rv = profileDefaultsDir->CopyToNative(profileDirParent, profileDirName);
372 if (NS_FAILED(rv)) {
373 // if copying failed, lets just ensure that the profile directory exists.
374 profileDirParent->AppendNative(profileDirName);
375 rv = profileDirParent->Create(nsIFile::DIRECTORY_TYPE, 0700);
376 if (NS_FAILED(rv))
377 return rv;
380 #if !defined(WINCE)
381 rv = profileDir->SetPermissions(0700);
382 if (NS_FAILED(rv))
383 return rv;
384 #endif
387 else {
388 PRBool isDir;
389 rv = profileDir->IsDirectory(&isDir);
391 if (NS_FAILED(rv))
392 return rv;
393 if (!isDir)
394 return NS_ERROR_FILE_NOT_DIRECTORY;
397 if (mNonSharedDirName.Length())
398 rv = InitNonSharedProfileDir();
400 return rv;
403 nsresult
404 nsProfileDirServiceProvider::InitNonSharedProfileDir()
406 nsresult rv;
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)) {
416 PRBool exists;
417 rv = localDir->Exists(&exists);
418 if (NS_SUCCEEDED(rv)) {
419 if (!exists) {
420 rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
422 else {
423 PRBool isDir;
424 rv = localDir->IsDirectory(&isDir);
425 if (NS_SUCCEEDED(rv)) {
426 if (!isDir)
427 rv = NS_ERROR_FILE_NOT_DIRECTORY;
430 if (NS_SUCCEEDED(rv))
431 mNonSharedProfileDir = localDir;
435 return rv;
438 nsresult
439 nsProfileDirServiceProvider::EnsureProfileFileExists(nsIFile *aFile, nsIFile *destDir)
441 nsresult rv;
442 PRBool exists;
444 rv = aFile->Exists(&exists);
445 if (NS_FAILED(rv))
446 return rv;
447 if (exists)
448 return NS_OK;
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));
454 if (NS_FAILED(rv)) {
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));
457 if (NS_FAILED(rv))
458 return rv;
461 nsCAutoString leafName;
462 rv = aFile->GetNativeLeafName(leafName);
463 if (NS_FAILED(rv))
464 return rv;
465 rv = defaultsFile->AppendNative(leafName);
466 if (NS_FAILED(rv))
467 return rv;
469 return defaultsFile->CopyTo(destDir, EmptyString());
472 nsresult
473 nsProfileDirServiceProvider::UndefineFileLocations()
475 nsresult rv;
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);
493 return NS_OK;
496 //*****************************************************************************
497 // Global creation function
498 //*****************************************************************************
500 nsresult NS_NewProfileDirServiceProvider(PRBool aNotifyObservers,
501 nsProfileDirServiceProvider** aProvider)
503 NS_ENSURE_ARG_POINTER(aProvider);
504 *aProvider = nsnull;
506 nsProfileDirServiceProvider *prov = new nsProfileDirServiceProvider(aNotifyObservers);
507 if (!prov)
508 return NS_ERROR_OUT_OF_MEMORY;
509 nsresult rv = prov->Initialize();
510 if (NS_FAILED(rv)) {
511 delete prov;
512 return rv;
514 NS_ADDREF(*aProvider = prov);
515 return NS_OK;