browser/components/dirprovider/DirectoryProvider.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "nsIDirectoryService.h"
michael@0 6 #include "DirectoryProvider.h"
michael@0 7
michael@0 8 #include "nsIFile.h"
michael@0 9 #include "nsISimpleEnumerator.h"
michael@0 10 #include "nsIPrefService.h"
michael@0 11 #include "nsIPrefBranch.h"
michael@0 12
michael@0 13 #include "nsArrayEnumerator.h"
michael@0 14 #include "nsEnumeratorUtils.h"
michael@0 15 #include "nsAppDirectoryServiceDefs.h"
michael@0 16 #include "nsDirectoryServiceDefs.h"
michael@0 17 #include "nsCategoryManagerUtils.h"
michael@0 18 #include "nsComponentManagerUtils.h"
michael@0 19 #include "nsCOMArray.h"
michael@0 20 #include "nsDirectoryServiceUtils.h"
michael@0 21 #include "mozilla/ModuleUtils.h"
michael@0 22 #include "nsServiceManagerUtils.h"
michael@0 23 #include "nsStringAPI.h"
michael@0 24 #include "nsXULAppAPI.h"
michael@0 25 #include "nsIPrefLocalizedString.h"
michael@0 26
michael@0 27 namespace mozilla {
michael@0 28 namespace browser {
michael@0 29
michael@0 30 NS_IMPL_ISUPPORTS(DirectoryProvider,
michael@0 31 nsIDirectoryServiceProvider,
michael@0 32 nsIDirectoryServiceProvider2)
michael@0 33
michael@0 34 NS_IMETHODIMP
michael@0 35 DirectoryProvider::GetFile(const char *aKey, bool *aPersist, nsIFile* *aResult)
michael@0 36 {
michael@0 37 nsresult rv;
michael@0 38
michael@0 39 *aResult = nullptr;
michael@0 40
michael@0 41 // NOTE: This function can be reentrant through the NS_GetSpecialDirectory
michael@0 42 // call, so be careful not to cause infinite recursion.
michael@0 43
michael@0 44 nsCOMPtr<nsIFile> file;
michael@0 45
michael@0 46 char const* leafName = nullptr;
michael@0 47
michael@0 48 if (!strcmp(aKey, NS_APP_BOOKMARKS_50_FILE)) {
michael@0 49 leafName = "bookmarks.html";
michael@0 50
michael@0 51 nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
michael@0 52 if (prefs) {
michael@0 53 nsCString path;
michael@0 54 rv = prefs->GetCharPref("browser.bookmarks.file", getter_Copies(path));
michael@0 55 if (NS_SUCCEEDED(rv)) {
michael@0 56 NS_NewNativeLocalFile(path, true, getter_AddRefs(file));
michael@0 57 }
michael@0 58 }
michael@0 59 }
michael@0 60 else {
michael@0 61 return NS_ERROR_FAILURE;
michael@0 62 }
michael@0 63
michael@0 64 nsDependentCString leafstr(leafName);
michael@0 65
michael@0 66 nsCOMPtr<nsIFile> parentDir;
michael@0 67 if (file) {
michael@0 68 rv = file->GetParent(getter_AddRefs(parentDir));
michael@0 69 if (NS_FAILED(rv))
michael@0 70 return rv;
michael@0 71 }
michael@0 72 else {
michael@0 73 rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(parentDir));
michael@0 74 if (NS_FAILED(rv))
michael@0 75 return rv;
michael@0 76
michael@0 77 rv = parentDir->Clone(getter_AddRefs(file));
michael@0 78 if (NS_FAILED(rv))
michael@0 79 return rv;
michael@0 80
michael@0 81 file->AppendNative(leafstr);
michael@0 82 }
michael@0 83
michael@0 84 *aPersist = true;
michael@0 85 NS_ADDREF(*aResult = file);
michael@0 86
michael@0 87 return NS_OK;
michael@0 88 }
michael@0 89
michael@0 90 static void
michael@0 91 AppendFileKey(const char *key, nsIProperties* aDirSvc,
michael@0 92 nsCOMArray<nsIFile> &array)
michael@0 93 {
michael@0 94 nsCOMPtr<nsIFile> file;
michael@0 95 nsresult rv = aDirSvc->Get(key, NS_GET_IID(nsIFile), getter_AddRefs(file));
michael@0 96 if (NS_FAILED(rv))
michael@0 97 return;
michael@0 98
michael@0 99 bool exists;
michael@0 100 rv = file->Exists(&exists);
michael@0 101 if (NS_FAILED(rv) || !exists)
michael@0 102 return;
michael@0 103
michael@0 104 array.AppendObject(file);
michael@0 105 }
michael@0 106
michael@0 107 // Appends the distribution-specific search engine directories to the
michael@0 108 // array. The directory structure is as follows:
michael@0 109
michael@0 110 // appdir/
michael@0 111 // \- distribution/
michael@0 112 // \- searchplugins/
michael@0 113 // |- common/
michael@0 114 // \- locale/
michael@0 115 // |- <locale 1>/
michael@0 116 // ...
michael@0 117 // \- <locale N>/
michael@0 118
michael@0 119 // common engines are loaded for all locales. If there is no locale
michael@0 120 // directory for the current locale, there is a pref:
michael@0 121 // "distribution.searchplugins.defaultLocale"
michael@0 122 // which specifies a default locale to use.
michael@0 123
michael@0 124 static void
michael@0 125 AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array)
michael@0 126 {
michael@0 127 nsCOMPtr<nsIFile> searchPlugins;
michael@0 128 nsresult rv = aDirSvc->Get(XRE_EXECUTABLE_FILE,
michael@0 129 NS_GET_IID(nsIFile),
michael@0 130 getter_AddRefs(searchPlugins));
michael@0 131 if (NS_FAILED(rv))
michael@0 132 return;
michael@0 133 searchPlugins->SetNativeLeafName(NS_LITERAL_CSTRING("distribution"));
michael@0 134 searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins"));
michael@0 135
michael@0 136 bool exists;
michael@0 137 rv = searchPlugins->Exists(&exists);
michael@0 138 if (NS_FAILED(rv) || !exists)
michael@0 139 return;
michael@0 140
michael@0 141 nsCOMPtr<nsIFile> commonPlugins;
michael@0 142 rv = searchPlugins->Clone(getter_AddRefs(commonPlugins));
michael@0 143 if (NS_SUCCEEDED(rv)) {
michael@0 144 commonPlugins->AppendNative(NS_LITERAL_CSTRING("common"));
michael@0 145 rv = commonPlugins->Exists(&exists);
michael@0 146 if (NS_SUCCEEDED(rv) && exists)
michael@0 147 array.AppendObject(commonPlugins);
michael@0 148 }
michael@0 149
michael@0 150 nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
michael@0 151 if (prefs) {
michael@0 152
michael@0 153 nsCOMPtr<nsIFile> localePlugins;
michael@0 154 rv = searchPlugins->Clone(getter_AddRefs(localePlugins));
michael@0 155 if (NS_FAILED(rv))
michael@0 156 return;
michael@0 157
michael@0 158 localePlugins->AppendNative(NS_LITERAL_CSTRING("locale"));
michael@0 159
michael@0 160 nsCString locale;
michael@0 161 nsCOMPtr<nsIPrefLocalizedString> prefString;
michael@0 162 rv = prefs->GetComplexValue("general.useragent.locale",
michael@0 163 NS_GET_IID(nsIPrefLocalizedString),
michael@0 164 getter_AddRefs(prefString));
michael@0 165 if (NS_SUCCEEDED(rv)) {
michael@0 166 nsAutoString wLocale;
michael@0 167 prefString->GetData(getter_Copies(wLocale));
michael@0 168 CopyUTF16toUTF8(wLocale, locale);
michael@0 169 } else {
michael@0 170 rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale));
michael@0 171 }
michael@0 172
michael@0 173 if (NS_SUCCEEDED(rv)) {
michael@0 174
michael@0 175 nsCOMPtr<nsIFile> curLocalePlugins;
michael@0 176 rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins));
michael@0 177 if (NS_SUCCEEDED(rv)) {
michael@0 178
michael@0 179 curLocalePlugins->AppendNative(locale);
michael@0 180 rv = curLocalePlugins->Exists(&exists);
michael@0 181 if (NS_SUCCEEDED(rv) && exists) {
michael@0 182 array.AppendObject(curLocalePlugins);
michael@0 183 return; // all done
michael@0 184 }
michael@0 185 }
michael@0 186 }
michael@0 187
michael@0 188 // we didn't append the locale dir - try the default one
michael@0 189 nsCString defLocale;
michael@0 190 rv = prefs->GetCharPref("distribution.searchplugins.defaultLocale",
michael@0 191 getter_Copies(defLocale));
michael@0 192 if (NS_SUCCEEDED(rv)) {
michael@0 193
michael@0 194 nsCOMPtr<nsIFile> defLocalePlugins;
michael@0 195 rv = localePlugins->Clone(getter_AddRefs(defLocalePlugins));
michael@0 196 if (NS_SUCCEEDED(rv)) {
michael@0 197
michael@0 198 defLocalePlugins->AppendNative(defLocale);
michael@0 199 rv = defLocalePlugins->Exists(&exists);
michael@0 200 if (NS_SUCCEEDED(rv) && exists)
michael@0 201 array.AppendObject(defLocalePlugins);
michael@0 202 }
michael@0 203 }
michael@0 204 }
michael@0 205 }
michael@0 206
michael@0 207 NS_IMETHODIMP
michael@0 208 DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult)
michael@0 209 {
michael@0 210 nsresult rv;
michael@0 211
michael@0 212 if (!strcmp(aKey, NS_APP_SEARCH_DIR_LIST)) {
michael@0 213 nsCOMPtr<nsIProperties> dirSvc
michael@0 214 (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
michael@0 215 if (!dirSvc)
michael@0 216 return NS_ERROR_FAILURE;
michael@0 217
michael@0 218 nsCOMArray<nsIFile> baseFiles;
michael@0 219
michael@0 220 /**
michael@0 221 * We want to preserve the following order, since the search service loads
michael@0 222 * engines in first-loaded-wins order.
michael@0 223 * - extension search plugin locations (prepended below using
michael@0 224 * NS_NewUnionEnumerator)
michael@0 225 * - distro search plugin locations
michael@0 226 * - user search plugin locations (profile)
michael@0 227 * - app search plugin location (shipped engines)
michael@0 228 */
michael@0 229 AppendDistroSearchDirs(dirSvc, baseFiles);
michael@0 230 AppendFileKey(NS_APP_USER_SEARCH_DIR, dirSvc, baseFiles);
michael@0 231 AppendFileKey(NS_APP_SEARCH_DIR, dirSvc, baseFiles);
michael@0 232
michael@0 233 nsCOMPtr<nsISimpleEnumerator> baseEnum;
michael@0 234 rv = NS_NewArrayEnumerator(getter_AddRefs(baseEnum), baseFiles);
michael@0 235 if (NS_FAILED(rv))
michael@0 236 return rv;
michael@0 237
michael@0 238 nsCOMPtr<nsISimpleEnumerator> list;
michael@0 239 rv = dirSvc->Get(XRE_EXTENSIONS_DIR_LIST,
michael@0 240 NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list));
michael@0 241 if (NS_FAILED(rv))
michael@0 242 return rv;
michael@0 243
michael@0 244 static char const *const kAppendSPlugins[] = {"searchplugins", nullptr};
michael@0 245
michael@0 246 nsCOMPtr<nsISimpleEnumerator> extEnum =
michael@0 247 new AppendingEnumerator(list, kAppendSPlugins);
michael@0 248 if (!extEnum)
michael@0 249 return NS_ERROR_OUT_OF_MEMORY;
michael@0 250
michael@0 251 return NS_NewUnionEnumerator(aResult, extEnum, baseEnum);
michael@0 252 }
michael@0 253
michael@0 254 return NS_ERROR_FAILURE;
michael@0 255 }
michael@0 256
michael@0 257 NS_IMPL_ISUPPORTS(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator)
michael@0 258
michael@0 259 NS_IMETHODIMP
michael@0 260 DirectoryProvider::AppendingEnumerator::HasMoreElements(bool *aResult)
michael@0 261 {
michael@0 262 *aResult = mNext ? true : false;
michael@0 263 return NS_OK;
michael@0 264 }
michael@0 265
michael@0 266 NS_IMETHODIMP
michael@0 267 DirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult)
michael@0 268 {
michael@0 269 if (aResult)
michael@0 270 NS_ADDREF(*aResult = mNext);
michael@0 271
michael@0 272 mNext = nullptr;
michael@0 273
michael@0 274 nsresult rv;
michael@0 275
michael@0 276 // Ignore all errors
michael@0 277
michael@0 278 bool more;
michael@0 279 while (NS_SUCCEEDED(mBase->HasMoreElements(&more)) && more) {
michael@0 280 nsCOMPtr<nsISupports> nextbasesupp;
michael@0 281 mBase->GetNext(getter_AddRefs(nextbasesupp));
michael@0 282
michael@0 283 nsCOMPtr<nsIFile> nextbase(do_QueryInterface(nextbasesupp));
michael@0 284 if (!nextbase)
michael@0 285 continue;
michael@0 286
michael@0 287 nextbase->Clone(getter_AddRefs(mNext));
michael@0 288 if (!mNext)
michael@0 289 continue;
michael@0 290
michael@0 291 char const *const * i = mAppendList;
michael@0 292 while (*i) {
michael@0 293 mNext->AppendNative(nsDependentCString(*i));
michael@0 294 ++i;
michael@0 295 }
michael@0 296
michael@0 297 bool exists;
michael@0 298 rv = mNext->Exists(&exists);
michael@0 299 if (NS_SUCCEEDED(rv) && exists)
michael@0 300 break;
michael@0 301
michael@0 302 mNext = nullptr;
michael@0 303 }
michael@0 304
michael@0 305 return NS_OK;
michael@0 306 }
michael@0 307
michael@0 308 DirectoryProvider::AppendingEnumerator::AppendingEnumerator
michael@0 309 (nsISimpleEnumerator* aBase,
michael@0 310 char const *const *aAppendList) :
michael@0 311 mBase(aBase),
michael@0 312 mAppendList(aAppendList)
michael@0 313 {
michael@0 314 // Initialize mNext to begin.
michael@0 315 GetNext(nullptr);
michael@0 316 }
michael@0 317
michael@0 318 } // namespace browser
michael@0 319 } // namespace mozilla

mercurial