inDOMUtils.cpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/ArrayUtils.h"
  6. #include "mozilla/EventStates.h"
  7. #include "inDOMUtils.h"
  8. #include "inLayoutUtils.h"
  9. #include "nsArray.h"
  10. #include "nsAutoPtr.h"
  11. #include "nsIServiceManager.h"
  12. #include "nsString.h"
  13. #include "nsIStyleSheetLinkingElement.h"
  14. #include "nsIContentInlines.h"
  15. #include "nsIDOMElement.h"
  16. #include "nsIDocument.h"
  17. #include "nsIPresShell.h"
  18. #include "nsIDOMDocument.h"
  19. #include "nsIDOMCharacterData.h"
  20. #include "nsRuleNode.h"
  21. #include "nsIStyleRule.h"
  22. #include "mozilla/css/StyleRule.h"
  23. #include "nsICSSStyleRuleDOMWrapper.h"
  24. #include "nsIDOMWindow.h"
  25. #include "nsXBLBinding.h"
  26. #include "nsXBLPrototypeBinding.h"
  27. #include "nsIMutableArray.h"
  28. #include "nsBindingManager.h"
  29. #include "ChildIterator.h"
  30. #include "nsComputedDOMStyle.h"
  31. #include "mozilla/EventStateManager.h"
  32. #include "nsIAtom.h"
  33. #include "nsRange.h"
  34. #include "nsContentList.h"
  35. #include "mozilla/StyleSheetInlines.h"
  36. #include "mozilla/dom/Element.h"
  37. #include "nsRuleWalker.h"
  38. #include "nsRuleProcessorData.h"
  39. #include "nsCSSPseudoClasses.h"
  40. #include "nsCSSRuleProcessor.h"
  41. #include "mozilla/dom/CSSLexer.h"
  42. #include "mozilla/dom/InspectorUtilsBinding.h"
  43. #include "mozilla/dom/ToJSValue.h"
  44. #include "nsCSSParser.h"
  45. #include "nsCSSProps.h"
  46. #include "nsCSSValue.h"
  47. #include "nsColor.h"
  48. #include "mozilla/StyleSetHandle.h"
  49. #include "mozilla/StyleSetHandleInlines.h"
  50. #include "nsStyleUtil.h"
  51. #include "nsQueryObject.h"
  52. using namespace mozilla;
  53. using namespace mozilla::css;
  54. using namespace mozilla::dom;
  55. ///////////////////////////////////////////////////////////////////////////////
  56. inDOMUtils::inDOMUtils()
  57. {
  58. }
  59. inDOMUtils::~inDOMUtils()
  60. {
  61. }
  62. NS_IMPL_ISUPPORTS(inDOMUtils, inIDOMUtils)
  63. ///////////////////////////////////////////////////////////////////////////////
  64. // inIDOMUtils
  65. NS_IMETHODIMP
  66. inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
  67. nsISupports ***aSheets)
  68. {
  69. NS_ENSURE_ARG_POINTER(aDocument);
  70. nsTArray<RefPtr<StyleSheet>> sheets;
  71. nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
  72. MOZ_ASSERT(document);
  73. // Get the agent, then user and finally xbl sheets in the style set.
  74. nsIPresShell* presShell = document->GetShell();
  75. if (presShell) {
  76. StyleSetHandle styleSet = presShell->StyleSet();
  77. SheetType sheetType = SheetType::Agent;
  78. for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
  79. sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
  80. }
  81. sheetType = SheetType::User;
  82. for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
  83. sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
  84. }
  85. if (styleSet->IsGecko()) {
  86. AutoTArray<CSSStyleSheet*, 32> xblSheetArray;
  87. styleSet->AsGecko()->AppendAllXBLStyleSheets(xblSheetArray);
  88. // The XBL stylesheet array will quite often be full of duplicates. Cope:
  89. nsTHashtable<nsPtrHashKey<CSSStyleSheet>> sheetSet;
  90. for (CSSStyleSheet* sheet : xblSheetArray) {
  91. if (!sheetSet.Contains(sheet)) {
  92. sheetSet.PutEntry(sheet);
  93. sheets.AppendElement(sheet);
  94. }
  95. }
  96. } else {
  97. NS_WARNING("stylo: XBL style sheets not supported yet");
  98. }
  99. }
  100. // Get the document sheets.
  101. for (size_t i = 0; i < document->SheetCount(); i++) {
  102. sheets.AppendElement(document->SheetAt(i));
  103. }
  104. nsISupports** ret = static_cast<nsISupports**>(moz_xmalloc(sheets.Length() *
  105. sizeof(nsISupports*)));
  106. for (size_t i = 0; i < sheets.Length(); i++) {
  107. NS_ADDREF(ret[i] = NS_ISUPPORTS_CAST(nsIDOMCSSStyleSheet*, sheets[i]));
  108. }
  109. *aLength = sheets.Length();
  110. *aSheets = ret;
  111. return NS_OK;
  112. }
  113. NS_IMETHODIMP
  114. inDOMUtils::IsIgnorableWhitespace(nsIDOMCharacterData *aDataNode,
  115. bool *aReturn)
  116. {
  117. NS_PRECONDITION(aReturn, "Must have an out parameter");
  118. NS_ENSURE_ARG_POINTER(aDataNode);
  119. *aReturn = false;
  120. nsCOMPtr<nsIContent> content = do_QueryInterface(aDataNode);
  121. NS_ASSERTION(content, "Does not implement nsIContent!");
  122. if (!content->TextIsOnlyWhitespace()) {
  123. return NS_OK;
  124. }
  125. // Okay. We have only white space. Let's check the white-space
  126. // property now and make sure that this isn't preformatted text...
  127. nsIFrame* frame = content->GetPrimaryFrame();
  128. if (frame) {
  129. const nsStyleText* text = frame->StyleText();
  130. *aReturn = !text->WhiteSpaceIsSignificant();
  131. }
  132. else {
  133. // empty inter-tag text node without frame, e.g., in between <table>\n<tr>
  134. *aReturn = true;
  135. }
  136. return NS_OK;
  137. }
  138. NS_IMETHODIMP
  139. inDOMUtils::GetParentForNode(nsIDOMNode* aNode,
  140. bool aShowingAnonymousContent,
  141. nsIDOMNode** aParent)
  142. {
  143. NS_ENSURE_ARG_POINTER(aNode);
  144. // First do the special cases -- document nodes and anonymous content
  145. nsCOMPtr<nsIDocument> doc(do_QueryInterface(aNode));
  146. nsCOMPtr<nsIDOMNode> parent;
  147. if (doc) {
  148. parent = inLayoutUtils::GetContainerFor(*doc);
  149. } else if (aShowingAnonymousContent) {
  150. nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
  151. if (content) {
  152. nsIContent* bparent = content->GetFlattenedTreeParent();
  153. parent = do_QueryInterface(bparent);
  154. }
  155. }
  156. if (!parent) {
  157. // Ok, just get the normal DOM parent node
  158. aNode->GetParentNode(getter_AddRefs(parent));
  159. }
  160. NS_IF_ADDREF(*aParent = parent);
  161. return NS_OK;
  162. }
  163. NS_IMETHODIMP
  164. inDOMUtils::GetChildrenForNode(nsIDOMNode* aNode,
  165. bool aShowingAnonymousContent,
  166. nsIDOMNodeList** aChildren)
  167. {
  168. NS_ENSURE_ARG_POINTER(aNode);
  169. NS_PRECONDITION(aChildren, "Must have an out parameter");
  170. nsCOMPtr<nsIDOMNodeList> kids;
  171. if (aShowingAnonymousContent) {
  172. nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
  173. if (content) {
  174. kids = content->GetChildren(nsIContent::eAllChildren);
  175. }
  176. }
  177. if (!kids) {
  178. aNode->GetChildNodes(getter_AddRefs(kids));
  179. }
  180. kids.forget(aChildren);
  181. return NS_OK;
  182. }
  183. NS_IMETHODIMP
  184. inDOMUtils::GetCSSStyleRules(nsIDOMElement *aElement,
  185. const nsAString& aPseudo,
  186. nsIArrayExtensions **_retval)
  187. {
  188. NS_ENSURE_ARG_POINTER(aElement);
  189. *_retval = nullptr;
  190. nsCOMPtr<nsIAtom> pseudoElt;
  191. if (!aPseudo.IsEmpty()) {
  192. pseudoElt = NS_Atomize(aPseudo);
  193. }
  194. nsRuleNode* ruleNode = nullptr;
  195. nsCOMPtr<Element> element = do_QueryInterface(aElement);
  196. NS_ENSURE_STATE(element);
  197. RefPtr<nsStyleContext> styleContext;
  198. GetRuleNodeForElement(element, pseudoElt, getter_AddRefs(styleContext), &ruleNode);
  199. if (!ruleNode) {
  200. // This can fail for elements that are not in the document or
  201. // if the document they're in doesn't have a presshell. Bail out.
  202. return NS_OK;
  203. }
  204. AutoTArray<nsRuleNode*, 16> ruleNodes;
  205. while (!ruleNode->IsRoot()) {
  206. ruleNodes.AppendElement(ruleNode);
  207. ruleNode = ruleNode->GetParent();
  208. }
  209. nsCOMPtr<nsIMutableArray> rules = nsArray::Create();
  210. for (nsRuleNode* ruleNode : Reversed(ruleNodes)) {
  211. RefPtr<Declaration> decl = do_QueryObject(ruleNode->GetRule());
  212. if (decl) {
  213. RefPtr<mozilla::css::StyleRule> styleRule =
  214. do_QueryObject(decl->GetOwningRule());
  215. if (styleRule) {
  216. nsCOMPtr<nsIDOMCSSRule> domRule = styleRule->GetDOMRule();
  217. if (domRule) {
  218. rules->AppendElement(domRule, /*weak =*/ false);
  219. }
  220. }
  221. }
  222. }
  223. rules.forget(_retval);
  224. return NS_OK;
  225. }
  226. static already_AddRefed<StyleRule>
  227. GetRuleFromDOMRule(nsIDOMCSSStyleRule *aRule, ErrorResult& rv)
  228. {
  229. nsCOMPtr<nsICSSStyleRuleDOMWrapper> rule = do_QueryInterface(aRule);
  230. if (!rule) {
  231. rv.Throw(NS_ERROR_INVALID_POINTER);
  232. return nullptr;
  233. }
  234. RefPtr<StyleRule> cssrule;
  235. rv = rule->GetCSSStyleRule(getter_AddRefs(cssrule));
  236. if (rv.Failed()) {
  237. return nullptr;
  238. }
  239. if (!cssrule) {
  240. rv.Throw(NS_ERROR_FAILURE);
  241. }
  242. return cssrule.forget();
  243. }
  244. NS_IMETHODIMP
  245. inDOMUtils::GetRuleLine(nsIDOMCSSRule* aRule, uint32_t* _retval)
  246. {
  247. NS_ENSURE_ARG_POINTER(aRule);
  248. Rule* rule = aRule->GetCSSRule();
  249. if (!rule) {
  250. return NS_ERROR_FAILURE;
  251. }
  252. *_retval = rule->GetLineNumber();
  253. return NS_OK;
  254. }
  255. NS_IMETHODIMP
  256. inDOMUtils::GetRuleColumn(nsIDOMCSSRule* aRule, uint32_t* _retval)
  257. {
  258. NS_ENSURE_ARG_POINTER(aRule);
  259. Rule* rule = aRule->GetCSSRule();
  260. if (!rule) {
  261. return NS_ERROR_FAILURE;
  262. }
  263. *_retval = rule->GetColumnNumber();
  264. return NS_OK;
  265. }
  266. NS_IMETHODIMP
  267. inDOMUtils::GetRelativeRuleLine(nsIDOMCSSRule* aRule, uint32_t* _retval)
  268. {
  269. NS_ENSURE_ARG_POINTER(aRule);
  270. Rule* rule = aRule->GetCSSRule();
  271. if (!rule) {
  272. return NS_ERROR_FAILURE;
  273. }
  274. uint32_t lineNumber = rule->GetLineNumber();
  275. CSSStyleSheet* sheet = rule->GetStyleSheet();
  276. if (sheet && lineNumber != 0) {
  277. nsINode* owningNode = sheet->GetOwnerNode();
  278. if (owningNode) {
  279. nsCOMPtr<nsIStyleSheetLinkingElement> link =
  280. do_QueryInterface(owningNode);
  281. if (link) {
  282. lineNumber -= link->GetLineNumber() - 1;
  283. }
  284. }
  285. }
  286. *_retval = lineNumber;
  287. return NS_OK;
  288. }
  289. NS_IMETHODIMP
  290. inDOMUtils::GetCSSLexer(const nsAString& aText, JSContext* aCx,
  291. JS::MutableHandleValue aResult)
  292. {
  293. MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
  294. JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
  295. nsAutoPtr<CSSLexer> lexer(new CSSLexer(aText));
  296. if (!WrapNewBindingNonWrapperCachedObject(aCx, scope, lexer, aResult)) {
  297. return NS_ERROR_FAILURE;
  298. }
  299. return NS_OK;
  300. }
  301. NS_IMETHODIMP
  302. inDOMUtils::GetSelectorCount(nsIDOMCSSStyleRule* aRule, uint32_t *aCount)
  303. {
  304. ErrorResult rv;
  305. RefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
  306. if (rv.Failed()) {
  307. return rv.StealNSResult();
  308. }
  309. uint32_t count = 0;
  310. for (nsCSSSelectorList* sel = rule->Selector(); sel; sel = sel->mNext) {
  311. ++count;
  312. }
  313. *aCount = count;
  314. return NS_OK;
  315. }
  316. static nsCSSSelectorList*
  317. GetSelectorAtIndex(nsIDOMCSSStyleRule* aRule, uint32_t aIndex, ErrorResult& rv)
  318. {
  319. RefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
  320. if (rv.Failed()) {
  321. return nullptr;
  322. }
  323. for (nsCSSSelectorList* sel = rule->Selector(); sel;
  324. sel = sel->mNext, --aIndex) {
  325. if (aIndex == 0) {
  326. return sel;
  327. }
  328. }
  329. // Ran out of selectors
  330. rv.Throw(NS_ERROR_INVALID_ARG);
  331. return nullptr;
  332. }
  333. NS_IMETHODIMP
  334. inDOMUtils::GetSelectorText(nsIDOMCSSStyleRule* aRule,
  335. uint32_t aSelectorIndex,
  336. nsAString& aText)
  337. {
  338. ErrorResult rv;
  339. nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
  340. if (rv.Failed()) {
  341. return rv.StealNSResult();
  342. }
  343. RefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
  344. MOZ_ASSERT(!rv.Failed(), "How could we get a selector but not a rule?");
  345. sel->mSelectors->ToString(aText, rule->GetStyleSheet(), false);
  346. return NS_OK;
  347. }
  348. NS_IMETHODIMP
  349. inDOMUtils::GetSpecificity(nsIDOMCSSStyleRule* aRule,
  350. uint32_t aSelectorIndex,
  351. uint64_t* aSpecificity)
  352. {
  353. ErrorResult rv;
  354. nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
  355. if (rv.Failed()) {
  356. return rv.StealNSResult();
  357. }
  358. *aSpecificity = sel->mWeight;
  359. return NS_OK;
  360. }
  361. NS_IMETHODIMP
  362. inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement,
  363. nsIDOMCSSStyleRule* aRule,
  364. uint32_t aSelectorIndex,
  365. const nsAString& aPseudo,
  366. bool* aMatches)
  367. {
  368. nsCOMPtr<Element> element = do_QueryInterface(aElement);
  369. NS_ENSURE_ARG_POINTER(element);
  370. ErrorResult rv;
  371. nsCSSSelectorList* tail = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
  372. if (rv.Failed()) {
  373. return rv.StealNSResult();
  374. }
  375. // We want just the one list item, not the whole list tail
  376. nsAutoPtr<nsCSSSelectorList> sel(tail->Clone(false));
  377. // Do not attempt to match if a pseudo element is requested and this is not
  378. // a pseudo element selector, or vice versa.
  379. if (aPseudo.IsEmpty() == sel->mSelectors->IsPseudoElement()) {
  380. *aMatches = false;
  381. return NS_OK;
  382. }
  383. if (!aPseudo.IsEmpty()) {
  384. // We need to make sure that the requested pseudo element type
  385. // matches the selector pseudo element type before proceeding.
  386. nsCOMPtr<nsIAtom> pseudoElt = NS_Atomize(aPseudo);
  387. if (sel->mSelectors->PseudoType() != nsCSSPseudoElements::
  388. GetPseudoType(pseudoElt, CSSEnabledState::eIgnoreEnabledState)) {
  389. *aMatches = false;
  390. return NS_OK;
  391. }
  392. // We have a matching pseudo element, now remove it so we can compare
  393. // directly against |element| when proceeding into SelectorListMatches.
  394. // It's OK to do this - we just cloned sel and nothing else is using it.
  395. sel->RemoveRightmostSelector();
  396. }
  397. element->OwnerDoc()->FlushPendingLinkUpdates();
  398. // XXXbz what exactly should we do with visited state here?
  399. TreeMatchContext matchingContext(false,
  400. nsRuleWalker::eRelevantLinkUnvisited,
  401. element->OwnerDoc(),
  402. TreeMatchContext::eNeverMatchVisited);
  403. *aMatches = nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
  404. sel);
  405. return NS_OK;
  406. }
  407. NS_IMETHODIMP
  408. inDOMUtils::IsInheritedProperty(const nsAString &aPropertyName, bool *_retval)
  409. {
  410. nsCSSPropertyID prop = nsCSSProps::
  411. LookupProperty(aPropertyName, CSSEnabledState::eIgnoreEnabledState);
  412. if (prop == eCSSProperty_UNKNOWN) {
  413. *_retval = false;
  414. return NS_OK;
  415. }
  416. if (prop == eCSSPropertyExtra_variable) {
  417. *_retval = true;
  418. return NS_OK;
  419. }
  420. if (nsCSSProps::IsShorthand(prop)) {
  421. prop = nsCSSProps::SubpropertyEntryFor(prop)[0];
  422. }
  423. nsStyleStructID sid = nsCSSProps::kSIDTable[prop];
  424. *_retval = !nsCachedStyleData::IsReset(sid);
  425. return NS_OK;
  426. }
  427. extern const char* const kCSSRawProperties[];
  428. NS_IMETHODIMP
  429. inDOMUtils::GetCSSPropertyNames(uint32_t aFlags, uint32_t* aCount,
  430. char16_t*** aProps)
  431. {
  432. // maxCount is the largest number of properties we could have; our actual
  433. // number might be smaller because properties might be disabled.
  434. uint32_t maxCount;
  435. if (aFlags & EXCLUDE_SHORTHANDS) {
  436. maxCount = eCSSProperty_COUNT_no_shorthands;
  437. } else {
  438. maxCount = eCSSProperty_COUNT;
  439. }
  440. if (aFlags & INCLUDE_ALIASES) {
  441. maxCount += (eCSSProperty_COUNT_with_aliases - eCSSProperty_COUNT);
  442. }
  443. char16_t** props =
  444. static_cast<char16_t**>(moz_xmalloc(maxCount * sizeof(char16_t*)));
  445. #define DO_PROP(_prop) \
  446. PR_BEGIN_MACRO \
  447. nsCSSPropertyID cssProp = nsCSSPropertyID(_prop); \
  448. if (nsCSSProps::IsEnabled(cssProp, CSSEnabledState::eForAllContent)) { \
  449. props[propCount] = \
  450. ToNewUnicode(nsDependentCString(kCSSRawProperties[_prop])); \
  451. ++propCount; \
  452. } \
  453. PR_END_MACRO
  454. // prop is the property id we're considering; propCount is how many properties
  455. // we've put into props so far.
  456. uint32_t prop = 0, propCount = 0;
  457. for ( ; prop < eCSSProperty_COUNT_no_shorthands; ++prop) {
  458. if (nsCSSProps::PropertyParseType(nsCSSPropertyID(prop)) !=
  459. CSS_PROPERTY_PARSE_INACCESSIBLE) {
  460. DO_PROP(prop);
  461. }
  462. }
  463. if (!(aFlags & EXCLUDE_SHORTHANDS)) {
  464. for ( ; prop < eCSSProperty_COUNT; ++prop) {
  465. // Some shorthands are also aliases
  466. if ((aFlags & INCLUDE_ALIASES) ||
  467. !nsCSSProps::PropHasFlags(nsCSSPropertyID(prop),
  468. CSS_PROPERTY_IS_ALIAS)) {
  469. DO_PROP(prop);
  470. }
  471. }
  472. }
  473. if (aFlags & INCLUDE_ALIASES) {
  474. for (prop = eCSSProperty_COUNT; prop < eCSSProperty_COUNT_with_aliases; ++prop) {
  475. DO_PROP(prop);
  476. }
  477. }
  478. #undef DO_PROP
  479. *aCount = propCount;
  480. *aProps = props;
  481. return NS_OK;
  482. }
  483. static void InsertNoDuplicates(nsTArray<nsString>& aArray,
  484. const nsAString& aString)
  485. {
  486. size_t i = aArray.IndexOfFirstElementGt(aString);
  487. if (i > 0 && aArray[i-1].Equals(aString)) {
  488. return;
  489. }
  490. aArray.InsertElementAt(i, aString);
  491. }
  492. static void GetKeywordsForProperty(const nsCSSPropertyID aProperty,
  493. nsTArray<nsString>& aArray)
  494. {
  495. if (nsCSSProps::IsShorthand(aProperty)) {
  496. // Shorthand props have no keywords.
  497. return;
  498. }
  499. const nsCSSProps::KTableEntry* keywordTable =
  500. nsCSSProps::kKeywordTableTable[aProperty];
  501. if (keywordTable) {
  502. for (size_t i = 0; keywordTable[i].mKeyword != eCSSKeyword_UNKNOWN; ++i) {
  503. nsCSSKeyword word = keywordTable[i].mKeyword;
  504. InsertNoDuplicates(aArray,
  505. NS_ConvertASCIItoUTF16(nsCSSKeywords::GetStringValue(word)));
  506. }
  507. }
  508. }
  509. static void GetColorsForProperty(const uint32_t aParserVariant,
  510. nsTArray<nsString>& aArray)
  511. {
  512. if (aParserVariant & VARIANT_COLOR) {
  513. // GetKeywordsForProperty and GetOtherValuesForProperty assume aArray is sorted,
  514. // and if aArray is not empty here, then it's not going to be sorted coming out.
  515. MOZ_ASSERT(aArray.Length() == 0);
  516. size_t size;
  517. const char * const *allColorNames = NS_AllColorNames(&size);
  518. nsString* utf16Names = aArray.AppendElements(size);
  519. for (size_t i = 0; i < size; i++) {
  520. CopyASCIItoUTF16(allColorNames[i], utf16Names[i]);
  521. }
  522. InsertNoDuplicates(aArray, NS_LITERAL_STRING("currentColor"));
  523. }
  524. return;
  525. }
  526. static void GetOtherValuesForProperty(const uint32_t aParserVariant,
  527. nsTArray<nsString>& aArray)
  528. {
  529. if (aParserVariant & VARIANT_AUTO) {
  530. InsertNoDuplicates(aArray, NS_LITERAL_STRING("auto"));
  531. }
  532. if (aParserVariant & VARIANT_NORMAL) {
  533. InsertNoDuplicates(aArray, NS_LITERAL_STRING("normal"));
  534. }
  535. if(aParserVariant & VARIANT_ALL) {
  536. InsertNoDuplicates(aArray, NS_LITERAL_STRING("all"));
  537. }
  538. if (aParserVariant & VARIANT_NONE) {
  539. InsertNoDuplicates(aArray, NS_LITERAL_STRING("none"));
  540. }
  541. if (aParserVariant & VARIANT_ELEMENT) {
  542. InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-element"));
  543. }
  544. if (aParserVariant & VARIANT_IMAGE_RECT) {
  545. InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-image-rect"));
  546. }
  547. if (aParserVariant & VARIANT_COLOR) {
  548. InsertNoDuplicates(aArray, NS_LITERAL_STRING("rgb"));
  549. InsertNoDuplicates(aArray, NS_LITERAL_STRING("hsl"));
  550. InsertNoDuplicates(aArray, NS_LITERAL_STRING("rgba"));
  551. InsertNoDuplicates(aArray, NS_LITERAL_STRING("hsla"));
  552. }
  553. if (aParserVariant & VARIANT_TIMING_FUNCTION) {
  554. InsertNoDuplicates(aArray, NS_LITERAL_STRING("cubic-bezier"));
  555. InsertNoDuplicates(aArray, NS_LITERAL_STRING("steps"));
  556. }
  557. if (aParserVariant & VARIANT_CALC) {
  558. InsertNoDuplicates(aArray, NS_LITERAL_STRING("calc"));
  559. InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-calc"));
  560. }
  561. if (aParserVariant & VARIANT_URL) {
  562. InsertNoDuplicates(aArray, NS_LITERAL_STRING("url"));
  563. }
  564. if (aParserVariant & VARIANT_GRADIENT) {
  565. InsertNoDuplicates(aArray, NS_LITERAL_STRING("linear-gradient"));
  566. InsertNoDuplicates(aArray, NS_LITERAL_STRING("radial-gradient"));
  567. InsertNoDuplicates(aArray, NS_LITERAL_STRING("repeating-linear-gradient"));
  568. InsertNoDuplicates(aArray, NS_LITERAL_STRING("repeating-radial-gradient"));
  569. InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-linear-gradient"));
  570. InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-radial-gradient"));
  571. InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-linear-gradient"));
  572. InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-radial-gradient"));
  573. }
  574. }
  575. NS_IMETHODIMP
  576. inDOMUtils::GetSubpropertiesForCSSProperty(const nsAString& aProperty,
  577. uint32_t* aLength,
  578. char16_t*** aValues)
  579. {
  580. nsCSSPropertyID propertyID =
  581. nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
  582. if (propertyID == eCSSProperty_UNKNOWN) {
  583. return NS_ERROR_FAILURE;
  584. }
  585. if (propertyID == eCSSPropertyExtra_variable) {
  586. *aValues = static_cast<char16_t**>(moz_xmalloc(sizeof(char16_t*)));
  587. (*aValues)[0] = ToNewUnicode(aProperty);
  588. *aLength = 1;
  589. return NS_OK;
  590. }
  591. if (!nsCSSProps::IsShorthand(propertyID)) {
  592. *aValues = static_cast<char16_t**>(moz_xmalloc(sizeof(char16_t*)));
  593. (*aValues)[0] = ToNewUnicode(nsCSSProps::GetStringValue(propertyID));
  594. *aLength = 1;
  595. return NS_OK;
  596. }
  597. // Count up how many subproperties we have.
  598. size_t subpropCount = 0;
  599. for (const nsCSSPropertyID *props = nsCSSProps::SubpropertyEntryFor(propertyID);
  600. *props != eCSSProperty_UNKNOWN; ++props) {
  601. ++subpropCount;
  602. }
  603. *aValues =
  604. static_cast<char16_t**>(moz_xmalloc(subpropCount * sizeof(char16_t*)));
  605. *aLength = subpropCount;
  606. for (const nsCSSPropertyID *props = nsCSSProps::SubpropertyEntryFor(propertyID),
  607. *props_start = props;
  608. *props != eCSSProperty_UNKNOWN; ++props) {
  609. (*aValues)[props-props_start] = ToNewUnicode(nsCSSProps::GetStringValue(*props));
  610. }
  611. return NS_OK;
  612. }
  613. NS_IMETHODIMP
  614. inDOMUtils::CssPropertyIsShorthand(const nsAString& aProperty, bool *_retval)
  615. {
  616. nsCSSPropertyID propertyID =
  617. nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
  618. if (propertyID == eCSSProperty_UNKNOWN) {
  619. return NS_ERROR_FAILURE;
  620. }
  621. if (propertyID == eCSSPropertyExtra_variable) {
  622. *_retval = false;
  623. } else {
  624. *_retval = nsCSSProps::IsShorthand(propertyID);
  625. }
  626. return NS_OK;
  627. }
  628. // A helper function that determines whether the given property
  629. // supports the given type.
  630. static bool
  631. PropertySupportsVariant(nsCSSPropertyID aPropertyID, uint32_t aVariant)
  632. {
  633. if (nsCSSProps::IsShorthand(aPropertyID)) {
  634. // We need a special case for border here, because while it resets
  635. // border-image, it can't actually parse an image.
  636. if (aPropertyID == eCSSProperty_border) {
  637. return (aVariant & (VARIANT_COLOR | VARIANT_LENGTH)) != 0;
  638. }
  639. for (const nsCSSPropertyID* props = nsCSSProps::SubpropertyEntryFor(aPropertyID);
  640. *props != eCSSProperty_UNKNOWN; ++props) {
  641. if (PropertySupportsVariant(*props, aVariant)) {
  642. return true;
  643. }
  644. }
  645. return false;
  646. }
  647. // Properties that are parsed by functions must have their
  648. // attributes hand-maintained here.
  649. if (nsCSSProps::PropHasFlags(aPropertyID, CSS_PROPERTY_VALUE_PARSER_FUNCTION) ||
  650. nsCSSProps::PropertyParseType(aPropertyID) == CSS_PROPERTY_PARSE_FUNCTION) {
  651. // These must all be special-cased.
  652. uint32_t supported;
  653. switch (aPropertyID) {
  654. case eCSSProperty_border_image_slice:
  655. case eCSSProperty_grid_template:
  656. case eCSSProperty_grid:
  657. supported = VARIANT_PN;
  658. break;
  659. case eCSSProperty_border_image_outset:
  660. supported = VARIANT_LN;
  661. break;
  662. case eCSSProperty_border_image_width:
  663. case eCSSProperty_stroke_dasharray:
  664. supported = VARIANT_LPN;
  665. break;
  666. case eCSSProperty_border_top_left_radius:
  667. case eCSSProperty_border_top_right_radius:
  668. case eCSSProperty_border_bottom_left_radius:
  669. case eCSSProperty_border_bottom_right_radius:
  670. case eCSSProperty_background_position:
  671. case eCSSProperty_background_position_x:
  672. case eCSSProperty_background_position_y:
  673. case eCSSProperty_background_size:
  674. case eCSSProperty_mask_position:
  675. case eCSSProperty_mask_position_x:
  676. case eCSSProperty_mask_position_y:
  677. case eCSSProperty_mask_size:
  678. case eCSSProperty_grid_auto_columns:
  679. case eCSSProperty_grid_auto_rows:
  680. case eCSSProperty_grid_template_columns:
  681. case eCSSProperty_grid_template_rows:
  682. case eCSSProperty_object_position:
  683. case eCSSProperty_scroll_snap_coordinate:
  684. case eCSSProperty_scroll_snap_destination:
  685. case eCSSProperty_transform_origin:
  686. case eCSSProperty_perspective_origin:
  687. case eCSSProperty__moz_outline_radius_topLeft:
  688. case eCSSProperty__moz_outline_radius_topRight:
  689. case eCSSProperty__moz_outline_radius_bottomLeft:
  690. case eCSSProperty__moz_outline_radius_bottomRight:
  691. supported = VARIANT_LP;
  692. break;
  693. case eCSSProperty_border_bottom_colors:
  694. case eCSSProperty_border_left_colors:
  695. case eCSSProperty_border_right_colors:
  696. case eCSSProperty_border_top_colors:
  697. supported = VARIANT_COLOR;
  698. break;
  699. case eCSSProperty_text_shadow:
  700. case eCSSProperty_box_shadow:
  701. supported = VARIANT_LENGTH | VARIANT_COLOR;
  702. break;
  703. case eCSSProperty_border_spacing:
  704. supported = VARIANT_LENGTH;
  705. break;
  706. case eCSSProperty_content:
  707. case eCSSProperty_cursor:
  708. case eCSSProperty_clip_path:
  709. case eCSSProperty_shape_outside:
  710. supported = VARIANT_URL;
  711. break;
  712. case eCSSProperty_fill:
  713. case eCSSProperty_stroke:
  714. supported = VARIANT_COLOR | VARIANT_URL;
  715. break;
  716. case eCSSProperty_image_orientation:
  717. supported = VARIANT_ANGLE;
  718. break;
  719. case eCSSProperty_filter:
  720. supported = VARIANT_URL;
  721. break;
  722. case eCSSProperty_grid_column_start:
  723. case eCSSProperty_grid_column_end:
  724. case eCSSProperty_grid_row_start:
  725. case eCSSProperty_grid_row_end:
  726. case eCSSProperty_font_weight:
  727. case eCSSProperty_initial_letter:
  728. supported = VARIANT_NUMBER;
  729. break;
  730. default:
  731. supported = 0;
  732. break;
  733. }
  734. return (supported & aVariant) != 0;
  735. }
  736. return (nsCSSProps::ParserVariant(aPropertyID) & aVariant) != 0;
  737. }
  738. NS_IMETHODIMP
  739. inDOMUtils::CssPropertySupportsType(const nsAString& aProperty, uint32_t aType,
  740. bool *_retval)
  741. {
  742. nsCSSPropertyID propertyID =
  743. nsCSSProps::LookupProperty(aProperty, CSSEnabledState::eForAllContent);
  744. if (propertyID == eCSSProperty_UNKNOWN) {
  745. return NS_ERROR_FAILURE;
  746. }
  747. if (propertyID >= eCSSProperty_COUNT) {
  748. *_retval = false;
  749. return NS_OK;
  750. }
  751. uint32_t variant;
  752. switch (aType) {
  753. case TYPE_LENGTH:
  754. variant = VARIANT_LENGTH;
  755. break;
  756. case TYPE_PERCENTAGE:
  757. variant = VARIANT_PERCENT;
  758. break;
  759. case TYPE_COLOR:
  760. variant = VARIANT_COLOR;
  761. break;
  762. case TYPE_URL:
  763. variant = VARIANT_URL;
  764. break;
  765. case TYPE_ANGLE:
  766. variant = VARIANT_ANGLE;
  767. break;
  768. case TYPE_FREQUENCY:
  769. variant = VARIANT_FREQUENCY;
  770. break;
  771. case TYPE_TIME:
  772. variant = VARIANT_TIME;
  773. break;
  774. case TYPE_GRADIENT:
  775. variant = VARIANT_GRADIENT;
  776. break;
  777. case TYPE_TIMING_FUNCTION:
  778. variant = VARIANT_TIMING_FUNCTION;
  779. break;
  780. case TYPE_IMAGE_RECT:
  781. variant = VARIANT_IMAGE_RECT;
  782. break;
  783. case TYPE_NUMBER:
  784. // Include integers under "number"?
  785. variant = VARIANT_NUMBER | VARIANT_INTEGER | VARIANT_OPACITY;
  786. break;
  787. default:
  788. // Unknown type
  789. return NS_ERROR_NOT_AVAILABLE;
  790. }
  791. *_retval = PropertySupportsVariant(propertyID, variant);
  792. return NS_OK;
  793. }
  794. NS_IMETHODIMP
  795. inDOMUtils::GetCSSValuesForProperty(const nsAString& aProperty,
  796. uint32_t* aLength,
  797. char16_t*** aValues)
  798. {
  799. nsCSSPropertyID propertyID = nsCSSProps::
  800. LookupProperty(aProperty, CSSEnabledState::eForAllContent);
  801. if (propertyID == eCSSProperty_UNKNOWN) {
  802. return NS_ERROR_FAILURE;
  803. }
  804. nsTArray<nsString> array;
  805. // We start collecting the values, BUT colors need to go in first, because array
  806. // needs to stay sorted, and the colors are sorted, so we just append them.
  807. if (propertyID == eCSSPropertyExtra_variable) {
  808. // No other values we can report.
  809. } else if (!nsCSSProps::IsShorthand(propertyID)) {
  810. // Property is longhand.
  811. uint32_t propertyParserVariant = nsCSSProps::ParserVariant(propertyID);
  812. // Get colors first.
  813. GetColorsForProperty(propertyParserVariant, array);
  814. if (propertyParserVariant & VARIANT_KEYWORD) {
  815. GetKeywordsForProperty(propertyID, array);
  816. }
  817. GetOtherValuesForProperty(propertyParserVariant, array);
  818. } else {
  819. // Property is shorthand.
  820. CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty, propertyID,
  821. CSSEnabledState::eForAllContent) {
  822. // Get colors (once) first.
  823. uint32_t propertyParserVariant = nsCSSProps::ParserVariant(*subproperty);
  824. if (propertyParserVariant & VARIANT_COLOR) {
  825. GetColorsForProperty(propertyParserVariant, array);
  826. break;
  827. }
  828. }
  829. CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty, propertyID,
  830. CSSEnabledState::eForAllContent) {
  831. uint32_t propertyParserVariant = nsCSSProps::ParserVariant(*subproperty);
  832. if (propertyParserVariant & VARIANT_KEYWORD) {
  833. GetKeywordsForProperty(*subproperty, array);
  834. }
  835. GetOtherValuesForProperty(propertyParserVariant, array);
  836. }
  837. }
  838. // All CSS properties take initial, inherit and unset.
  839. InsertNoDuplicates(array, NS_LITERAL_STRING("initial"));
  840. InsertNoDuplicates(array, NS_LITERAL_STRING("inherit"));
  841. InsertNoDuplicates(array, NS_LITERAL_STRING("unset"));
  842. *aLength = array.Length();
  843. char16_t** ret =
  844. static_cast<char16_t**>(moz_xmalloc(*aLength * sizeof(char16_t*)));
  845. for (uint32_t i = 0; i < *aLength; ++i) {
  846. ret[i] = ToNewUnicode(array[i]);
  847. }
  848. *aValues = ret;
  849. return NS_OK;
  850. }
  851. NS_IMETHODIMP
  852. inDOMUtils::ColorNameToRGB(const nsAString& aColorName, JSContext* aCx,
  853. JS::MutableHandle<JS::Value> aValue)
  854. {
  855. nscolor color;
  856. if (!NS_ColorNameToRGB(aColorName, &color)) {
  857. return NS_ERROR_INVALID_ARG;
  858. }
  859. InspectorRGBTriple triple;
  860. triple.mR = NS_GET_R(color);
  861. triple.mG = NS_GET_G(color);
  862. triple.mB = NS_GET_B(color);
  863. if (!ToJSValue(aCx, triple, aValue)) {
  864. return NS_ERROR_FAILURE;
  865. }
  866. return NS_OK;
  867. }
  868. NS_IMETHODIMP
  869. inDOMUtils::RgbToColorName(uint8_t aR, uint8_t aG, uint8_t aB,
  870. nsAString& aColorName)
  871. {
  872. const char* color = NS_RGBToColorName(NS_RGB(aR, aG, aB));
  873. if (!color) {
  874. aColorName.Truncate();
  875. return NS_ERROR_INVALID_ARG;
  876. }
  877. aColorName.AssignASCII(color);
  878. return NS_OK;
  879. }
  880. NS_IMETHODIMP
  881. inDOMUtils::ColorToRGBA(const nsAString& aColorString, JSContext* aCx,
  882. JS::MutableHandle<JS::Value> aValue)
  883. {
  884. nscolor color = 0;
  885. nsCSSParser cssParser;
  886. nsCSSValue cssValue;
  887. bool isColor = cssParser.ParseColorString(aColorString, nullptr, 0,
  888. cssValue, true);
  889. if (!isColor) {
  890. aValue.setNull();
  891. return NS_OK;
  892. }
  893. nsRuleNode::ComputeColor(cssValue, nullptr, nullptr, color);
  894. InspectorRGBATuple tuple;
  895. tuple.mR = NS_GET_R(color);
  896. tuple.mG = NS_GET_G(color);
  897. tuple.mB = NS_GET_B(color);
  898. tuple.mA = nsStyleUtil::ColorComponentToFloat(NS_GET_A(color));
  899. if (!ToJSValue(aCx, tuple, aValue)) {
  900. return NS_ERROR_FAILURE;
  901. }
  902. return NS_OK;
  903. }
  904. NS_IMETHODIMP
  905. inDOMUtils::IsValidCSSColor(const nsAString& aColorString, bool *_retval)
  906. {
  907. nsCSSParser cssParser;
  908. nsCSSValue cssValue;
  909. *_retval = cssParser.ParseColorString(aColorString, nullptr, 0, cssValue, true);
  910. return NS_OK;
  911. }
  912. NS_IMETHODIMP
  913. inDOMUtils::CssPropertyIsValid(const nsAString& aPropertyName,
  914. const nsAString& aPropertyValue,
  915. bool *_retval)
  916. {
  917. nsCSSPropertyID propertyID = nsCSSProps::
  918. LookupProperty(aPropertyName, CSSEnabledState::eIgnoreEnabledState);
  919. if (propertyID == eCSSProperty_UNKNOWN) {
  920. *_retval = false;
  921. return NS_OK;
  922. }
  923. if (propertyID == eCSSPropertyExtra_variable) {
  924. *_retval = true;
  925. return NS_OK;
  926. }
  927. // Get a parser, parse the property.
  928. nsCSSParser parser;
  929. *_retval = parser.IsValueValidForProperty(propertyID, aPropertyValue);
  930. return NS_OK;
  931. }
  932. NS_IMETHODIMP
  933. inDOMUtils::GetBindingURLs(nsIDOMElement *aElement, nsIArray **_retval)
  934. {
  935. NS_ENSURE_ARG_POINTER(aElement);
  936. *_retval = nullptr;
  937. nsCOMPtr<nsIMutableArray> urls = do_CreateInstance(NS_ARRAY_CONTRACTID);
  938. if (!urls)
  939. return NS_ERROR_FAILURE;
  940. nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
  941. NS_ENSURE_ARG_POINTER(content);
  942. nsXBLBinding *binding = content->GetXBLBinding();
  943. while (binding) {
  944. urls->AppendElement(binding->PrototypeBinding()->BindingURI(), false);
  945. binding = binding->GetBaseBinding();
  946. }
  947. urls.forget(_retval);
  948. return NS_OK;
  949. }
  950. NS_IMETHODIMP
  951. inDOMUtils::SetContentState(nsIDOMElement* aElement,
  952. EventStates::InternalType aState,
  953. bool* aRetVal)
  954. {
  955. NS_ENSURE_ARG_POINTER(aElement);
  956. RefPtr<EventStateManager> esm =
  957. inLayoutUtils::GetEventStateManagerFor(aElement);
  958. NS_ENSURE_TRUE(esm, NS_ERROR_INVALID_ARG);
  959. nsCOMPtr<nsIContent> content;
  960. content = do_QueryInterface(aElement);
  961. NS_ENSURE_TRUE(content, NS_ERROR_INVALID_ARG);
  962. *aRetVal = esm->SetContentState(content, EventStates(aState));
  963. return NS_OK;
  964. }
  965. NS_IMETHODIMP
  966. inDOMUtils::RemoveContentState(nsIDOMElement* aElement,
  967. EventStates::InternalType aState,
  968. bool* aRetVal)
  969. {
  970. NS_ENSURE_ARG_POINTER(aElement);
  971. RefPtr<EventStateManager> esm =
  972. inLayoutUtils::GetEventStateManagerFor(aElement);
  973. NS_ENSURE_TRUE(esm, NS_ERROR_INVALID_ARG);
  974. *aRetVal = esm->SetContentState(nullptr, EventStates(aState));
  975. return NS_OK;
  976. }
  977. NS_IMETHODIMP
  978. inDOMUtils::GetContentState(nsIDOMElement* aElement,
  979. EventStates::InternalType* aState)
  980. {
  981. *aState = 0;
  982. nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
  983. NS_ENSURE_ARG_POINTER(content);
  984. // NOTE: if this method is removed,
  985. // please remove GetInternalValue from EventStates
  986. *aState = content->AsElement()->State().GetInternalValue();
  987. return NS_OK;
  988. }
  989. /* static */ nsresult
  990. inDOMUtils::GetRuleNodeForElement(dom::Element* aElement,
  991. nsIAtom* aPseudo,
  992. nsStyleContext** aStyleContext,
  993. nsRuleNode** aRuleNode)
  994. {
  995. MOZ_ASSERT(aElement);
  996. *aRuleNode = nullptr;
  997. *aStyleContext = nullptr;
  998. nsIDocument* doc = aElement->GetComposedDoc();
  999. NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
  1000. nsIPresShell *presShell = doc->GetShell();
  1001. NS_ENSURE_TRUE(presShell, NS_ERROR_UNEXPECTED);
  1002. nsPresContext *presContext = presShell->GetPresContext();
  1003. NS_ENSURE_TRUE(presContext, NS_ERROR_UNEXPECTED);
  1004. presContext->EnsureSafeToHandOutCSSRules();
  1005. RefPtr<nsStyleContext> sContext =
  1006. nsComputedDOMStyle::GetStyleContextForElement(aElement, aPseudo, presShell);
  1007. if (sContext) {
  1008. *aRuleNode = sContext->RuleNode();
  1009. sContext.forget(aStyleContext);
  1010. }
  1011. return NS_OK;
  1012. }
  1013. NS_IMETHODIMP
  1014. inDOMUtils::GetUsedFontFaces(nsIDOMRange* aRange,
  1015. nsIDOMFontFaceList** aFontFaceList)
  1016. {
  1017. return static_cast<nsRange*>(aRange)->GetUsedFontFaces(aFontFaceList);
  1018. }
  1019. static EventStates
  1020. GetStatesForPseudoClass(const nsAString& aStatePseudo)
  1021. {
  1022. // An array of the states that are relevant for various pseudoclasses.
  1023. // XXXbz this duplicates code in nsCSSRuleProcessor
  1024. static const EventStates sPseudoClassStates[] = {
  1025. #define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
  1026. EventStates(),
  1027. #define CSS_STATE_PSEUDO_CLASS(_name, _value, _flags, _pref, _states) \
  1028. _states,
  1029. #include "nsCSSPseudoClassList.h"
  1030. #undef CSS_STATE_PSEUDO_CLASS
  1031. #undef CSS_PSEUDO_CLASS
  1032. // Add more entries for our fake values to make sure we can't
  1033. // index out of bounds into this array no matter what.
  1034. EventStates(),
  1035. EventStates()
  1036. };
  1037. static_assert(MOZ_ARRAY_LENGTH(sPseudoClassStates) ==
  1038. static_cast<size_t>(CSSPseudoClassType::MAX),
  1039. "Length of PseudoClassStates array is incorrect");
  1040. nsCOMPtr<nsIAtom> atom = NS_Atomize(aStatePseudo);
  1041. CSSPseudoClassType type = nsCSSPseudoClasses::
  1042. GetPseudoType(atom, CSSEnabledState::eIgnoreEnabledState);
  1043. // Ignore :any-link so we don't give the element simultaneous
  1044. // visited and unvisited style state
  1045. if (type == CSSPseudoClassType::anyLink ||
  1046. type == CSSPseudoClassType::mozAnyLink) {
  1047. return EventStates();
  1048. }
  1049. // Our array above is long enough that indexing into it with
  1050. // NotPseudo is ok.
  1051. return sPseudoClassStates[static_cast<CSSPseudoClassTypeBase>(type)];
  1052. }
  1053. NS_IMETHODIMP
  1054. inDOMUtils::GetCSSPseudoElementNames(uint32_t* aLength, char16_t*** aNames)
  1055. {
  1056. nsTArray<nsIAtom*> array;
  1057. const CSSPseudoElementTypeBase pseudoCount =
  1058. static_cast<CSSPseudoElementTypeBase>(CSSPseudoElementType::Count);
  1059. for (CSSPseudoElementTypeBase i = 0; i < pseudoCount; ++i) {
  1060. CSSPseudoElementType type = static_cast<CSSPseudoElementType>(i);
  1061. if (nsCSSPseudoElements::IsEnabled(type, CSSEnabledState::eForAllContent)) {
  1062. nsIAtom* atom = nsCSSPseudoElements::GetPseudoAtom(type);
  1063. array.AppendElement(atom);
  1064. }
  1065. }
  1066. *aLength = array.Length();
  1067. char16_t** ret =
  1068. static_cast<char16_t**>(moz_xmalloc(*aLength * sizeof(char16_t*)));
  1069. for (uint32_t i = 0; i < *aLength; ++i) {
  1070. ret[i] = ToNewUnicode(nsDependentAtomString(array[i]));
  1071. }
  1072. *aNames = ret;
  1073. return NS_OK;
  1074. }
  1075. NS_IMETHODIMP
  1076. inDOMUtils::AddPseudoClassLock(nsIDOMElement *aElement,
  1077. const nsAString &aPseudoClass)
  1078. {
  1079. EventStates state = GetStatesForPseudoClass(aPseudoClass);
  1080. if (state.IsEmpty()) {
  1081. return NS_OK;
  1082. }
  1083. nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
  1084. NS_ENSURE_ARG_POINTER(element);
  1085. element->LockStyleStates(state);
  1086. return NS_OK;
  1087. }
  1088. NS_IMETHODIMP
  1089. inDOMUtils::RemovePseudoClassLock(nsIDOMElement *aElement,
  1090. const nsAString &aPseudoClass)
  1091. {
  1092. EventStates state = GetStatesForPseudoClass(aPseudoClass);
  1093. if (state.IsEmpty()) {
  1094. return NS_OK;
  1095. }
  1096. nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
  1097. NS_ENSURE_ARG_POINTER(element);
  1098. element->UnlockStyleStates(state);
  1099. return NS_OK;
  1100. }
  1101. NS_IMETHODIMP
  1102. inDOMUtils::HasPseudoClassLock(nsIDOMElement *aElement,
  1103. const nsAString &aPseudoClass,
  1104. bool *_retval)
  1105. {
  1106. EventStates state = GetStatesForPseudoClass(aPseudoClass);
  1107. if (state.IsEmpty()) {
  1108. *_retval = false;
  1109. return NS_OK;
  1110. }
  1111. nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
  1112. NS_ENSURE_ARG_POINTER(element);
  1113. EventStates locks = element->LockedStyleStates();
  1114. *_retval = locks.HasAllStates(state);
  1115. return NS_OK;
  1116. }
  1117. NS_IMETHODIMP
  1118. inDOMUtils::ClearPseudoClassLocks(nsIDOMElement *aElement)
  1119. {
  1120. nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
  1121. NS_ENSURE_ARG_POINTER(element);
  1122. element->ClearStyleStateLocks();
  1123. return NS_OK;
  1124. }
  1125. NS_IMETHODIMP
  1126. inDOMUtils::ParseStyleSheet(nsIDOMCSSStyleSheet *aSheet,
  1127. const nsAString& aInput)
  1128. {
  1129. RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
  1130. NS_ENSURE_ARG_POINTER(sheet);
  1131. return sheet->ReparseSheet(aInput);
  1132. }
  1133. NS_IMETHODIMP
  1134. inDOMUtils::ScrollElementIntoView(nsIDOMElement *aElement)
  1135. {
  1136. nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
  1137. NS_ENSURE_ARG_POINTER(content);
  1138. nsIPresShell* presShell = content->OwnerDoc()->GetShell();
  1139. if (!presShell) {
  1140. return NS_OK;
  1141. }
  1142. presShell->ScrollContentIntoView(content,
  1143. nsIPresShell::ScrollAxis(),
  1144. nsIPresShell::ScrollAxis(),
  1145. nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
  1146. return NS_OK;
  1147. }