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