1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/dirprovider/DirectoryProvider.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,319 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsIDirectoryService.h" 1.9 +#include "DirectoryProvider.h" 1.10 + 1.11 +#include "nsIFile.h" 1.12 +#include "nsISimpleEnumerator.h" 1.13 +#include "nsIPrefService.h" 1.14 +#include "nsIPrefBranch.h" 1.15 + 1.16 +#include "nsArrayEnumerator.h" 1.17 +#include "nsEnumeratorUtils.h" 1.18 +#include "nsAppDirectoryServiceDefs.h" 1.19 +#include "nsDirectoryServiceDefs.h" 1.20 +#include "nsCategoryManagerUtils.h" 1.21 +#include "nsComponentManagerUtils.h" 1.22 +#include "nsCOMArray.h" 1.23 +#include "nsDirectoryServiceUtils.h" 1.24 +#include "mozilla/ModuleUtils.h" 1.25 +#include "nsServiceManagerUtils.h" 1.26 +#include "nsStringAPI.h" 1.27 +#include "nsXULAppAPI.h" 1.28 +#include "nsIPrefLocalizedString.h" 1.29 + 1.30 +namespace mozilla { 1.31 +namespace browser { 1.32 + 1.33 +NS_IMPL_ISUPPORTS(DirectoryProvider, 1.34 + nsIDirectoryServiceProvider, 1.35 + nsIDirectoryServiceProvider2) 1.36 + 1.37 +NS_IMETHODIMP 1.38 +DirectoryProvider::GetFile(const char *aKey, bool *aPersist, nsIFile* *aResult) 1.39 +{ 1.40 + nsresult rv; 1.41 + 1.42 + *aResult = nullptr; 1.43 + 1.44 + // NOTE: This function can be reentrant through the NS_GetSpecialDirectory 1.45 + // call, so be careful not to cause infinite recursion. 1.46 + 1.47 + nsCOMPtr<nsIFile> file; 1.48 + 1.49 + char const* leafName = nullptr; 1.50 + 1.51 + if (!strcmp(aKey, NS_APP_BOOKMARKS_50_FILE)) { 1.52 + leafName = "bookmarks.html"; 1.53 + 1.54 + nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); 1.55 + if (prefs) { 1.56 + nsCString path; 1.57 + rv = prefs->GetCharPref("browser.bookmarks.file", getter_Copies(path)); 1.58 + if (NS_SUCCEEDED(rv)) { 1.59 + NS_NewNativeLocalFile(path, true, getter_AddRefs(file)); 1.60 + } 1.61 + } 1.62 + } 1.63 + else { 1.64 + return NS_ERROR_FAILURE; 1.65 + } 1.66 + 1.67 + nsDependentCString leafstr(leafName); 1.68 + 1.69 + nsCOMPtr<nsIFile> parentDir; 1.70 + if (file) { 1.71 + rv = file->GetParent(getter_AddRefs(parentDir)); 1.72 + if (NS_FAILED(rv)) 1.73 + return rv; 1.74 + } 1.75 + else { 1.76 + rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(parentDir)); 1.77 + if (NS_FAILED(rv)) 1.78 + return rv; 1.79 + 1.80 + rv = parentDir->Clone(getter_AddRefs(file)); 1.81 + if (NS_FAILED(rv)) 1.82 + return rv; 1.83 + 1.84 + file->AppendNative(leafstr); 1.85 + } 1.86 + 1.87 + *aPersist = true; 1.88 + NS_ADDREF(*aResult = file); 1.89 + 1.90 + return NS_OK; 1.91 +} 1.92 + 1.93 +static void 1.94 +AppendFileKey(const char *key, nsIProperties* aDirSvc, 1.95 + nsCOMArray<nsIFile> &array) 1.96 +{ 1.97 + nsCOMPtr<nsIFile> file; 1.98 + nsresult rv = aDirSvc->Get(key, NS_GET_IID(nsIFile), getter_AddRefs(file)); 1.99 + if (NS_FAILED(rv)) 1.100 + return; 1.101 + 1.102 + bool exists; 1.103 + rv = file->Exists(&exists); 1.104 + if (NS_FAILED(rv) || !exists) 1.105 + return; 1.106 + 1.107 + array.AppendObject(file); 1.108 +} 1.109 + 1.110 +// Appends the distribution-specific search engine directories to the 1.111 +// array. The directory structure is as follows: 1.112 + 1.113 +// appdir/ 1.114 +// \- distribution/ 1.115 +// \- searchplugins/ 1.116 +// |- common/ 1.117 +// \- locale/ 1.118 +// |- <locale 1>/ 1.119 +// ... 1.120 +// \- <locale N>/ 1.121 + 1.122 +// common engines are loaded for all locales. If there is no locale 1.123 +// directory for the current locale, there is a pref: 1.124 +// "distribution.searchplugins.defaultLocale" 1.125 +// which specifies a default locale to use. 1.126 + 1.127 +static void 1.128 +AppendDistroSearchDirs(nsIProperties* aDirSvc, nsCOMArray<nsIFile> &array) 1.129 +{ 1.130 + nsCOMPtr<nsIFile> searchPlugins; 1.131 + nsresult rv = aDirSvc->Get(XRE_EXECUTABLE_FILE, 1.132 + NS_GET_IID(nsIFile), 1.133 + getter_AddRefs(searchPlugins)); 1.134 + if (NS_FAILED(rv)) 1.135 + return; 1.136 + searchPlugins->SetNativeLeafName(NS_LITERAL_CSTRING("distribution")); 1.137 + searchPlugins->AppendNative(NS_LITERAL_CSTRING("searchplugins")); 1.138 + 1.139 + bool exists; 1.140 + rv = searchPlugins->Exists(&exists); 1.141 + if (NS_FAILED(rv) || !exists) 1.142 + return; 1.143 + 1.144 + nsCOMPtr<nsIFile> commonPlugins; 1.145 + rv = searchPlugins->Clone(getter_AddRefs(commonPlugins)); 1.146 + if (NS_SUCCEEDED(rv)) { 1.147 + commonPlugins->AppendNative(NS_LITERAL_CSTRING("common")); 1.148 + rv = commonPlugins->Exists(&exists); 1.149 + if (NS_SUCCEEDED(rv) && exists) 1.150 + array.AppendObject(commonPlugins); 1.151 + } 1.152 + 1.153 + nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); 1.154 + if (prefs) { 1.155 + 1.156 + nsCOMPtr<nsIFile> localePlugins; 1.157 + rv = searchPlugins->Clone(getter_AddRefs(localePlugins)); 1.158 + if (NS_FAILED(rv)) 1.159 + return; 1.160 + 1.161 + localePlugins->AppendNative(NS_LITERAL_CSTRING("locale")); 1.162 + 1.163 + nsCString locale; 1.164 + nsCOMPtr<nsIPrefLocalizedString> prefString; 1.165 + rv = prefs->GetComplexValue("general.useragent.locale", 1.166 + NS_GET_IID(nsIPrefLocalizedString), 1.167 + getter_AddRefs(prefString)); 1.168 + if (NS_SUCCEEDED(rv)) { 1.169 + nsAutoString wLocale; 1.170 + prefString->GetData(getter_Copies(wLocale)); 1.171 + CopyUTF16toUTF8(wLocale, locale); 1.172 + } else { 1.173 + rv = prefs->GetCharPref("general.useragent.locale", getter_Copies(locale)); 1.174 + } 1.175 + 1.176 + if (NS_SUCCEEDED(rv)) { 1.177 + 1.178 + nsCOMPtr<nsIFile> curLocalePlugins; 1.179 + rv = localePlugins->Clone(getter_AddRefs(curLocalePlugins)); 1.180 + if (NS_SUCCEEDED(rv)) { 1.181 + 1.182 + curLocalePlugins->AppendNative(locale); 1.183 + rv = curLocalePlugins->Exists(&exists); 1.184 + if (NS_SUCCEEDED(rv) && exists) { 1.185 + array.AppendObject(curLocalePlugins); 1.186 + return; // all done 1.187 + } 1.188 + } 1.189 + } 1.190 + 1.191 + // we didn't append the locale dir - try the default one 1.192 + nsCString defLocale; 1.193 + rv = prefs->GetCharPref("distribution.searchplugins.defaultLocale", 1.194 + getter_Copies(defLocale)); 1.195 + if (NS_SUCCEEDED(rv)) { 1.196 + 1.197 + nsCOMPtr<nsIFile> defLocalePlugins; 1.198 + rv = localePlugins->Clone(getter_AddRefs(defLocalePlugins)); 1.199 + if (NS_SUCCEEDED(rv)) { 1.200 + 1.201 + defLocalePlugins->AppendNative(defLocale); 1.202 + rv = defLocalePlugins->Exists(&exists); 1.203 + if (NS_SUCCEEDED(rv) && exists) 1.204 + array.AppendObject(defLocalePlugins); 1.205 + } 1.206 + } 1.207 + } 1.208 +} 1.209 + 1.210 +NS_IMETHODIMP 1.211 +DirectoryProvider::GetFiles(const char *aKey, nsISimpleEnumerator* *aResult) 1.212 +{ 1.213 + nsresult rv; 1.214 + 1.215 + if (!strcmp(aKey, NS_APP_SEARCH_DIR_LIST)) { 1.216 + nsCOMPtr<nsIProperties> dirSvc 1.217 + (do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID)); 1.218 + if (!dirSvc) 1.219 + return NS_ERROR_FAILURE; 1.220 + 1.221 + nsCOMArray<nsIFile> baseFiles; 1.222 + 1.223 + /** 1.224 + * We want to preserve the following order, since the search service loads 1.225 + * engines in first-loaded-wins order. 1.226 + * - extension search plugin locations (prepended below using 1.227 + * NS_NewUnionEnumerator) 1.228 + * - distro search plugin locations 1.229 + * - user search plugin locations (profile) 1.230 + * - app search plugin location (shipped engines) 1.231 + */ 1.232 + AppendDistroSearchDirs(dirSvc, baseFiles); 1.233 + AppendFileKey(NS_APP_USER_SEARCH_DIR, dirSvc, baseFiles); 1.234 + AppendFileKey(NS_APP_SEARCH_DIR, dirSvc, baseFiles); 1.235 + 1.236 + nsCOMPtr<nsISimpleEnumerator> baseEnum; 1.237 + rv = NS_NewArrayEnumerator(getter_AddRefs(baseEnum), baseFiles); 1.238 + if (NS_FAILED(rv)) 1.239 + return rv; 1.240 + 1.241 + nsCOMPtr<nsISimpleEnumerator> list; 1.242 + rv = dirSvc->Get(XRE_EXTENSIONS_DIR_LIST, 1.243 + NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list)); 1.244 + if (NS_FAILED(rv)) 1.245 + return rv; 1.246 + 1.247 + static char const *const kAppendSPlugins[] = {"searchplugins", nullptr}; 1.248 + 1.249 + nsCOMPtr<nsISimpleEnumerator> extEnum = 1.250 + new AppendingEnumerator(list, kAppendSPlugins); 1.251 + if (!extEnum) 1.252 + return NS_ERROR_OUT_OF_MEMORY; 1.253 + 1.254 + return NS_NewUnionEnumerator(aResult, extEnum, baseEnum); 1.255 + } 1.256 + 1.257 + return NS_ERROR_FAILURE; 1.258 +} 1.259 + 1.260 +NS_IMPL_ISUPPORTS(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator) 1.261 + 1.262 +NS_IMETHODIMP 1.263 +DirectoryProvider::AppendingEnumerator::HasMoreElements(bool *aResult) 1.264 +{ 1.265 + *aResult = mNext ? true : false; 1.266 + return NS_OK; 1.267 +} 1.268 + 1.269 +NS_IMETHODIMP 1.270 +DirectoryProvider::AppendingEnumerator::GetNext(nsISupports* *aResult) 1.271 +{ 1.272 + if (aResult) 1.273 + NS_ADDREF(*aResult = mNext); 1.274 + 1.275 + mNext = nullptr; 1.276 + 1.277 + nsresult rv; 1.278 + 1.279 + // Ignore all errors 1.280 + 1.281 + bool more; 1.282 + while (NS_SUCCEEDED(mBase->HasMoreElements(&more)) && more) { 1.283 + nsCOMPtr<nsISupports> nextbasesupp; 1.284 + mBase->GetNext(getter_AddRefs(nextbasesupp)); 1.285 + 1.286 + nsCOMPtr<nsIFile> nextbase(do_QueryInterface(nextbasesupp)); 1.287 + if (!nextbase) 1.288 + continue; 1.289 + 1.290 + nextbase->Clone(getter_AddRefs(mNext)); 1.291 + if (!mNext) 1.292 + continue; 1.293 + 1.294 + char const *const * i = mAppendList; 1.295 + while (*i) { 1.296 + mNext->AppendNative(nsDependentCString(*i)); 1.297 + ++i; 1.298 + } 1.299 + 1.300 + bool exists; 1.301 + rv = mNext->Exists(&exists); 1.302 + if (NS_SUCCEEDED(rv) && exists) 1.303 + break; 1.304 + 1.305 + mNext = nullptr; 1.306 + } 1.307 + 1.308 + return NS_OK; 1.309 +} 1.310 + 1.311 +DirectoryProvider::AppendingEnumerator::AppendingEnumerator 1.312 + (nsISimpleEnumerator* aBase, 1.313 + char const *const *aAppendList) : 1.314 + mBase(aBase), 1.315 + mAppendList(aAppendList) 1.316 +{ 1.317 + // Initialize mNext to begin. 1.318 + GetNext(nullptr); 1.319 +} 1.320 + 1.321 +} // namespace browser 1.322 +} // namespace mozilla