1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is mozilla.org code.
15 : *
16 : * The Initial Developer of the Original Code is
17 : * Netscape Communications Corporation.
18 : * Portions created by the Initial Developer are Copyright (C) 2001
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Joe Hewitt <hewitt@netscape.com> (original author)
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "inCSSValueSearch.h"
39 :
40 : #include "nsIComponentManager.h"
41 : #include "nsIServiceManager.h"
42 : #include "nsVoidArray.h"
43 : #include "nsReadableUtils.h"
44 : #include "nsIDOMDocument.h"
45 : #include "nsIDOMStyleSheetList.h"
46 : #include "nsIDOMCSSStyleSheet.h"
47 : #include "nsIDOMCSSRuleList.h"
48 : #include "nsIDOMCSSStyleRule.h"
49 : #include "nsIDOMCSSStyleDeclaration.h"
50 : #include "nsIDOMCSSImportRule.h"
51 : #include "nsIDOMCSSMediaRule.h"
52 : #include "nsIURI.h"
53 : #include "nsNetUtil.h"
54 :
55 : ///////////////////////////////////////////////////////////////////////////////
56 0 : inCSSValueSearch::inCSSValueSearch()
57 : : mResults(nsnull),
58 : mProperties(nsnull),
59 : mResultCount(0),
60 : mPropertyCount(0),
61 : mIsActive(false),
62 : mHoldResults(true),
63 : mReturnRelativeURLs(true),
64 0 : mNormalizeChromeURLs(false)
65 : {
66 0 : nsCSSProps::AddRefTable();
67 0 : mProperties = new nsCSSProperty[100];
68 0 : }
69 :
70 0 : inCSSValueSearch::~inCSSValueSearch()
71 : {
72 0 : delete[] mProperties;
73 0 : delete mResults;
74 0 : nsCSSProps::ReleaseTable();
75 0 : }
76 :
77 0 : NS_IMPL_ISUPPORTS2(inCSSValueSearch, inISearchProcess, inICSSValueSearch)
78 :
79 : ///////////////////////////////////////////////////////////////////////////////
80 : // inISearchProcess
81 :
82 : NS_IMETHODIMP
83 0 : inCSSValueSearch::GetIsActive(bool *aIsActive)
84 : {
85 0 : *aIsActive = mIsActive;
86 0 : return NS_OK;
87 : }
88 :
89 : NS_IMETHODIMP
90 0 : inCSSValueSearch::GetResultCount(PRInt32 *aResultCount)
91 : {
92 0 : *aResultCount = mResultCount;
93 0 : return NS_OK;
94 : }
95 :
96 : NS_IMETHODIMP
97 0 : inCSSValueSearch::GetHoldResults(bool *aHoldResults)
98 : {
99 0 : *aHoldResults = mHoldResults;
100 0 : return NS_OK;
101 : }
102 :
103 : NS_IMETHODIMP
104 0 : inCSSValueSearch::SetHoldResults(bool aHoldResults)
105 : {
106 0 : mHoldResults = aHoldResults;
107 0 : return NS_OK;
108 : }
109 :
110 : NS_IMETHODIMP
111 0 : inCSSValueSearch::SearchSync()
112 : {
113 0 : InitSearch();
114 :
115 0 : if (!mDocument) {
116 0 : return NS_OK;
117 : }
118 :
119 0 : nsCOMPtr<nsIURI> baseURI;
120 0 : nsCOMPtr<nsIDocument> idoc = do_QueryInterface(mDocument);
121 0 : if (idoc) {
122 0 : baseURI = idoc->GetBaseURI();
123 : }
124 :
125 0 : nsCOMPtr<nsIDOMStyleSheetList> sheets;
126 0 : nsresult rv = mDocument->GetStyleSheets(getter_AddRefs(sheets));
127 0 : NS_ENSURE_SUCCESS(rv, NS_OK);
128 :
129 : PRUint32 length;
130 0 : sheets->GetLength(&length);
131 0 : for (PRUint32 i = 0; i < length; ++i) {
132 0 : nsCOMPtr<nsIDOMStyleSheet> sheet;
133 0 : sheets->Item(i, getter_AddRefs(sheet));
134 0 : nsCOMPtr<nsIDOMCSSStyleSheet> cssSheet = do_QueryInterface(sheet);
135 0 : if (cssSheet)
136 0 : SearchStyleSheet(cssSheet, baseURI);
137 : }
138 :
139 : // XXX would be nice to search inline style as well.
140 :
141 0 : return NS_OK;
142 : }
143 :
144 : NS_IMETHODIMP
145 0 : inCSSValueSearch::SearchAsync(inISearchObserver *aObserver)
146 : {
147 0 : InitSearch();
148 0 : mObserver = aObserver;
149 :
150 0 : return NS_OK;
151 : }
152 :
153 :
154 : NS_IMETHODIMP
155 0 : inCSSValueSearch::SearchStop()
156 : {
157 0 : KillSearch(inISearchObserver::IN_INTERRUPTED);
158 0 : return NS_OK;
159 : }
160 :
161 : NS_IMETHODIMP
162 0 : inCSSValueSearch::SearchStep(bool* _retval)
163 : {
164 :
165 0 : return NS_OK;
166 : }
167 :
168 :
169 : NS_IMETHODIMP
170 0 : inCSSValueSearch::GetStringResultAt(PRInt32 aIndex, nsAString& _retval)
171 : {
172 0 : if (mHoldResults) {
173 0 : nsAutoString* result = mResults->ElementAt(aIndex);
174 0 : _retval = *result;
175 0 : } else if (aIndex == mResultCount-1) {
176 0 : _retval = mLastResult;
177 : } else {
178 0 : return NS_ERROR_FAILURE;
179 : }
180 0 : return NS_OK;
181 : }
182 :
183 : NS_IMETHODIMP
184 0 : inCSSValueSearch::GetIntResultAt(PRInt32 aIndex, PRInt32 *_retval)
185 : {
186 0 : return NS_ERROR_NOT_IMPLEMENTED;
187 : }
188 :
189 : NS_IMETHODIMP
190 0 : inCSSValueSearch::GetUIntResultAt(PRInt32 aIndex, PRUint32 *_retval)
191 : {
192 0 : return NS_ERROR_NOT_IMPLEMENTED;
193 : }
194 :
195 : ///////////////////////////////////////////////////////////////////////////////
196 : // inICSSValueSearch
197 :
198 : NS_IMETHODIMP
199 0 : inCSSValueSearch::GetDocument(nsIDOMDocument** aDocument)
200 : {
201 0 : *aDocument = mDocument;
202 0 : NS_IF_ADDREF(*aDocument);
203 0 : return NS_OK;
204 : }
205 :
206 : NS_IMETHODIMP
207 0 : inCSSValueSearch::SetDocument(nsIDOMDocument* aDocument)
208 : {
209 0 : mDocument = aDocument;
210 0 : return NS_OK;
211 : }
212 :
213 : NS_IMETHODIMP
214 0 : inCSSValueSearch::GetBaseURL(PRUnichar** aBaseURL)
215 : {
216 0 : if (!(*aBaseURL = ToNewUnicode(mBaseURL)))
217 0 : return NS_ERROR_OUT_OF_MEMORY;
218 0 : return NS_OK;
219 : }
220 :
221 : NS_IMETHODIMP
222 0 : inCSSValueSearch::SetBaseURL(const PRUnichar* aBaseURL)
223 : {
224 0 : mBaseURL.Assign(aBaseURL);
225 0 : return NS_OK;
226 : }
227 :
228 : NS_IMETHODIMP
229 0 : inCSSValueSearch::GetReturnRelativeURLs(bool* aReturnRelativeURLs)
230 : {
231 0 : *aReturnRelativeURLs = mReturnRelativeURLs;
232 0 : return NS_OK;
233 : }
234 :
235 : NS_IMETHODIMP
236 0 : inCSSValueSearch::SetReturnRelativeURLs(bool aReturnRelativeURLs)
237 : {
238 0 : mReturnRelativeURLs = aReturnRelativeURLs;
239 0 : return NS_OK;
240 : }
241 :
242 : NS_IMETHODIMP
243 0 : inCSSValueSearch::GetNormalizeChromeURLs(bool *aNormalizeChromeURLs)
244 : {
245 0 : *aNormalizeChromeURLs = mNormalizeChromeURLs;
246 0 : return NS_OK;
247 : }
248 :
249 : NS_IMETHODIMP
250 0 : inCSSValueSearch::SetNormalizeChromeURLs(bool aNormalizeChromeURLs)
251 : {
252 0 : mNormalizeChromeURLs = aNormalizeChromeURLs;
253 0 : return NS_OK;
254 : }
255 :
256 : NS_IMETHODIMP
257 0 : inCSSValueSearch::AddPropertyCriteria(const PRUnichar *aPropName)
258 : {
259 : nsCSSProperty prop =
260 0 : nsCSSProps::LookupProperty(nsDependentString(aPropName));
261 0 : mProperties[mPropertyCount] = prop;
262 0 : mPropertyCount++;
263 0 : return NS_OK;
264 : }
265 :
266 : NS_IMETHODIMP
267 0 : inCSSValueSearch::GetTextCriteria(PRUnichar** aTextCriteria)
268 : {
269 0 : if (!(*aTextCriteria = ToNewUnicode(mTextCriteria)))
270 0 : return NS_ERROR_OUT_OF_MEMORY;
271 0 : return NS_OK;
272 : }
273 :
274 : NS_IMETHODIMP
275 0 : inCSSValueSearch::SetTextCriteria(const PRUnichar* aTextCriteria)
276 : {
277 0 : mTextCriteria.Assign(aTextCriteria);
278 0 : return NS_OK;
279 : }
280 :
281 : ///////////////////////////////////////////////////////////////////////////////
282 : // inCSSValueSearch
283 :
284 : nsresult
285 0 : inCSSValueSearch::InitSearch()
286 : {
287 0 : if (mHoldResults) {
288 0 : mResults = new nsTArray<nsAutoString *>();
289 : }
290 :
291 0 : mResultCount = 0;
292 :
293 0 : return NS_OK;
294 : }
295 :
296 : nsresult
297 0 : inCSSValueSearch::KillSearch(PRInt16 aResult)
298 : {
299 0 : mIsActive = true;
300 0 : mObserver->OnSearchEnd(this, aResult);
301 :
302 0 : return NS_OK;
303 : }
304 :
305 : nsresult
306 0 : inCSSValueSearch::SearchStyleSheet(nsIDOMCSSStyleSheet* aStyleSheet, nsIURI* aBaseURL)
307 : {
308 0 : nsCOMPtr<nsIURI> baseURL;
309 0 : nsAutoString href;
310 0 : aStyleSheet->GetHref(href);
311 0 : if (href.IsEmpty())
312 0 : baseURL = aBaseURL;
313 : else
314 0 : NS_NewURI(getter_AddRefs(baseURL), href, nsnull, aBaseURL);
315 :
316 0 : nsCOMPtr<nsIDOMCSSRuleList> rules;
317 0 : nsresult rv = aStyleSheet->GetCssRules(getter_AddRefs(rules));
318 0 : NS_ENSURE_SUCCESS(rv, rv);
319 :
320 0 : return SearchRuleList(rules, baseURL);
321 : }
322 :
323 : nsresult
324 0 : inCSSValueSearch::SearchRuleList(nsIDOMCSSRuleList* aRuleList, nsIURI* aBaseURL)
325 : {
326 : PRUint32 length;
327 0 : aRuleList->GetLength(&length);
328 0 : for (PRUint32 i = 0; i < length; ++i) {
329 0 : nsCOMPtr<nsIDOMCSSRule> rule;
330 0 : aRuleList->Item(i, getter_AddRefs(rule));
331 : PRUint16 type;
332 0 : rule->GetType(&type);
333 0 : switch (type) {
334 : case nsIDOMCSSRule::STYLE_RULE: {
335 0 : nsCOMPtr<nsIDOMCSSStyleRule> styleRule = do_QueryInterface(rule);
336 0 : SearchStyleRule(styleRule, aBaseURL);
337 0 : } break;
338 : case nsIDOMCSSRule::IMPORT_RULE: {
339 0 : nsCOMPtr<nsIDOMCSSImportRule> importRule = do_QueryInterface(rule);
340 0 : nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
341 0 : importRule->GetStyleSheet(getter_AddRefs(childSheet));
342 0 : if (childSheet)
343 0 : SearchStyleSheet(childSheet, aBaseURL);
344 0 : } break;
345 : case nsIDOMCSSRule::MEDIA_RULE: {
346 0 : nsCOMPtr<nsIDOMCSSMediaRule> mediaRule = do_QueryInterface(rule);
347 0 : nsCOMPtr<nsIDOMCSSRuleList> childRules;
348 0 : mediaRule->GetCssRules(getter_AddRefs(childRules));
349 0 : SearchRuleList(childRules, aBaseURL);
350 0 : } break;
351 : default:
352 : // XXX handle nsIDOMCSSRule::PAGE_RULE if we ever support it
353 0 : break;
354 : }
355 : }
356 0 : return NS_OK;
357 : }
358 :
359 : nsresult
360 0 : inCSSValueSearch::SearchStyleRule(nsIDOMCSSStyleRule* aStyleRule, nsIURI* aBaseURL)
361 : {
362 0 : nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
363 0 : nsresult rv = aStyleRule->GetStyle(getter_AddRefs(decl));
364 0 : NS_ENSURE_SUCCESS(rv, rv);
365 :
366 : PRUint32 length;
367 0 : decl->GetLength(&length);
368 0 : nsAutoString property, value;
369 0 : for (PRUint32 i = 0; i < length; ++i) {
370 0 : decl->Item(i, property);
371 : // XXX This probably ought to use GetPropertyCSSValue if it were
372 : // implemented.
373 0 : decl->GetPropertyValue(property, value);
374 0 : SearchStyleValue(value, aBaseURL);
375 : }
376 0 : return NS_OK;
377 : }
378 :
379 : nsresult
380 0 : inCSSValueSearch::SearchStyleValue(const nsAFlatString& aValue, nsIURI* aBaseURL)
381 : {
382 0 : if (StringBeginsWith(aValue, NS_LITERAL_STRING("url(")) &&
383 0 : StringEndsWith(aValue, NS_LITERAL_STRING(")"))) {
384 : const nsASingleFragmentString &url =
385 0 : Substring(aValue, 4, aValue.Length() - 5);
386 : // XXXldb Need to do more with |mReturnRelativeURLs|, perhaps?
387 0 : nsCOMPtr<nsIURI> uri;
388 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nsnull, aBaseURL);
389 0 : NS_ENSURE_SUCCESS(rv, rv);
390 0 : nsCAutoString spec;
391 0 : uri->GetSpec(spec);
392 0 : nsAutoString *result = new NS_ConvertUTF8toUTF16(spec);
393 0 : if (mReturnRelativeURLs)
394 0 : EqualizeURL(result);
395 0 : mResults->AppendElement(result);
396 0 : ++mResultCount;
397 : }
398 :
399 0 : return NS_OK;
400 : }
401 :
402 : nsresult
403 0 : inCSSValueSearch::EqualizeURL(nsAutoString* aURL)
404 : {
405 0 : if (mNormalizeChromeURLs) {
406 0 : if (aURL->Find("chrome://", false, 0, 1) >= 0) {
407 0 : PRUint32 len = aURL->Length();
408 0 : PRUnichar* result = new PRUnichar[len-8];
409 0 : const PRUnichar* src = aURL->get();
410 0 : PRUint32 i = 9;
411 0 : PRUint32 milestone = 0;
412 0 : PRUint32 s = 0;
413 0 : while (i < len) {
414 0 : if (src[i] == '/') {
415 0 : milestone += 1;
416 : }
417 0 : if (milestone != 1) {
418 0 : result[i-9-s] = src[i];
419 : } else {
420 0 : s++;
421 : }
422 0 : i++;
423 : }
424 0 : result[i-9-s] = 0;
425 :
426 0 : aURL->Assign(result);
427 0 : delete [] result;
428 : }
429 : } else {
430 : }
431 :
432 0 : return NS_OK;
433 : }
|