|
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 "inCSSValueSearch.h" |
|
6 |
|
7 #include "mozilla/dom/StyleSheetList.h" |
|
8 #include "nsCSSStyleSheet.h" |
|
9 #include "nsIComponentManager.h" |
|
10 #include "nsIServiceManager.h" |
|
11 #include "nsReadableUtils.h" |
|
12 #include "nsIDOMDocument.h" |
|
13 #include "nsIDOMStyleSheetList.h" |
|
14 #include "nsIDOMCSSStyleSheet.h" |
|
15 #include "nsIDOMCSSRuleList.h" |
|
16 #include "nsIDOMCSSStyleRule.h" |
|
17 #include "nsIDOMCSSStyleDeclaration.h" |
|
18 #include "nsIDOMCSSImportRule.h" |
|
19 #include "nsIDOMCSSMediaRule.h" |
|
20 #include "nsIDOMCSSSupportsRule.h" |
|
21 #include "nsIURI.h" |
|
22 #include "nsIDocument.h" |
|
23 #include "nsNetUtil.h" |
|
24 |
|
25 using namespace mozilla; |
|
26 |
|
27 /////////////////////////////////////////////////////////////////////////////// |
|
28 inCSSValueSearch::inCSSValueSearch() |
|
29 : mResults(nullptr), |
|
30 mProperties(nullptr), |
|
31 mResultCount(0), |
|
32 mPropertyCount(0), |
|
33 mIsActive(false), |
|
34 mHoldResults(true), |
|
35 mReturnRelativeURLs(true), |
|
36 mNormalizeChromeURLs(false) |
|
37 { |
|
38 nsCSSProps::AddRefTable(); |
|
39 mProperties = new nsCSSProperty[100]; |
|
40 } |
|
41 |
|
42 inCSSValueSearch::~inCSSValueSearch() |
|
43 { |
|
44 delete[] mProperties; |
|
45 delete mResults; |
|
46 nsCSSProps::ReleaseTable(); |
|
47 } |
|
48 |
|
49 NS_IMPL_ISUPPORTS(inCSSValueSearch, inISearchProcess, inICSSValueSearch) |
|
50 |
|
51 /////////////////////////////////////////////////////////////////////////////// |
|
52 // inISearchProcess |
|
53 |
|
54 NS_IMETHODIMP |
|
55 inCSSValueSearch::GetIsActive(bool *aIsActive) |
|
56 { |
|
57 *aIsActive = mIsActive; |
|
58 return NS_OK; |
|
59 } |
|
60 |
|
61 NS_IMETHODIMP |
|
62 inCSSValueSearch::GetResultCount(int32_t *aResultCount) |
|
63 { |
|
64 *aResultCount = mResultCount; |
|
65 return NS_OK; |
|
66 } |
|
67 |
|
68 NS_IMETHODIMP |
|
69 inCSSValueSearch::GetHoldResults(bool *aHoldResults) |
|
70 { |
|
71 *aHoldResults = mHoldResults; |
|
72 return NS_OK; |
|
73 } |
|
74 |
|
75 NS_IMETHODIMP |
|
76 inCSSValueSearch::SetHoldResults(bool aHoldResults) |
|
77 { |
|
78 mHoldResults = aHoldResults; |
|
79 return NS_OK; |
|
80 } |
|
81 |
|
82 NS_IMETHODIMP |
|
83 inCSSValueSearch::SearchSync() |
|
84 { |
|
85 InitSearch(); |
|
86 |
|
87 if (!mDocument) { |
|
88 return NS_OK; |
|
89 } |
|
90 |
|
91 nsCOMPtr<nsIDocument> document = do_QueryInterface(mDocument); |
|
92 MOZ_ASSERT(document); |
|
93 |
|
94 nsCOMPtr<nsIURI> baseURI = document->GetBaseURI(); |
|
95 |
|
96 nsRefPtr<dom::StyleSheetList> sheets = document->StyleSheets(); |
|
97 MOZ_ASSERT(sheets); |
|
98 |
|
99 uint32_t length = sheets->Length(); |
|
100 for (uint32_t i = 0; i < length; ++i) { |
|
101 nsRefPtr<nsCSSStyleSheet> sheet = sheets->Item(i); |
|
102 SearchStyleSheet(sheet, baseURI); |
|
103 } |
|
104 |
|
105 // XXX would be nice to search inline style as well. |
|
106 |
|
107 return NS_OK; |
|
108 } |
|
109 |
|
110 NS_IMETHODIMP |
|
111 inCSSValueSearch::SearchAsync(inISearchObserver *aObserver) |
|
112 { |
|
113 InitSearch(); |
|
114 mObserver = aObserver; |
|
115 |
|
116 return NS_OK; |
|
117 } |
|
118 |
|
119 |
|
120 NS_IMETHODIMP |
|
121 inCSSValueSearch::SearchStop() |
|
122 { |
|
123 KillSearch(inISearchObserver::IN_INTERRUPTED); |
|
124 return NS_OK; |
|
125 } |
|
126 |
|
127 NS_IMETHODIMP |
|
128 inCSSValueSearch::SearchStep(bool* _retval) |
|
129 { |
|
130 |
|
131 return NS_OK; |
|
132 } |
|
133 |
|
134 |
|
135 NS_IMETHODIMP |
|
136 inCSSValueSearch::GetStringResultAt(int32_t aIndex, nsAString& _retval) |
|
137 { |
|
138 if (mHoldResults) { |
|
139 nsAutoString* result = mResults->ElementAt(aIndex); |
|
140 _retval = *result; |
|
141 } else if (aIndex == mResultCount-1) { |
|
142 _retval = mLastResult; |
|
143 } else { |
|
144 return NS_ERROR_FAILURE; |
|
145 } |
|
146 return NS_OK; |
|
147 } |
|
148 |
|
149 NS_IMETHODIMP |
|
150 inCSSValueSearch::GetIntResultAt(int32_t aIndex, int32_t *_retval) |
|
151 { |
|
152 return NS_ERROR_NOT_IMPLEMENTED; |
|
153 } |
|
154 |
|
155 NS_IMETHODIMP |
|
156 inCSSValueSearch::GetUIntResultAt(int32_t aIndex, uint32_t *_retval) |
|
157 { |
|
158 return NS_ERROR_NOT_IMPLEMENTED; |
|
159 } |
|
160 |
|
161 /////////////////////////////////////////////////////////////////////////////// |
|
162 // inICSSValueSearch |
|
163 |
|
164 NS_IMETHODIMP |
|
165 inCSSValueSearch::GetDocument(nsIDOMDocument** aDocument) |
|
166 { |
|
167 *aDocument = mDocument; |
|
168 NS_IF_ADDREF(*aDocument); |
|
169 return NS_OK; |
|
170 } |
|
171 |
|
172 NS_IMETHODIMP |
|
173 inCSSValueSearch::SetDocument(nsIDOMDocument* aDocument) |
|
174 { |
|
175 mDocument = aDocument; |
|
176 return NS_OK; |
|
177 } |
|
178 |
|
179 NS_IMETHODIMP |
|
180 inCSSValueSearch::GetBaseURL(char16_t** aBaseURL) |
|
181 { |
|
182 if (!(*aBaseURL = ToNewUnicode(mBaseURL))) |
|
183 return NS_ERROR_OUT_OF_MEMORY; |
|
184 return NS_OK; |
|
185 } |
|
186 |
|
187 NS_IMETHODIMP |
|
188 inCSSValueSearch::SetBaseURL(const char16_t* aBaseURL) |
|
189 { |
|
190 mBaseURL.Assign(aBaseURL); |
|
191 return NS_OK; |
|
192 } |
|
193 |
|
194 NS_IMETHODIMP |
|
195 inCSSValueSearch::GetReturnRelativeURLs(bool* aReturnRelativeURLs) |
|
196 { |
|
197 *aReturnRelativeURLs = mReturnRelativeURLs; |
|
198 return NS_OK; |
|
199 } |
|
200 |
|
201 NS_IMETHODIMP |
|
202 inCSSValueSearch::SetReturnRelativeURLs(bool aReturnRelativeURLs) |
|
203 { |
|
204 mReturnRelativeURLs = aReturnRelativeURLs; |
|
205 return NS_OK; |
|
206 } |
|
207 |
|
208 NS_IMETHODIMP |
|
209 inCSSValueSearch::GetNormalizeChromeURLs(bool *aNormalizeChromeURLs) |
|
210 { |
|
211 *aNormalizeChromeURLs = mNormalizeChromeURLs; |
|
212 return NS_OK; |
|
213 } |
|
214 |
|
215 NS_IMETHODIMP |
|
216 inCSSValueSearch::SetNormalizeChromeURLs(bool aNormalizeChromeURLs) |
|
217 { |
|
218 mNormalizeChromeURLs = aNormalizeChromeURLs; |
|
219 return NS_OK; |
|
220 } |
|
221 |
|
222 NS_IMETHODIMP |
|
223 inCSSValueSearch::AddPropertyCriteria(const char16_t *aPropName) |
|
224 { |
|
225 nsCSSProperty prop = |
|
226 nsCSSProps::LookupProperty(nsDependentString(aPropName), |
|
227 nsCSSProps::eIgnoreEnabledState); |
|
228 mProperties[mPropertyCount] = prop; |
|
229 mPropertyCount++; |
|
230 return NS_OK; |
|
231 } |
|
232 |
|
233 NS_IMETHODIMP |
|
234 inCSSValueSearch::GetTextCriteria(char16_t** aTextCriteria) |
|
235 { |
|
236 if (!(*aTextCriteria = ToNewUnicode(mTextCriteria))) |
|
237 return NS_ERROR_OUT_OF_MEMORY; |
|
238 return NS_OK; |
|
239 } |
|
240 |
|
241 NS_IMETHODIMP |
|
242 inCSSValueSearch::SetTextCriteria(const char16_t* aTextCriteria) |
|
243 { |
|
244 mTextCriteria.Assign(aTextCriteria); |
|
245 return NS_OK; |
|
246 } |
|
247 |
|
248 /////////////////////////////////////////////////////////////////////////////// |
|
249 // inCSSValueSearch |
|
250 |
|
251 nsresult |
|
252 inCSSValueSearch::InitSearch() |
|
253 { |
|
254 if (mHoldResults) { |
|
255 mResults = new nsTArray<nsAutoString *>(); |
|
256 } |
|
257 |
|
258 mResultCount = 0; |
|
259 |
|
260 return NS_OK; |
|
261 } |
|
262 |
|
263 nsresult |
|
264 inCSSValueSearch::KillSearch(int16_t aResult) |
|
265 { |
|
266 mIsActive = true; |
|
267 mObserver->OnSearchEnd(this, aResult); |
|
268 |
|
269 return NS_OK; |
|
270 } |
|
271 |
|
272 nsresult |
|
273 inCSSValueSearch::SearchStyleSheet(nsIDOMCSSStyleSheet* aStyleSheet, nsIURI* aBaseURL) |
|
274 { |
|
275 nsCOMPtr<nsIURI> baseURL; |
|
276 nsAutoString href; |
|
277 aStyleSheet->GetHref(href); |
|
278 if (href.IsEmpty()) |
|
279 baseURL = aBaseURL; |
|
280 else |
|
281 NS_NewURI(getter_AddRefs(baseURL), href, nullptr, aBaseURL); |
|
282 |
|
283 nsCOMPtr<nsIDOMCSSRuleList> rules; |
|
284 nsresult rv = aStyleSheet->GetCssRules(getter_AddRefs(rules)); |
|
285 NS_ENSURE_SUCCESS(rv, rv); |
|
286 |
|
287 return SearchRuleList(rules, baseURL); |
|
288 } |
|
289 |
|
290 nsresult |
|
291 inCSSValueSearch::SearchRuleList(nsIDOMCSSRuleList* aRuleList, nsIURI* aBaseURL) |
|
292 { |
|
293 uint32_t length; |
|
294 aRuleList->GetLength(&length); |
|
295 for (uint32_t i = 0; i < length; ++i) { |
|
296 nsCOMPtr<nsIDOMCSSRule> rule; |
|
297 aRuleList->Item(i, getter_AddRefs(rule)); |
|
298 uint16_t type; |
|
299 rule->GetType(&type); |
|
300 switch (type) { |
|
301 case nsIDOMCSSRule::STYLE_RULE: { |
|
302 nsCOMPtr<nsIDOMCSSStyleRule> styleRule = do_QueryInterface(rule); |
|
303 SearchStyleRule(styleRule, aBaseURL); |
|
304 } break; |
|
305 case nsIDOMCSSRule::IMPORT_RULE: { |
|
306 nsCOMPtr<nsIDOMCSSImportRule> importRule = do_QueryInterface(rule); |
|
307 nsCOMPtr<nsIDOMCSSStyleSheet> childSheet; |
|
308 importRule->GetStyleSheet(getter_AddRefs(childSheet)); |
|
309 if (childSheet) |
|
310 SearchStyleSheet(childSheet, aBaseURL); |
|
311 } break; |
|
312 case nsIDOMCSSRule::MEDIA_RULE: { |
|
313 nsCOMPtr<nsIDOMCSSMediaRule> mediaRule = do_QueryInterface(rule); |
|
314 nsCOMPtr<nsIDOMCSSRuleList> childRules; |
|
315 mediaRule->GetCssRules(getter_AddRefs(childRules)); |
|
316 SearchRuleList(childRules, aBaseURL); |
|
317 } break; |
|
318 case nsIDOMCSSRule::SUPPORTS_RULE: { |
|
319 nsCOMPtr<nsIDOMCSSSupportsRule> supportsRule = do_QueryInterface(rule); |
|
320 nsCOMPtr<nsIDOMCSSRuleList> childRules; |
|
321 supportsRule->GetCssRules(getter_AddRefs(childRules)); |
|
322 SearchRuleList(childRules, aBaseURL); |
|
323 } break; |
|
324 default: |
|
325 // XXX handle nsIDOMCSSRule::PAGE_RULE if we ever support it |
|
326 break; |
|
327 } |
|
328 } |
|
329 return NS_OK; |
|
330 } |
|
331 |
|
332 nsresult |
|
333 inCSSValueSearch::SearchStyleRule(nsIDOMCSSStyleRule* aStyleRule, nsIURI* aBaseURL) |
|
334 { |
|
335 nsCOMPtr<nsIDOMCSSStyleDeclaration> decl; |
|
336 nsresult rv = aStyleRule->GetStyle(getter_AddRefs(decl)); |
|
337 NS_ENSURE_SUCCESS(rv, rv); |
|
338 |
|
339 uint32_t length; |
|
340 decl->GetLength(&length); |
|
341 nsAutoString property, value; |
|
342 for (uint32_t i = 0; i < length; ++i) { |
|
343 decl->Item(i, property); |
|
344 // XXX This probably ought to use GetPropertyCSSValue if it were |
|
345 // implemented. |
|
346 decl->GetPropertyValue(property, value); |
|
347 SearchStyleValue(value, aBaseURL); |
|
348 } |
|
349 return NS_OK; |
|
350 } |
|
351 |
|
352 nsresult |
|
353 inCSSValueSearch::SearchStyleValue(const nsAFlatString& aValue, nsIURI* aBaseURL) |
|
354 { |
|
355 if (StringBeginsWith(aValue, NS_LITERAL_STRING("url(")) && |
|
356 StringEndsWith(aValue, NS_LITERAL_STRING(")"))) { |
|
357 const nsASingleFragmentString &url = |
|
358 Substring(aValue, 4, aValue.Length() - 5); |
|
359 // XXXldb Need to do more with |mReturnRelativeURLs|, perhaps? |
|
360 nsCOMPtr<nsIURI> uri; |
|
361 nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, aBaseURL); |
|
362 NS_ENSURE_SUCCESS(rv, rv); |
|
363 nsAutoCString spec; |
|
364 uri->GetSpec(spec); |
|
365 nsAutoString *result = new NS_ConvertUTF8toUTF16(spec); |
|
366 if (mReturnRelativeURLs) |
|
367 EqualizeURL(result); |
|
368 mResults->AppendElement(result); |
|
369 ++mResultCount; |
|
370 } |
|
371 |
|
372 return NS_OK; |
|
373 } |
|
374 |
|
375 nsresult |
|
376 inCSSValueSearch::EqualizeURL(nsAutoString* aURL) |
|
377 { |
|
378 if (mNormalizeChromeURLs) { |
|
379 if (aURL->Find("chrome://", false, 0, 1) >= 0) { |
|
380 uint32_t len = aURL->Length(); |
|
381 char16_t* result = new char16_t[len-8]; |
|
382 const char16_t* src = aURL->get(); |
|
383 uint32_t i = 9; |
|
384 uint32_t milestone = 0; |
|
385 uint32_t s = 0; |
|
386 while (i < len) { |
|
387 if (src[i] == '/') { |
|
388 milestone += 1; |
|
389 } |
|
390 if (milestone != 1) { |
|
391 result[i-9-s] = src[i]; |
|
392 } else { |
|
393 s++; |
|
394 } |
|
395 i++; |
|
396 } |
|
397 result[i-9-s] = 0; |
|
398 |
|
399 aURL->Assign(result); |
|
400 delete [] result; |
|
401 } |
|
402 } else { |
|
403 } |
|
404 |
|
405 return NS_OK; |
|
406 } |