Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / SelectorChecker.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27
28 #include "config.h"
29 #include "core/css/SelectorChecker.h"
30
31 #include "core/HTMLNames.h"
32 #include "core/css/CSSSelectorList.h"
33 #include "core/css/SiblingTraversalStrategies.h"
34 #include "core/dom/Document.h"
35 #include "core/dom/ElementTraversal.h"
36 #include "core/dom/FullscreenElementStack.h"
37 #include "core/dom/NodeRenderStyle.h"
38 #include "core/dom/Text.h"
39 #include "core/dom/shadow/InsertionPoint.h"
40 #include "core/dom/shadow/ShadowRoot.h"
41 #include "core/editing/FrameSelection.h"
42 #include "core/frame/LocalFrame.h"
43 #include "core/html/HTMLDocument.h"
44 #include "core/html/HTMLFrameElementBase.h"
45 #include "core/html/HTMLInputElement.h"
46 #include "core/html/HTMLOptionElement.h"
47 #include "core/html/parser/HTMLParserIdioms.h"
48 #include "core/html/track/vtt/VTTElement.h"
49 #include "core/inspector/InspectorInstrumentation.h"
50 #include "core/page/FocusController.h"
51 #include "core/rendering/RenderObject.h"
52 #include "core/rendering/RenderScrollbar.h"
53 #include "core/rendering/style/RenderStyle.h"
54 #include "platform/scroll/ScrollableArea.h"
55 #include "platform/scroll/ScrollbarTheme.h"
56
57 namespace WebCore {
58
59 using namespace HTMLNames;
60
61 SelectorChecker::SelectorChecker(Document& document, Mode mode)
62     : m_strictParsing(!document.inQuirksMode())
63     , m_documentIsHTML(document.isHTMLDocument())
64     , m_mode(mode)
65 {
66 }
67
68 static bool matchesCustomPseudoElement(const Element* element, const CSSSelector& selector)
69 {
70     ShadowRoot* root = element->containingShadowRoot();
71     if (!root || root->type() != ShadowRoot::UserAgentShadowRoot)
72         return false;
73
74     if (element->shadowPseudoId() != selector.value())
75         return false;
76
77     return true;
78 }
79
80 Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, bool allowToCrossBoundary) const
81 {
82     // CrossesBoundary means we don't care any context.scope. So we can walk up from a shadow root to its shadow host.
83     if (allowToCrossBoundary)
84         return context.element->parentOrShadowHostElement();
85
86     // If context.scope is a shadow root, we should walk up to its shadow host.
87     if ((context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot) && context.scope == context.element->containingShadowRoot())
88         return context.element->parentOrShadowHostElement();
89
90     if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope)
91         return context.element->parentElement();
92
93     // If context.scope is some element in some shadow tree and querySelector initialized the context,
94     // e.g. shadowRoot.querySelector(':host *'),
95     // (a) context.element has the same treescope as context.scope, need to walk up to its shadow host.
96     // (b) Otherwise, should not walk up from a shadow root to a shadow host.
97     if (context.scope && context.scope->treeScope() == context.element->treeScope())
98         return context.element->parentOrShadowHostElement();
99
100     return context.element->parentElement();
101 }
102
103 bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingContext& context) const
104 {
105     if (!(context.behaviorAtBoundary & SelectorChecker::ScopeContainsLastMatchedElement))
106         return true;
107
108     ASSERT(context.scope);
109     if (context.scope->treeScope() == context.element->treeScope())
110         return true;
111
112     // Because Blink treats a shadow host's TreeScope as a separate one from its descendent shadow roots,
113     // if the last matched element is a shadow host, the condition above isn't met, even though it
114     // should be.
115     return context.element == context.scope->shadowHost() && (!context.previousElement || context.previousElement->isInDescendantTreeOf(context.element));
116 }
117
118 static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheckingContext& context)
119 {
120     if (context.scope && context.scope->isInShadowTree())
121         return context.element == context.scope->shadowHost();
122
123     return false;
124 }
125
126 // Recursive check of selectors and combinators
127 // It can return 4 different values:
128 // * SelectorMatches          - the selector matches the element e
129 // * SelectorFailsLocally     - the selector fails for the element e
130 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
131 // * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
132 template<typename SiblingTraversalStrategy>
133 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const
134 {
135     // first selector has to match
136     unsigned specificity = 0;
137     if (!checkOne(context, siblingTraversalStrategy, &specificity))
138         return SelectorFailsLocally;
139
140     if (context.selector->match() == CSSSelector::PseudoElement) {
141         if (context.selector->isCustomPseudoElement()) {
142             if (!matchesCustomPseudoElement(context.element, *context.selector))
143                 return SelectorFailsLocally;
144         } else if (context.selector->isContentPseudoElement()) {
145             if (!context.element->isInShadowTree() || !context.element->isInsertionPoint())
146                 return SelectorFailsLocally;
147         } else if (context.selector->isShadowPseudoElement()) {
148             if (!context.element->isInShadowTree() || !context.previousElement)
149                 return SelectorFailsCompletely;
150         } else {
151             if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules)
152                 return SelectorFailsLocally;
153
154             PseudoId pseudoId = CSSSelector::pseudoId(context.selector->pseudoType());
155             if (pseudoId == FIRST_LETTER)
156                 context.element->document().styleEngine()->setUsesFirstLetterRules(true);
157             if (pseudoId != NOPSEUDO && m_mode != SharingRules && result)
158                 result->dynamicPseudo = pseudoId;
159         }
160     }
161
162     // Prepare next selector
163     if (context.selector->isLastInTagHistory()) {
164         if (scopeContainsLastMatchedElement(context)) {
165             if (result)
166                 result->specificity += specificity;
167             return SelectorMatches;
168         }
169         return SelectorFailsLocally;
170     }
171
172     Match match;
173     if (context.selector->relation() != CSSSelector::SubSelector) {
174         // Abort if the next selector would exceed the scope.
175         if (nextSelectorExceedsScope(context))
176             return SelectorFailsCompletely;
177
178         // Bail-out if this selector is irrelevant for the pseudoId
179         if (context.pseudoId != NOPSEUDO && (!result || context.pseudoId != result->dynamicPseudo))
180             return SelectorFailsCompletely;
181
182         if (result) {
183             TemporaryChange<PseudoId> dynamicPseudoScope(result->dynamicPseudo, NOPSEUDO);
184             match = matchForRelation(context, siblingTraversalStrategy, result);
185         } else {
186             return matchForRelation(context, siblingTraversalStrategy, 0);
187         }
188     } else {
189         match = matchForSubSelector(context, siblingTraversalStrategy, result);
190     }
191     if (match != SelectorMatches || !result)
192         return match;
193
194     result->specificity += specificity;
195     return SelectorMatches;
196 }
197
198 static inline SelectorChecker::SelectorCheckingContext prepareNextContextForRelation(const SelectorChecker::SelectorCheckingContext& context)
199 {
200     SelectorChecker::SelectorCheckingContext nextContext(context);
201     ASSERT(context.selector->tagHistory());
202     nextContext.selector = context.selector->tagHistory();
203     return nextContext;
204 }
205
206 static inline bool isAuthorShadowRoot(const Node* node)
207 {
208     return node && node->isShadowRoot() && toShadowRoot(node)->type() == ShadowRoot::AuthorShadowRoot;
209 }
210
211 template<typename SiblingTraversalStrategy>
212 SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const
213 {
214     SelectorCheckingContext nextContext = prepareNextContextForRelation(context);
215
216     PseudoId dynamicPseudo = result ? result->dynamicPseudo : NOPSEUDO;
217     // a selector is invalid if something follows a pseudo-element
218     // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
219     // to follow the pseudo elements.
220     nextContext.hasScrollbarPseudo = dynamicPseudo != NOPSEUDO && (context.scrollbar || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER);
221     nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION;
222     if ((context.elementStyle || m_mode == CollectingCSSRules || m_mode == CollectingStyleRules || m_mode == QueryingRules) && dynamicPseudo != NOPSEUDO
223         && !nextContext.hasSelectionPseudo
224         && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass))
225         return SelectorFailsCompletely;
226
227     nextContext.isSubSelector = true;
228     return match(nextContext, siblingTraversalStrategy, result);
229 }
230
231 static bool selectorMatchesShadowRoot(const CSSSelector* selector)
232 {
233     return selector && selector->isShadowPseudoElement();
234 }
235
236 template<typename SiblingTraversalStrategy>
237 SelectorChecker::Match SelectorChecker::matchForPseudoShadow(const ContainerNode* node, const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const
238 {
239     if (!isAuthorShadowRoot(node))
240         return SelectorFailsCompletely;
241     return match(context, siblingTraversalStrategy, result);
242 }
243
244 template<typename SiblingTraversalStrategy>
245 SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const
246 {
247     SelectorCheckingContext nextContext = prepareNextContextForRelation(context);
248     nextContext.previousElement = context.element;
249
250     CSSSelector::Relation relation = context.selector->relation();
251
252     // Disable :visited matching when we see the first link or try to match anything else than an ancestors.
253     if (!context.isSubSelector && (context.element->isLink() || (relation != CSSSelector::Descendant && relation != CSSSelector::Child)))
254         nextContext.visitedMatchType = VisitedMatchDisabled;
255
256     nextContext.pseudoId = NOPSEUDO;
257
258     switch (relation) {
259     case CSSSelector::Descendant:
260         if (context.selector->relationIsAffectedByPseudoContent()) {
261             for (Element* element = context.element; element; element = element->parentElement()) {
262                 if (matchForShadowDistributed(element, siblingTraversalStrategy, nextContext, result) == SelectorMatches)
263                     return SelectorMatches;
264             }
265             return SelectorFailsCompletely;
266         }
267         nextContext.isSubSelector = false;
268         nextContext.elementStyle = 0;
269
270         if (selectorMatchesShadowRoot(nextContext.selector))
271             return matchForPseudoShadow(context.element->containingShadowRoot(), nextContext, siblingTraversalStrategy, result);
272
273         for (nextContext.element = parentElement(context); nextContext.element; nextContext.element = parentElement(nextContext)) {
274             Match match = this->match(nextContext, siblingTraversalStrategy, result);
275             if (match == SelectorMatches || match == SelectorFailsCompletely)
276                 return match;
277             if (nextSelectorExceedsScope(nextContext))
278                 return SelectorFailsCompletely;
279         }
280         return SelectorFailsCompletely;
281     case CSSSelector::Child:
282         {
283             if (context.selector->relationIsAffectedByPseudoContent())
284                 return matchForShadowDistributed(context.element, siblingTraversalStrategy, nextContext, result);
285
286             nextContext.isSubSelector = false;
287             nextContext.elementStyle = 0;
288
289             if (selectorMatchesShadowRoot(nextContext.selector))
290                 return matchForPseudoShadow(context.element->parentNode(), nextContext, siblingTraversalStrategy, result);
291
292             nextContext.element = parentElement(context);
293             if (!nextContext.element)
294                 return SelectorFailsCompletely;
295             return match(nextContext, siblingTraversalStrategy, result);
296         }
297     case CSSSelector::DirectAdjacent:
298         // Shadow roots can't have sibling elements
299         if (selectorMatchesShadowRoot(nextContext.selector))
300             return SelectorFailsCompletely;
301
302         if (m_mode == ResolvingStyle) {
303             if (ContainerNode* parent = context.element->parentElementOrShadowRoot())
304                 parent->setChildrenAffectedByDirectAdjacentRules();
305         }
306         nextContext.element = ElementTraversal::previousSibling(*context.element);
307         if (!nextContext.element)
308             return SelectorFailsAllSiblings;
309         nextContext.isSubSelector = false;
310         nextContext.elementStyle = 0;
311         return match(nextContext, siblingTraversalStrategy, result);
312
313     case CSSSelector::IndirectAdjacent:
314         // Shadow roots can't have sibling elements
315         if (selectorMatchesShadowRoot(nextContext.selector))
316             return SelectorFailsCompletely;
317
318         if (m_mode == ResolvingStyle) {
319             if (ContainerNode* parent = context.element->parentElementOrShadowRoot())
320                 parent->setChildrenAffectedByIndirectAdjacentRules();
321         }
322         nextContext.element = ElementTraversal::previousSibling(*context.element);
323         nextContext.isSubSelector = false;
324         nextContext.elementStyle = 0;
325         for (; nextContext.element; nextContext.element = ElementTraversal::previousSibling(*nextContext.element)) {
326             Match match = this->match(nextContext, siblingTraversalStrategy, result);
327             if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely)
328                 return match;
329         };
330         return SelectorFailsAllSiblings;
331
332     case CSSSelector::ShadowPseudo:
333         {
334             // If we're in the same tree-scope as the scoping element, then following a shadow descendant combinator would escape that and thus the scope.
335             if (context.scope && context.scope->shadowHost() && context.scope->shadowHost()->treeScope() == context.element->treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithinTreeScope)
336                 return SelectorFailsCompletely;
337
338             Element* shadowHost = context.element->shadowHost();
339             if (!shadowHost)
340                 return SelectorFailsCompletely;
341             nextContext.element = shadowHost;
342             nextContext.isSubSelector = false;
343             nextContext.elementStyle = 0;
344             return this->match(nextContext, siblingTraversalStrategy, result);
345         }
346
347     case CSSSelector::ShadowDeep:
348         {
349             nextContext.isSubSelector = false;
350             nextContext.elementStyle = 0;
351             for (nextContext.element = parentElement(context, true); nextContext.element; nextContext.element = parentElement(nextContext, true)) {
352                 Match match = this->match(nextContext, siblingTraversalStrategy, result);
353                 if (match == SelectorMatches || match == SelectorFailsCompletely)
354                     return match;
355                 if (nextSelectorExceedsScope(nextContext))
356                     return SelectorFailsCompletely;
357             }
358             return SelectorFailsCompletely;
359         }
360
361     case CSSSelector::SubSelector:
362         ASSERT_NOT_REACHED();
363     }
364
365     ASSERT_NOT_REACHED();
366     return SelectorFailsCompletely;
367 }
368
369 template<typename SiblingTraversalStrategy>
370 SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* element, const SiblingTraversalStrategy& siblingTraversalStrategy, SelectorCheckingContext& nextContext, MatchResult* result) const
371 {
372     ASSERT(element);
373     WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
374
375     const ContainerNode* scope = nextContext.scope;
376     BehaviorAtBoundary behaviorAtBoundary = nextContext.behaviorAtBoundary;
377
378     collectDestinationInsertionPoints(*element, insertionPoints);
379     for (size_t i = 0; i < insertionPoints.size(); ++i) {
380         nextContext.element = insertionPoints[i];
381
382         // If a given scope is a shadow host of an insertion point but behaviorAtBoundary doesn't have ScopeIsShadowRoot,
383         // we need to update behaviorAtBoundary to make selectors like ":host > ::content" work correctly.
384         if (m_mode == SharingRules) {
385             nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowRoot);
386             nextContext.scope = insertionPoints[i]->containingShadowRoot();
387         } else if (scope == insertionPoints[i]->containingShadowRoot() && !(behaviorAtBoundary & ScopeIsShadowRoot)) {
388             nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowRoot);
389         } else {
390             nextContext.behaviorAtBoundary = behaviorAtBoundary;
391         }
392
393         nextContext.isSubSelector = false;
394         nextContext.elementStyle = 0;
395         if (match(nextContext, siblingTraversalStrategy, result) == SelectorMatches)
396             return SelectorMatches;
397     }
398     return SelectorFailsLocally;
399 }
400
401 template<typename CharType>
402 static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned length)
403 {
404     for (unsigned i = 0; i < length; ++i)
405         if (isHTMLSpace<CharType>(string[i]))
406             return true;
407     return false;
408 }
409
410 static inline bool containsHTMLSpace(const AtomicString& string)
411 {
412     if (LIKELY(string.is8Bit()))
413         return containsHTMLSpaceTemplate<LChar>(string.characters8(), string.length());
414     return containsHTMLSpaceTemplate<UChar>(string.characters16(), string.length());
415 }
416
417 static bool attributeValueMatches(const Attribute& attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive)
418 {
419     const AtomicString& value = attributeItem.value();
420     if (value.isNull())
421         return false;
422
423     switch (match) {
424     case CSSSelector::Exact:
425         if (caseSensitive ? selectorValue != value : !equalIgnoringCase(selectorValue, value))
426             return false;
427         break;
428     case CSSSelector::List:
429         {
430             // Ignore empty selectors or selectors containing HTML spaces
431             if (selectorValue.isEmpty() || containsHTMLSpace(selectorValue))
432                 return false;
433
434             unsigned startSearchAt = 0;
435             while (true) {
436                 size_t foundPos = value.find(selectorValue, startSearchAt, caseSensitive);
437                 if (foundPos == kNotFound)
438                     return false;
439                 if (!foundPos || isHTMLSpace<UChar>(value[foundPos - 1])) {
440                     unsigned endStr = foundPos + selectorValue.length();
441                     if (endStr == value.length() || isHTMLSpace<UChar>(value[endStr]))
442                         break; // We found a match.
443                 }
444
445                 // No match. Keep looking.
446                 startSearchAt = foundPos + 1;
447             }
448             break;
449         }
450     case CSSSelector::Contain:
451         if (!value.contains(selectorValue, caseSensitive) || selectorValue.isEmpty())
452             return false;
453         break;
454     case CSSSelector::Begin:
455         if (!value.startsWith(selectorValue, caseSensitive) || selectorValue.isEmpty())
456             return false;
457         break;
458     case CSSSelector::End:
459         if (!value.endsWith(selectorValue, caseSensitive) || selectorValue.isEmpty())
460             return false;
461         break;
462     case CSSSelector::Hyphen:
463         if (value.length() < selectorValue.length())
464             return false;
465         if (!value.startsWith(selectorValue, caseSensitive))
466             return false;
467         // It they start the same, check for exact match or following '-':
468         if (value.length() != selectorValue.length() && value[selectorValue.length()] != '-')
469             return false;
470         break;
471     case CSSSelector::PseudoClass:
472     case CSSSelector::PseudoElement:
473     default:
474         break;
475     }
476
477     return true;
478 }
479
480 static bool anyAttributeMatches(Element& element, CSSSelector::Match match, const CSSSelector& selector)
481 {
482     const QualifiedName& selectorAttr = selector.attribute();
483     ASSERT(selectorAttr.localName() != starAtom); // Should not be possible from the CSS grammar.
484
485     // Synchronize the attribute in case it is lazy-computed.
486     // Currently all lazy properties have a null namespace, so only pass localName().
487     element.synchronizeAttribute(selectorAttr.localName());
488
489     if (!element.hasAttributesWithoutUpdate())
490         return false;
491
492     const AtomicString& selectorValue =  selector.value();
493
494     AttributeCollection attributes = element.attributes();
495     AttributeCollection::const_iterator end = attributes.end();
496     for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) {
497         const Attribute& attributeItem = *it;
498
499         if (!attributeItem.matches(selectorAttr))
500             continue;
501
502         if (attributeValueMatches(attributeItem, match, selectorValue, true))
503             return true;
504
505         // Case sensitivity for attribute matching is looser than hasAttribute or
506         // Element::shouldIgnoreAttributeCase() for now. Unclear if that's correct.
507         bool caseSensitive = !element.document().isHTMLDocument() || HTMLDocument::isCaseSensitiveAttribute(selectorAttr);
508
509         // If case-insensitive, re-check, and count if result differs.
510         // See http://code.google.com/p/chromium/issues/detail?id=327060
511         if (!caseSensitive && attributeValueMatches(attributeItem, match, selectorValue, false)) {
512             UseCounter::count(element.document(), UseCounter::CaseInsensitiveAttrSelectorMatch);
513             return true;
514         }
515     }
516
517     return false;
518 }
519
520 template<typename SiblingTraversalStrategy>
521 bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, unsigned* specificity) const
522 {
523     ASSERT(context.element);
524     Element& element = *context.element;
525     ASSERT(context.selector);
526     const CSSSelector& selector = *context.selector;
527
528     bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.behaviorAtBoundary, context.scope);
529
530     // Only :host and :ancestor should match the host: http://drafts.csswg.org/css-scoping/#host-element
531     if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass()
532         && !(context.behaviorAtBoundary & TreatShadowHostAsNormalScope))
533         return false;
534
535     if (selector.match() == CSSSelector::Tag)
536         return SelectorChecker::tagMatches(element, selector.tagQName());
537
538     if (selector.match() == CSSSelector::Class)
539         return element.hasClass() && element.classNames().contains(selector.value());
540
541     if (selector.match() == CSSSelector::Id)
542         return element.hasID() && element.idForStyleResolution() == selector.value();
543
544     if (selector.isAttributeSelector())
545         return anyAttributeMatches(element, selector.match(), selector);
546
547     if (selector.match() == CSSSelector::PseudoClass) {
548         // Handle :not up front.
549         if (selector.pseudoType() == CSSSelector::PseudoNot) {
550             SelectorCheckingContext subContext(context);
551             subContext.isSubSelector = true;
552             ASSERT(selector.selectorList());
553             for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = subContext.selector->tagHistory()) {
554                 // :not cannot nest. I don't really know why this is a
555                 // restriction in CSS3, but it is, so let's honor it.
556                 // the parser enforces that this never occurs
557                 ASSERT(subContext.selector->pseudoType() != CSSSelector::PseudoNot);
558                 // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
559                 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.visitedMatchType == VisitedMatchEnabled))
560                     return true;
561                 // context.scope is not available if m_mode == SharingRules.
562                 // We cannot determine whether :host or :scope matches a given element or not.
563                 if (m_mode == SharingRules && (subContext.selector->isHostPseudoClass() || subContext.selector->pseudoType() == CSSSelector::PseudoScope))
564                     return true;
565                 if (!checkOne(subContext, DOMSiblingTraversalStrategy()))
566                     return true;
567             }
568         } else if (context.hasScrollbarPseudo) {
569             // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
570             // (since there are no elements involved).
571             return checkScrollbarPseudoClass(context, &element.document(), selector);
572         } else if (context.hasSelectionPseudo) {
573             if (selector.pseudoType() == CSSSelector::PseudoWindowInactive)
574                 return !element.document().page()->focusController().isActive();
575         }
576
577         // Normal element pseudo class checking.
578         switch (selector.pseudoType()) {
579             // Pseudo classes:
580         case CSSSelector::PseudoNot:
581             break; // Already handled up above.
582         case CSSSelector::PseudoEmpty:
583             {
584                 bool result = true;
585                 for (Node* n = element.firstChild(); n; n = n->nextSibling()) {
586                     if (n->isElementNode()) {
587                         result = false;
588                         break;
589                     }
590                     if (n->isTextNode()) {
591                         Text* textNode = toText(n);
592                         if (!textNode->data().isEmpty()) {
593                             result = false;
594                             break;
595                         }
596                     }
597                 }
598                 if (m_mode == ResolvingStyle) {
599                     element.setStyleAffectedByEmpty();
600                     if (context.elementStyle)
601                         context.elementStyle->setEmptyState(result);
602                     else if (element.renderStyle() && (element.document().styleEngine()->usesSiblingRules() || element.renderStyle()->unique()))
603                         element.renderStyle()->setEmptyState(result);
604                 }
605                 return result;
606             }
607         case CSSSelector::PseudoFirstChild:
608             // first-child matches the first child that is an element
609             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
610                 bool result = siblingTraversalStrategy.isFirstChild(element);
611                 if (m_mode == ResolvingStyle) {
612                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle();
613                     parent->setChildrenAffectedByFirstChildRules();
614                     if (result && childStyle)
615                         childStyle->setFirstChildState();
616                 }
617                 return result;
618             }
619             break;
620         case CSSSelector::PseudoFirstOfType:
621             // first-of-type matches the first element of its type
622             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
623                 bool result = siblingTraversalStrategy.isFirstOfType(element, element.tagQName());
624                 if (m_mode == ResolvingStyle)
625                     parent->setChildrenAffectedByForwardPositionalRules();
626                 return result;
627             }
628             break;
629         case CSSSelector::PseudoLastChild:
630             // last-child matches the last child that is an element
631             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
632                 bool result = parent->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(element);
633                 if (m_mode == ResolvingStyle) {
634                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle();
635                     parent->setChildrenAffectedByLastChildRules();
636                     if (result && childStyle)
637                         childStyle->setLastChildState();
638                 }
639                 return result;
640             }
641             break;
642         case CSSSelector::PseudoLastOfType:
643             // last-of-type matches the last element of its type
644             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
645                 if (m_mode == ResolvingStyle)
646                     parent->setChildrenAffectedByBackwardPositionalRules();
647                 if (!parent->isFinishedParsingChildren())
648                     return false;
649                 return siblingTraversalStrategy.isLastOfType(element, element.tagQName());
650             }
651             break;
652         case CSSSelector::PseudoOnlyChild:
653             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
654                 bool firstChild = siblingTraversalStrategy.isFirstChild(element);
655                 bool onlyChild = firstChild && parent->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(element);
656                 if (m_mode == ResolvingStyle) {
657                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle();
658                     parent->setChildrenAffectedByFirstChildRules();
659                     parent->setChildrenAffectedByLastChildRules();
660                     if (firstChild && childStyle)
661                         childStyle->setFirstChildState();
662                     if (onlyChild && childStyle)
663                         childStyle->setLastChildState();
664                 }
665                 return onlyChild;
666             }
667             break;
668         case CSSSelector::PseudoOnlyOfType:
669             // FIXME: This selector is very slow.
670             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
671                 if (m_mode == ResolvingStyle) {
672                     parent->setChildrenAffectedByForwardPositionalRules();
673                     parent->setChildrenAffectedByBackwardPositionalRules();
674                 }
675                 if (!parent->isFinishedParsingChildren())
676                     return false;
677                 return siblingTraversalStrategy.isFirstOfType(element, element.tagQName()) && siblingTraversalStrategy.isLastOfType(element, element.tagQName());
678             }
679             break;
680         case CSSSelector::PseudoNthChild:
681             if (!selector.parseNth())
682                 break;
683             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
684                 int count = 1 + siblingTraversalStrategy.countElementsBefore(element);
685                 if (m_mode == ResolvingStyle) {
686                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle();
687                     if (childStyle)
688                         childStyle->setUnique();
689                     parent->setChildrenAffectedByForwardPositionalRules();
690                 }
691
692                 if (selector.matchNth(count))
693                     return true;
694             }
695             break;
696         case CSSSelector::PseudoNthOfType:
697             if (!selector.parseNth())
698                 break;
699             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
700                 int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefore(element, element.tagQName());
701                 if (m_mode == ResolvingStyle)
702                     parent->setChildrenAffectedByForwardPositionalRules();
703
704                 if (selector.matchNth(count))
705                     return true;
706             }
707             break;
708         case CSSSelector::PseudoNthLastChild:
709             if (!selector.parseNth())
710                 break;
711             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
712                 if (m_mode == ResolvingStyle)
713                     parent->setChildrenAffectedByBackwardPositionalRules();
714                 if (!parent->isFinishedParsingChildren())
715                     return false;
716                 int count = 1 + siblingTraversalStrategy.countElementsAfter(element);
717                 if (selector.matchNth(count))
718                     return true;
719             }
720             break;
721         case CSSSelector::PseudoNthLastOfType:
722             if (!selector.parseNth())
723                 break;
724             if (ContainerNode* parent = element.parentElementOrDocumentFragment()) {
725                 if (m_mode == ResolvingStyle)
726                     parent->setChildrenAffectedByBackwardPositionalRules();
727                 if (!parent->isFinishedParsingChildren())
728                     return false;
729
730                 int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfter(element, element.tagQName());
731                 if (selector.matchNth(count))
732                     return true;
733             }
734             break;
735         case CSSSelector::PseudoTarget:
736             if (element == element.document().cssTarget())
737                 return true;
738             break;
739         case CSSSelector::PseudoAny:
740             {
741                 SelectorCheckingContext subContext(context);
742                 subContext.isSubSelector = true;
743                 ASSERT(selector.selectorList());
744                 for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) {
745                     if (match(subContext, siblingTraversalStrategy) == SelectorMatches)
746                         return true;
747                 }
748             }
749             break;
750         case CSSSelector::PseudoAutofill:
751             if (!element.isFormControlElement())
752                 break;
753             return toHTMLFormControlElement(element).isAutofilled();
754         case CSSSelector::PseudoAnyLink:
755         case CSSSelector::PseudoLink:
756             // :visited and :link matches are separated later when applying the style. Here both classes match all links...
757             return element.isLink();
758         case CSSSelector::PseudoVisited:
759             // ...except if :visited matching is disabled for ancestor/sibling matching.
760             return element.isLink() && context.visitedMatchType == VisitedMatchEnabled;
761         case CSSSelector::PseudoDrag:
762             if (m_mode == ResolvingStyle) {
763                 if (context.elementStyle)
764                     context.elementStyle->setAffectedByDrag();
765                 else
766                     element.setChildrenOrSiblingsAffectedByDrag();
767             }
768             if (element.renderer() && element.renderer()->isDragging())
769                 return true;
770             break;
771         case CSSSelector::PseudoFocus:
772             if (m_mode == ResolvingStyle) {
773                 if (context.elementStyle)
774                     context.elementStyle->setAffectedByFocus();
775                 else
776                     element.setChildrenOrSiblingsAffectedByFocus();
777             }
778             return matchesFocusPseudoClass(element);
779         case CSSSelector::PseudoHover:
780             // If we're in quirks mode, then hover should never match anchors with no
781             // href and *:hover should not match anything. This is important for sites like wsj.com.
782             if (m_strictParsing || context.isSubSelector || element.isLink()) {
783                 if (m_mode == ResolvingStyle) {
784                     if (context.elementStyle)
785                         context.elementStyle->setAffectedByHover();
786                     else
787                         element.setChildrenOrSiblingsAffectedByHover();
788                 }
789                 if (element.hovered() || InspectorInstrumentation::forcePseudoState(&element, CSSSelector::PseudoHover))
790                     return true;
791             }
792             break;
793         case CSSSelector::PseudoActive:
794             // If we're in quirks mode, then :active should never match anchors with no
795             // href and *:active should not match anything.
796             if (m_strictParsing || context.isSubSelector || element.isLink()) {
797                 if (m_mode == ResolvingStyle) {
798                     if (context.elementStyle)
799                         context.elementStyle->setAffectedByActive();
800                     else
801                         element.setChildrenOrSiblingsAffectedByActive();
802                 }
803                 if (element.active() || InspectorInstrumentation::forcePseudoState(&element, CSSSelector::PseudoActive))
804                     return true;
805             }
806             break;
807         case CSSSelector::PseudoEnabled:
808             if (element.isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element))
809                 return !element.isDisabledFormControl();
810             break;
811         case CSSSelector::PseudoFullPageMedia:
812             return element.document().isMediaDocument();
813             break;
814         case CSSSelector::PseudoDefault:
815             return element.isDefaultButtonForForm();
816         case CSSSelector::PseudoDisabled:
817             if (element.isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element))
818                 return element.isDisabledFormControl();
819             break;
820         case CSSSelector::PseudoReadOnly:
821             return element.matchesReadOnlyPseudoClass();
822         case CSSSelector::PseudoReadWrite:
823             return element.matchesReadWritePseudoClass();
824         case CSSSelector::PseudoOptional:
825             return element.isOptionalFormControl();
826         case CSSSelector::PseudoRequired:
827             return element.isRequiredFormControl();
828         case CSSSelector::PseudoValid:
829             element.document().setContainsValidityStyleRules();
830             return element.willValidate() && element.isValidFormControlElement();
831         case CSSSelector::PseudoInvalid:
832             element.document().setContainsValidityStyleRules();
833             return element.willValidate() && !element.isValidFormControlElement();
834         case CSSSelector::PseudoChecked:
835             {
836                 if (isHTMLInputElement(element)) {
837                     HTMLInputElement& inputElement = toHTMLInputElement(element);
838                     // Even though WinIE allows checked and indeterminate to
839                     // co-exist, the CSS selector spec says that you can't be
840                     // both checked and indeterminate. We will behave like WinIE
841                     // behind the scenes and just obey the CSS spec here in the
842                     // test for matching the pseudo.
843                     if (inputElement.shouldAppearChecked() && !inputElement.shouldAppearIndeterminate())
844                         return true;
845                 } else if (isHTMLOptionElement(element) && toHTMLOptionElement(element).selected())
846                     return true;
847                 break;
848             }
849         case CSSSelector::PseudoIndeterminate:
850             return element.shouldAppearIndeterminate();
851         case CSSSelector::PseudoRoot:
852             if (element == element.document().documentElement())
853                 return true;
854             break;
855         case CSSSelector::PseudoLang:
856             {
857                 AtomicString value;
858                 if (element.isVTTElement())
859                     value = toVTTElement(element).language();
860                 else
861                     value = element.computeInheritedLanguage();
862                 const AtomicString& argument = selector.argument();
863                 if (value.isEmpty() || !value.startsWith(argument, false))
864                     break;
865                 if (value.length() != argument.length() && value[argument.length()] != '-')
866                     break;
867                 return true;
868             }
869         case CSSSelector::PseudoFullScreen:
870             // While a Document is in the fullscreen state, and the document's current fullscreen
871             // element is an element in the document, the 'full-screen' pseudoclass applies to
872             // that element. Also, an <iframe>, <object> or <embed> element whose child browsing
873             // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
874             if (isHTMLFrameElementBase(element) && element.containsFullScreenElement())
875                 return true;
876             if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(element.document())) {
877                 if (!fullscreen->webkitIsFullScreen())
878                     return false;
879                 return element == fullscreen->webkitCurrentFullScreenElement();
880             }
881             return false;
882         case CSSSelector::PseudoFullScreenAncestor:
883             return element.containsFullScreenElement();
884         case CSSSelector::PseudoFullScreenDocument:
885             // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies
886             // to all elements of that Document.
887             if (!FullscreenElementStack::isFullScreen(element.document()))
888                 return false;
889             return true;
890         case CSSSelector::PseudoInRange:
891             element.document().setContainsValidityStyleRules();
892             return element.isInRange();
893         case CSSSelector::PseudoOutOfRange:
894             element.document().setContainsValidityStyleRules();
895             return element.isOutOfRange();
896         case CSSSelector::PseudoFutureCue:
897             return (element.isVTTElement() && !toVTTElement(element).isPastNode());
898         case CSSSelector::PseudoPastCue:
899             return (element.isVTTElement() && toVTTElement(element).isPastNode());
900
901         case CSSSelector::PseudoScope:
902             {
903                 if (m_mode == SharingRules)
904                     return true;
905                 const Node* contextualReferenceNode = !context.scope ? element.document().documentElement() : context.scope;
906                 if (element == contextualReferenceNode)
907                     return true;
908                 break;
909             }
910
911         case CSSSelector::PseudoUnresolved:
912             if (element.isUnresolvedCustomElement())
913                 return true;
914             break;
915
916         case CSSSelector::PseudoHost:
917         case CSSSelector::PseudoHostContext:
918             {
919                 if (m_mode == SharingRules)
920                     return true;
921                 // :host only matches a shadow host when :host is in a shadow tree of the shadow host.
922                 if (!context.scope)
923                     return false;
924                 const ContainerNode* shadowHost = context.scope->shadowHost();
925                 if (!shadowHost || shadowHost != element)
926                     return false;
927                 ASSERT(element.shadow());
928
929                 // For empty parameter case, i.e. just :host or :host().
930                 if (!selector.selectorList()) // Use *'s specificity. So just 0.
931                     return true;
932
933                 SelectorCheckingContext subContext(context);
934                 subContext.isSubSelector = true;
935
936                 bool matched = false;
937                 unsigned maxSpecificity = 0;
938
939                 // If one of simple selectors matches an element, returns SelectorMatches. Just "OR".
940                 for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) {
941                     subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHostParameter;
942                     subContext.scope = context.scope;
943                     // Use NodeRenderingTraversal to traverse a composed ancestor list of a given element.
944                     Element* nextElement = &element;
945                     SelectorCheckingContext hostContext(subContext);
946                     do {
947                         MatchResult subResult;
948                         hostContext.element = nextElement;
949                         if (match(hostContext, siblingTraversalStrategy, &subResult) == SelectorMatches) {
950                             matched = true;
951                             // Consider div:host(div:host(div:host(div:host...))).
952                             maxSpecificity = std::max(maxSpecificity, hostContext.selector->specificity() + subResult.specificity);
953                             break;
954                         }
955                         hostContext.behaviorAtBoundary = DoesNotCrossBoundary;
956                         hostContext.scope = 0;
957
958                         if (selector.pseudoType() == CSSSelector::PseudoHost)
959                             break;
960
961                         hostContext.elementStyle = 0;
962                         nextElement = NodeRenderingTraversal::parentElement(nextElement);
963                     } while (nextElement);
964                 }
965                 if (matched) {
966                     if (specificity)
967                         *specificity = maxSpecificity;
968                     return true;
969                 }
970             }
971             break;
972
973         case CSSSelector::PseudoHorizontal:
974         case CSSSelector::PseudoVertical:
975         case CSSSelector::PseudoDecrement:
976         case CSSSelector::PseudoIncrement:
977         case CSSSelector::PseudoStart:
978         case CSSSelector::PseudoEnd:
979         case CSSSelector::PseudoDoubleButton:
980         case CSSSelector::PseudoSingleButton:
981         case CSSSelector::PseudoNoButton:
982         case CSSSelector::PseudoCornerPresent:
983             return false;
984
985         case CSSSelector::PseudoUnknown:
986         case CSSSelector::PseudoNotParsed:
987         default:
988             ASSERT_NOT_REACHED();
989             break;
990         }
991         return false;
992     } else if (selector.match() == CSSSelector::PseudoElement && selector.pseudoType() == CSSSelector::PseudoCue) {
993         SelectorCheckingContext subContext(context);
994         subContext.isSubSelector = true;
995         subContext.behaviorAtBoundary = StaysWithinTreeScope;
996
997         const CSSSelector* contextSelector = context.selector;
998         ASSERT(contextSelector);
999         for (subContext.selector = contextSelector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) {
1000             if (match(subContext, siblingTraversalStrategy) == SelectorMatches)
1001                 return true;
1002         }
1003         return false;
1004     }
1005     // ### add the rest of the checks...
1006     return true;
1007 }
1008
1009 bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& context, Document* document, const CSSSelector& selector) const
1010 {
1011     RenderScrollbar* scrollbar = context.scrollbar;
1012     ScrollbarPart part = context.scrollbarPart;
1013
1014     // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventually :window-inactive should become a real
1015     // pseudo class and just apply to everything.
1016     if (selector.pseudoType() == CSSSelector::PseudoWindowInactive)
1017         return !document->page()->focusController().isActive();
1018
1019     if (!scrollbar)
1020         return false;
1021
1022     ASSERT(selector.match() == CSSSelector::PseudoClass);
1023     switch (selector.pseudoType()) {
1024     case CSSSelector::PseudoEnabled:
1025         return scrollbar->enabled();
1026     case CSSSelector::PseudoDisabled:
1027         return !scrollbar->enabled();
1028     case CSSSelector::PseudoHover:
1029         {
1030             ScrollbarPart hoveredPart = scrollbar->hoveredPart();
1031             if (part == ScrollbarBGPart)
1032                 return hoveredPart != NoPart;
1033             if (part == TrackBGPart)
1034                 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
1035             return part == hoveredPart;
1036         }
1037     case CSSSelector::PseudoActive:
1038         {
1039             ScrollbarPart pressedPart = scrollbar->pressedPart();
1040             if (part == ScrollbarBGPart)
1041                 return pressedPart != NoPart;
1042             if (part == TrackBGPart)
1043                 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
1044             return part == pressedPart;
1045         }
1046     case CSSSelector::PseudoHorizontal:
1047         return scrollbar->orientation() == HorizontalScrollbar;
1048     case CSSSelector::PseudoVertical:
1049         return scrollbar->orientation() == VerticalScrollbar;
1050     case CSSSelector::PseudoDecrement:
1051         return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
1052     case CSSSelector::PseudoIncrement:
1053         return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
1054     case CSSSelector::PseudoStart:
1055         return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
1056     case CSSSelector::PseudoEnd:
1057         return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
1058     case CSSSelector::PseudoDoubleButton:
1059         {
1060             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
1061             if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
1062                 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
1063             if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
1064                 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
1065             return false;
1066         }
1067     case CSSSelector::PseudoSingleButton:
1068         {
1069             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
1070             if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
1071                 return buttonsPlacement == ScrollbarButtonsSingle;
1072             return false;
1073         }
1074     case CSSSelector::PseudoNoButton:
1075         {
1076             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
1077             if (part == BackTrackPart)
1078                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
1079             if (part == ForwardTrackPart)
1080                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
1081             return false;
1082         }
1083     case CSSSelector::PseudoCornerPresent:
1084         return scrollbar->scrollableArea()->isScrollCornerVisible();
1085     default:
1086         return false;
1087     }
1088 }
1089
1090 unsigned SelectorChecker::determineLinkMatchType(const CSSSelector& selector)
1091 {
1092     unsigned linkMatchType = MatchAll;
1093
1094     // Statically determine if this selector will match a link in visited, unvisited or any state, or never.
1095     // :visited never matches other elements than the innermost link element.
1096     for (const CSSSelector* current = &selector; current; current = current->tagHistory()) {
1097         switch (current->pseudoType()) {
1098         case CSSSelector::PseudoNot:
1099             {
1100                 // :not(:visited) is equivalent to :link. Parser enforces that :not can't nest.
1101                 ASSERT(current->selectorList());
1102                 for (const CSSSelector* subSelector = current->selectorList()->first(); subSelector; subSelector = subSelector->tagHistory()) {
1103                     CSSSelector::PseudoType subType = subSelector->pseudoType();
1104                     if (subType == CSSSelector::PseudoVisited)
1105                         linkMatchType &= ~SelectorChecker::MatchVisited;
1106                     else if (subType == CSSSelector::PseudoLink)
1107                         linkMatchType &= ~SelectorChecker::MatchLink;
1108                 }
1109             }
1110             break;
1111         case CSSSelector::PseudoLink:
1112             linkMatchType &= ~SelectorChecker::MatchVisited;
1113             break;
1114         case CSSSelector::PseudoVisited:
1115             linkMatchType &= ~SelectorChecker::MatchLink;
1116             break;
1117         default:
1118             // We don't support :link and :visited inside :-webkit-any.
1119             break;
1120         }
1121         CSSSelector::Relation relation = current->relation();
1122         if (relation == CSSSelector::SubSelector)
1123             continue;
1124         if (relation != CSSSelector::Descendant && relation != CSSSelector::Child)
1125             return linkMatchType;
1126         if (linkMatchType != MatchAll)
1127             return linkMatchType;
1128     }
1129     return linkMatchType;
1130 }
1131
1132 bool SelectorChecker::isFrameFocused(const Element& element)
1133 {
1134     return element.document().frame() && element.document().frame()->selection().isFocusedAndActive();
1135 }
1136
1137 bool SelectorChecker::matchesFocusPseudoClass(const Element& element)
1138 {
1139     if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(&element), CSSSelector::PseudoFocus))
1140         return true;
1141     return element.focused() && isFrameFocused(element);
1142 }
1143
1144 template
1145 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, const DOMSiblingTraversalStrategy&, MatchResult*) const;
1146
1147 template
1148 SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext&, const ShadowDOMSiblingTraversalStrategy&, MatchResult*) const;
1149
1150 }