Title: [89132] trunk/Source/WebCore
Revision
89132
Author
apav...@chromium.org
Date
2011-06-17 03:13:52 -0700 (Fri, 17 Jun 2011)

Log Message

2011-06-17  Alexander Pavlov  <apav...@chromium.org>

        Reviewed by David Hyatt.

        Web Inspector: support for emulating element's pseudo class state in styleRulesForElement()
        https://bugs.webkit.org/show_bug.cgi?id=61070

        This patch is a slight rework of a solution by Alexander Udalov.
        It is supposed to help implement a feature in Web Inspector to examine
        style rules matched for different states of a given element.
        Web Inspector is supposed to pass a mask of ForcePseudoClassFlags to
        styleRulesForElement(), so that it will filter only the rules whose state
        (a set of pseudo classes in their selectors) matches a given
        mask, ignoring the state of the element itself.
        DoNotForcePseudoClassMask is the default behaviour; it always examines
        the state of a given element to make a match.

        Tests will be provided in a subsequent Web Inspector change employing this functionality.

        * css/CSSStyleSelector.cpp:
        (WebCore::CSSStyleSelector::initForStyleResolve):
        (WebCore::CSSStyleSelector::styleRulesForElement):
        (WebCore::CSSStyleSelector::pseudoStyleRulesForElement):
        (WebCore::CSSStyleSelector::checkSelector):
        (WebCore::CSSStyleSelector::SelectorChecker::checkSelector):
        (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector):
        * css/CSSStyleSelector.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (89131 => 89132)


--- trunk/Source/WebCore/ChangeLog	2011-06-17 10:05:13 UTC (rev 89131)
+++ trunk/Source/WebCore/ChangeLog	2011-06-17 10:13:52 UTC (rev 89132)
@@ -1,3 +1,31 @@
+2011-06-17  Alexander Pavlov  <apav...@chromium.org>
+
+        Reviewed by David Hyatt.
+
+        Web Inspector: support for emulating element's pseudo class state in styleRulesForElement()
+        https://bugs.webkit.org/show_bug.cgi?id=61070
+
+        This patch is a slight rework of a solution by Alexander Udalov.
+        It is supposed to help implement a feature in Web Inspector to examine
+        style rules matched for different states of a given element.
+        Web Inspector is supposed to pass a mask of ForcePseudoClassFlags to
+        styleRulesForElement(), so that it will filter only the rules whose state
+        (a set of pseudo classes in their selectors) matches a given
+        mask, ignoring the state of the element itself.
+        DoNotForcePseudoClassMask is the default behaviour; it always examines
+        the state of a given element to make a match.
+
+        Tests will be provided in a subsequent Web Inspector change employing this functionality.
+
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::initForStyleResolve):
+        (WebCore::CSSStyleSelector::styleRulesForElement):
+        (WebCore::CSSStyleSelector::pseudoStyleRulesForElement):
+        (WebCore::CSSStyleSelector::checkSelector):
+        (WebCore::CSSStyleSelector::SelectorChecker::checkSelector):
+        (WebCore::CSSStyleSelector::SelectorChecker::checkOneSelector):
+        * css/CSSStyleSelector.h:
+
 2011-06-17  Yury Semikhatsky  <yu...@chromium.org>
 
         Reviewed by Pavel Feldman.

Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (89131 => 89132)


--- trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-06-17 10:05:13 UTC (rev 89131)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-06-17 10:13:52 UTC (rev 89132)
@@ -884,6 +884,8 @@
     m_ruleList = 0;
 
     m_fontDirty = false;
+
+    m_forcePseudoClassMask = DoNotForcePseudoClassMask;
 }
 
 static inline const AtomicString* linkAttribute(Node* node)
@@ -2018,12 +2020,12 @@
     }
 }
 
-PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude)
+PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude, unsigned forcePseudoClassMask)
 {
-    return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
+    return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude, forcePseudoClassMask);
 }
 
-PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
+PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude, unsigned forcePseudoClassMask)
 {
     if (!e || !e->document()->haveStylesheetsLoaded())
         return 0;
@@ -2032,6 +2034,7 @@
 
     initElement(e);
     initForStyleResolve(e, 0, pseudoId);
+    m_forcePseudoClassMask = forcePseudoClassMask;
 
     if (rulesToInclude & UAAndUserCSSRules) {
         int firstUARule = -1, lastUARule = -1;
@@ -2056,6 +2059,7 @@
     }
 
     m_checker.m_collectRulesOnly = false;
+    m_forcePseudoClassMask = DoNotForcePseudoClassMask;
    
     return m_ruleList.release();
 }
@@ -2078,7 +2082,7 @@
     }
 
     // Slow path.
-    SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
+    SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, false, m_forcePseudoClassMask, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
     if (match != SelectorMatches)
         return false;
     if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
@@ -2207,7 +2211,7 @@
 // * SelectorMatches         - the selector matches the element e
 // * SelectorFailsLocally    - the selector fails for the element e
 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
-CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
+CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
 {
 #if ENABLE(SVG)
     // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
@@ -2217,7 +2221,7 @@
 #endif
 
     // first selector has to match
-    if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, encounteredLink, elementStyle, elementParentStyle))
+    if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle))
         return SelectorFailsLocally;
 
     // The rest of the selectors has to match
@@ -2251,7 +2255,7 @@
                 if (!n || !n->isElementNode())
                     return SelectorFailsCompletely;
                 e = static_cast<Element*>(n);
-                SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
+                SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
                 if (match != SelectorFailsLocally)
                     return match;
             }
@@ -2262,7 +2266,7 @@
             if (!n || !n->isElementNode())
                 return SelectorFailsCompletely;
             e = static_cast<Element*>(n);
-            return checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
+            return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
         }
         case CSSSelector::DirectAdjacent:
         {
@@ -2278,7 +2282,7 @@
                 return SelectorFailsLocally;
             e = static_cast<Element*>(n);
             m_matchVisitedPseudoClass = false;
-            return checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
+            return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
         }
         case CSSSelector::IndirectAdjacent:
             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
@@ -2294,7 +2298,7 @@
                     return SelectorFailsLocally;
                 e = static_cast<Element*>(n);
                 m_matchVisitedPseudoClass = false;
-                SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
+                SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
                 if (match != SelectorFailsLocally)
                     return match;
             };
@@ -2306,14 +2310,14 @@
             if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION &&
                 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
                 return SelectorFailsCompletely;
-            return checkSelector(sel, e, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle);
+            return checkSelector(sel, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle);
         case CSSSelector::ShadowDescendant:
         {
             Node* shadowHostNode = e->shadowAncestorNode();
             if (shadowHostNode == e || !shadowHostNode->isElementNode())
                 return SelectorFailsCompletely;
             e = static_cast<Element*>(shadowHostNode);
-            return checkSelector(sel, e, dynamicPseudo, false, encounteredLink);
+            return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
         }
     }
 
@@ -2387,7 +2391,7 @@
     return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
 }
 
-bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
+bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
 {
     ASSERT(e);
     if (!e)
@@ -2481,7 +2485,7 @@
                 // the parser enforces that this never occurs
                 ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot);
 
-                if (!checkOneSelector(subSel, e, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle))
+                if (!checkOneSelector(subSel, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle))
                     return true;
             }
         } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
@@ -2492,9 +2496,29 @@
             if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
                 return !m_document->page()->focusController()->isActive();
         }
-        
+
+        CSSSelector::PseudoType pseudoType = sel->pseudoType();
+
+        // Check forced pseudo class mask first.
+        if (forcePseudoClassMask != DoNotForcePseudoClassMask) {
+            switch (pseudoType) {
+            case CSSSelector::PseudoLink:
+                return forcePseudoClassMask & ForceLink;
+            case CSSSelector::PseudoVisited:
+                return forcePseudoClassMask & ForceVisited;
+            case CSSSelector::PseudoFocus:
+                return forcePseudoClassMask & ForceFocus;
+            case CSSSelector::PseudoHover:
+                return forcePseudoClassMask & ForceHover;
+            case CSSSelector::PseudoActive:
+                return forcePseudoClassMask & ForceActive;
+            default:
+                break;
+            }
+        }
+ 
         // Normal element pseudo class checking.
-        switch (sel->pseudoType()) {
+        switch (pseudoType) {
             // Pseudo classes:
             case CSSSelector::PseudoNot:
                 break; // Already handled up above.
@@ -2790,7 +2814,7 @@
                 break;
             case CSSSelector::PseudoAny:
                 for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) {
-                    if (checkSelector(selector, e, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle) == SelectorMatches)
+                    if (checkSelector(selector, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle) == SelectorMatches)
                         return true;
                 }
                 break;

Modified: trunk/Source/WebCore/css/CSSStyleSelector.h (89131 => 89132)


--- trunk/Source/WebCore/css/CSSStyleSelector.h	2011-06-17 10:05:13 UTC (rev 89131)
+++ trunk/Source/WebCore/css/CSSStyleSelector.h	2011-06-17 10:13:52 UTC (rev 89132)
@@ -130,6 +130,16 @@
         PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&);
 
     public:
+        enum ForcePseudoClassFlags {
+            ForceNone = 0,
+            DoNotForcePseudoClassMask = 1 << 0,
+            ForceHover = 1 << 1,
+            ForceFocus = 1 << 2,
+            ForceActive = 1 << 3,
+            ForceLink = 1 << 4,
+            ForceVisited = 1 << 5
+        };
+
         // These methods will give back the set of rules that matched for a given element (or a pseudo-element).
         enum CSSRuleFilter {
             UAAndUserCSSRules   = 1 << 1,
@@ -139,8 +149,8 @@
             AllButEmptyCSSRules = UAAndUserCSSRules | AuthorCSSRules | CrossOriginCSSRules,
             AllCSSRules         = AllButEmptyCSSRules | EmptyCSSRules,
         };
-        PassRefPtr<CSSRuleList> styleRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules);
-        PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules);
+        PassRefPtr<CSSRuleList> styleRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules, unsigned forcePseudoClassMask = DoNotForcePseudoClassMask);
+        PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules, unsigned forcePseudoClassMask = DoNotForcePseudoClassMask);
 
         // Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return
         // the correct font size scaled relative to the user's default (medium).
@@ -265,8 +275,8 @@
             SelectorChecker(Document*, bool strictParsing);
 
             bool checkSelector(CSSSelector*, Element*) const;
-            SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
-            bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle*, RenderStyle* elementParentStyle) const;
+            SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask = DoNotForcePseudoClassMask, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
+            bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle*, RenderStyle* elementParentStyle) const;
             bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
             static bool fastCheckSelector(const CSSSelector*, const Element*);
 
@@ -363,6 +373,7 @@
         CSSValue* m_lineHeightValue;
         bool m_fontDirty;
         bool m_matchAuthorAndUserStyles;
+        unsigned m_forcePseudoClassMask; // enum ForcePseudoClassFlags
         
         RefPtr<CSSFontSelector> m_fontSelector;
         Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to