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