From 4492b5f8e774bf3b4f21e4e468fc052cbcbb468a Mon Sep 17 00:00:00 2001 From: Thomas Groman Date: Mon, 16 Dec 2019 19:48:42 -0800 Subject: initial commit --- components/dirprovider/DirectoryProvider.cpp | 268 +++++++++++++++++++++++++++ components/dirprovider/DirectoryProvider.h | 51 +++++ components/dirprovider/moz.build | 13 ++ 3 files changed, 332 insertions(+) create mode 100644 components/dirprovider/DirectoryProvider.cpp create mode 100644 components/dirprovider/DirectoryProvider.h create mode 100644 components/dirprovider/moz.build (limited to 'components/dirprovider') diff --git a/components/dirprovider/DirectoryProvider.cpp b/components/dirprovider/DirectoryProvider.cpp new file mode 100644 index 0000000..85728b3 --- /dev/null +++ b/components/dirprovider/DirectoryProvider.cpp @@ -0,0 +1,268 @@ +/* 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 &array) +{ + nsCOMPtr 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/ +// |- / +// ... +// \- / + +// 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 &array) +{ + nsCOMPtr 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 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 prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); + if (prefs) { + + nsCOMPtr localePlugins; + rv = searchPlugins->Clone(getter_AddRefs(localePlugins)); + if (NS_FAILED(rv)) + return; + + localePlugins->AppendNative(NS_LITERAL_CSTRING("locale")); + + nsCString locale; + nsCOMPtr 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 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 + } + } + } + + // we didn't append the locale dir - try the default one + nsCString defLocale; + rv = prefs->GetCharPref("distribution.searchplugins.defaultLocale", + getter_Copies(defLocale)); + if (NS_SUCCEEDED(rv)) { + + nsCOMPtr 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); + } + } + } +} + +NS_IMETHODIMP +DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult) +{ + nsresult rv; + + if (!strcmp(aKey, NS_APP_SEARCH_DIR_LIST)) { + nsCOMPtr dirSvc + (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID)); + if (!dirSvc) + return NS_ERROR_FAILURE; + + nsCOMArray baseFiles; + + /** + * We want to preserve the following order, since the search service loads + * engines in first-loaded-wins order. + * - extension search plugin locations (prepended below using + * NS_NewUnionEnumerator) + * - distro search plugin locations + * - user search plugin locations (profile) + * - app search plugin location (shipped engines) + */ + AppendDistroSearchDirs(dirSvc, baseFiles); + AppendFileKey(NS_APP_USER_SEARCH_DIR, dirSvc, baseFiles); + AppendFileKey(NS_APP_SEARCH_DIR, dirSvc, baseFiles); + + nsCOMPtr baseEnum; + rv = NS_NewArrayEnumerator(getter_AddRefs(baseEnum), baseFiles); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr 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 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 nextbasesupp; + mBase->GetNext(getter_AddRefs(nextbasesupp)); + + nsCOMPtr 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/components/dirprovider/DirectoryProvider.h b/components/dirprovider/DirectoryProvider.h new file mode 100644 index 0000000..43fa85a --- /dev/null +++ b/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 mBase; + char const *const *const mAppendList; + nsCOMPtr mNext; + }; +}; + +} // namespace browser +} // namespace mozilla + +#endif // DirectoryProvider_h__ diff --git a/components/dirprovider/moz.build b/components/dirprovider/moz.build new file mode 100644 index 0000000..b01c4a3 --- /dev/null +++ b/components/dirprovider/moz.build @@ -0,0 +1,13 @@ +# -*- Mode: python; c-basic-offset: 4; 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'] -- cgit v1.2.3