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/. */
6 #include "mozilla/ArrayUtils.h"
7 #include "mozilla/EventStates.h"
9 #include "inDOMUtils.h"
10 #include "inLayoutUtils.h"
12 #include "nsIServiceManager.h"
13 #include "nsISupportsArray.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"
34 #include "nsContentList.h"
35 #include "mozilla/CSSStyleSheet.h"
36 #include "mozilla/dom/Element.h"
37 #include "nsRuleWalker.h"
38 #include "nsRuleProcessorData.h"
39 #include "nsCSSRuleProcessor.h"
40 #include "mozilla/dom/InspectorUtilsBinding.h"
41 #include "mozilla/dom/ToJSValue.h"
42 #include "nsCSSParser.h"
43 #include "nsCSSProps.h"
44 #include "nsCSSValue.h"
46 #include "nsStyleSet.h"
47 #include "nsStyleUtil.h"
49 using namespace mozilla
;
50 using namespace mozilla::css
;
51 using namespace mozilla::dom
;
53 ///////////////////////////////////////////////////////////////////////////////
55 inDOMUtils::inDOMUtils()
59 inDOMUtils::~inDOMUtils()
63 NS_IMPL_ISUPPORTS(inDOMUtils
, inIDOMUtils
)
65 ///////////////////////////////////////////////////////////////////////////////
69 inDOMUtils::GetAllStyleSheets(nsIDOMDocument
*aDocument
, uint32_t *aLength
,
70 nsISupports
***aSheets
)
72 NS_ENSURE_ARG_POINTER(aDocument
);
74 nsCOMArray
<nsISupports
> sheets
;
76 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(aDocument
);
79 // Get the agent, then user sheets in the style set.
80 nsIPresShell
* presShell
= document
->GetShell();
82 nsStyleSet
* styleSet
= presShell
->StyleSet();
83 nsStyleSet::sheetType sheetType
= nsStyleSet::eAgentSheet
;
84 for (int32_t i
= 0; i
< styleSet
->SheetCount(sheetType
); i
++) {
85 sheets
.AppendElement(styleSet
->StyleSheetAt(sheetType
, i
));
87 sheetType
= nsStyleSet::eUserSheet
;
88 for (int32_t i
= 0; i
< styleSet
->SheetCount(sheetType
); i
++) {
89 sheets
.AppendElement(styleSet
->StyleSheetAt(sheetType
, i
));
93 // Get the document sheets.
94 for (int32_t i
= 0; i
< document
->GetNumberOfStyleSheets(); i
++) {
95 sheets
.AppendElement(document
->GetStyleSheetAt(i
));
98 nsISupports
** ret
= static_cast<nsISupports
**>(NS_Alloc(sheets
.Count() *
99 sizeof(nsISupports
*)));
101 for (int32_t i
= 0; i
< sheets
.Count(); i
++) {
102 NS_ADDREF(ret
[i
] = sheets
[i
]);
105 *aLength
= sheets
.Count();
112 inDOMUtils::IsIgnorableWhitespace(nsIDOMCharacterData
*aDataNode
,
115 NS_PRECONDITION(aReturn
, "Must have an out parameter");
117 NS_ENSURE_ARG_POINTER(aDataNode
);
121 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aDataNode
);
122 NS_ASSERTION(content
, "Does not implement nsIContent!");
124 if (!content
->TextIsOnlyWhitespace()) {
128 // Okay. We have only white space. Let's check the white-space
129 // property now and make sure that this isn't preformatted text...
130 nsIFrame
* frame
= content
->GetPrimaryFrame();
132 const nsStyleText
* text
= frame
->StyleText();
133 *aReturn
= !text
->WhiteSpaceIsSignificant();
136 // empty inter-tag text node without frame, e.g., in between <table>\n<tr>
144 inDOMUtils::GetParentForNode(nsIDOMNode
* aNode
,
145 bool aShowingAnonymousContent
,
146 nsIDOMNode
** aParent
)
148 NS_ENSURE_ARG_POINTER(aNode
);
150 // First do the special cases -- document nodes and anonymous content
151 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aNode
));
152 nsCOMPtr
<nsIDOMNode
> parent
;
155 parent
= inLayoutUtils::GetContainerFor(*doc
);
156 } else if (aShowingAnonymousContent
) {
157 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aNode
);
159 nsIContent
* bparent
= content
->GetXBLInsertionParent();
160 parent
= do_QueryInterface(bparent
);
165 // Ok, just get the normal DOM parent node
166 aNode
->GetParentNode(getter_AddRefs(parent
));
169 NS_IF_ADDREF(*aParent
= parent
);
174 inDOMUtils::GetChildrenForNode(nsIDOMNode
* aNode
,
175 bool aShowingAnonymousContent
,
176 nsIDOMNodeList
** aChildren
)
178 NS_ENSURE_ARG_POINTER(aNode
);
179 NS_PRECONDITION(aChildren
, "Must have an out parameter");
181 nsCOMPtr
<nsIDOMNodeList
> kids
;
183 if (aShowingAnonymousContent
) {
184 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aNode
);
186 kids
= content
->GetChildren(nsIContent::eAllChildren
);
191 aNode
->GetChildNodes(getter_AddRefs(kids
));
194 kids
.forget(aChildren
);
199 inDOMUtils::GetCSSStyleRules(nsIDOMElement
*aElement
,
200 const nsAString
& aPseudo
,
201 nsISupportsArray
**_retval
)
203 NS_ENSURE_ARG_POINTER(aElement
);
207 nsCOMPtr
<nsIAtom
> pseudoElt
;
208 if (!aPseudo
.IsEmpty()) {
209 pseudoElt
= do_GetAtom(aPseudo
);
212 nsRuleNode
* ruleNode
= nullptr;
213 nsCOMPtr
<Element
> element
= do_QueryInterface(aElement
);
214 NS_ENSURE_STATE(element
);
215 nsRefPtr
<nsStyleContext
> styleContext
;
216 GetRuleNodeForElement(element
, pseudoElt
, getter_AddRefs(styleContext
), &ruleNode
);
218 // This can fail for elements that are not in the document or
219 // if the document they're in doesn't have a presshell. Bail out.
223 nsCOMPtr
<nsISupportsArray
> rules
;
224 NS_NewISupportsArray(getter_AddRefs(rules
));
225 if (!rules
) return NS_ERROR_OUT_OF_MEMORY
;
227 nsRefPtr
<mozilla::css::StyleRule
> cssRule
;
228 for ( ; !ruleNode
->IsRoot(); ruleNode
= ruleNode
->GetParent()) {
229 cssRule
= do_QueryObject(ruleNode
->GetRule());
231 nsCOMPtr
<nsIDOMCSSRule
> domRule
= cssRule
->GetDOMRule();
233 rules
->InsertElementAt(domRule
, 0);
243 static already_AddRefed
<StyleRule
>
244 GetRuleFromDOMRule(nsIDOMCSSStyleRule
*aRule
, ErrorResult
& rv
)
246 nsCOMPtr
<nsICSSStyleRuleDOMWrapper
> rule
= do_QueryInterface(aRule
);
248 rv
.Throw(NS_ERROR_INVALID_POINTER
);
252 nsRefPtr
<StyleRule
> cssrule
;
253 rv
= rule
->GetCSSStyleRule(getter_AddRefs(cssrule
));
259 rv
.Throw(NS_ERROR_FAILURE
);
261 return cssrule
.forget();
265 inDOMUtils::GetRuleLine(nsIDOMCSSRule
* aRule
, uint32_t* _retval
)
267 NS_ENSURE_ARG_POINTER(aRule
);
269 Rule
* rule
= aRule
->GetCSSRule();
271 return NS_ERROR_FAILURE
;
274 *_retval
= rule
->GetLineNumber();
279 inDOMUtils::GetRuleColumn(nsIDOMCSSRule
* aRule
, uint32_t* _retval
)
281 NS_ENSURE_ARG_POINTER(aRule
);
283 Rule
* rule
= aRule
->GetCSSRule();
285 return NS_ERROR_FAILURE
;
288 *_retval
= rule
->GetColumnNumber();
293 inDOMUtils::GetSelectorCount(nsIDOMCSSStyleRule
* aRule
, uint32_t *aCount
)
296 nsRefPtr
<StyleRule
> rule
= GetRuleFromDOMRule(aRule
, rv
);
298 return rv
.ErrorCode();
302 for (nsCSSSelectorList
* sel
= rule
->Selector(); sel
; sel
= sel
->mNext
) {
309 static nsCSSSelectorList
*
310 GetSelectorAtIndex(nsIDOMCSSStyleRule
* aRule
, uint32_t aIndex
, ErrorResult
& rv
)
312 nsRefPtr
<StyleRule
> rule
= GetRuleFromDOMRule(aRule
, rv
);
317 for (nsCSSSelectorList
* sel
= rule
->Selector(); sel
;
318 sel
= sel
->mNext
, --aIndex
) {
324 // Ran out of selectors
325 rv
.Throw(NS_ERROR_INVALID_ARG
);
330 inDOMUtils::GetSelectorText(nsIDOMCSSStyleRule
* aRule
,
331 uint32_t aSelectorIndex
,
335 nsCSSSelectorList
* sel
= GetSelectorAtIndex(aRule
, aSelectorIndex
, rv
);
337 return rv
.ErrorCode();
340 nsRefPtr
<StyleRule
> rule
= GetRuleFromDOMRule(aRule
, rv
);
341 MOZ_ASSERT(!rv
.Failed(), "How could we get a selector but not a rule?");
343 sel
->mSelectors
->ToString(aText
, rule
->GetStyleSheet(), false);
348 inDOMUtils::GetSpecificity(nsIDOMCSSStyleRule
* aRule
,
349 uint32_t aSelectorIndex
,
350 uint64_t* aSpecificity
)
353 nsCSSSelectorList
* sel
= GetSelectorAtIndex(aRule
, aSelectorIndex
, rv
);
355 return rv
.ErrorCode();
358 *aSpecificity
= sel
->mWeight
;
363 inDOMUtils::SelectorMatchesElement(nsIDOMElement
* aElement
,
364 nsIDOMCSSStyleRule
* aRule
,
365 uint32_t aSelectorIndex
,
366 const nsAString
& aPseudo
,
369 nsCOMPtr
<Element
> element
= do_QueryInterface(aElement
);
370 NS_ENSURE_ARG_POINTER(element
);
373 nsCSSSelectorList
* tail
= GetSelectorAtIndex(aRule
, aSelectorIndex
, rv
);
375 return rv
.ErrorCode();
378 // We want just the one list item, not the whole list tail
379 nsAutoPtr
<nsCSSSelectorList
> sel(tail
->Clone(false));
381 // Do not attempt to match if a pseudo element is requested and this is not
382 // a pseudo element selector, or vice versa.
383 if (aPseudo
.IsEmpty() == sel
->mSelectors
->IsPseudoElement()) {
388 if (!aPseudo
.IsEmpty()) {
389 // We need to make sure that the requested pseudo element type
390 // matches the selector pseudo element type before proceeding.
391 nsCOMPtr
<nsIAtom
> pseudoElt
= do_GetAtom(aPseudo
);
392 if (sel
->mSelectors
->PseudoType() !=
393 nsCSSPseudoElements::GetPseudoType(pseudoElt
)) {
398 // We have a matching pseudo element, now remove it so we can compare
399 // directly against |element| when proceeding into SelectorListMatches.
400 // It's OK to do this - we just cloned sel and nothing else is using it.
401 sel
->RemoveRightmostSelector();
404 element
->OwnerDoc()->FlushPendingLinkUpdates();
405 // XXXbz what exactly should we do with visited state here?
406 TreeMatchContext
matchingContext(false,
407 nsRuleWalker::eRelevantLinkUnvisited
,
409 TreeMatchContext::eNeverMatchVisited
);
410 *aMatches
= nsCSSRuleProcessor::SelectorListMatches(element
, matchingContext
,
416 inDOMUtils::IsInheritedProperty(const nsAString
&aPropertyName
, bool *_retval
)
419 nsCSSProps::LookupProperty(aPropertyName
, nsCSSProps::eIgnoreEnabledState
);
420 if (prop
== eCSSProperty_UNKNOWN
) {
425 if (prop
== eCSSPropertyExtra_variable
) {
430 if (nsCSSProps::IsShorthand(prop
)) {
431 prop
= nsCSSProps::SubpropertyEntryFor(prop
)[0];
434 nsStyleStructID sid
= nsCSSProps::kSIDTable
[prop
];
435 *_retval
= !nsCachedStyleData::IsReset(sid
);
439 extern const char* const kCSSRawProperties
[];
442 inDOMUtils::GetCSSPropertyNames(uint32_t aFlags
, uint32_t* aCount
,
445 // maxCount is the largest number of properties we could have; our actual
446 // number might be smaller because properties might be disabled.
448 if (aFlags
& EXCLUDE_SHORTHANDS
) {
449 maxCount
= eCSSProperty_COUNT_no_shorthands
;
451 maxCount
= eCSSProperty_COUNT
;
454 if (aFlags
& INCLUDE_ALIASES
) {
455 maxCount
+= (eCSSProperty_COUNT_with_aliases
- eCSSProperty_COUNT
);
459 static_cast<char16_t
**>(nsMemory::Alloc(maxCount
* sizeof(char16_t
*)));
461 #define DO_PROP(_prop) \
463 nsCSSProperty cssProp = nsCSSProperty(_prop); \
464 if (nsCSSProps::IsEnabled(cssProp)) { \
466 ToNewUnicode(nsDependentCString(kCSSRawProperties[_prop])); \
471 // prop is the property id we're considering; propCount is how many properties
472 // we've put into props so far.
473 uint32_t prop
= 0, propCount
= 0;
474 for ( ; prop
< eCSSProperty_COUNT_no_shorthands
; ++prop
) {
475 if (nsCSSProps::PropertyParseType(nsCSSProperty(prop
)) !=
476 CSS_PROPERTY_PARSE_INACCESSIBLE
) {
481 if (!(aFlags
& EXCLUDE_SHORTHANDS
)) {
482 for ( ; prop
< eCSSProperty_COUNT
; ++prop
) {
483 // Some shorthands are also aliases
484 if ((aFlags
& INCLUDE_ALIASES
) ||
485 !nsCSSProps::PropHasFlags(nsCSSProperty(prop
),
486 CSS_PROPERTY_IS_ALIAS
)) {
492 if (aFlags
& INCLUDE_ALIASES
) {
493 for (prop
= eCSSProperty_COUNT
; prop
< eCSSProperty_COUNT_with_aliases
; ++prop
) {
506 static void InsertNoDuplicates(nsTArray
<nsString
>& aArray
,
507 const nsAString
& aString
)
509 size_t i
= aArray
.IndexOfFirstElementGt(aString
);
510 if (i
> 0 && aArray
[i
-1].Equals(aString
)) {
513 aArray
.InsertElementAt(i
, aString
);
516 static void GetKeywordsForProperty(const nsCSSProperty aProperty
,
517 nsTArray
<nsString
>& aArray
)
519 if (nsCSSProps::IsShorthand(aProperty
)) {
520 // Shorthand props have no keywords.
523 const nsCSSProps::KTableValue
*keywordTable
=
524 nsCSSProps::kKeywordTableTable
[aProperty
];
525 if (keywordTable
&& keywordTable
!= nsCSSProps::kBoxPropSourceKTable
) {
527 while (nsCSSKeyword(keywordTable
[i
]) != eCSSKeyword_UNKNOWN
) {
528 nsCSSKeyword word
= nsCSSKeyword(keywordTable
[i
]);
529 InsertNoDuplicates(aArray
,
530 NS_ConvertASCIItoUTF16(nsCSSKeywords::GetStringValue(word
)));
531 // Increment counter by 2, because in this table every second
532 // element is a nsCSSKeyword.
538 static void GetColorsForProperty(const uint32_t aParserVariant
,
539 nsTArray
<nsString
>& aArray
)
541 if (aParserVariant
& VARIANT_COLOR
) {
542 // GetKeywordsForProperty and GetOtherValuesForProperty assume aArray is sorted,
543 // and if aArray is not empty here, then it's not going to be sorted coming out.
544 MOZ_ASSERT(aArray
.Length() == 0);
546 const char * const *allColorNames
= NS_AllColorNames(&size
);
547 for (size_t i
= 0; i
< size
; i
++) {
548 CopyASCIItoUTF16(allColorNames
[i
], *aArray
.AppendElement());
554 static void GetOtherValuesForProperty(const uint32_t aParserVariant
,
555 nsTArray
<nsString
>& aArray
)
557 if (aParserVariant
& VARIANT_AUTO
) {
558 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("auto"));
560 if (aParserVariant
& VARIANT_NORMAL
) {
561 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("normal"));
563 if(aParserVariant
& VARIANT_ALL
) {
564 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("all"));
566 if (aParserVariant
& VARIANT_NONE
) {
567 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("none"));
569 if (aParserVariant
& VARIANT_ELEMENT
) {
570 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("-moz-element"));
572 if (aParserVariant
& VARIANT_IMAGE_RECT
) {
573 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("-moz-image-rect"));
575 if (aParserVariant
& VARIANT_COLOR
) {
576 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("rgb"));
577 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("hsl"));
578 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("rgba"));
579 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("hsla"));
581 if (aParserVariant
& VARIANT_TIMING_FUNCTION
) {
582 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("cubic-bezier"));
583 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("steps"));
585 if (aParserVariant
& VARIANT_CALC
) {
586 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("calc"));
587 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("-moz-calc"));
589 if (aParserVariant
& VARIANT_URL
) {
590 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("url"));
592 if (aParserVariant
& VARIANT_GRADIENT
) {
593 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("linear-gradient"));
594 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("radial-gradient"));
595 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("repeating-linear-gradient"));
596 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("repeating-radial-gradient"));
597 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("-moz-linear-gradient"));
598 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("-moz-radial-gradient"));
599 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("-moz-repeating-linear-gradient"));
600 InsertNoDuplicates(aArray
, NS_LITERAL_STRING("-moz-repeating-radial-gradient"));
605 inDOMUtils::GetSubpropertiesForCSSProperty(const nsAString
& aProperty
,
609 nsCSSProperty propertyID
=
610 nsCSSProps::LookupProperty(aProperty
, nsCSSProps::eEnabledForAllContent
);
612 if (propertyID
== eCSSProperty_UNKNOWN
||
613 propertyID
== eCSSPropertyExtra_variable
) {
614 return NS_ERROR_FAILURE
;
617 nsTArray
<nsString
> array
;
618 if (!nsCSSProps::IsShorthand(propertyID
)) {
619 *aValues
= static_cast<char16_t
**>(nsMemory::Alloc(sizeof(char16_t
*)));
620 (*aValues
)[0] = ToNewUnicode(nsCSSProps::GetStringValue(propertyID
));
625 // Count up how many subproperties we have.
626 size_t subpropCount
= 0;
627 for (const nsCSSProperty
*props
= nsCSSProps::SubpropertyEntryFor(propertyID
);
628 *props
!= eCSSProperty_UNKNOWN
; ++props
) {
633 static_cast<char16_t
**>(nsMemory::Alloc(subpropCount
* sizeof(char16_t
*)));
634 *aLength
= subpropCount
;
635 for (const nsCSSProperty
*props
= nsCSSProps::SubpropertyEntryFor(propertyID
),
636 *props_start
= props
;
637 *props
!= eCSSProperty_UNKNOWN
; ++props
) {
638 (*aValues
)[props
-props_start
] = ToNewUnicode(nsCSSProps::GetStringValue(*props
));
644 inDOMUtils::CssPropertyIsShorthand(const nsAString
& aProperty
, bool *_retval
)
646 nsCSSProperty propertyID
=
647 nsCSSProps::LookupProperty(aProperty
, nsCSSProps::eEnabledForAllContent
);
648 if (propertyID
== eCSSProperty_UNKNOWN
) {
649 return NS_ERROR_FAILURE
;
652 *_retval
= nsCSSProps::IsShorthand(propertyID
);
657 inDOMUtils::CssPropertySupportsType(const nsAString
& aProperty
, uint32_t aType
,
660 nsCSSProperty propertyID
=
661 nsCSSProps::LookupProperty(aProperty
, nsCSSProps::eEnabledForAllContent
);
662 if (propertyID
== eCSSProperty_UNKNOWN
) {
663 return NS_ERROR_FAILURE
;
669 variant
= VARIANT_LENGTH
;
671 case TYPE_PERCENTAGE
:
672 variant
= VARIANT_PERCENT
;
675 variant
= VARIANT_COLOR
;
678 variant
= VARIANT_URL
;
681 variant
= VARIANT_ANGLE
;
684 variant
= VARIANT_FREQUENCY
;
687 variant
= VARIANT_TIME
;
690 variant
= VARIANT_GRADIENT
;
692 case TYPE_TIMING_FUNCTION
:
693 variant
= VARIANT_TIMING_FUNCTION
;
695 case TYPE_IMAGE_RECT
:
696 variant
= VARIANT_IMAGE_RECT
;
699 // Include integers under "number"?
700 variant
= VARIANT_NUMBER
| VARIANT_INTEGER
;
704 return NS_ERROR_NOT_AVAILABLE
;
707 if (!nsCSSProps::IsShorthand(propertyID
)) {
708 *_retval
= nsCSSProps::ParserVariant(propertyID
) & variant
;
712 for (const nsCSSProperty
* props
= nsCSSProps::SubpropertyEntryFor(propertyID
);
713 *props
!= eCSSProperty_UNKNOWN
; ++props
) {
714 if (nsCSSProps::ParserVariant(*props
) & variant
) {
725 inDOMUtils::GetCSSValuesForProperty(const nsAString
& aProperty
,
729 nsCSSProperty propertyID
= nsCSSProps::LookupProperty(aProperty
,
730 nsCSSProps::eEnabledForAllContent
);
731 if (propertyID
== eCSSProperty_UNKNOWN
) {
732 return NS_ERROR_FAILURE
;
735 nsTArray
<nsString
> array
;
736 // We start collecting the values, BUT colors need to go in first, because array
737 // needs to stay sorted, and the colors are sorted, so we just append them.
738 if (propertyID
== eCSSPropertyExtra_variable
) {
739 // No other values we can report.
740 } else if (!nsCSSProps::IsShorthand(propertyID
)) {
741 // Property is longhand.
742 uint32_t propertyParserVariant
= nsCSSProps::ParserVariant(propertyID
);
744 GetColorsForProperty(propertyParserVariant
, array
);
745 if (propertyParserVariant
& VARIANT_KEYWORD
) {
746 GetKeywordsForProperty(propertyID
, array
);
748 GetOtherValuesForProperty(propertyParserVariant
, array
);
750 // Property is shorthand.
751 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty
, propertyID
) {
752 // Get colors (once) first.
753 uint32_t propertyParserVariant
= nsCSSProps::ParserVariant(*subproperty
);
754 if (propertyParserVariant
& VARIANT_COLOR
) {
755 GetColorsForProperty(propertyParserVariant
, array
);
759 CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty
, propertyID
) {
760 uint32_t propertyParserVariant
= nsCSSProps::ParserVariant(*subproperty
);
761 if (propertyParserVariant
& VARIANT_KEYWORD
) {
762 GetKeywordsForProperty(*subproperty
, array
);
764 GetOtherValuesForProperty(propertyParserVariant
, array
);
767 // All CSS properties take initial, inherit and unset.
768 InsertNoDuplicates(array
, NS_LITERAL_STRING("initial"));
769 InsertNoDuplicates(array
, NS_LITERAL_STRING("inherit"));
770 InsertNoDuplicates(array
, NS_LITERAL_STRING("unset"));
772 *aLength
= array
.Length();
774 static_cast<char16_t
**>(NS_Alloc(*aLength
* sizeof(char16_t
*)));
775 for (uint32_t i
= 0; i
< *aLength
; ++i
) {
776 ret
[i
] = ToNewUnicode(array
[i
]);
783 inDOMUtils::ColorNameToRGB(const nsAString
& aColorName
, JSContext
* aCx
,
784 JS::MutableHandle
<JS::Value
> aValue
)
787 if (!NS_ColorNameToRGB(aColorName
, &color
)) {
788 return NS_ERROR_INVALID_ARG
;
791 InspectorRGBTriple triple
;
792 triple
.mR
= NS_GET_R(color
);
793 triple
.mG
= NS_GET_G(color
);
794 triple
.mB
= NS_GET_B(color
);
796 if (!ToJSValue(aCx
, triple
, aValue
)) {
797 return NS_ERROR_FAILURE
;
804 inDOMUtils::RgbToColorName(uint8_t aR
, uint8_t aG
, uint8_t aB
,
805 nsAString
& aColorName
)
807 const char* color
= NS_RGBToColorName(NS_RGB(aR
, aG
, aB
));
809 aColorName
.Truncate();
810 return NS_ERROR_INVALID_ARG
;
813 aColorName
.AssignASCII(color
);
818 inDOMUtils::ColorToRGBA(const nsAString
& aColorString
, JSContext
* aCx
,
819 JS::MutableHandle
<JS::Value
> aValue
)
822 nsCSSParser cssParser
;
825 bool isColor
= cssParser
.ParseColorString(aColorString
, nullptr, 0,
833 nsRuleNode::ComputeColor(cssValue
, nullptr, nullptr, color
);
835 InspectorRGBATuple tuple
;
836 tuple
.mR
= NS_GET_R(color
);
837 tuple
.mG
= NS_GET_G(color
);
838 tuple
.mB
= NS_GET_B(color
);
839 tuple
.mA
= nsStyleUtil::ColorComponentToFloat(NS_GET_A(color
));
841 if (!ToJSValue(aCx
, tuple
, aValue
)) {
842 return NS_ERROR_FAILURE
;
849 inDOMUtils::IsValidCSSColor(const nsAString
& aColorString
, bool *_retval
)
851 nsCSSParser cssParser
;
853 *_retval
= cssParser
.ParseColorString(aColorString
, nullptr, 0, cssValue
, true);
858 inDOMUtils::CssPropertyIsValid(const nsAString
& aPropertyName
,
859 const nsAString
& aPropertyValue
,
862 nsCSSProperty propertyID
=
863 nsCSSProps::LookupProperty(aPropertyName
, nsCSSProps::eIgnoreEnabledState
);
865 if (propertyID
== eCSSProperty_UNKNOWN
) {
870 // Get a parser, parse the property.
872 *_retval
= parser
.IsValueValidForProperty(propertyID
, aPropertyValue
);
878 inDOMUtils::GetBindingURLs(nsIDOMElement
*aElement
, nsIArray
**_retval
)
880 NS_ENSURE_ARG_POINTER(aElement
);
884 nsCOMPtr
<nsIMutableArray
> urls
= do_CreateInstance(NS_ARRAY_CONTRACTID
);
886 return NS_ERROR_FAILURE
;
888 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aElement
);
889 NS_ENSURE_ARG_POINTER(content
);
891 nsXBLBinding
*binding
= content
->GetXBLBinding();
894 urls
->AppendElement(binding
->PrototypeBinding()->BindingURI(), false);
895 binding
= binding
->GetBaseBinding();
898 NS_ADDREF(*_retval
= urls
);
903 inDOMUtils::SetContentState(nsIDOMElement
* aElement
,
904 EventStates::InternalType aState
)
906 NS_ENSURE_ARG_POINTER(aElement
);
908 nsRefPtr
<EventStateManager
> esm
=
909 inLayoutUtils::GetEventStateManagerFor(aElement
);
911 nsCOMPtr
<nsIContent
> content
;
912 content
= do_QueryInterface(aElement
);
914 // XXX Invalid cast of bool to nsresult (bug 778108)
915 return (nsresult
)esm
->SetContentState(content
, EventStates(aState
));
918 return NS_ERROR_FAILURE
;
922 inDOMUtils::GetContentState(nsIDOMElement
* aElement
,
923 EventStates::InternalType
* aState
)
926 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aElement
);
927 NS_ENSURE_ARG_POINTER(content
);
929 // NOTE: if this method is removed,
930 // please remove GetInternalValue from EventStates
931 *aState
= content
->AsElement()->State().GetInternalValue();
935 /* static */ nsresult
936 inDOMUtils::GetRuleNodeForElement(dom::Element
* aElement
,
938 nsStyleContext
** aStyleContext
,
939 nsRuleNode
** aRuleNode
)
941 MOZ_ASSERT(aElement
);
943 *aRuleNode
= nullptr;
944 *aStyleContext
= nullptr;
946 nsIDocument
* doc
= aElement
->GetComposedDoc();
947 NS_ENSURE_TRUE(doc
, NS_ERROR_UNEXPECTED
);
949 nsIPresShell
*presShell
= doc
->GetShell();
950 NS_ENSURE_TRUE(presShell
, NS_ERROR_UNEXPECTED
);
952 nsPresContext
*presContext
= presShell
->GetPresContext();
953 NS_ENSURE_TRUE(presContext
, NS_ERROR_UNEXPECTED
);
955 presContext
->EnsureSafeToHandOutCSSRules();
957 nsRefPtr
<nsStyleContext
> sContext
=
958 nsComputedDOMStyle::GetStyleContextForElement(aElement
, aPseudo
, presShell
);
960 *aRuleNode
= sContext
->RuleNode();
961 sContext
.forget(aStyleContext
);
967 inDOMUtils::GetUsedFontFaces(nsIDOMRange
* aRange
,
968 nsIDOMFontFaceList
** aFontFaceList
)
970 return static_cast<nsRange
*>(aRange
)->GetUsedFontFaces(aFontFaceList
);
974 GetStatesForPseudoClass(const nsAString
& aStatePseudo
)
976 // An array of the states that are relevant for various pseudoclasses.
977 // XXXbz this duplicates code in nsCSSRuleProcessor
978 static const EventStates sPseudoClassStates
[] = {
979 #define CSS_PSEUDO_CLASS(_name, _value, _pref) \
981 #define CSS_STATE_PSEUDO_CLASS(_name, _value, _pref, _states) \
983 #include "nsCSSPseudoClassList.h"
984 #undef CSS_STATE_PSEUDO_CLASS
985 #undef CSS_PSEUDO_CLASS
987 // Add more entries for our fake values to make sure we can't
988 // index out of bounds into this array no matter what.
992 static_assert(MOZ_ARRAY_LENGTH(sPseudoClassStates
) ==
993 nsCSSPseudoClasses::ePseudoClass_NotPseudoClass
+ 1,
994 "Length of PseudoClassStates array is incorrect");
996 nsCOMPtr
<nsIAtom
> atom
= do_GetAtom(aStatePseudo
);
998 // Ignore :moz-any-link so we don't give the element simultaneous
999 // visited and unvisited style state
1000 if (nsCSSPseudoClasses::GetPseudoType(atom
) ==
1001 nsCSSPseudoClasses::ePseudoClass_mozAnyLink
) {
1002 return EventStates();
1004 // Our array above is long enough that indexing into it with
1005 // NotPseudoClass is ok.
1006 return sPseudoClassStates
[nsCSSPseudoClasses::GetPseudoType(atom
)];
1010 inDOMUtils::AddPseudoClassLock(nsIDOMElement
*aElement
,
1011 const nsAString
&aPseudoClass
)
1013 EventStates state
= GetStatesForPseudoClass(aPseudoClass
);
1014 if (state
.IsEmpty()) {
1018 nsCOMPtr
<mozilla::dom::Element
> element
= do_QueryInterface(aElement
);
1019 NS_ENSURE_ARG_POINTER(element
);
1021 element
->LockStyleStates(state
);
1027 inDOMUtils::RemovePseudoClassLock(nsIDOMElement
*aElement
,
1028 const nsAString
&aPseudoClass
)
1030 EventStates state
= GetStatesForPseudoClass(aPseudoClass
);
1031 if (state
.IsEmpty()) {
1035 nsCOMPtr
<mozilla::dom::Element
> element
= do_QueryInterface(aElement
);
1036 NS_ENSURE_ARG_POINTER(element
);
1038 element
->UnlockStyleStates(state
);
1044 inDOMUtils::HasPseudoClassLock(nsIDOMElement
*aElement
,
1045 const nsAString
&aPseudoClass
,
1048 EventStates state
= GetStatesForPseudoClass(aPseudoClass
);
1049 if (state
.IsEmpty()) {
1054 nsCOMPtr
<mozilla::dom::Element
> element
= do_QueryInterface(aElement
);
1055 NS_ENSURE_ARG_POINTER(element
);
1057 EventStates locks
= element
->LockedStyleStates();
1059 *_retval
= locks
.HasAllStates(state
);
1064 inDOMUtils::ClearPseudoClassLocks(nsIDOMElement
*aElement
)
1066 nsCOMPtr
<mozilla::dom::Element
> element
= do_QueryInterface(aElement
);
1067 NS_ENSURE_ARG_POINTER(element
);
1069 element
->ClearStyleStateLocks();
1075 inDOMUtils::ParseStyleSheet(nsIDOMCSSStyleSheet
*aSheet
,
1076 const nsAString
& aInput
)
1078 nsRefPtr
<CSSStyleSheet
> sheet
= do_QueryObject(aSheet
);
1079 NS_ENSURE_ARG_POINTER(sheet
);
1081 return sheet
->ParseSheet(aInput
);
1085 inDOMUtils::ScrollElementIntoView(nsIDOMElement
*aElement
)
1087 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aElement
);
1088 NS_ENSURE_ARG_POINTER(content
);
1090 nsIPresShell
* presShell
= content
->OwnerDoc()->GetShell();
1095 presShell
->ScrollContentIntoView(content
,
1096 nsIPresShell::ScrollAxis(),
1097 nsIPresShell::ScrollAxis(),
1098 nsIPresShell::SCROLL_OVERFLOW_HIDDEN
);