diff options
Diffstat (limited to 'application/basilisk/components/dirprovider')
3 files changed, 356 insertions, 0 deletions
diff --git a/application/basilisk/components/dirprovider/DirectoryProvider.cpp b/application/basilisk/components/dirprovider/DirectoryProvider.cpp new file mode 100644 index 000000000..8b7c0b9e0 --- /dev/null +++ b/application/basilisk/components/dirprovider/DirectoryProvider.cpp @@ -0,0 +1,286 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIDirectoryService.h" +#include "DirectoryProvider.h" + +#include "nsIFile.h" +#include "nsISimpleEnumerator.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" + +#include "nsArrayEnumerator.h" +#include "nsEnumeratorUtils.h" +#include "nsAppDirectoryServiceDefs.h" +#include "nsDirectoryServiceDefs.h" +#include "nsCategoryManagerUtils.h" +#include "nsComponentManagerUtils.h" +#include "nsCOMArray.h" +#include "nsDirectoryServiceUtils.h" +#include "mozilla/ModuleUtils.h" +#include "nsServiceManagerUtils.h" +#include "nsStringAPI.h" +#include "nsXULAppAPI.h" +#include "nsIPrefLocalizedString.h" + +namespace mozilla { +namespace browser { + +NS_IMPL_ISUPPORTS(DirectoryProvider, + nsIDirectoryServiceProvider, + nsIDirectoryServiceProvider2) + +NS_IMETHODIMP +DirectoryProvider::GetFile(const char *aKey, bool *aPersist, nsIFile* *aResult) +{ + return NS_ERROR_FAILURE; +} + +static void +AppendFileKey(const char *key, nsIProperties* aDirSvc, + nsCOMArray<nsIFile> &array) +{ + nsCOMPtr<nsIFile> file; + nsresult rv = aDirSvc->Get(key, NS_GET_IID(nsIFile), getter_AddRefs(file)); + if (NS_FAILED(rv)) + return; + + bool exists; + rv = file->Exists(&exists); + if (NS_FAILED(rv) || !exists) + return; + + array.AppendObject(file); +} + +// Appends the distribution-specific search engine directories to the +// array. The directory structure is as follows: + +// appdir/ +// \- distribution/ +// \- searchplugins/ +// |- common/ +// \- locale/ +// |- <locale 1>/ +// ... +// \- <locale N>/ + +// common engines are loaded for all locales. If there is no locale +// directory for the current locale, there is a pref: +// "distribution.searchplugins.defaultLocale" +// which specifies a default locale to use. + +static void +AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array) +{ + nsCOMPtr<nsIFile> searchPlugins; + nsresult rv = aDirSvc->Get(XRE_APP_DISTRIBUTION_DIR, + NS_GET_IID(nsIFile), + getter_AddRefs(searchPlugins)); + if (NS_FAILED(rv)) + return; + searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins")); + + bool exists; + rv = searchPlugins->Exists(&exists); + if (NS_FAILED(rv) || !exists) + return; + + nsCOMPtr<nsIFile> commonPlugins; + rv = searchPlugins->Clone(getter_AddRefs(commonPlugins)); + if (NS_SUCCEEDED(rv)) { + commonPlugins->AppendNative(NS_LITERAL_CSTRING("common")); + rv = commonPlugins->Exists(&exists); + if (NS_SUCCEEDED(rv) && exists) + array.AppendObject(commonPlugins); + } + + nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + + nsCOMPtr<nsIFile> localePlugins; + rv = searchPlugins->Clone(getter_AddRefs(localePlugins)); + if (NS_FAILED(rv)) + return; + + localePlugins->AppendNative(NS_LITERAL_CSTRING("locale")); + + nsCString defLocale; + rv = prefs->GetCharPref("distribution.searchplugins.defaultLocale", + getter_Copies(defLocale)); + if (NS_SUCCEEDED(rv)) { + + nsCOMPtr<nsIFile> defLocalePlugins; + rv = localePlugins->Clone(getter_AddRefs(defLocalePlugins)); + if (NS_SUCCEEDED(rv)) { + + defLocalePlugins->AppendNative(defLocale); + rv = defLocalePlugins->Exists(&exists); + if (NS_SUCCEEDED(rv) && exists) { + array.AppendObject(defLocalePlugins); + return; // all done + } + } + } + + // we didn't have a defaultLocale, use the user agent locale + nsCString locale; + nsCOMPtr<nsIPrefLocalizedString> prefString; + rv = prefs->GetComplexValue("general.useragent.locale", + NS_GET_IID(nsIPrefLocalizedString), + getter_AddRefs(prefString)); + if (NS_SUCCEEDED(rv)) { + nsAutoString wLocale; + prefString->GetData(getter_Copies(wLocale)); + CopyUTF16toUTF8(wLocale, locale); + } else { + rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale)); + } + + if (NS_SUCCEEDED(rv)) { + + nsCOMPtr<nsIFile> curLocalePlugins; + rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins)); + if (NS_SUCCEEDED(rv)) { + + curLocalePlugins->AppendNative(locale); + rv = curLocalePlugins->Exists(&exists); + if (NS_SUCCEEDED(rv) && exists) { + array.AppendObject(curLocalePlugins); + return; // all done + } + } + } + } +} + +NS_IMETHODIMP +DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult) +{ + /** + * We want to preserve the following order, since the search service loads + * engines in first-loaded-wins order. + * - distro search plugin locations (Loaded by the search service using + * NS_APP_DISTRIBUTION_SEARCH_DIR_LIST) + * + * - engines shipped in chrome (Loaded from jar files by the search + * service) + * + * Then other locations, from NS_APP_SEARCH_DIR_LIST: + * - extension search plugin locations (prepended below using + * NS_NewUnionEnumerator) + * - user search plugin locations (profile) + */ + + nsresult rv; + + if (!strcmp(aKey, NS_APP_DISTRIBUTION_SEARCH_DIR_LIST)) { + nsCOMPtr<nsIProperties> dirSvc + (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID)); + if (!dirSvc) + return NS_ERROR_FAILURE; + + nsCOMArray<nsIFile> distroFiles; + AppendDistroSearchDirs(dirSvc, distroFiles); + + return NS_NewArrayEnumerator(aResult, distroFiles); + } + + if (!strcmp(aKey, NS_APP_SEARCH_DIR_LIST)) { + nsCOMPtr<nsIProperties> dirSvc + (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID)); + if (!dirSvc) + return NS_ERROR_FAILURE; + + nsCOMArray<nsIFile> baseFiles; + + AppendFileKey(NS_APP_USER_SEARCH_DIR, dirSvc, baseFiles); + + nsCOMPtr<nsISimpleEnumerator> baseEnum; + rv = NS_NewArrayEnumerator(getter_AddRefs(baseEnum), baseFiles); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr<nsISimpleEnumerator> list; + rv = dirSvc->Get(XRE_EXTENSIONS_DIR_LIST, + NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list)); + if (NS_FAILED(rv)) + return rv; + + static char const *const kAppendSPlugins[] = {"searchplugins", nullptr}; + + nsCOMPtr<nsISimpleEnumerator> extEnum = + new AppendingEnumerator(list, kAppendSPlugins); + if (!extEnum) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_NewUnionEnumerator(aResult, extEnum, baseEnum); + } + + return NS_ERROR_FAILURE; +} + +NS_IMPL_ISUPPORTS(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator) + +NS_IMETHODIMP +DirectoryProvider::AppendingEnumerator::HasMoreElements(bool *aResult) +{ + *aResult = mNext ? true : false; + return NS_OK; +} + +NS_IMETHODIMP +DirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult) +{ + if (aResult) + NS_ADDREF(*aResult = mNext); + + mNext = nullptr; + + nsresult rv; + + // Ignore all errors + + bool more; + while (NS_SUCCEEDED(mBase->HasMoreElements(&more)) && more) { + nsCOMPtr<nsISupports> nextbasesupp; + mBase->GetNext(getter_AddRefs(nextbasesupp)); + + nsCOMPtr<nsIFile> nextbase(do_QueryInterface(nextbasesupp)); + if (!nextbase) + continue; + + nextbase->Clone(getter_AddRefs(mNext)); + if (!mNext) + continue; + + char const *const * i = mAppendList; + while (*i) { + mNext->AppendNative(nsDependentCString(*i)); + ++i; + } + + bool exists; + rv = mNext->Exists(&exists); + if (NS_SUCCEEDED(rv) && exists) + break; + + mNext = nullptr; + } + + return NS_OK; +} + +DirectoryProvider::AppendingEnumerator::AppendingEnumerator + (nsISimpleEnumerator* aBase, + char const *const *aAppendList) : + mBase(aBase), + mAppendList(aAppendList) +{ + // Initialize mNext to begin. + GetNext(nullptr); +} + +} // namespace browser +} // namespace mozilla diff --git a/application/basilisk/components/dirprovider/DirectoryProvider.h b/application/basilisk/components/dirprovider/DirectoryProvider.h new file mode 100644 index 000000000..43fa85ab9 --- /dev/null +++ b/application/basilisk/components/dirprovider/DirectoryProvider.h @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DirectoryProvider_h__ +#define DirectoryProvider_h__ + +#include "nsIDirectoryService.h" +#include "nsComponentManagerUtils.h" +#include "nsISimpleEnumerator.h" +#include "nsIFile.h" +#include "mozilla/Attributes.h" + +#define NS_BROWSERDIRECTORYPROVIDER_CONTRACTID \ + "@mozilla.org/browser/directory-provider;1" + +namespace mozilla { +namespace browser { + +class DirectoryProvider final : public nsIDirectoryServiceProvider2 +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDIRECTORYSERVICEPROVIDER + NS_DECL_NSIDIRECTORYSERVICEPROVIDER2 + +private: + ~DirectoryProvider() {} + + class AppendingEnumerator final : public nsISimpleEnumerator + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSISIMPLEENUMERATOR + + AppendingEnumerator(nsISimpleEnumerator* aBase, + char const *const *aAppendList); + + private: + ~AppendingEnumerator() {} + + nsCOMPtr<nsISimpleEnumerator> mBase; + char const *const *const mAppendList; + nsCOMPtr<nsIFile> mNext; + }; +}; + +} // namespace browser +} // namespace mozilla + +#endif // DirectoryProvider_h__ diff --git a/application/basilisk/components/dirprovider/moz.build b/application/basilisk/components/dirprovider/moz.build new file mode 100644 index 000000000..799d4deb3 --- /dev/null +++ b/application/basilisk/components/dirprovider/moz.build @@ -0,0 +1,19 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +EXPORTS.mozilla.browser += [ + 'DirectoryProvider.h', +] + +SOURCES += [ + 'DirectoryProvider.cpp', +] + +FINAL_LIBRARY = 'browsercomps' + +LOCAL_INCLUDES += [ + '../build' +] |