1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/inspector/inDOMUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,880 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "mozilla/ArrayUtils.h" 1.10 +#include "mozilla/EventStates.h" 1.11 + 1.12 +#include "inDOMUtils.h" 1.13 +#include "inLayoutUtils.h" 1.14 + 1.15 +#include "nsIServiceManager.h" 1.16 +#include "nsISupportsArray.h" 1.17 +#include "nsString.h" 1.18 +#include "nsIDOMElement.h" 1.19 +#include "nsIDocument.h" 1.20 +#include "nsIPresShell.h" 1.21 +#include "nsIDOMDocument.h" 1.22 +#include "nsIDOMCharacterData.h" 1.23 +#include "nsRuleNode.h" 1.24 +#include "nsIStyleRule.h" 1.25 +#include "mozilla/css/StyleRule.h" 1.26 +#include "nsICSSStyleRuleDOMWrapper.h" 1.27 +#include "nsIDOMWindow.h" 1.28 +#include "nsXBLBinding.h" 1.29 +#include "nsXBLPrototypeBinding.h" 1.30 +#include "nsIMutableArray.h" 1.31 +#include "nsBindingManager.h" 1.32 +#include "ChildIterator.h" 1.33 +#include "nsComputedDOMStyle.h" 1.34 +#include "mozilla/EventStateManager.h" 1.35 +#include "nsIAtom.h" 1.36 +#include "nsRange.h" 1.37 +#include "nsContentList.h" 1.38 +#include "mozilla/dom/Element.h" 1.39 +#include "nsCSSStyleSheet.h" 1.40 +#include "nsRuleWalker.h" 1.41 +#include "nsRuleProcessorData.h" 1.42 +#include "nsCSSRuleProcessor.h" 1.43 +#include "mozilla/dom/InspectorUtilsBinding.h" 1.44 +#include "nsCSSProps.h" 1.45 +#include "nsColor.h" 1.46 +#include "nsStyleSet.h" 1.47 + 1.48 +using namespace mozilla; 1.49 +using namespace mozilla::css; 1.50 +using namespace mozilla::dom; 1.51 + 1.52 +/////////////////////////////////////////////////////////////////////////////// 1.53 + 1.54 +inDOMUtils::inDOMUtils() 1.55 +{ 1.56 +} 1.57 + 1.58 +inDOMUtils::~inDOMUtils() 1.59 +{ 1.60 +} 1.61 + 1.62 +NS_IMPL_ISUPPORTS(inDOMUtils, inIDOMUtils) 1.63 + 1.64 +/////////////////////////////////////////////////////////////////////////////// 1.65 +// inIDOMUtils 1.66 + 1.67 +NS_IMETHODIMP 1.68 +inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength, 1.69 + nsISupports ***aSheets) 1.70 +{ 1.71 + NS_ENSURE_ARG_POINTER(aDocument); 1.72 + 1.73 + nsCOMArray<nsISupports> sheets; 1.74 + 1.75 + nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument); 1.76 + MOZ_ASSERT(document); 1.77 + 1.78 + // Get the agent, then user sheets in the style set. 1.79 + nsIPresShell* presShell = document->GetShell(); 1.80 + if (presShell) { 1.81 + nsStyleSet* styleSet = presShell->StyleSet(); 1.82 + nsStyleSet::sheetType sheetType = nsStyleSet::eAgentSheet; 1.83 + for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) { 1.84 + sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i)); 1.85 + } 1.86 + sheetType = nsStyleSet::eUserSheet; 1.87 + for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) { 1.88 + sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i)); 1.89 + } 1.90 + } 1.91 + 1.92 + // Get the document sheets. 1.93 + for (int32_t i = 0; i < document->GetNumberOfStyleSheets(); i++) { 1.94 + sheets.AppendElement(document->GetStyleSheetAt(i)); 1.95 + } 1.96 + 1.97 + nsISupports** ret = static_cast<nsISupports**>(NS_Alloc(sheets.Count() * 1.98 + sizeof(nsISupports*))); 1.99 + 1.100 + for (int32_t i = 0; i < sheets.Count(); i++) { 1.101 + NS_ADDREF(ret[i] = sheets[i]); 1.102 + } 1.103 + 1.104 + *aLength = sheets.Count(); 1.105 + *aSheets = ret; 1.106 + 1.107 + return NS_OK; 1.108 +} 1.109 + 1.110 +NS_IMETHODIMP 1.111 +inDOMUtils::IsIgnorableWhitespace(nsIDOMCharacterData *aDataNode, 1.112 + bool *aReturn) 1.113 +{ 1.114 + NS_PRECONDITION(aReturn, "Must have an out parameter"); 1.115 + 1.116 + NS_ENSURE_ARG_POINTER(aDataNode); 1.117 + 1.118 + *aReturn = false; 1.119 + 1.120 + nsCOMPtr<nsIContent> content = do_QueryInterface(aDataNode); 1.121 + NS_ASSERTION(content, "Does not implement nsIContent!"); 1.122 + 1.123 + if (!content->TextIsOnlyWhitespace()) { 1.124 + return NS_OK; 1.125 + } 1.126 + 1.127 + // Okay. We have only white space. Let's check the white-space 1.128 + // property now and make sure that this isn't preformatted text... 1.129 + nsIFrame* frame = content->GetPrimaryFrame(); 1.130 + if (frame) { 1.131 + const nsStyleText* text = frame->StyleText(); 1.132 + *aReturn = !text->WhiteSpaceIsSignificant(); 1.133 + } 1.134 + else { 1.135 + // empty inter-tag text node without frame, e.g., in between <table>\n<tr> 1.136 + *aReturn = true; 1.137 + } 1.138 + 1.139 + return NS_OK; 1.140 +} 1.141 + 1.142 +NS_IMETHODIMP 1.143 +inDOMUtils::GetParentForNode(nsIDOMNode* aNode, 1.144 + bool aShowingAnonymousContent, 1.145 + nsIDOMNode** aParent) 1.146 +{ 1.147 + NS_ENSURE_ARG_POINTER(aNode); 1.148 + 1.149 + // First do the special cases -- document nodes and anonymous content 1.150 + nsCOMPtr<nsIDocument> doc(do_QueryInterface(aNode)); 1.151 + nsCOMPtr<nsIDOMNode> parent; 1.152 + 1.153 + if (doc) { 1.154 + parent = inLayoutUtils::GetContainerFor(*doc); 1.155 + } else if (aShowingAnonymousContent) { 1.156 + nsCOMPtr<nsIContent> content = do_QueryInterface(aNode); 1.157 + if (content) { 1.158 + nsIContent* bparent = content->GetXBLInsertionParent(); 1.159 + parent = do_QueryInterface(bparent); 1.160 + } 1.161 + } 1.162 + 1.163 + if (!parent) { 1.164 + // Ok, just get the normal DOM parent node 1.165 + aNode->GetParentNode(getter_AddRefs(parent)); 1.166 + } 1.167 + 1.168 + NS_IF_ADDREF(*aParent = parent); 1.169 + return NS_OK; 1.170 +} 1.171 + 1.172 +NS_IMETHODIMP 1.173 +inDOMUtils::GetChildrenForNode(nsIDOMNode* aNode, 1.174 + bool aShowingAnonymousContent, 1.175 + nsIDOMNodeList** aChildren) 1.176 +{ 1.177 + NS_ENSURE_ARG_POINTER(aNode); 1.178 + NS_PRECONDITION(aChildren, "Must have an out parameter"); 1.179 + 1.180 + nsCOMPtr<nsIDOMNodeList> kids; 1.181 + 1.182 + if (aShowingAnonymousContent) { 1.183 + nsCOMPtr<nsIContent> content = do_QueryInterface(aNode); 1.184 + if (content) { 1.185 + kids = content->GetChildren(nsIContent::eAllChildren); 1.186 + } 1.187 + } 1.188 + 1.189 + if (!kids) { 1.190 + aNode->GetChildNodes(getter_AddRefs(kids)); 1.191 + } 1.192 + 1.193 + kids.forget(aChildren); 1.194 + return NS_OK; 1.195 +} 1.196 + 1.197 +NS_IMETHODIMP 1.198 +inDOMUtils::GetCSSStyleRules(nsIDOMElement *aElement, 1.199 + const nsAString& aPseudo, 1.200 + nsISupportsArray **_retval) 1.201 +{ 1.202 + NS_ENSURE_ARG_POINTER(aElement); 1.203 + 1.204 + *_retval = nullptr; 1.205 + 1.206 + nsCOMPtr<nsIAtom> pseudoElt; 1.207 + if (!aPseudo.IsEmpty()) { 1.208 + pseudoElt = do_GetAtom(aPseudo); 1.209 + } 1.210 + 1.211 + nsRuleNode* ruleNode = nullptr; 1.212 + nsCOMPtr<Element> element = do_QueryInterface(aElement); 1.213 + NS_ENSURE_STATE(element); 1.214 + nsRefPtr<nsStyleContext> styleContext; 1.215 + GetRuleNodeForElement(element, pseudoElt, getter_AddRefs(styleContext), &ruleNode); 1.216 + if (!ruleNode) { 1.217 + // This can fail for elements that are not in the document or 1.218 + // if the document they're in doesn't have a presshell. Bail out. 1.219 + return NS_OK; 1.220 + } 1.221 + 1.222 + nsCOMPtr<nsISupportsArray> rules; 1.223 + NS_NewISupportsArray(getter_AddRefs(rules)); 1.224 + if (!rules) return NS_ERROR_OUT_OF_MEMORY; 1.225 + 1.226 + nsRefPtr<mozilla::css::StyleRule> cssRule; 1.227 + for ( ; !ruleNode->IsRoot(); ruleNode = ruleNode->GetParent()) { 1.228 + cssRule = do_QueryObject(ruleNode->GetRule()); 1.229 + if (cssRule) { 1.230 + nsCOMPtr<nsIDOMCSSRule> domRule = cssRule->GetDOMRule(); 1.231 + if (domRule) 1.232 + rules->InsertElementAt(domRule, 0); 1.233 + } 1.234 + } 1.235 + 1.236 + *_retval = rules; 1.237 + NS_ADDREF(*_retval); 1.238 + 1.239 + return NS_OK; 1.240 +} 1.241 + 1.242 +static already_AddRefed<StyleRule> 1.243 +GetRuleFromDOMRule(nsIDOMCSSStyleRule *aRule, ErrorResult& rv) 1.244 +{ 1.245 + nsCOMPtr<nsICSSStyleRuleDOMWrapper> rule = do_QueryInterface(aRule); 1.246 + if (!rule) { 1.247 + rv.Throw(NS_ERROR_INVALID_POINTER); 1.248 + return nullptr; 1.249 + } 1.250 + 1.251 + nsRefPtr<StyleRule> cssrule; 1.252 + rv = rule->GetCSSStyleRule(getter_AddRefs(cssrule)); 1.253 + if (rv.Failed()) { 1.254 + return nullptr; 1.255 + } 1.256 + 1.257 + if (!cssrule) { 1.258 + rv.Throw(NS_ERROR_FAILURE); 1.259 + } 1.260 + return cssrule.forget(); 1.261 +} 1.262 + 1.263 +NS_IMETHODIMP 1.264 +inDOMUtils::GetRuleLine(nsIDOMCSSStyleRule *aRule, uint32_t *_retval) 1.265 +{ 1.266 + ErrorResult rv; 1.267 + nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv); 1.268 + if (rv.Failed()) { 1.269 + return rv.ErrorCode(); 1.270 + } 1.271 + 1.272 + *_retval = rule->GetLineNumber(); 1.273 + return NS_OK; 1.274 +} 1.275 + 1.276 +NS_IMETHODIMP 1.277 +inDOMUtils::GetRuleColumn(nsIDOMCSSStyleRule *aRule, uint32_t *_retval) 1.278 +{ 1.279 + ErrorResult rv; 1.280 + nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv); 1.281 + if (rv.Failed()) { 1.282 + return rv.ErrorCode(); 1.283 + } 1.284 + *_retval = rule->GetColumnNumber(); 1.285 + return NS_OK; 1.286 +} 1.287 + 1.288 +NS_IMETHODIMP 1.289 +inDOMUtils::GetSelectorCount(nsIDOMCSSStyleRule* aRule, uint32_t *aCount) 1.290 +{ 1.291 + ErrorResult rv; 1.292 + nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv); 1.293 + if (rv.Failed()) { 1.294 + return rv.ErrorCode(); 1.295 + } 1.296 + 1.297 + uint32_t count = 0; 1.298 + for (nsCSSSelectorList* sel = rule->Selector(); sel; sel = sel->mNext) { 1.299 + ++count; 1.300 + } 1.301 + *aCount = count; 1.302 + return NS_OK; 1.303 +} 1.304 + 1.305 +static nsCSSSelectorList* 1.306 +GetSelectorAtIndex(nsIDOMCSSStyleRule* aRule, uint32_t aIndex, ErrorResult& rv) 1.307 +{ 1.308 + nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv); 1.309 + if (rv.Failed()) { 1.310 + return nullptr; 1.311 + } 1.312 + 1.313 + for (nsCSSSelectorList* sel = rule->Selector(); sel; 1.314 + sel = sel->mNext, --aIndex) { 1.315 + if (aIndex == 0) { 1.316 + return sel; 1.317 + } 1.318 + } 1.319 + 1.320 + // Ran out of selectors 1.321 + rv.Throw(NS_ERROR_INVALID_ARG); 1.322 + return nullptr; 1.323 +} 1.324 + 1.325 +NS_IMETHODIMP 1.326 +inDOMUtils::GetSelectorText(nsIDOMCSSStyleRule* aRule, 1.327 + uint32_t aSelectorIndex, 1.328 + nsAString& aText) 1.329 +{ 1.330 + ErrorResult rv; 1.331 + nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv); 1.332 + if (rv.Failed()) { 1.333 + return rv.ErrorCode(); 1.334 + } 1.335 + 1.336 + nsRefPtr<StyleRule> rule = GetRuleFromDOMRule(aRule, rv); 1.337 + MOZ_ASSERT(!rv.Failed(), "How could we get a selector but not a rule?"); 1.338 + 1.339 + sel->mSelectors->ToString(aText, rule->GetStyleSheet(), false); 1.340 + return NS_OK; 1.341 +} 1.342 + 1.343 +NS_IMETHODIMP 1.344 +inDOMUtils::GetSpecificity(nsIDOMCSSStyleRule* aRule, 1.345 + uint32_t aSelectorIndex, 1.346 + uint64_t* aSpecificity) 1.347 +{ 1.348 + ErrorResult rv; 1.349 + nsCSSSelectorList* sel = GetSelectorAtIndex(aRule, aSelectorIndex, rv); 1.350 + if (rv.Failed()) { 1.351 + return rv.ErrorCode(); 1.352 + } 1.353 + 1.354 + *aSpecificity = sel->mWeight; 1.355 + return NS_OK; 1.356 +} 1.357 + 1.358 +NS_IMETHODIMP 1.359 +inDOMUtils::SelectorMatchesElement(nsIDOMElement* aElement, 1.360 + nsIDOMCSSStyleRule* aRule, 1.361 + uint32_t aSelectorIndex, 1.362 + bool* aMatches) 1.363 +{ 1.364 + nsCOMPtr<Element> element = do_QueryInterface(aElement); 1.365 + NS_ENSURE_ARG_POINTER(element); 1.366 + 1.367 + ErrorResult rv; 1.368 + nsCSSSelectorList* tail = GetSelectorAtIndex(aRule, aSelectorIndex, rv); 1.369 + if (rv.Failed()) { 1.370 + return rv.ErrorCode(); 1.371 + } 1.372 + 1.373 + // We want just the one list item, not the whole list tail 1.374 + nsAutoPtr<nsCSSSelectorList> sel(tail->Clone(false)); 1.375 + 1.376 + // SelectorListMatches does not handle selectors that begin with a 1.377 + // pseudo-element, which you can get from selectors like 1.378 + // |input::-moz-placeholder:hover|. This function doesn't take 1.379 + // a pseudo-element nsIAtom*, so we know we can't match. 1.380 + if (sel->mSelectors->IsPseudoElement()) { 1.381 + *aMatches = false; 1.382 + return NS_OK; 1.383 + } 1.384 + 1.385 + element->OwnerDoc()->FlushPendingLinkUpdates(); 1.386 + // XXXbz what exactly should we do with visited state here? 1.387 + TreeMatchContext matchingContext(false, 1.388 + nsRuleWalker::eRelevantLinkUnvisited, 1.389 + element->OwnerDoc(), 1.390 + TreeMatchContext::eNeverMatchVisited); 1.391 + *aMatches = nsCSSRuleProcessor::SelectorListMatches(element, matchingContext, 1.392 + sel); 1.393 + return NS_OK; 1.394 +} 1.395 + 1.396 +NS_IMETHODIMP 1.397 +inDOMUtils::IsInheritedProperty(const nsAString &aPropertyName, bool *_retval) 1.398 +{ 1.399 + nsCSSProperty prop = 1.400 + nsCSSProps::LookupProperty(aPropertyName, nsCSSProps::eIgnoreEnabledState); 1.401 + if (prop == eCSSProperty_UNKNOWN) { 1.402 + *_retval = false; 1.403 + return NS_OK; 1.404 + } 1.405 + 1.406 + if (prop == eCSSPropertyExtra_variable) { 1.407 + *_retval = true; 1.408 + return NS_OK; 1.409 + } 1.410 + 1.411 + if (nsCSSProps::IsShorthand(prop)) { 1.412 + prop = nsCSSProps::SubpropertyEntryFor(prop)[0]; 1.413 + } 1.414 + 1.415 + nsStyleStructID sid = nsCSSProps::kSIDTable[prop]; 1.416 + *_retval = !nsCachedStyleData::IsReset(sid); 1.417 + return NS_OK; 1.418 +} 1.419 + 1.420 +extern const char* const kCSSRawProperties[]; 1.421 + 1.422 +NS_IMETHODIMP 1.423 +inDOMUtils::GetCSSPropertyNames(uint32_t aFlags, uint32_t* aCount, 1.424 + char16_t*** aProps) 1.425 +{ 1.426 + // maxCount is the largest number of properties we could have; our actual 1.427 + // number might be smaller because properties might be disabled. 1.428 + uint32_t maxCount; 1.429 + if (aFlags & EXCLUDE_SHORTHANDS) { 1.430 + maxCount = eCSSProperty_COUNT_no_shorthands; 1.431 + } else { 1.432 + maxCount = eCSSProperty_COUNT; 1.433 + } 1.434 + 1.435 + if (aFlags & INCLUDE_ALIASES) { 1.436 + maxCount += (eCSSProperty_COUNT_with_aliases - eCSSProperty_COUNT); 1.437 + } 1.438 + 1.439 + char16_t** props = 1.440 + static_cast<char16_t**>(nsMemory::Alloc(maxCount * sizeof(char16_t*))); 1.441 + 1.442 +#define DO_PROP(_prop) \ 1.443 + PR_BEGIN_MACRO \ 1.444 + nsCSSProperty cssProp = nsCSSProperty(_prop); \ 1.445 + if (nsCSSProps::IsEnabled(cssProp)) { \ 1.446 + props[propCount] = \ 1.447 + ToNewUnicode(nsDependentCString(kCSSRawProperties[_prop])); \ 1.448 + ++propCount; \ 1.449 + } \ 1.450 + PR_END_MACRO 1.451 + 1.452 + // prop is the property id we're considering; propCount is how many properties 1.453 + // we've put into props so far. 1.454 + uint32_t prop = 0, propCount = 0; 1.455 + for ( ; prop < eCSSProperty_COUNT_no_shorthands; ++prop) { 1.456 + if (nsCSSProps::PropertyParseType(nsCSSProperty(prop)) != 1.457 + CSS_PROPERTY_PARSE_INACCESSIBLE) { 1.458 + DO_PROP(prop); 1.459 + } 1.460 + } 1.461 + 1.462 + if (!(aFlags & EXCLUDE_SHORTHANDS)) { 1.463 + for ( ; prop < eCSSProperty_COUNT; ++prop) { 1.464 + // Some shorthands are also aliases 1.465 + if ((aFlags & INCLUDE_ALIASES) || 1.466 + !nsCSSProps::PropHasFlags(nsCSSProperty(prop), 1.467 + CSS_PROPERTY_IS_ALIAS)) { 1.468 + DO_PROP(prop); 1.469 + } 1.470 + } 1.471 + } 1.472 + 1.473 + if (aFlags & INCLUDE_ALIASES) { 1.474 + for (prop = eCSSProperty_COUNT; prop < eCSSProperty_COUNT_with_aliases; ++prop) { 1.475 + DO_PROP(prop); 1.476 + } 1.477 + } 1.478 + 1.479 +#undef DO_PROP 1.480 + 1.481 + *aCount = propCount; 1.482 + *aProps = props; 1.483 + 1.484 + return NS_OK; 1.485 +} 1.486 + 1.487 +static void InsertNoDuplicates(nsTArray<nsString>& aArray, 1.488 + const nsAString& aString) 1.489 +{ 1.490 + size_t i = aArray.IndexOfFirstElementGt(aString); 1.491 + if (i > 0 && aArray[i-1].Equals(aString)) { 1.492 + return; 1.493 + } 1.494 + aArray.InsertElementAt(i, aString); 1.495 +} 1.496 + 1.497 +static void GetKeywordsForProperty(const nsCSSProperty aProperty, 1.498 + nsTArray<nsString>& aArray) 1.499 +{ 1.500 + if (nsCSSProps::IsShorthand(aProperty)) { 1.501 + // Shorthand props have no keywords. 1.502 + return; 1.503 + } 1.504 + const nsCSSProps::KTableValue *keywordTable = 1.505 + nsCSSProps::kKeywordTableTable[aProperty]; 1.506 + if (keywordTable && keywordTable != nsCSSProps::kBoxPropSourceKTable) { 1.507 + size_t i = 0; 1.508 + while (nsCSSKeyword(keywordTable[i]) != eCSSKeyword_UNKNOWN) { 1.509 + nsCSSKeyword word = nsCSSKeyword(keywordTable[i]); 1.510 + InsertNoDuplicates(aArray, 1.511 + NS_ConvertASCIItoUTF16(nsCSSKeywords::GetStringValue(word))); 1.512 + // Increment counter by 2, because in this table every second 1.513 + // element is a nsCSSKeyword. 1.514 + i += 2; 1.515 + } 1.516 + } 1.517 +} 1.518 + 1.519 +static void GetColorsForProperty(const uint32_t aParserVariant, 1.520 + nsTArray<nsString>& aArray) 1.521 +{ 1.522 + if (aParserVariant & VARIANT_COLOR) { 1.523 + // GetKeywordsForProperty and GetOtherValuesForProperty assume aArray is sorted, 1.524 + // and if aArray is not empty here, then it's not going to be sorted coming out. 1.525 + MOZ_ASSERT(aArray.Length() == 0); 1.526 + size_t size; 1.527 + const char * const *allColorNames = NS_AllColorNames(&size); 1.528 + for (size_t i = 0; i < size; i++) { 1.529 + CopyASCIItoUTF16(allColorNames[i], *aArray.AppendElement()); 1.530 + } 1.531 + } 1.532 + return; 1.533 +} 1.534 + 1.535 +static void GetOtherValuesForProperty(const uint32_t aParserVariant, 1.536 + nsTArray<nsString>& aArray) 1.537 +{ 1.538 + if (aParserVariant & VARIANT_AUTO) { 1.539 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("auto")); 1.540 + } 1.541 + if (aParserVariant & VARIANT_NORMAL) { 1.542 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("normal")); 1.543 + } 1.544 + if(aParserVariant & VARIANT_ALL) { 1.545 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("all")); 1.546 + } 1.547 + if (aParserVariant & VARIANT_NONE) { 1.548 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("none")); 1.549 + } 1.550 + if (aParserVariant & VARIANT_ELEMENT) { 1.551 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-element")); 1.552 + } 1.553 + if (aParserVariant & VARIANT_IMAGE_RECT) { 1.554 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-image-rect")); 1.555 + } 1.556 + if (aParserVariant & VARIANT_COLOR) { 1.557 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("rgb")); 1.558 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("hsl")); 1.559 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("rgba")); 1.560 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("hsla")); 1.561 + } 1.562 + if (aParserVariant & VARIANT_TIMING_FUNCTION) { 1.563 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("cubic-bezier")); 1.564 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("steps")); 1.565 + } 1.566 + if (aParserVariant & VARIANT_CALC) { 1.567 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("calc")); 1.568 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-calc")); 1.569 + } 1.570 + if (aParserVariant & VARIANT_URL) { 1.571 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("url")); 1.572 + } 1.573 + if (aParserVariant & VARIANT_GRADIENT) { 1.574 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("linear-gradient")); 1.575 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("radial-gradient")); 1.576 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("repeating-linear-gradient")); 1.577 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("repeating-radial-gradient")); 1.578 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-linear-gradient")); 1.579 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-radial-gradient")); 1.580 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-linear-gradient")); 1.581 + InsertNoDuplicates(aArray, NS_LITERAL_STRING("-moz-repeating-radial-gradient")); 1.582 + } 1.583 +} 1.584 + 1.585 +NS_IMETHODIMP 1.586 +inDOMUtils::GetCSSValuesForProperty(const nsAString& aProperty, 1.587 + uint32_t* aLength, 1.588 + char16_t*** aValues) 1.589 +{ 1.590 + nsCSSProperty propertyID = nsCSSProps::LookupProperty(aProperty, 1.591 + nsCSSProps::eEnabledForAllContent); 1.592 + if (propertyID == eCSSProperty_UNKNOWN) { 1.593 + return NS_ERROR_FAILURE; 1.594 + } 1.595 + 1.596 + nsTArray<nsString> array; 1.597 + // We start collecting the values, BUT colors need to go in first, because array 1.598 + // needs to stay sorted, and the colors are sorted, so we just append them. 1.599 + if (propertyID == eCSSPropertyExtra_variable) { 1.600 + // No other values we can report. 1.601 + } else if (!nsCSSProps::IsShorthand(propertyID)) { 1.602 + // Property is longhand. 1.603 + uint32_t propertyParserVariant = nsCSSProps::ParserVariant(propertyID); 1.604 + // Get colors first. 1.605 + GetColorsForProperty(propertyParserVariant, array); 1.606 + if (propertyParserVariant & VARIANT_KEYWORD) { 1.607 + GetKeywordsForProperty(propertyID, array); 1.608 + } 1.609 + GetOtherValuesForProperty(propertyParserVariant, array); 1.610 + } else { 1.611 + // Property is shorthand. 1.612 + CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty, propertyID) { 1.613 + // Get colors (once) first. 1.614 + uint32_t propertyParserVariant = nsCSSProps::ParserVariant(*subproperty); 1.615 + if (propertyParserVariant & VARIANT_COLOR) { 1.616 + GetColorsForProperty(propertyParserVariant, array); 1.617 + break; 1.618 + } 1.619 + } 1.620 + CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subproperty, propertyID) { 1.621 + uint32_t propertyParserVariant = nsCSSProps::ParserVariant(*subproperty); 1.622 + if (propertyParserVariant & VARIANT_KEYWORD) { 1.623 + GetKeywordsForProperty(*subproperty, array); 1.624 + } 1.625 + GetOtherValuesForProperty(propertyParserVariant, array); 1.626 + } 1.627 + } 1.628 + // All CSS properties take initial, inherit and unset. 1.629 + InsertNoDuplicates(array, NS_LITERAL_STRING("initial")); 1.630 + InsertNoDuplicates(array, NS_LITERAL_STRING("inherit")); 1.631 + InsertNoDuplicates(array, NS_LITERAL_STRING("unset")); 1.632 + 1.633 + *aLength = array.Length(); 1.634 + char16_t** ret = 1.635 + static_cast<char16_t**>(NS_Alloc(*aLength * sizeof(char16_t*))); 1.636 + for (uint32_t i = 0; i < *aLength; ++i) { 1.637 + ret[i] = ToNewUnicode(array[i]); 1.638 + } 1.639 + *aValues = ret; 1.640 + return NS_OK; 1.641 +} 1.642 + 1.643 +NS_IMETHODIMP 1.644 +inDOMUtils::ColorNameToRGB(const nsAString& aColorName, JSContext* aCx, 1.645 + JS::MutableHandle<JS::Value> aValue) 1.646 +{ 1.647 + nscolor color; 1.648 + if (!NS_ColorNameToRGB(aColorName, &color)) { 1.649 + return NS_ERROR_INVALID_ARG; 1.650 + } 1.651 + 1.652 + InspectorRGBTriple triple; 1.653 + triple.mR = NS_GET_R(color); 1.654 + triple.mG = NS_GET_G(color); 1.655 + triple.mB = NS_GET_B(color); 1.656 + 1.657 + if (!triple.ToObject(aCx, aValue)) { 1.658 + return NS_ERROR_FAILURE; 1.659 + } 1.660 + 1.661 + return NS_OK; 1.662 +} 1.663 + 1.664 +NS_IMETHODIMP 1.665 +inDOMUtils::RgbToColorName(uint8_t aR, uint8_t aG, uint8_t aB, 1.666 + nsAString& aColorName) 1.667 +{ 1.668 + const char* color = NS_RGBToColorName(NS_RGB(aR, aG, aB)); 1.669 + if (!color) { 1.670 + aColorName.Truncate(); 1.671 + return NS_ERROR_INVALID_ARG; 1.672 + } 1.673 + 1.674 + aColorName.AssignASCII(color); 1.675 + return NS_OK; 1.676 +} 1.677 + 1.678 +NS_IMETHODIMP 1.679 +inDOMUtils::GetBindingURLs(nsIDOMElement *aElement, nsIArray **_retval) 1.680 +{ 1.681 + NS_ENSURE_ARG_POINTER(aElement); 1.682 + 1.683 + *_retval = nullptr; 1.684 + 1.685 + nsCOMPtr<nsIMutableArray> urls = do_CreateInstance(NS_ARRAY_CONTRACTID); 1.686 + if (!urls) 1.687 + return NS_ERROR_FAILURE; 1.688 + 1.689 + nsCOMPtr<nsIContent> content = do_QueryInterface(aElement); 1.690 + NS_ENSURE_ARG_POINTER(content); 1.691 + 1.692 + nsXBLBinding *binding = content->GetXBLBinding(); 1.693 + 1.694 + while (binding) { 1.695 + urls->AppendElement(binding->PrototypeBinding()->BindingURI(), false); 1.696 + binding = binding->GetBaseBinding(); 1.697 + } 1.698 + 1.699 + NS_ADDREF(*_retval = urls); 1.700 + return NS_OK; 1.701 +} 1.702 + 1.703 +NS_IMETHODIMP 1.704 +inDOMUtils::SetContentState(nsIDOMElement* aElement, 1.705 + EventStates::InternalType aState) 1.706 +{ 1.707 + NS_ENSURE_ARG_POINTER(aElement); 1.708 + 1.709 + nsRefPtr<EventStateManager> esm = 1.710 + inLayoutUtils::GetEventStateManagerFor(aElement); 1.711 + if (esm) { 1.712 + nsCOMPtr<nsIContent> content; 1.713 + content = do_QueryInterface(aElement); 1.714 + 1.715 + // XXX Invalid cast of bool to nsresult (bug 778108) 1.716 + return (nsresult)esm->SetContentState(content, EventStates(aState)); 1.717 + } 1.718 + 1.719 + return NS_ERROR_FAILURE; 1.720 +} 1.721 + 1.722 +NS_IMETHODIMP 1.723 +inDOMUtils::GetContentState(nsIDOMElement* aElement, 1.724 + EventStates::InternalType* aState) 1.725 +{ 1.726 + *aState = 0; 1.727 + nsCOMPtr<nsIContent> content = do_QueryInterface(aElement); 1.728 + NS_ENSURE_ARG_POINTER(content); 1.729 + 1.730 + // NOTE: if this method is removed, 1.731 + // please remove GetInternalValue from EventStates 1.732 + *aState = content->AsElement()->State().GetInternalValue(); 1.733 + return NS_OK; 1.734 +} 1.735 + 1.736 +/* static */ nsresult 1.737 +inDOMUtils::GetRuleNodeForElement(dom::Element* aElement, 1.738 + nsIAtom* aPseudo, 1.739 + nsStyleContext** aStyleContext, 1.740 + nsRuleNode** aRuleNode) 1.741 +{ 1.742 + MOZ_ASSERT(aElement); 1.743 + 1.744 + *aRuleNode = nullptr; 1.745 + *aStyleContext = nullptr; 1.746 + 1.747 + nsIDocument* doc = aElement->GetDocument(); 1.748 + NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED); 1.749 + 1.750 + nsIPresShell *presShell = doc->GetShell(); 1.751 + NS_ENSURE_TRUE(presShell, NS_ERROR_UNEXPECTED); 1.752 + 1.753 + nsPresContext *presContext = presShell->GetPresContext(); 1.754 + NS_ENSURE_TRUE(presContext, NS_ERROR_UNEXPECTED); 1.755 + 1.756 + presContext->EnsureSafeToHandOutCSSRules(); 1.757 + 1.758 + nsRefPtr<nsStyleContext> sContext = 1.759 + nsComputedDOMStyle::GetStyleContextForElement(aElement, aPseudo, presShell); 1.760 + if (sContext) { 1.761 + *aRuleNode = sContext->RuleNode(); 1.762 + sContext.forget(aStyleContext); 1.763 + } 1.764 + return NS_OK; 1.765 +} 1.766 + 1.767 +NS_IMETHODIMP 1.768 +inDOMUtils::GetUsedFontFaces(nsIDOMRange* aRange, 1.769 + nsIDOMFontFaceList** aFontFaceList) 1.770 +{ 1.771 + return static_cast<nsRange*>(aRange)->GetUsedFontFaces(aFontFaceList); 1.772 +} 1.773 + 1.774 +static EventStates 1.775 +GetStatesForPseudoClass(const nsAString& aStatePseudo) 1.776 +{ 1.777 + // An array of the states that are relevant for various pseudoclasses. 1.778 + // XXXbz this duplicates code in nsCSSRuleProcessor 1.779 + static const EventStates sPseudoClassStates[] = { 1.780 +#define CSS_PSEUDO_CLASS(_name, _value, _pref) \ 1.781 + EventStates(), 1.782 +#define CSS_STATE_PSEUDO_CLASS(_name, _value, _pref, _states) \ 1.783 + _states, 1.784 +#include "nsCSSPseudoClassList.h" 1.785 +#undef CSS_STATE_PSEUDO_CLASS 1.786 +#undef CSS_PSEUDO_CLASS 1.787 + 1.788 + // Add more entries for our fake values to make sure we can't 1.789 + // index out of bounds into this array no matter what. 1.790 + EventStates(), 1.791 + EventStates() 1.792 + }; 1.793 + static_assert(MOZ_ARRAY_LENGTH(sPseudoClassStates) == 1.794 + nsCSSPseudoClasses::ePseudoClass_NotPseudoClass + 1, 1.795 + "Length of PseudoClassStates array is incorrect"); 1.796 + 1.797 + nsCOMPtr<nsIAtom> atom = do_GetAtom(aStatePseudo); 1.798 + 1.799 + // Ignore :moz-any-link so we don't give the element simultaneous 1.800 + // visited and unvisited style state 1.801 + if (nsCSSPseudoClasses::GetPseudoType(atom) == 1.802 + nsCSSPseudoClasses::ePseudoClass_mozAnyLink) { 1.803 + return EventStates(); 1.804 + } 1.805 + // Our array above is long enough that indexing into it with 1.806 + // NotPseudoClass is ok. 1.807 + return sPseudoClassStates[nsCSSPseudoClasses::GetPseudoType(atom)]; 1.808 +} 1.809 + 1.810 +NS_IMETHODIMP 1.811 +inDOMUtils::AddPseudoClassLock(nsIDOMElement *aElement, 1.812 + const nsAString &aPseudoClass) 1.813 +{ 1.814 + EventStates state = GetStatesForPseudoClass(aPseudoClass); 1.815 + if (state.IsEmpty()) { 1.816 + return NS_OK; 1.817 + } 1.818 + 1.819 + nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement); 1.820 + NS_ENSURE_ARG_POINTER(element); 1.821 + 1.822 + element->LockStyleStates(state); 1.823 + 1.824 + return NS_OK; 1.825 +} 1.826 + 1.827 +NS_IMETHODIMP 1.828 +inDOMUtils::RemovePseudoClassLock(nsIDOMElement *aElement, 1.829 + const nsAString &aPseudoClass) 1.830 +{ 1.831 + EventStates state = GetStatesForPseudoClass(aPseudoClass); 1.832 + if (state.IsEmpty()) { 1.833 + return NS_OK; 1.834 + } 1.835 + 1.836 + nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement); 1.837 + NS_ENSURE_ARG_POINTER(element); 1.838 + 1.839 + element->UnlockStyleStates(state); 1.840 + 1.841 + return NS_OK; 1.842 +} 1.843 + 1.844 +NS_IMETHODIMP 1.845 +inDOMUtils::HasPseudoClassLock(nsIDOMElement *aElement, 1.846 + const nsAString &aPseudoClass, 1.847 + bool *_retval) 1.848 +{ 1.849 + EventStates state = GetStatesForPseudoClass(aPseudoClass); 1.850 + if (state.IsEmpty()) { 1.851 + *_retval = false; 1.852 + return NS_OK; 1.853 + } 1.854 + 1.855 + nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement); 1.856 + NS_ENSURE_ARG_POINTER(element); 1.857 + 1.858 + EventStates locks = element->LockedStyleStates(); 1.859 + 1.860 + *_retval = locks.HasAllStates(state); 1.861 + return NS_OK; 1.862 +} 1.863 + 1.864 +NS_IMETHODIMP 1.865 +inDOMUtils::ClearPseudoClassLocks(nsIDOMElement *aElement) 1.866 +{ 1.867 + nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aElement); 1.868 + NS_ENSURE_ARG_POINTER(element); 1.869 + 1.870 + element->ClearStyleStateLocks(); 1.871 + 1.872 + return NS_OK; 1.873 +} 1.874 + 1.875 +NS_IMETHODIMP 1.876 +inDOMUtils::ParseStyleSheet(nsIDOMCSSStyleSheet *aSheet, 1.877 + const nsAString& aInput) 1.878 +{ 1.879 + nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(aSheet); 1.880 + NS_ENSURE_ARG_POINTER(sheet); 1.881 + 1.882 + return sheet->ParseSheet(aInput); 1.883 +}