Back to index

lightning-sunbird  0.9+nobinonly
inCSSValueSearch.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Joe Hewitt <hewitt@netscape.com> (original author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "inCSSValueSearch.h"
00039 
00040 #include "nsIComponentManager.h"
00041 #include "nsIServiceManager.h"
00042 #include "nsVoidArray.h"
00043 #include "nsReadableUtils.h"
00044 #include "nsIDOMDocumentStyle.h"
00045 #include "nsIDOM3Node.h"
00046 #include "nsIDOMStyleSheetList.h"
00047 #include "nsIDOMCSSStyleSheet.h"
00048 #include "nsIDOMCSSRuleList.h"
00049 #include "nsIDOMCSSStyleRule.h"
00050 #include "nsIDOMCSSStyleDeclaration.h"
00051 #include "nsIDOMCSSImportRule.h"
00052 #include "nsIDOMCSSMediaRule.h"
00053 #include "nsIURI.h"
00054 #include "nsNetUtil.h"
00055 
00056 static NS_DEFINE_CID(kInspectorCSSUtilsCID, NS_INSPECTORCSSUTILS_CID);
00057 
00059 inCSSValueSearch::inCSSValueSearch()
00060   : mResults(nsnull),
00061     mProperties(nsnull),
00062     mResultCount(0),
00063     mPropertyCount(0),
00064     mIsActive(PR_FALSE),
00065     mHoldResults(PR_TRUE),
00066     mReturnRelativeURLs(PR_TRUE),
00067     mNormalizeChromeURLs(PR_FALSE)
00068 {
00069   mProperties = new nsCSSProperty[100];
00070   mCSSUtils = do_GetService(kInspectorCSSUtilsCID);
00071 }
00072 
00073 inCSSValueSearch::~inCSSValueSearch()
00074 {
00075   delete[] mProperties;
00076   delete mResults;
00077 }
00078 
00079 NS_IMPL_ISUPPORTS2(inCSSValueSearch, inISearchProcess, inICSSValueSearch)
00080 
00081 
00082 // inISearchProcess
00083 
00084 NS_IMETHODIMP 
00085 inCSSValueSearch::GetIsActive(PRBool *aIsActive)
00086 {
00087   *aIsActive = mIsActive;
00088   return NS_OK;
00089 }
00090 
00091 NS_IMETHODIMP 
00092 inCSSValueSearch::GetResultCount(PRInt32 *aResultCount)
00093 {
00094   *aResultCount = mResultCount;
00095   return NS_OK;
00096 }
00097 
00098 NS_IMETHODIMP 
00099 inCSSValueSearch::GetHoldResults(PRBool *aHoldResults)
00100 {
00101   *aHoldResults = mHoldResults;
00102   return NS_OK;
00103 }
00104 
00105 NS_IMETHODIMP 
00106 inCSSValueSearch::SetHoldResults(PRBool aHoldResults)
00107 {
00108   mHoldResults = aHoldResults;
00109   return NS_OK;
00110 }
00111 
00112 NS_IMETHODIMP 
00113 inCSSValueSearch::SearchSync()
00114 {
00115   InitSearch();
00116 
00117   nsCOMPtr<nsIURI> baseURL;
00118   nsCOMPtr<nsIDOM3Node> dom3Node = do_QueryInterface(mDocument);
00119   if (dom3Node) {
00120     nsAutoString uri;
00121     dom3Node->GetBaseURI(uri);
00122     NS_NewURI(getter_AddRefs(baseURL), uri);
00123   }
00124   
00125   nsCOMPtr<nsIDOMDocumentStyle> doc = do_QueryInterface(mDocument);
00126   if (doc) {
00127     nsCOMPtr<nsIDOMStyleSheetList> sheets;
00128     nsresult rv = doc->GetStyleSheets(getter_AddRefs(sheets));
00129     NS_ENSURE_SUCCESS(rv, NS_OK);
00130 
00131     PRUint32 length;
00132     sheets->GetLength(&length);
00133     for (PRUint32 i = 0; i < length; ++i) {
00134       nsCOMPtr<nsIDOMStyleSheet> sheet;
00135       sheets->Item(i, getter_AddRefs(sheet));
00136       nsCOMPtr<nsIDOMCSSStyleSheet> cssSheet = do_QueryInterface(sheet);
00137       if (cssSheet)
00138         SearchStyleSheet(cssSheet, baseURL);
00139     }
00140   }
00141 
00142   // XXX would be nice to search inline style as well.
00143 
00144   return NS_OK;
00145 }
00146 
00147 NS_IMETHODIMP 
00148 inCSSValueSearch::SearchAsync(inISearchObserver *aObserver)
00149 {
00150   InitSearch();
00151   mObserver = aObserver;
00152 
00153   return NS_OK;
00154 }
00155 
00156 
00157 NS_IMETHODIMP
00158 inCSSValueSearch::SearchStop()
00159 {
00160   KillSearch(inISearchObserver::INTERRUPTED);
00161   return NS_OK;
00162 }
00163 
00164 NS_IMETHODIMP
00165 inCSSValueSearch::SearchStep(PRBool* _retval)
00166 {
00167 
00168   return NS_OK;
00169 }
00170 
00171 
00172 NS_IMETHODIMP 
00173 inCSSValueSearch::GetStringResultAt(PRInt32 aIndex, nsAString& _retval)
00174 {
00175   if (mHoldResults) {
00176     nsAutoString* result = (nsAutoString*)mResults->ElementAt(aIndex);
00177     _retval = *result;
00178   } else if (aIndex == mResultCount-1) {
00179     _retval = mLastResult;
00180   } else {
00181     return NS_ERROR_FAILURE;
00182   }
00183   return NS_OK;
00184 }
00185 
00186 NS_IMETHODIMP 
00187 inCSSValueSearch::GetIntResultAt(PRInt32 aIndex, PRInt32 *_retval)
00188 {
00189   return NS_ERROR_NOT_IMPLEMENTED;
00190 }
00191 
00192 NS_IMETHODIMP 
00193 inCSSValueSearch::GetUIntResultAt(PRInt32 aIndex, PRUint32 *_retval)
00194 {
00195   return NS_ERROR_NOT_IMPLEMENTED;
00196 }
00197 
00199 // inICSSValueSearch
00200 
00201 NS_IMETHODIMP 
00202 inCSSValueSearch::GetDocument(nsIDOMDocument** aDocument)
00203 {
00204   *aDocument = mDocument;
00205   NS_IF_ADDREF(*aDocument);
00206   return NS_OK;
00207 }
00208 
00209 NS_IMETHODIMP 
00210 inCSSValueSearch::SetDocument(nsIDOMDocument* aDocument)
00211 {
00212   mDocument = aDocument;
00213   return NS_OK;
00214 }
00215 
00216 NS_IMETHODIMP 
00217 inCSSValueSearch::GetBaseURL(PRUnichar** aBaseURL)
00218 {
00219   if (!(*aBaseURL = ToNewUnicode(mBaseURL)))
00220     return NS_ERROR_OUT_OF_MEMORY;
00221   return NS_OK;
00222 }
00223 
00224 NS_IMETHODIMP 
00225 inCSSValueSearch::SetBaseURL(const PRUnichar* aBaseURL)
00226 {
00227   mBaseURL.Assign(aBaseURL);
00228   return NS_OK;
00229 }
00230 
00231 NS_IMETHODIMP 
00232 inCSSValueSearch::GetReturnRelativeURLs(PRBool* aReturnRelativeURLs)
00233 {
00234   *aReturnRelativeURLs = mReturnRelativeURLs;
00235   return NS_OK;
00236 }
00237 
00238 NS_IMETHODIMP 
00239 inCSSValueSearch::SetReturnRelativeURLs(PRBool aReturnRelativeURLs)
00240 {
00241   mReturnRelativeURLs = aReturnRelativeURLs;
00242   return NS_OK;
00243 }
00244 
00245 NS_IMETHODIMP 
00246 inCSSValueSearch::GetNormalizeChromeURLs(PRBool *aNormalizeChromeURLs)
00247 {
00248   *aNormalizeChromeURLs = mNormalizeChromeURLs;
00249   return NS_OK;
00250 }
00251 
00252 NS_IMETHODIMP
00253 inCSSValueSearch::SetNormalizeChromeURLs(PRBool aNormalizeChromeURLs)
00254 {
00255   mNormalizeChromeURLs = aNormalizeChromeURLs;
00256   return NS_OK;
00257 }
00258 
00259 NS_IMETHODIMP 
00260 inCSSValueSearch::AddPropertyCriteria(const PRUnichar *aPropName)
00261 {
00262   nsCSSProperty prop;
00263   mCSSUtils->LookupCSSProperty(nsDependentString(aPropName), &prop);
00264   mProperties[mPropertyCount] = prop;
00265   mPropertyCount++;
00266   return NS_OK;
00267 }
00268 
00269 NS_IMETHODIMP 
00270 inCSSValueSearch::GetTextCriteria(PRUnichar** aTextCriteria)
00271 {
00272   if (!(*aTextCriteria = ToNewUnicode(mTextCriteria)))
00273     return NS_ERROR_OUT_OF_MEMORY;
00274   return NS_OK;
00275 }
00276 
00277 NS_IMETHODIMP 
00278 inCSSValueSearch::SetTextCriteria(const PRUnichar* aTextCriteria)
00279 {
00280   mTextCriteria.Assign(aTextCriteria);
00281   return NS_OK;
00282 }
00283 
00285 // inCSSValueSearch
00286 
00287 nsresult
00288 inCSSValueSearch::InitSearch()
00289 {
00290   if (mHoldResults) {
00291     mResults = new nsVoidArray();
00292   }
00293   
00294   mResultCount = 0;
00295 
00296   return NS_OK;
00297 }
00298 
00299 nsresult
00300 inCSSValueSearch::KillSearch(PRInt16 aResult)
00301 {
00302   mIsActive = PR_TRUE;
00303   mObserver->OnSearchEnd(this, aResult);
00304 
00305   return NS_OK;
00306 }
00307 
00308 nsresult
00309 inCSSValueSearch::SearchStyleSheet(nsIDOMCSSStyleSheet* aStyleSheet, nsIURI* aBaseURL)
00310 {
00311   nsCOMPtr<nsIURI> baseURL;
00312   nsAutoString href;
00313   aStyleSheet->GetHref(href);
00314   if (href.IsEmpty())
00315     baseURL = aBaseURL;
00316   else
00317     NS_NewURI(getter_AddRefs(baseURL), href, nsnull, aBaseURL);
00318 
00319   nsCOMPtr<nsIDOMCSSRuleList> rules;
00320   nsresult rv = aStyleSheet->GetCssRules(getter_AddRefs(rules));
00321   NS_ENSURE_SUCCESS(rv, rv);
00322 
00323   return SearchRuleList(rules, baseURL);
00324 }
00325 
00326 nsresult
00327 inCSSValueSearch::SearchRuleList(nsIDOMCSSRuleList* aRuleList, nsIURI* aBaseURL)
00328 {
00329   PRUint32 length;
00330   aRuleList->GetLength(&length);
00331   for (PRUint32 i = 0; i < length; ++i) {
00332     nsCOMPtr<nsIDOMCSSRule> rule;
00333     aRuleList->Item(i, getter_AddRefs(rule));
00334     PRUint16 type;
00335     rule->GetType(&type);
00336     switch (type) {
00337       case nsIDOMCSSRule::STYLE_RULE: {
00338         nsCOMPtr<nsIDOMCSSStyleRule> styleRule = do_QueryInterface(rule);
00339         SearchStyleRule(styleRule, aBaseURL);
00340       } break;
00341       case nsIDOMCSSRule::IMPORT_RULE: {
00342         nsCOMPtr<nsIDOMCSSImportRule> importRule = do_QueryInterface(rule);
00343         nsCOMPtr<nsIDOMCSSStyleSheet> childSheet;
00344         importRule->GetStyleSheet(getter_AddRefs(childSheet));
00345         if (childSheet)
00346           SearchStyleSheet(childSheet, aBaseURL);
00347       } break;
00348       case nsIDOMCSSRule::MEDIA_RULE: {
00349         nsCOMPtr<nsIDOMCSSMediaRule> mediaRule = do_QueryInterface(rule);
00350         nsCOMPtr<nsIDOMCSSRuleList> childRules;
00351         mediaRule->GetCssRules(getter_AddRefs(childRules));
00352         SearchRuleList(childRules, aBaseURL);
00353       } break;
00354       default:
00355         // XXX handle nsIDOMCSSRule::PAGE_RULE if we ever support it
00356         break;
00357     }
00358   }
00359   return NS_OK;
00360 }
00361 
00362 nsresult
00363 inCSSValueSearch::SearchStyleRule(nsIDOMCSSStyleRule* aStyleRule, nsIURI* aBaseURL)
00364 {
00365   nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
00366   nsresult rv = aStyleRule->GetStyle(getter_AddRefs(decl));
00367   NS_ENSURE_SUCCESS(rv, rv);
00368   
00369   PRUint32 length;
00370   decl->GetLength(&length);
00371   nsAutoString property, value;
00372   for (PRUint32 i = 0; i < length; ++i) {
00373     decl->Item(i, property);
00374     // XXX This probably ought to use GetPropertyCSSValue if it were
00375     // implemented.
00376     decl->GetPropertyValue(property, value);
00377     SearchStyleValue(value, aBaseURL);
00378   }
00379   return NS_OK;
00380 }
00381 
00382 nsresult
00383 inCSSValueSearch::SearchStyleValue(const nsAFlatString& aValue, nsIURI* aBaseURL)
00384 {
00385   if (StringBeginsWith(aValue, NS_LITERAL_STRING("url(")) &&
00386       StringEndsWith(aValue, NS_LITERAL_STRING(")"))) {
00387     const nsASingleFragmentString &url =
00388       Substring(aValue, 4, aValue.Length() - 5);
00389     // XXXldb Need to do more with |mReturnRelativeURLs|, perhaps?
00390     nsCOMPtr<nsIURI> uri;
00391     nsresult rv = NS_NewURI(getter_AddRefs(uri), url, nsnull, aBaseURL);
00392     NS_ENSURE_SUCCESS(rv, rv);
00393     nsCAutoString spec;
00394     uri->GetSpec(spec);
00395     nsAutoString *result = new NS_ConvertUTF8toUTF16(spec);
00396     if (mReturnRelativeURLs)
00397       EqualizeURL(result);
00398     mResults->AppendElement(result);
00399     ++mResultCount;
00400   }
00401 
00402   return NS_OK;
00403 }
00404 
00405 nsresult
00406 inCSSValueSearch::EqualizeURL(nsAutoString* aURL)
00407 {
00408   if (mNormalizeChromeURLs) {
00409     if (aURL->Find("chrome://", PR_FALSE, 0, 1) >= 0) {
00410       PRUint32 len = aURL->Length();
00411       char* result = new char[len-8];
00412       const PRUnichar* src = aURL->get();
00413       PRUint32 i = 9;
00414       PRUint32 milestone = 0;
00415       PRUint32 s = 0;
00416       while (i < len) {
00417         if (src[i] == '/') {
00418           milestone += 1;
00419         } 
00420         if (milestone != 1) {
00421           result[i-9-s] = src[i];
00422         } else {
00423           s++;
00424         }
00425         i++;
00426       }
00427       result[i-9-s] = 0;
00428 
00429       aURL->AssignWithConversion(result);
00430       delete [] result;
00431     }
00432   } else {
00433   }
00434 
00435   return NS_OK;
00436 }