Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / browser / components / dirprovider / nsBrowserDirectoryProvider.cpp
blob5f58c918afd26fc6db16ff149d3af1fdcefd1349
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Mozilla Firefox browser.
16 * The Initial Developer of the Original Code is
17 * Benjamin Smedberg <benjamin@smedbergs.us>
19 * Portions created by the Initial Developer are Copyright (C) 2005
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsIDirectoryService.h"
40 #include "nsIFile.h"
41 #include "nsISimpleEnumerator.h"
42 #include "nsIPrefService.h"
43 #include "nsIPrefBranch.h"
45 #include "nsArrayEnumerator.h"
46 #include "nsEnumeratorUtils.h"
47 #include "nsBrowserDirectoryServiceDefs.h"
48 #include "nsAppDirectoryServiceDefs.h"
49 #include "nsDirectoryServiceDefs.h"
50 #include "nsCategoryManagerUtils.h"
51 #include "nsComponentManagerUtils.h"
52 #include "nsCOMArray.h"
53 #include "nsDirectoryServiceUtils.h"
54 #include "nsIGenericFactory.h"
55 #include "nsServiceManagerUtils.h"
56 #include "nsStringAPI.h"
57 #include "nsXULAppAPI.h"
59 class nsBrowserDirectoryProvider :
60 public nsIDirectoryServiceProvider2
62 public:
63 NS_DECL_ISUPPORTS
64 NS_DECL_NSIDIRECTORYSERVICEPROVIDER
65 NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
67 static NS_METHOD Register(nsIComponentManager* aCompMgr,
68 nsIFile* aPath, const char *aLoaderStr,
69 const char *aType,
70 const nsModuleComponentInfo *aInfo);
72 static NS_METHOD Unregister(nsIComponentManager* aCompMgr,
73 nsIFile* aPath, const char *aLoaderStr,
74 const nsModuleComponentInfo *aInfo);
76 private:
77 nsresult RestoreBookmarksFromBackup(const nsACString& aLeafName,
78 nsIFile* aParentDir, nsIFile* aTarget);
79 void EnsureProfileFile(const nsACString& aLeafName,
80 nsIFile* aParentDir, nsIFile* aTarget);
82 class AppendingEnumerator : public nsISimpleEnumerator
84 public:
85 NS_DECL_ISUPPORTS
86 NS_DECL_NSISIMPLEENUMERATOR
88 AppendingEnumerator(nsISimpleEnumerator* aBase,
89 char const *const *aAppendList);
91 private:
92 nsCOMPtr<nsISimpleEnumerator> mBase;
93 char const *const *const mAppendList;
94 nsCOMPtr<nsIFile> mNext;
98 NS_IMPL_ISUPPORTS2(nsBrowserDirectoryProvider,
99 nsIDirectoryServiceProvider,
100 nsIDirectoryServiceProvider2)
102 NS_IMETHODIMP
103 nsBrowserDirectoryProvider::GetFile(const char *aKey, PRBool *aPersist,
104 nsIFile* *aResult)
106 nsresult rv;
108 *aResult = nsnull;
110 // NOTE: This function can be reentrant through the NS_GetSpecialDirectory
111 // call, so be careful not to cause infinite recursion.
113 nsCOMPtr<nsIFile> file;
115 char const* leafName = nsnull;
117 if (!strcmp(aKey, NS_APP_BOOKMARKS_50_FILE)) {
118 leafName = "bookmarks.html";
120 nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
121 if (prefs) {
122 nsCString path;
123 rv = prefs->GetCharPref("browser.bookmarks.file", getter_Copies(path));
124 if (NS_SUCCEEDED(rv)) {
125 NS_NewNativeLocalFile(path, PR_TRUE, (nsILocalFile**)(nsIFile**) getter_AddRefs(file));
129 else if (!strcmp(aKey, NS_APP_EXISTING_PREF_OVERRIDE)) {
130 rv = NS_GetSpecialDirectory(NS_APP_DEFAULTS_50_DIR,
131 getter_AddRefs(file));
132 NS_ENSURE_SUCCESS(rv, rv);
134 file->AppendNative(NS_LITERAL_CSTRING("existing-profile-defaults.js"));
135 file.swap(*aResult);
136 return NS_OK;
138 else if (!strcmp(aKey, NS_APP_MICROSUMMARY_DIR)) {
139 rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
140 getter_AddRefs(file));
141 NS_ENSURE_SUCCESS(rv, rv);
143 file->AppendNative(NS_LITERAL_CSTRING("microsummary-generators"));
144 file.swap(*aResult);
145 return NS_OK;
147 else if (!strcmp(aKey, NS_APP_USER_MICROSUMMARY_DIR)) {
148 rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
149 getter_AddRefs(file));
150 NS_ENSURE_SUCCESS(rv, rv);
152 file->AppendNative(NS_LITERAL_CSTRING("microsummary-generators"));
153 file.swap(*aResult);
154 return NS_OK;
156 else {
157 return NS_ERROR_FAILURE;
160 nsDependentCString leafstr(leafName);
162 nsCOMPtr<nsIFile> parentDir;
163 if (file) {
164 rv = file->GetParent(getter_AddRefs(parentDir));
165 if (NS_FAILED(rv))
166 return rv;
168 else {
169 rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(parentDir));
170 if (NS_FAILED(rv))
171 return rv;
173 rv = parentDir->Clone(getter_AddRefs(file));
174 if (NS_FAILED(rv))
175 return rv;
177 file->AppendNative(leafstr);
180 *aPersist = PR_TRUE;
181 NS_ADDREF(*aResult = file);
183 return NS_OK;
186 static void
187 AppendFileKey(const char *key, nsIProperties* aDirSvc,
188 nsCOMArray<nsIFile> &array)
190 nsCOMPtr<nsIFile> file;
191 nsresult rv = aDirSvc->Get(key, NS_GET_IID(nsIFile), getter_AddRefs(file));
192 if (NS_FAILED(rv))
193 return;
195 PRBool exists;
196 rv = file->Exists(&exists);
197 if (NS_FAILED(rv) || !exists)
198 return;
200 array.AppendObject(file);
203 // Appends the distribution-specific search engine directories to the
204 // array. The directory structure is as follows:
206 // appdir/
207 // \- distribution/
208 // \- searchplugins/
209 // |- common/
210 // \- locale/
211 // |- <locale 1>/
212 // ...
213 // \- <locale N>/
215 // common engines are loaded for all locales. If there is no locale
216 // directory for the current locale, there is a pref:
217 // "distribution.searchplugins.defaultLocale"
218 // which specifies a default locale to use.
220 static void
221 AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
223 nsCOMPtr<nsIFile> searchPlugins;
224 nsresult rv = aDirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
225 NS_GET_IID(nsIFile),
226 getter_AddRefs(searchPlugins));
227 if (NS_FAILED(rv))
228 return;
229 searchPlugins->AppendNative(NS_LITERAL_CSTRING("distribution"));
230 searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins"));
232 PRBool exists;
233 rv = searchPlugins->Exists(&exists);
234 if (NS_FAILED(rv) || !exists)
235 return;
237 nsCOMPtr<nsIFile> commonPlugins;
238 rv = searchPlugins->Clone(getter_AddRefs(commonPlugins));
239 if (NS_SUCCEEDED(rv)) {
240 commonPlugins->AppendNative(NS_LITERAL_CSTRING("common"));
241 rv = commonPlugins->Exists(&exists);
242 if (NS_SUCCEEDED(rv) && exists)
243 array.AppendObject(commonPlugins);
246 nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
247 if (prefs) {
249 nsCOMPtr<nsIFile> localePlugins;
250 rv = searchPlugins->Clone(getter_AddRefs(localePlugins));
251 if (NS_FAILED(rv))
252 return;
254 localePlugins->AppendNative(NS_LITERAL_CSTRING("locale"));
256 nsCString locale;
257 rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale));
258 if (NS_SUCCEEDED(rv)) {
260 nsCOMPtr<nsIFile> curLocalePlugins;
261 rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins));
262 if (NS_SUCCEEDED(rv)) {
264 curLocalePlugins->AppendNative(locale);
265 rv = curLocalePlugins->Exists(&exists);
266 if (NS_SUCCEEDED(rv) && exists) {
267 array.AppendObject(curLocalePlugins);
268 return; // all done
273 // we didn't append the locale dir - try the default one
274 nsCString defLocale;
275 rv = prefs->GetCharPref("distribution.searchplugins.defaultLocale",
276 getter_Copies(defLocale));
277 if (NS_SUCCEEDED(rv)) {
279 nsCOMPtr<nsIFile> defLocalePlugins;
280 rv = localePlugins->Clone(getter_AddRefs(defLocalePlugins));
281 if (NS_SUCCEEDED(rv)) {
283 defLocalePlugins->AppendNative(defLocale);
284 rv = defLocalePlugins->Exists(&exists);
285 if (NS_SUCCEEDED(rv) && exists)
286 array.AppendObject(defLocalePlugins);
292 NS_IMETHODIMP
293 nsBrowserDirectoryProvider::GetFiles(const char *aKey,
294 nsISimpleEnumerator* *aResult)
296 nsresult rv;
298 if (!strcmp(aKey, NS_APP_SEARCH_DIR_LIST)) {
299 nsCOMPtr<nsIProperties> dirSvc
300 (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
301 if (!dirSvc)
302 return NS_ERROR_FAILURE;
304 nsCOMArray<nsIFile> baseFiles;
306 AppendDistroSearchDirs(dirSvc, baseFiles);
307 AppendFileKey(NS_APP_SEARCH_DIR, dirSvc, baseFiles);
308 AppendFileKey(NS_APP_USER_SEARCH_DIR, dirSvc, baseFiles);
310 nsCOMPtr<nsISimpleEnumerator> baseEnum;
311 rv = NS_NewArrayEnumerator(getter_AddRefs(baseEnum), baseFiles);
312 if (NS_FAILED(rv))
313 return rv;
315 nsCOMPtr<nsISimpleEnumerator> list;
316 rv = dirSvc->Get(XRE_EXTENSIONS_DIR_LIST,
317 NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list));
318 if (NS_FAILED(rv))
319 return rv;
321 static char const *const kAppendSPlugins[] = {"searchplugins", nsnull};
323 nsCOMPtr<nsISimpleEnumerator> extEnum =
324 new AppendingEnumerator(list, kAppendSPlugins);
325 if (!extEnum)
326 return NS_ERROR_OUT_OF_MEMORY;
328 return NS_NewUnionEnumerator(aResult, extEnum, baseEnum);
331 return NS_ERROR_FAILURE;
334 static char const kContractID[] = "@mozilla.org/browser/directory-provider;1";
336 // {6DEB193C-F87D-4078-BC78-5E64655B4D62}
337 #define NS_BROWSERDIRECTORYPROVIDER_CID \
338 { 0x6deb193c, 0xf87d, 0x4078, { 0xbc, 0x78, 0x5e, 0x64, 0x65, 0x5b, 0x4d, 0x62 } }
340 NS_METHOD
341 nsBrowserDirectoryProvider::Register(nsIComponentManager* aCompMgr,
342 nsIFile* aPath, const char *aLoaderStr,
343 const char *aType,
344 const nsModuleComponentInfo *aInfo)
346 nsresult rv;
348 nsCOMPtr<nsICategoryManager> catMan
349 (do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
350 if (!catMan)
351 return NS_ERROR_FAILURE;
353 rv = catMan->AddCategoryEntry(XPCOM_DIRECTORY_PROVIDER_CATEGORY,
354 "browser-directory-provider",
355 kContractID, PR_TRUE, PR_TRUE, nsnull);
356 return rv;
360 NS_METHOD
361 nsBrowserDirectoryProvider::Unregister(nsIComponentManager* aCompMgr,
362 nsIFile* aPath, const char *aLoaderStr,
363 const nsModuleComponentInfo *aInfo)
365 nsresult rv;
367 nsCOMPtr<nsICategoryManager> catMan
368 (do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
369 if (!catMan)
370 return NS_ERROR_FAILURE;
372 rv = catMan->DeleteCategoryEntry(XPCOM_DIRECTORY_PROVIDER_CATEGORY,
373 "browser-directory-provider", PR_TRUE);
374 return rv;
377 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserDirectoryProvider)
379 static const nsModuleComponentInfo components[] = {
381 "nsBrowserDirectoryProvider",
382 NS_BROWSERDIRECTORYPROVIDER_CID,
383 kContractID,
384 nsBrowserDirectoryProviderConstructor,
385 nsBrowserDirectoryProvider::Register,
386 nsBrowserDirectoryProvider::Unregister
390 NS_IMPL_NSGETMODULE(BrowserDirProvider, components)
391 NS_IMPL_ISUPPORTS1(nsBrowserDirectoryProvider::AppendingEnumerator,
392 nsISimpleEnumerator)
394 NS_IMETHODIMP
395 nsBrowserDirectoryProvider::AppendingEnumerator::HasMoreElements(PRBool *aResult)
397 *aResult = mNext ? PR_TRUE : PR_FALSE;
398 return NS_OK;
401 NS_IMETHODIMP
402 nsBrowserDirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult)
404 if (aResult)
405 NS_ADDREF(*aResult = mNext);
407 mNext = nsnull;
409 nsresult rv;
411 // Ignore all errors
413 PRBool more;
414 while (NS_SUCCEEDED(mBase->HasMoreElements(&more)) && more) {
415 nsCOMPtr<nsISupports> nextbasesupp;
416 mBase->GetNext(getter_AddRefs(nextbasesupp));
418 nsCOMPtr<nsIFile> nextbase(do_QueryInterface(nextbasesupp));
419 if (!nextbase)
420 continue;
422 nextbase->Clone(getter_AddRefs(mNext));
423 if (!mNext)
424 continue;
426 char const *const * i = mAppendList;
427 while (*i) {
428 mNext->AppendNative(nsDependentCString(*i));
429 ++i;
432 PRBool exists;
433 rv = mNext->Exists(&exists);
434 if (NS_SUCCEEDED(rv) && exists)
435 break;
437 mNext = nsnull;
440 return NS_OK;
443 nsBrowserDirectoryProvider::AppendingEnumerator::AppendingEnumerator
444 (nsISimpleEnumerator* aBase,
445 char const *const *aAppendList) :
446 mBase(aBase),
447 mAppendList(aAppendList)
449 // Initialize mNext to begin.
450 GetNext(nsnull);