inCSSValueSearch.cpp 9.5 KB

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