layout/inspector/inDOMUtils.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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"
    14 #include "nsString.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/dom/Element.h"
    36 #include "nsCSSStyleSheet.h"
    37 #include "nsRuleWalker.h"
    38 #include "nsRuleProcessorData.h"
    39 #include "nsCSSRuleProcessor.h"
    40 #include "mozilla/dom/InspectorUtilsBinding.h"
    41 #include "nsCSSProps.h"
    42 #include "nsColor.h"
    43 #include "nsStyleSet.h"
    45 using namespace mozilla;
    46 using namespace mozilla::css;
    47 using namespace mozilla::dom;
    49 ///////////////////////////////////////////////////////////////////////////////
    51 inDOMUtils::inDOMUtils()
    52 {
    53 }
    55 inDOMUtils::~inDOMUtils()
    56 {
    57 }
    59 NS_IMPL_ISUPPORTS(inDOMUtils, inIDOMUtils)
    61 ///////////////////////////////////////////////////////////////////////////////
    62 // inIDOMUtils
    64 NS_IMETHODIMP
    65 inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
    66                               nsISupports ***aSheets)
    67 {
    68   NS_ENSURE_ARG_POINTER(aDocument);
    70   nsCOMArray<nsISupports> sheets;
    72   nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
    73   MOZ_ASSERT(document);
    75   // Get the agent, then user sheets in the style set.
    76   nsIPresShell* presShell = document->GetShell();
    77   if (presShell) {
    78     nsStyleSet* styleSet = presShell->StyleSet();
    79     nsStyleSet::sheetType sheetType = nsStyleSet::eAgentSheet;
    80     for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
    81       sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
    82     }
    83     sheetType = nsStyleSet::eUserSheet;
    84     for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
    85       sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
    86     }
    87   }
    89   // Get the document sheets.
    90   for (int32_t i = 0; i < document->GetNumberOfStyleSheets(); i++) {
    91     sheets.AppendElement(document->GetStyleSheetAt(i));
    92   }
    94   nsISupports** ret = static_cast<nsISupports**>(NS_Alloc(sheets.Count() *
    95                                                  sizeof(nsISupports*)));
    97   for (int32_t i = 0; i < sheets.Count(); i++) {
    98     NS_ADDREF(ret[i] = sheets[i]);
    99   }
   101   *aLength = sheets.Count();
   102   *aSheets = ret;
   104   return NS_OK;
   105 }
   107 NS_IMETHODIMP
   108 inDOMUtils::IsIgnorableWhitespace(nsIDOMCharacterData *aDataNode,
   109                                   bool *aReturn)
   110 {
   111   NS_PRECONDITION(aReturn, "Must have an out parameter");
   113   NS_ENSURE_ARG_POINTER(aDataNode);
   115   *aReturn = false;
   117   nsCOMPtr<nsIContent> content = do_QueryInterface(aDataNode);
   118   NS_ASSERTION(content, "Does not implement nsIContent!");
   120   if (!content->TextIsOnlyWhitespace()) {
   121     return NS_OK;
   122   }
   124   // Okay.  We have only white space.  Let's check the white-space
   125   // property now and make sure that this isn't preformatted text...
   126   nsIFrame* frame = content->GetPrimaryFrame();
   127   if (frame) {
   128     const nsStyleText* text = frame->StyleText();
   129     *aReturn = !text->WhiteSpaceIsSignificant();
   130   }
   131   else {
   132     // empty inter-tag text node without frame, e.g., in between <table>\n<tr>
   133     *aReturn = true;
   134   }
   136   return NS_OK;
   137 }
   139 NS_IMETHODIMP
   140 inDOMUtils::GetParentForNode(nsIDOMNode* aNode,
   141                              bool aShowingAnonymousContent,
   142                              nsIDOMNode** aParent)
   143 {
   144   NS_ENSURE_ARG_POINTER(aNode);
   146   // First do the special cases -- document nodes and anonymous content
   147   nsCOMPtr<nsIDocument> doc(do_QueryInterface(aNode));
   148   nsCOMPtr<nsIDOMNode> parent;
   150   if (doc) {
   151     parent = inLayoutUtils::GetContainerFor(*doc);
   152   } else if (aShowingAnonymousContent) {
   153     nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   154     if (content) {
   155       nsIContent* bparent = content->GetXBLInsertionParent();
   156       parent = do_QueryInterface(bparent);
   157     }
   158   }
   160   if (!parent) {
   161     // Ok, just get the normal DOM parent node
   162     aNode->GetParentNode(getter_AddRefs(parent));
   163   }
   165   NS_IF_ADDREF(*aParent = parent);
   166   return NS_OK;
   167 }
   169 NS_IMETHODIMP
   170 inDOMUtils::GetChildrenForNode(nsIDOMNode* aNode,
   171                                bool aShowingAnonymousContent,
   172                                nsIDOMNodeList** aChildren)
   173 {
   174   NS_ENSURE_ARG_POINTER(aNode);
   175   NS_PRECONDITION(aChildren, "Must have an out parameter");
   177   nsCOMPtr<nsIDOMNodeList> kids;
   179   if (aShowingAnonymousContent) {
   180     nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   181     if (content) {
   182       kids = content->GetChildren(nsIContent::eAllChildren);
   183     }
   184   }
   186   if (!kids) {
   187     aNode->GetChildNodes(getter_AddRefs(kids));
   188   }
   190   kids.forget(aChildren);
   191   return NS_OK;
   192 }
   194 NS_IMETHODIMP
   195 inDOMUtils::GetCSSStyleRules(nsIDOMElement *aElement,
   196                              const nsAString& aPseudo,
   197                              nsISupportsArray **_retval)
   198 {
   199   NS_ENSURE_ARG_POINTER(aElement);
   201   *_retval = nullptr;
   203   nsCOMPtr<nsIAtom> pseudoElt;
   204   if (!aPseudo.IsEmpty()) {
   205     pseudoElt = do_GetAtom(aPseudo);
   206   }
   208   nsRuleNode* ruleNode = nullptr;
   209   nsCOMPtr<Element> element = do_QueryInterface(aElement);
   210   NS_ENSURE_STATE(element);
   211   nsRefPtr<nsStyleContext> styleContext;
   212   GetRuleNodeForElement(element, pseudoElt, getter_AddRefs(styleContext), &ruleNode);
   213   if (!ruleNode) {
   214     // This can fail for elements that are not in the document or
   215     // if the document they're in doesn't have a presshell.  Bail out.
   216     return NS_OK;
   217   }
   219   nsCOMPtr<nsISupportsArray> rules;
   220   NS_NewISupportsArray(getter_AddRefs(rules));
   221   if (!rules) return NS_ERROR_OUT_OF_MEMORY;
   223   nsRefPtr<mozilla::css::StyleRule> cssRule;
   224   for ( ; !ruleNode->IsRoot(); ruleNode = ruleNode->GetParent()) {
   225     cssRule = do_QueryObject(ruleNode->GetRule());
   226     if (cssRule) {
   227       nsCOMPtr<nsIDOMCSSRule> domRule = cssRule->GetDOMRule();
   228       if (domRule)
   229         rules->InsertElementAt(domRule, 0);
   230     }
   231   }
   233   *_retval = rules;
   234   NS_ADDREF(*_retval);
   236   return NS_OK;
   237 }
   239 static already_AddRefed<StyleRule>
   240 GetRuleFromDOMRule(nsIDOMCSSStyleRule *aRule, ErrorResult& rv)
   241 {
   242   nsCOMPtr<nsICSSStyleRuleDOMWrapper> rule = do_QueryInterface(aRule);
   243   if (!rule) {
   244     rv.Throw(NS_ERROR_INVALID_POINTER);
   245     return nullptr;
   246   }
   248   nsRefPtr<StyleRule> cssrule;
   249   rv = rule->GetCSSStyleRule(getter_AddRefs(cssrule));
   250   if (rv.Failed()) {
   251     return nullptr;
   252   }
   254   if (!cssrule) {
   255     rv.Throw(NS_ERROR_FAILURE);
   256   }
   257   return cssrule.forget();
   258 }
   260 NS_IMETHODIMP
   261 inDOMUtils::GetRuleLine(nsIDOMCSSStyleRule *aRule, uint32_t *_retval)
   262 {
   263   ErrorResult rv;
   264   nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
   265   if (rv.Failed()) {
   266     return rv.ErrorCode();
   267   }
   269   *_retval = rule->GetLineNumber();
   270   return NS_OK;
   271 }
   273 NS_IMETHODIMP
   274 inDOMUtils::GetRuleColumn(nsIDOMCSSStyleRule *aRule, uint32_t *_retval)
   275 {
   276   ErrorResult rv;
   277   nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
   278   if (rv.Failed()) {
   279     return rv.ErrorCode();
   280   }
   281   *_retval = rule->GetColumnNumber();
   282   return NS_OK;
   283 }
   285 NS_IMETHODIMP
   286 inDOMUtils::GetSelectorCount(nsIDOMCSSStyleRule* aRule, uint32_t *aCount)
   287 {
   288   ErrorResult rv;
   289   nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
   290   if (rv.Failed()) {
   291     return rv.ErrorCode();
   292   }
   294   uint32_t count = 0;
   295   for (nsCSSSelectorList* sel = rule->Selector(); sel; sel = sel->mNext) {
   296     ++count;
   297   }
   298   *aCount = count;
   299   return NS_OK;
   300 }
   302 static nsCSSSelectorList*
   303 GetSelectorAtIndex(nsIDOMCSSStyleRule* aRule, uint32_t aIndex, ErrorResult& rv)
   304 {
   305   nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
   306   if (rv.Failed()) {
   307     return nullptr;
   308   }
   310   for (nsCSSSelectorList* sel = rule->Selector(); sel;
   311        sel = sel->mNext, --aIndex) {
   312     if (aIndex == 0) {
   313       return sel;
   314     }
   315   }
   317   // Ran out of selectors
   318   rv.Throw(NS_ERROR_INVALID_ARG);
   319   return nullptr;
   320 }
   322 NS_IMETHODIMP
   323 inDOMUtils::GetSelectorText(nsIDOMCSSStyleRule* aRule,
   324                             uint32_t aSelectorIndex,
   325                             nsAString& aText)
   326 {
   327   ErrorResult rv;
   328   nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
   329   if (rv.Failed()) {
   330     return rv.ErrorCode();
   331   }
   333   nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv);
   334   MOZ_ASSERT(!rv.Failed(), "How could we get a selector but not a rule?");
   336   sel->mSelectors->ToString(aText, rule->GetStyleSheet(), false);
   337   return NS_OK;
   338 }
   340 NS_IMETHODIMP
   341 inDOMUtils::GetSpecificity(nsIDOMCSSStyleRule* aRule,
   342                             uint32_t aSelectorIndex,
   343                             uint64_t* aSpecificity)
   344 {
   345   ErrorResult rv;
   346   nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
   347   if (rv.Failed()) {
   348     return rv.ErrorCode();
   349   }
   351   *aSpecificity = sel->mWeight;
   352   return NS_OK;
   353 }
   355 NS_IMETHODIMP
   356 inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement,
   357                                    nsIDOMCSSStyleRule* aRule,
   358                                    uint32_t aSelectorIndex,
   359                                    bool* aMatches)
   360 {
   361   nsCOMPtr<Element> element = do_QueryInterface(aElement);
   362   NS_ENSURE_ARG_POINTER(element);
   364   ErrorResult rv;
   365   nsCSSSelectorList* tail = GetSelectorAtIndex(aRule, aSelectorIndex, rv);
   366   if (rv.Failed()) {
   367     return rv.ErrorCode();
   368   }
   370   // We want just the one list item, not the whole list tail
   371   nsAutoPtr<nsCSSSelectorList> sel(tail->Clone(false));
   373   // SelectorListMatches does not handle selectors that begin with a
   374   // pseudo-element, which you can get from selectors like
   375   // |input::-moz-placeholder:hover|.  This function doesn't take
   376   // a pseudo-element nsIAtom*, so we know we can't match.
   377   if (sel->mSelectors->IsPseudoElement()) {
   378     *aMatches = false;
   379     return NS_OK;
   380   }
   382   element->OwnerDoc()->FlushPendingLinkUpdates();
   383   // XXXbz what exactly should we do with visited state here?
   384   TreeMatchContext matchingContext(false,
   385                                    nsRuleWalker::eRelevantLinkUnvisited,
   386                                    element->OwnerDoc(),
   387                                    TreeMatchContext::eNeverMatchVisited);
   388   *aMatches = nsCSSRuleProcessor::SelectorListMatches(element, matchingContext,
   389                                                       sel);
   390   return NS_OK;
   391 }
   393 NS_IMETHODIMP
   394 inDOMUtils::IsInheritedProperty(const nsAString &aPropertyName, bool *_retval)
   395 {
   396   nsCSSProperty prop =
   397     nsCSSProps::LookupProperty(aPropertyName, nsCSSProps::eIgnoreEnabledState);
   398   if (prop == eCSSProperty_UNKNOWN) {
   399     *_retval = false;
   400     return NS_OK;
   401   }
   403   if (prop == eCSSPropertyExtra_variable) {
   404     *_retval = true;
   405     return NS_OK;
   406   }
   408   if (nsCSSProps::IsShorthand(prop)) {
   409     prop = nsCSSProps::SubpropertyEntryFor(prop)[0];
   410   }
   412   nsStyleStructID sid = nsCSSProps::kSIDTable[prop];
   413   *_retval = !nsCachedStyleData::IsReset(sid);
   414   return NS_OK;
   415 }
   417 extern const char* const kCSSRawProperties[];
   419 NS_IMETHODIMP
   420 inDOMUtils::GetCSSPropertyNames(uint32_t aFlags, uint32_t* aCount,
   421                                 char16_t*** aProps)
   422 {
   423   // maxCount is the largest number of properties we could have; our actual
   424   // number might be smaller because properties might be disabled.
   425   uint32_t maxCount;
   426   if (aFlags & EXCLUDE_SHORTHANDS) {
   427     maxCount = eCSSProperty_COUNT_no_shorthands;
   428   } else {
   429     maxCount = eCSSProperty_COUNT;
   430   }
   432   if (aFlags & INCLUDE_ALIASES) {
   433     maxCount += (eCSSProperty_COUNT_with_aliases - eCSSProperty_COUNT);
   434   }
   436   char16_t** props =
   437     static_cast<char16_t**>(nsMemory::Alloc(maxCount * sizeof(char16_t*)));
   439 #define DO_PROP(_prop)                                                  \
   440   PR_BEGIN_MACRO                                                        \
   441     nsCSSProperty cssProp = nsCSSProperty(_prop);                       \
   442     if (nsCSSProps::IsEnabled(cssProp)) {                               \
   443       props[propCount] =                                                \
   444         ToNewUnicode(nsDependentCString(kCSSRawProperties[_prop]));     \
   445       ++propCount;                                                      \
   446     }                                                                   \
   447   PR_END_MACRO
   449   // prop is the property id we're considering; propCount is how many properties
   450   // we've put into props so far.
   451   uint32_t prop = 0, propCount = 0;
   452   for ( ; prop < eCSSProperty_COUNT_no_shorthands; ++prop) {
   453     if (nsCSSProps::PropertyParseType(nsCSSProperty(prop)) !=
   454         CSS_PROPERTY_PARSE_INACCESSIBLE) {
   455       DO_PROP(prop);
   456     }
   457   }
   459   if (!(aFlags & EXCLUDE_SHORTHANDS)) {
   460     for ( ; prop < eCSSProperty_COUNT; ++prop) {
   461       // Some shorthands are also aliases
   462       if ((aFlags & INCLUDE_ALIASES) ||
   463           !nsCSSProps::PropHasFlags(nsCSSProperty(prop),
   464                                     CSS_PROPERTY_IS_ALIAS)) {
   465         DO_PROP(prop);
   466       }
   467     }
   468   }
   470   if (aFlags & INCLUDE_ALIASES) {
   471     for (prop = eCSSProperty_COUNT; prop < eCSSProperty_COUNT_with_aliases; ++prop) {
   472       DO_PROP(prop);
   473     }
   474   }
   476 #undef DO_PROP
   478   *aCount = propCount;
   479   *aProps = props;
   481   return NS_OK;
   482 }
   484 static void InsertNoDuplicates(nsTArray<nsString>& aArray,
   485                                const nsAString& aString)
   486 {
   487   size_t i = aArray.IndexOfFirstElementGt(aString);
   488   if (i > 0 && aArray[i-1].Equals(aString)) {
   489     return;
   490   }
   491   aArray.InsertElementAt(i, aString);
   492 }
   494 static void GetKeywordsForProperty(const nsCSSProperty aProperty,
   495                                    nsTArray<nsString>& aArray)
   496 {
   497   if (nsCSSProps::IsShorthand(aProperty)) {
   498     // Shorthand props have no keywords.
   499     return;
   500   }
   501   const nsCSSProps::KTableValue *keywordTable =
   502     nsCSSProps::kKeywordTableTable[aProperty];
   503   if (keywordTable && keywordTable != nsCSSProps::kBoxPropSourceKTable) {
   504     size_t i = 0;
   505     while (nsCSSKeyword(keywordTable[i]) != eCSSKeyword_UNKNOWN) {
   506       nsCSSKeyword word = nsCSSKeyword(keywordTable[i]);
   507       InsertNoDuplicates(aArray,
   508                          NS_ConvertASCIItoUTF16(nsCSSKeywords::GetStringValue(word)));
   509       // Increment counter by 2, because in this table every second
   510       // element is a nsCSSKeyword.
   511       i += 2;
   512     }
   513   }
   514 }
   516 static void GetColorsForProperty(const uint32_t aParserVariant,
   517                                  nsTArray<nsString>& aArray)
   518 {
   519   if (aParserVariant & VARIANT_COLOR) {
   520     // GetKeywordsForProperty and GetOtherValuesForProperty assume aArray is sorted,
   521     // and if aArray is not empty here, then it's not going to be sorted coming out.
   522     MOZ_ASSERT(aArray.Length() == 0);
   523     size_t size;
   524     const char * const *allColorNames = NS_AllColorNames(&size);
   525     for (size_t i = 0; i < size; i++) {
   526       CopyASCIItoUTF16(allColorNames[i], *aArray.AppendElement());
   527     }
   528   }
   529   return;
   530 }
   532 static void GetOtherValuesForProperty(const uint32_t aParserVariant,
   533                                       nsTArray<nsString>& aArray)
   534 {
   535   if (aParserVariant & VARIANT_AUTO) {
   536     InsertNoDuplicates(aArray, NS_LITERAL_STRING("auto"));
   537   }
   538   if (aParserVariant & VARIANT_NORMAL) {
   539     InsertNoDuplicates(aArray, NS_LITERAL_STRING("normal"));
   540   }
   541   if(aParserVariant & VARIANT_ALL) {
   542     InsertNoDuplicates(aArray, NS_LITERAL_STRING("all"));
   543   }
   544   if (aParserVariant & VARIANT_NONE) {
   545     InsertNoDuplicates(aArray, NS_LITERAL_STRING("none"));
   546   }
   547   if (aParserVariant & VARIANT_ELEMENT) {
   548     InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-element"));
   549   }
   550   if (aParserVariant & VARIANT_IMAGE_RECT) {
   551     InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-image-rect"));
   552   }
   553   if (aParserVariant & VARIANT_COLOR) {
   554     InsertNoDuplicates(aArray, NS_LITERAL_STRING("rgb"));
   555     InsertNoDuplicates(aArray, NS_LITERAL_STRING("hsl"));
   556     InsertNoDuplicates(aArray, NS_LITERAL_STRING("rgba"));
   557     InsertNoDuplicates(aArray, NS_LITERAL_STRING("hsla"));
   558   }
   559   if (aParserVariant & VARIANT_TIMING_FUNCTION) {
   560     InsertNoDuplicates(aArray, NS_LITERAL_STRING("cubic-bezier"));
   561     InsertNoDuplicates(aArray, NS_LITERAL_STRING("steps"));
   562   }
   563   if (aParserVariant & VARIANT_CALC) {
   564     InsertNoDuplicates(aArray, NS_LITERAL_STRING("calc"));
   565     InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-calc"));
   566   }
   567   if (aParserVariant & VARIANT_URL) {
   568     InsertNoDuplicates(aArray, NS_LITERAL_STRING("url"));
   569   }
   570   if (aParserVariant & VARIANT_GRADIENT) {
   571     InsertNoDuplicates(aArray, NS_LITERAL_STRING("linear-gradient"));
   572     InsertNoDuplicates(aArray, NS_LITERAL_STRING("radial-gradient"));
   573     InsertNoDuplicates(aArray, NS_LITERAL_STRING("repeating-linear-gradient"));
   574     InsertNoDuplicates(aArray, NS_LITERAL_STRING("repeating-radial-gradient"));
   575     InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-linear-gradient"));
   576     InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-radial-gradient"));
   577     InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-linear-gradient"));
   578     InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-radial-gradient"));
   579   }
   580 }
   582 NS_IMETHODIMP
   583 inDOMUtils::GetCSSValuesForProperty(const nsAString& aProperty,
   584                                     uint32_t* aLength,
   585                                     char16_t*** aValues)
   586 {
   587   nsCSSProperty propertyID = nsCSSProps::LookupProperty(aProperty,
   588                                                         nsCSSProps::eEnabledForAllContent);
   589   if (propertyID == eCSSProperty_UNKNOWN) {
   590     return NS_ERROR_FAILURE;
   591   }
   593   nsTArray<nsString> array;
   594   // We start collecting the values, BUT colors need to go in first, because array
   595   // needs to stay sorted, and the colors are sorted, so we just append them.
   596   if (propertyID == eCSSPropertyExtra_variable) {
   597     // No other values we can report.
   598   } else if (!nsCSSProps::IsShorthand(propertyID)) {
   599     // Property is longhand.
   600     uint32_t propertyParserVariant = nsCSSProps::ParserVariant(propertyID);
   601     // Get colors first.
   602     GetColorsForProperty(propertyParserVariant, array);
   603     if (propertyParserVariant & VARIANT_KEYWORD) {
   604       GetKeywordsForProperty(propertyID, array);
   605     }
   606     GetOtherValuesForProperty(propertyParserVariant, array);
   607   } else {
   608     // Property is shorthand.
   609     CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty, propertyID) {
   610       // Get colors (once) first.
   611       uint32_t propertyParserVariant = nsCSSProps::ParserVariant(*subproperty);
   612       if (propertyParserVariant & VARIANT_COLOR) {
   613         GetColorsForProperty(propertyParserVariant, array);
   614         break;
   615       }
   616     }
   617     CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty, propertyID) {
   618       uint32_t propertyParserVariant = nsCSSProps::ParserVariant(*subproperty);
   619       if (propertyParserVariant & VARIANT_KEYWORD) {
   620         GetKeywordsForProperty(*subproperty, array);
   621       }
   622       GetOtherValuesForProperty(propertyParserVariant, array);
   623     }
   624   }
   625   // All CSS properties take initial, inherit and unset.
   626   InsertNoDuplicates(array, NS_LITERAL_STRING("initial"));
   627   InsertNoDuplicates(array, NS_LITERAL_STRING("inherit"));
   628   InsertNoDuplicates(array, NS_LITERAL_STRING("unset"));
   630   *aLength = array.Length();
   631   char16_t** ret =
   632     static_cast<char16_t**>(NS_Alloc(*aLength * sizeof(char16_t*)));
   633   for (uint32_t i = 0; i < *aLength; ++i) {
   634     ret[i] = ToNewUnicode(array[i]);
   635   }
   636   *aValues = ret;
   637   return NS_OK;
   638 }
   640 NS_IMETHODIMP
   641 inDOMUtils::ColorNameToRGB(const nsAString& aColorName, JSContext* aCx,
   642                            JS::MutableHandle<JS::Value> aValue)
   643 {
   644   nscolor color;
   645   if (!NS_ColorNameToRGB(aColorName, &color)) {
   646     return NS_ERROR_INVALID_ARG;
   647   }
   649   InspectorRGBTriple triple;
   650   triple.mR = NS_GET_R(color);
   651   triple.mG = NS_GET_G(color);
   652   triple.mB = NS_GET_B(color);
   654   if (!triple.ToObject(aCx, aValue)) {
   655     return NS_ERROR_FAILURE;
   656   }
   658   return NS_OK;
   659 }
   661 NS_IMETHODIMP
   662 inDOMUtils::RgbToColorName(uint8_t aR, uint8_t aG, uint8_t aB,
   663                            nsAString& aColorName)
   664 {
   665   const char* color = NS_RGBToColorName(NS_RGB(aR, aG, aB));
   666   if (!color) {
   667     aColorName.Truncate();
   668     return NS_ERROR_INVALID_ARG;
   669   }
   671   aColorName.AssignASCII(color);
   672   return NS_OK;
   673 }
   675 NS_IMETHODIMP
   676 inDOMUtils::GetBindingURLs(nsIDOMElement *aElement, nsIArray **_retval)
   677 {
   678   NS_ENSURE_ARG_POINTER(aElement);
   680   *_retval = nullptr;
   682   nsCOMPtr<nsIMutableArray> urls = do_CreateInstance(NS_ARRAY_CONTRACTID);
   683   if (!urls)
   684     return NS_ERROR_FAILURE;
   686   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
   687   NS_ENSURE_ARG_POINTER(content);
   689   nsXBLBinding *binding = content->GetXBLBinding();
   691   while (binding) {
   692     urls->AppendElement(binding->PrototypeBinding()->BindingURI(), false);
   693     binding = binding->GetBaseBinding();
   694   }
   696   NS_ADDREF(*_retval = urls);
   697   return NS_OK;
   698 }
   700 NS_IMETHODIMP
   701 inDOMUtils::SetContentState(nsIDOMElement* aElement,
   702                             EventStates::InternalType aState)
   703 {
   704   NS_ENSURE_ARG_POINTER(aElement);
   706   nsRefPtr<EventStateManager> esm =
   707     inLayoutUtils::GetEventStateManagerFor(aElement);
   708   if (esm) {
   709     nsCOMPtr<nsIContent> content;
   710     content = do_QueryInterface(aElement);
   712     // XXX Invalid cast of bool to nsresult (bug 778108)
   713     return (nsresult)esm->SetContentState(content, EventStates(aState));
   714   }
   716   return NS_ERROR_FAILURE;
   717 }
   719 NS_IMETHODIMP
   720 inDOMUtils::GetContentState(nsIDOMElement* aElement,
   721                             EventStates::InternalType* aState)
   722 {
   723   *aState = 0;
   724   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
   725   NS_ENSURE_ARG_POINTER(content);
   727   // NOTE: if this method is removed,
   728   // please remove GetInternalValue from EventStates
   729   *aState = content->AsElement()->State().GetInternalValue();
   730   return NS_OK;
   731 }
   733 /* static */ nsresult
   734 inDOMUtils::GetRuleNodeForElement(dom::Element* aElement,
   735                                   nsIAtom* aPseudo,
   736                                   nsStyleContext** aStyleContext,
   737                                   nsRuleNode** aRuleNode)
   738 {
   739   MOZ_ASSERT(aElement);
   741   *aRuleNode = nullptr;
   742   *aStyleContext = nullptr;
   744   nsIDocument* doc = aElement->GetDocument();
   745   NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
   747   nsIPresShell *presShell = doc->GetShell();
   748   NS_ENSURE_TRUE(presShell, NS_ERROR_UNEXPECTED);
   750   nsPresContext *presContext = presShell->GetPresContext();
   751   NS_ENSURE_TRUE(presContext, NS_ERROR_UNEXPECTED);
   753   presContext->EnsureSafeToHandOutCSSRules();
   755   nsRefPtr<nsStyleContext> sContext =
   756     nsComputedDOMStyle::GetStyleContextForElement(aElement, aPseudo, presShell);
   757   if (sContext) {
   758     *aRuleNode = sContext->RuleNode();
   759     sContext.forget(aStyleContext);
   760   }
   761   return NS_OK;
   762 }
   764 NS_IMETHODIMP
   765 inDOMUtils::GetUsedFontFaces(nsIDOMRange* aRange,
   766                              nsIDOMFontFaceList** aFontFaceList)
   767 {
   768   return static_cast<nsRange*>(aRange)->GetUsedFontFaces(aFontFaceList);
   769 }
   771 static EventStates
   772 GetStatesForPseudoClass(const nsAString& aStatePseudo)
   773 {
   774   // An array of the states that are relevant for various pseudoclasses.
   775   // XXXbz this duplicates code in nsCSSRuleProcessor
   776   static const EventStates sPseudoClassStates[] = {
   777 #define CSS_PSEUDO_CLASS(_name, _value, _pref)	\
   778     EventStates(),
   779 #define CSS_STATE_PSEUDO_CLASS(_name, _value, _pref, _states)	\
   780     _states,
   781 #include "nsCSSPseudoClassList.h"
   782 #undef CSS_STATE_PSEUDO_CLASS
   783 #undef CSS_PSEUDO_CLASS
   785     // Add more entries for our fake values to make sure we can't
   786     // index out of bounds into this array no matter what.
   787     EventStates(),
   788     EventStates()
   789   };
   790   static_assert(MOZ_ARRAY_LENGTH(sPseudoClassStates) ==
   791                 nsCSSPseudoClasses::ePseudoClass_NotPseudoClass + 1,
   792                 "Length of PseudoClassStates array is incorrect");
   794   nsCOMPtr<nsIAtom> atom = do_GetAtom(aStatePseudo);
   796   // Ignore :moz-any-link so we don't give the element simultaneous
   797   // visited and unvisited style state
   798   if (nsCSSPseudoClasses::GetPseudoType(atom) ==
   799       nsCSSPseudoClasses::ePseudoClass_mozAnyLink) {
   800     return EventStates();
   801   }
   802   // Our array above is long enough that indexing into it with
   803   // NotPseudoClass is ok.
   804   return sPseudoClassStates[nsCSSPseudoClasses::GetPseudoType(atom)];
   805 }
   807 NS_IMETHODIMP
   808 inDOMUtils::AddPseudoClassLock(nsIDOMElement *aElement,
   809                                const nsAString &aPseudoClass)
   810 {
   811   EventStates state = GetStatesForPseudoClass(aPseudoClass);
   812   if (state.IsEmpty()) {
   813     return NS_OK;
   814   }
   816   nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
   817   NS_ENSURE_ARG_POINTER(element);
   819   element->LockStyleStates(state);
   821   return NS_OK;
   822 }
   824 NS_IMETHODIMP
   825 inDOMUtils::RemovePseudoClassLock(nsIDOMElement *aElement,
   826                                   const nsAString &aPseudoClass)
   827 {
   828   EventStates state = GetStatesForPseudoClass(aPseudoClass);
   829   if (state.IsEmpty()) {
   830     return NS_OK;
   831   }
   833   nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
   834   NS_ENSURE_ARG_POINTER(element);
   836   element->UnlockStyleStates(state);
   838   return NS_OK;
   839 }
   841 NS_IMETHODIMP
   842 inDOMUtils::HasPseudoClassLock(nsIDOMElement *aElement,
   843                                const nsAString &aPseudoClass,
   844                                bool *_retval)
   845 {
   846   EventStates state = GetStatesForPseudoClass(aPseudoClass);
   847   if (state.IsEmpty()) {
   848     *_retval = false;
   849     return NS_OK;
   850   }
   852   nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
   853   NS_ENSURE_ARG_POINTER(element);
   855   EventStates locks = element->LockedStyleStates();
   857   *_retval = locks.HasAllStates(state);
   858   return NS_OK;
   859 }
   861 NS_IMETHODIMP
   862 inDOMUtils::ClearPseudoClassLocks(nsIDOMElement *aElement)
   863 {
   864   nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement);
   865   NS_ENSURE_ARG_POINTER(element);
   867   element->ClearStyleStateLocks();
   869   return NS_OK;
   870 }
   872 NS_IMETHODIMP
   873 inDOMUtils::ParseStyleSheet(nsIDOMCSSStyleSheet *aSheet,
   874                             const nsAString& aInput)
   875 {
   876   nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(aSheet);
   877   NS_ENSURE_ARG_POINTER(sheet);
   879   return sheet->ParseSheet(aInput);
   880 }

mercurial