Bug 1330843 - Part 2: Add an argument to ResolvePseudoElementStyle and FileRules to allow script-created NAC to match document rules. r? draft
authorBenjamin Chen <bechen@mozilla.com>
Fri, 13 Jan 2017 15:59:49 +0800
changeset 460555 d7a6fe54924a17377d99e3a9139d5b63811fa677
parent 460554 9550ed1dba81f466095269517a8a090d00aaa113
child 542069 189b7802810d230c8c1b43373175dcea846f11fb
push id41414
push userbmo:cam@mcc.id.au
push dateFri, 13 Jan 2017 08:00:17 +0000
bugs1330843
milestone53.0a1
Bug 1330843 - Part 2: Add an argument to ResolvePseudoElementStyle and FileRules to allow script-created NAC to match document rules. r? MozReview-Commit-ID: CPyl6AyV2a3
layout/base/nsCSSFrameConstructor.cpp
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/StyleSetHandle.h
layout/style/StyleSetHandleInlines.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -5077,17 +5077,18 @@ nsCSSFrameConstructor::ResolveStyleConte
         nsFrame::CorrectStyleParentFrame(aContent->GetParentElement()
                                                  ->GetPrimaryFrame(),
                                          pseudoAtom);
       MOZ_ASSERT(styleParentFrame, "NAC pseudo that has a parent element surely "
                                    "must also have a style parent frame");
       result = styleSet->ResolvePseudoElementStyle(parentElement,
                                                    pseudoType,
                                                    styleParentFrame->StyleContext(),
-                                                   aContent->AsElement());
+                                                   aContent->AsElement(),
+                                                   nsStyleSet::eDontSkipDocSheets);
     }
   } else {
     NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
                  "shouldn't waste time creating style contexts for "
                  "comments and processing instructions");
     result = styleSet->ResolveStyleForText(aContent, aParentStyleContext);
   }
 
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -202,22 +202,25 @@ ServoStyleSet::ResolveStyleForOtherNonEl
                     nsCSSAnonBoxes::mozOtherNonElement,
                     CSSPseudoElementType::AnonBox);
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
                                          CSSPseudoElementType aType,
                                          nsStyleContext* aParentContext,
-                                         Element* aPseudoElement)
+                                         Element* aPseudoElement,
+                                         uint32_t aFlags)
 {
   if (aPseudoElement) {
     NS_ERROR("stylo: We don't support CSS_PSEUDO_ELEMENT_SUPPORTS_USER_ACTION_STATE yet");
   }
 
+  // XXXheycam We need to do something with (aFlags & eDontSkipDocSheets).
+
   // NB: We ignore aParentContext, on the assumption that pseudo element styles
   // should just inherit from aOriginatingElement's primary style, which Servo
   // already knows.
   MOZ_ASSERT(aType < CSSPseudoElementType::Count);
   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
 
   RefPtr<ServoComputedValues> computedValues =
     Servo_ResolvePseudoStyle(aOriginatingElement, pseudoTag,
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -71,17 +71,18 @@ public:
 
   already_AddRefed<nsStyleContext>
   ResolveStyleForOtherNonElement(nsStyleContext* aParentContext);
 
   already_AddRefed<nsStyleContext>
   ResolvePseudoElementStyle(dom::Element* aOriginatingElement,
                             mozilla::CSSPseudoElementType aType,
                             nsStyleContext* aParentContext,
-                            dom::Element* aPseudoElement);
+                            dom::Element* aPseudoElement,
+                            uint32_t aFlags = 0);
 
   // Resolves style for a (possibly-pseudo) Element without assuming that the
   // style has been resolved, and without worrying about setting the style
   // context up to live in the style context tree (a null parent is used).
   already_AddRefed<nsStyleContext>
   ResolveTransientStyle(dom::Element* aElement,
                         mozilla::CSSPseudoElementType aPseudoType);
 
--- a/layout/style/StyleSetHandle.h
+++ b/layout/style/StyleSetHandle.h
@@ -126,17 +126,18 @@ public:
     ResolveStyleForText(nsIContent* aTextNode,
                         nsStyleContext* aParentContext);
     inline already_AddRefed<nsStyleContext>
     ResolveStyleForOtherNonElement(nsStyleContext* aParentContext);
     inline already_AddRefed<nsStyleContext>
     ResolvePseudoElementStyle(dom::Element* aParentElement,
                               mozilla::CSSPseudoElementType aType,
                               nsStyleContext* aParentContext,
-                              dom::Element* aPseudoElement);
+                              dom::Element* aPseudoElement,
+                              uint32_t aFlags = 0);
     inline already_AddRefed<nsStyleContext>
     ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext,
                              uint32_t aFlags = 0);
     inline nsresult AppendStyleSheet(SheetType aType, StyleSheet* aSheet);
     inline nsresult PrependStyleSheet(SheetType aType, StyleSheet* aSheet);
     inline nsresult RemoveStyleSheet(SheetType aType, StyleSheet* aSheet);
     inline nsresult ReplaceSheets(SheetType aType,
                            const nsTArray<RefPtr<StyleSheet>>& aNewSheets);
--- a/layout/style/StyleSetHandleInlines.h
+++ b/layout/style/StyleSetHandleInlines.h
@@ -106,20 +106,21 @@ StyleSetHandle::Ptr::ResolveStyleForOthe
 {
   FORWARD(ResolveStyleForOtherNonElement, (aParentContext));
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolvePseudoElementStyle(dom::Element* aParentElement,
                                                CSSPseudoElementType aType,
                                                nsStyleContext* aParentContext,
-                                               dom::Element* aPseudoElement)
+                                               dom::Element* aPseudoElement,
+                                               uint32_t aFlags)
 {
   FORWARD(ResolvePseudoElementStyle, (aParentElement, aType, aParentContext,
-                                      aPseudoElement));
+                                      aPseudoElement, aFlags));
 }
 
 // aFlags is an nsStyleSet flags bitfield
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
                                               nsStyleContext* aParentContext,
                                               uint32_t aFlags)
 {
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -1091,17 +1091,17 @@ nsStyleSet::AssertNoCSSRules(nsRuleNode*
   }
 }
 #endif
 
 // Enumerate the rules in a way that cares about the order of the rules.
 void
 nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
                       RuleProcessorData* aData, Element* aElement,
-                      nsRuleWalker* aRuleWalker)
+                      nsRuleWalker* aRuleWalker, uint32_t aFlags)
 {
   PROFILER_LABEL("nsStyleSet", "FileRules",
     js::ProfileEntry::Category::CSS);
 
   NS_ASSERTION(mBatching == 0, "rule processors out of date");
 
   // Cascading order:
   // [least important]
@@ -1149,17 +1149,18 @@ nsStyleSet::FileRules(nsIStyleRuleProces
   aRuleWalker->SetLevel(SheetType::Doc, false, true);
   bool cutOffInheritance = false;
   if (mBindingManager && aElement) {
     // We can supply additional document-level sheets that should be walked.
     mBindingManager->WalkRules(aCollectorFunc,
                                static_cast<ElementDependentRuleProcessorData*>(aData),
                                &cutOffInheritance);
   }
-  if (!skipUserStyles && !cutOffInheritance && // NOTE: different
+  if (((!skipUserStyles && !cutOffInheritance) // NOTE: different
+       || (aFlags & eDontSkipDocSheets)) &&
       mRuleProcessors[SheetType::Doc])
     (*aCollectorFunc)(mRuleProcessors[SheetType::Doc], aData);
   nsRuleNode* lastDocRN = aRuleWalker->CurrentNode();
   bool haveImportantDocRules = !aRuleWalker->GetCheckForImportantRules();
   nsTArray<nsRuleNode*> lastScopedRNs;
   nsTArray<bool> haveImportantScopedRules;
   bool haveAnyImportantScopedRules = false;
   if (!skipUserStyles && !cutOffInheritance &&
@@ -1816,34 +1817,35 @@ nsStyleSet::WalkDisableTextZoomRule(Elem
   if (aElement->IsSVGElement(nsGkAtoms::text))
     aRuleWalker->Forward(mDisableTextZoomStyleRule);
 }
 
 already_AddRefed<nsStyleContext>
 nsStyleSet::ResolvePseudoElementStyle(Element* aParentElement,
                                       CSSPseudoElementType aType,
                                       nsStyleContext* aParentContext,
-                                      Element* aPseudoElement)
+                                      Element* aPseudoElement,
+                                      uint32_t aFlags)
 {
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   NS_ASSERTION(aType < CSSPseudoElementType::Count,
                "must have pseudo element type");
   NS_ASSERTION(aParentElement, "Must have parent element");
 
   nsRuleWalker ruleWalker(mRuleTree, mAuthorStyleDisabled);
   TreeMatchContext treeContext(true, nsRuleWalker::eRelevantLinkUnvisited,
                                aParentElement->OwnerDoc());
   InitStyleScopes(treeContext, aParentElement);
   PseudoElementRuleProcessorData data(PresContext(), aParentElement,
                                       &ruleWalker, aType, treeContext,
                                       aPseudoElement);
   WalkRestrictionRule(aType, &ruleWalker);
   FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
-            aParentElement, &ruleWalker);
+            aParentElement, &ruleWalker, aFlags);
 
   nsRuleNode *ruleNode = ruleWalker.CurrentNode();
   nsRuleNode *visitedRuleNode = nullptr;
 
   if (treeContext.HaveRelevantLink()) {
     treeContext.ResetForVisitedMatching();
     ruleWalker.Reset();
     WalkRestrictionRule(aType, &ruleWalker);
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -203,26 +203,35 @@ class nsStyleSet final
   // its pseudo.
   //
   // (Perhaps mozOtherNonElement should go away and we shouldn't even
   // create style contexts for such content nodes.  However, not doing
   // any rule matching for them is a first step.)
   already_AddRefed<nsStyleContext>
   ResolveStyleForOtherNonElement(nsStyleContext* aParentContext);
 
+  /**
+   * Bit-flags that can be passed to ResolvePseudoElementStyle and
+   * FileRules in their parameter 'aFlags'.
+   */
+  enum {
+    eNormal = 0,
+    eDontSkipDocSheets = 1 << 0
+  };
   // Get a style context for a pseudo-element.  aParentElement must be
   // non-null.  aPseudoID is the CSSPseudoElementType for the
   // pseudo-element.  aPseudoElement must be non-null if the pseudo-element
   // type is one that allows user action pseudo-classes after it or allows
   // style attributes; otherwise, it is ignored.
   already_AddRefed<nsStyleContext>
   ResolvePseudoElementStyle(mozilla::dom::Element* aParentElement,
                             mozilla::CSSPseudoElementType aType,
                             nsStyleContext* aParentContext,
-                            mozilla::dom::Element* aPseudoElement);
+                            mozilla::dom::Element* aPseudoElement,
+                            uint32_t aFlags = eNormal);
 
   // This functions just like ResolvePseudoElementStyle except that it will
   // return nullptr if there are no explicit style rules for that
   // pseudo element.
   already_AddRefed<nsStyleContext>
   ProbePseudoElementStyle(mozilla::dom::Element* aParentElement,
                           mozilla::CSSPseudoElementType aType,
                           nsStyleContext* aParentContext);
@@ -245,17 +254,16 @@ class nsStyleSet final
 
     // Indicates that we should skip the flex/grid item specific chunk of
     // ApplyStyleFixups().  This is useful if our parent has "display: flex"
     // or "display: grid" but we can tell we're not going to honor that (e.g. if
     // it's the outer frame of a button widget, and we're the inline frame for
     // the button's label).
     eSkipParentDisplayBasedStyleFixup = 1 << 3
   };
-
   // Get a style context for an anonymous box.  aPseudoTag is the
   // pseudo-tag to use and must be non-null.  aFlags will be forwarded
   // to a GetContext call internally.
   already_AddRefed<nsStyleContext>
   ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext,
                            uint32_t aFlags = eNoFlags);
 
 #ifdef MOZ_XUL
@@ -495,17 +503,17 @@ private:
 
   // Enumerate the rules in a way that cares about the order of the
   // rules.
   // aElement is the element the rules are for.  It might be null.  aData
   // is the closure to pass to aCollectorFunc.  If aContent is not null,
   // aData must be a RuleProcessorData*
   void FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
                  RuleProcessorData* aData, mozilla::dom::Element* aElement,
-                 nsRuleWalker* aRuleWalker);
+                 nsRuleWalker* aRuleWalker, uint32_t aFlags = eNormal);
 
   // Enumerate all the rules in a way that doesn't care about the order
   // of the rules and break out if the enumeration is halted.
   void WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
                           ElementDependentRuleProcessorData* aData,
                           bool aWalkAllXBLStylesheets);
 
   // Helper for ResolveStyleWithReplacement