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