summaryrefslogtreecommitdiffstats
path: root/components/dirprovider/DirectoryProvider.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'components/dirprovider/DirectoryProvider.cpp')
-rw-r--r--components/dirprovider/DirectoryProvider.cpp268
1 files changed, 268 insertions, 0 deletions
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<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 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
+ }
+ }
+ }
+
+ // 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<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);
+ }
+ }
+ }
+}
+
+NS_IMETHODIMP
+DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult)
+{
+ nsresult rv;
+
+ 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;
+
+ /**
+ * 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<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