Update comment added in r92139 per Darin's suggestion.
[WebKit.git] / Source / WebCore / css / CSSStyleSelector.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 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 "CSSStyleSelector.h"
30
31 #include "Attribute.h"
32 #include "ContentData.h"
33 #include "CounterContent.h"
34 #include "CursorList.h"
35 #include "CSSBorderImageValue.h"
36 #include "CSSCursorImageValue.h"
37 #include "CSSFontFaceRule.h"
38 #include "CSSFontSelector.h"
39 #include "CSSImportRule.h"
40 #include "CSSLineBoxContainValue.h"
41 #include "CSSMediaRule.h"
42 #include "CSSPageRule.h"
43 #include "CSSParser.h"
44 #include "CSSPrimitiveValueMappings.h"
45 #include "CSSPropertyNames.h"
46 #include "CSSReflectValue.h"
47 #include "CSSRuleList.h"
48 #include "CSSSelector.h"
49 #include "CSSSelectorList.h"
50 #include "CSSStyleApplyProperty.h"
51 #include "CSSStyleRule.h"
52 #include "CSSStyleSheet.h"
53 #include "CSSTimingFunctionValue.h"
54 #include "CSSValueList.h"
55 #include "CachedImage.h"
56 #include "Counter.h"
57 #include "FocusController.h"
58 #include "FontFamilyValue.h"
59 #include "FontValue.h"
60 #include "Frame.h"
61 #include "FrameSelection.h"
62 #include "FrameView.h"
63 #include "HTMLDocument.h"
64 #include "HTMLElement.h"
65 #include "HTMLFrameElementBase.h"
66 #include "HTMLInputElement.h"
67 #include "HTMLNames.h"
68 #include "HTMLProgressElement.h"
69 #include "HTMLTextAreaElement.h"
70 #include "KeyframeList.h"
71 #include "LinkHash.h"
72 #include "Matrix3DTransformOperation.h"
73 #include "MatrixTransformOperation.h"
74 #include "MediaList.h"
75 #include "MediaQueryEvaluator.h"
76 #include "NodeRenderStyle.h"
77 #include "Page.h"
78 #include "PageGroup.h"
79 #include "Pair.h"
80 #include "PerspectiveTransformOperation.h"
81 #include "QuotesData.h"
82 #include "Rect.h"
83 #include "RenderScrollbar.h"
84 #include "RenderScrollbarTheme.h"
85 #include "RenderStyleConstants.h"
86 #include "RenderTheme.h"
87 #include "RotateTransformOperation.h"
88 #include "ScaleTransformOperation.h"
89 #include "SecurityOrigin.h"
90 #include "Settings.h"
91 #include "ShadowData.h"
92 #include "ShadowValue.h"
93 #include "SkewTransformOperation.h"
94 #include "StyleCachedImage.h"
95 #include "StylePendingImage.h"
96 #include "StyleGeneratedImage.h"
97 #include "StyleSheetList.h"
98 #include "Text.h"
99 #include "TransformationMatrix.h"
100 #include "TranslateTransformOperation.h"
101 #include "UserAgentStyleSheets.h"
102 #include "WebKitCSSKeyframeRule.h"
103 #include "WebKitCSSKeyframesRule.h"
104 #include "WebKitCSSTransformValue.h"
105 #include "XMLNames.h"
106 #include <wtf/StdLibExtras.h>
107 #include <wtf/Vector.h>
108
109 #if USE(PLATFORM_STRATEGIES)
110 #include "PlatformStrategies.h"
111 #include "VisitedLinkStrategy.h"
112 #endif
113
114 #if ENABLE(DASHBOARD_SUPPORT)
115 #include "DashboardRegion.h"
116 #endif
117
118 #if ENABLE(SVG)
119 #include "XLinkNames.h"
120 #include "SVGNames.h"
121 #endif
122
123 #if PLATFORM(QT)
124 #include <qwebhistoryinterface.h>
125 #endif
126
127 using namespace std;
128
129 namespace WebCore {
130
131 using namespace HTMLNames;
132
133 #define HANDLE_INHERIT(prop, Prop) \
134 if (isInherit) { \
135     m_style->set##Prop(m_parentStyle->prop()); \
136     return; \
137 }
138
139 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
140 HANDLE_INHERIT(prop, Prop) \
141 if (isInitial) { \
142     m_style->set##Prop(RenderStyle::initial##Prop()); \
143     return; \
144 }
145
146 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
147 HANDLE_INHERIT(prop, Prop) \
148 if (isInitial) { \
149     m_style->set##Prop(RenderStyle::initial##Value());\
150     return;\
151 }
152
153 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
154 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
155 if (primitiveValue) \
156     m_style->set##Prop(*primitiveValue);
157
158 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
159 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
160 if (primitiveValue) \
161     m_style->set##Prop(*primitiveValue);
162
163 #define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
164 if (isInherit) { \
165     AnimationList* list = m_style->accessAnimations(); \
166     const AnimationList* parentList = m_parentStyle->animations(); \
167     size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
168     for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
169         if (list->size() <= i) \
170             list->append(Animation::create()); \
171         list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
172     } \
173     \
174     /* Reset any remaining animations to not have the property set. */ \
175     for ( ; i < list->size(); ++i) \
176         list->animation(i)->clear##Prop(); \
177 } else if (isInitial) { \
178     AnimationList* list = m_style->accessAnimations(); \
179     if (list->isEmpty()) \
180         list->append(Animation::create()); \
181     list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
182     for (size_t i = 1; i < list->size(); ++i) \
183         list->animation(0)->clear##Prop(); \
184 }
185
186 #define HANDLE_ANIMATION_VALUE(prop, Prop, value) { \
187 HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
188 if (isInherit || isInitial) \
189     return; \
190 AnimationList* list = m_style->accessAnimations(); \
191 size_t childIndex = 0; \
192 if (value->isValueList()) { \
193     /* Walk each value and put it into an animation, creating new animations as needed. */ \
194     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { \
195         if (childIndex <= list->size()) \
196             list->append(Animation::create()); \
197         mapAnimation##Prop(list->animation(childIndex), i.value()); \
198         ++childIndex; \
199     } \
200 } else { \
201     if (list->isEmpty()) \
202         list->append(Animation::create()); \
203     mapAnimation##Prop(list->animation(childIndex), value); \
204     childIndex = 1; \
205 } \
206 for ( ; childIndex < list->size(); ++childIndex) { \
207     /* Reset all remaining animations to not have the property set. */ \
208     list->animation(childIndex)->clear##Prop(); \
209 } \
210 }
211
212 #define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
213 if (isInherit) { \
214     AnimationList* list = m_style->accessTransitions(); \
215     const AnimationList* parentList = m_parentStyle->transitions(); \
216     size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
217     for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
218         if (list->size() <= i) \
219             list->append(Animation::create()); \
220         list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
221     } \
222     \
223     /* Reset any remaining transitions to not have the property set. */ \
224     for ( ; i < list->size(); ++i) \
225         list->animation(i)->clear##Prop(); \
226 } else if (isInitial) { \
227     AnimationList* list = m_style->accessTransitions(); \
228     if (list->isEmpty()) \
229         list->append(Animation::create()); \
230     list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
231     for (size_t i = 1; i < list->size(); ++i) \
232         list->animation(0)->clear##Prop(); \
233 }
234
235 #define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \
236 HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
237 if (isInherit || isInitial) \
238     return; \
239 AnimationList* list = m_style->accessTransitions(); \
240 size_t childIndex = 0; \
241 if (value->isValueList()) { \
242     /* Walk each value and put it into a transition, creating new animations as needed. */ \
243     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { \
244         if (childIndex <= list->size()) \
245             list->append(Animation::create()); \
246         mapAnimation##Prop(list->animation(childIndex), i.value()); \
247         ++childIndex; \
248     } \
249 } else { \
250     if (list->isEmpty()) \
251         list->append(Animation::create()); \
252     mapAnimation##Prop(list->animation(childIndex), value); \
253     childIndex = 1; \
254 } \
255 for ( ; childIndex < list->size(); ++childIndex) { \
256     /* Reset all remaining transitions to not have the property set. */ \
257     list->animation(childIndex)->clear##Prop(); \
258 } \
259 }
260
261 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
262 if (id == propID) { \
263     m_style->set##Prop(m_parentStyle->prop()); \
264     return; \
265 }
266     
267 #define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
268 if (id == propID) { \
269     if (m_parentStyle->prop().isValid()) \
270         m_style->set##Prop(m_parentStyle->prop()); \
271     else \
272         m_style->set##Prop(m_parentStyle->propAlt()); \
273     return; \
274 }
275
276 #define HANDLE_INITIAL_COND(propID, Prop) \
277 if (id == propID) { \
278     m_style->set##Prop(RenderStyle::initial##Prop()); \
279     return; \
280 }
281
282 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
283 if (id == propID) { \
284     m_style->set##Prop(RenderStyle::initial##Value()); \
285     return; \
286 }
287
288 class RuleData {
289 public:
290     RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
291
292     unsigned position() const { return m_position; }
293     CSSStyleRule* rule() const { return m_rule; }
294     CSSSelector* selector() const { return m_selector; }
295     
296     bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
297     bool hasMultipartSelector() const { return m_hasMultipartSelector; }
298     bool hasTopSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasTopSelectorMatchingHTMLBasedOnRuleHash; }
299     unsigned specificity() const { return m_specificity; }
300     
301     // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
302     static const unsigned maximumIdentifierCount = 4;
303     const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
304
305 private:
306     void collectDescendantSelectorIdentifierHashes();
307     void collectIdentifierHashes(const CSSSelector*, unsigned& identifierCount);
308     
309     CSSStyleRule* m_rule;
310     CSSSelector* m_selector;
311     unsigned m_specificity;
312     unsigned m_position : 29;
313     bool m_hasFastCheckableSelector : 1;
314     bool m_hasMultipartSelector : 1;
315     bool m_hasTopSelectorMatchingHTMLBasedOnRuleHash : 1;
316     // Use plain array instead of a Vector to minimize memory overhead.
317     unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
318 };
319
320 class RuleSet {
321     WTF_MAKE_NONCOPYABLE(RuleSet);
322 public:
323     RuleSet();
324     ~RuleSet();
325     
326     typedef HashMap<AtomicStringImpl*, Vector<RuleData>*> AtomRuleMap;
327     
328     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
329
330     void addStyleRule(CSSStyleRule* item);
331     void addRule(CSSStyleRule* rule, CSSSelector* sel);
332     void addPageRule(CSSStyleRule* rule, CSSSelector* sel);
333     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
334                       CSSStyleRule* rule, CSSSelector* sel);
335     void shrinkToFit();
336     void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
337
338     void collectFeatures(CSSStyleSelector::Features&) const;
339     
340     const Vector<RuleData>* getIDRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
341     const Vector<RuleData>* getClassRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
342     const Vector<RuleData>* getTagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
343     const Vector<RuleData>* getPseudoRules(AtomicStringImpl* key) const { return m_pseudoRules.get(key); }
344     const Vector<RuleData>* getUniversalRules() const { return &m_universalRules; }
345     const Vector<RuleData>* getPageRules() const { return &m_pageRules; }
346     
347 public:
348     AtomRuleMap m_idRules;
349     AtomRuleMap m_classRules;
350     AtomRuleMap m_tagRules;
351     AtomRuleMap m_pseudoRules;
352     Vector<RuleData> m_universalRules;
353     Vector<RuleData> m_pageRules;
354     unsigned m_ruleCount;
355     bool m_autoShrinkToFitEnabled;
356 };
357
358 static RuleSet* defaultStyle;
359 static RuleSet* defaultQuirksStyle;
360 static RuleSet* defaultPrintStyle;
361 static RuleSet* defaultViewSourceStyle;
362 static CSSStyleSheet* simpleDefaultStyleSheet;
363     
364 static RuleSet* siblingRulesInDefaultStyle;
365
366 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
367
368 static void loadFullDefaultStyle();
369 static void loadSimpleDefaultStyle();
370 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
371 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}";
372
373 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
374 {
375     return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
376 }
377
378 static inline void collectSiblingRulesInDefaultStyle()
379 {
380     CSSStyleSelector::Features features;
381     defaultStyle->collectFeatures(features);
382     ASSERT(features.idsInRules.isEmpty());
383     delete siblingRulesInDefaultStyle;
384     siblingRulesInDefaultStyle = features.siblingRules.leakPtr();
385 }
386
387 static inline void assertNoSiblingRulesInDefaultStyle()
388 {
389 #ifndef NDEBUG
390     if (siblingRulesInDefaultStyle)
391         return;
392     collectSiblingRulesInDefaultStyle();
393     ASSERT(!siblingRulesInDefaultStyle);
394 #endif
395 }
396     
397 static const MediaQueryEvaluator& screenEval()
398 {
399     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
400     return staticScreenEval;
401 }
402
403 static const MediaQueryEvaluator& printEval()
404 {
405     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
406     return staticPrintEval;
407 }
408
409 static CSSMutableStyleDeclaration* leftToRightDeclaration()
410 {
411     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create()));
412     if (!leftToRightDecl->length()) {
413         leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false, false);
414         leftToRightDecl->setStrictParsing(false);
415     }
416     return leftToRightDecl.get();
417 }
418
419 static CSSMutableStyleDeclaration* rightToLeftDeclaration()
420 {
421     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create()));
422     if (!rightToLeftDecl->length()) {
423         rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false, false);
424         rightToLeftDecl->setStrictParsing(false);
425     }
426     return rightToLeftDecl.get();
427 }
428
429 CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
430                                    CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets,
431                                    bool strictParsing, bool matchAuthorAndUserStyles)
432     : m_backgroundData(BackgroundFillLayer)
433     , m_checker(document, strictParsing)
434     , m_element(0)
435     , m_styledElement(0)
436     , m_elementLinkState(NotInsideLink)
437     , m_fontSelector(CSSFontSelector::create(document))
438     , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty())
439 {
440     m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;
441     
442     Element* root = document->documentElement();
443
444     if (!defaultStyle) {
445         if (!root || elementCanUseSimpleDefaultStyle(root))
446             loadSimpleDefaultStyle();
447         else {
448             loadFullDefaultStyle();
449         }
450     }
451
452     // construct document root element default style. this is needed
453     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
454     // This is here instead of constructor, because when constructor is run,
455     // document doesn't have documentElement
456     // NOTE: this assumes that element that gets passed to styleForElement -call
457     // is always from the document that owns the style selector
458     FrameView* view = document->view();
459     if (view)
460         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
461     else
462         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
463
464     if (root)
465         m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
466
467     if (m_rootDefaultStyle && view)
468         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
469
470     m_authorStyle = adoptPtr(new RuleSet);
471     // Adding rules from multiple sheets, shrink at the end.
472     m_authorStyle->disableAutoShrinkToFit();
473
474     // FIXME: This sucks! The user sheet is reparsed every time!
475     OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet);
476     if (pageUserSheet)
477         tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
478     if (pageGroupUserSheets) {
479         unsigned length = pageGroupUserSheets->size();
480         for (unsigned i = 0; i < length; i++) {
481             if (pageGroupUserSheets->at(i)->isUserStyleSheet())
482                 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
483             else
484                 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
485         }
486     }
487     if (documentUserSheets) {
488         unsigned length = documentUserSheets->size();
489         for (unsigned i = 0; i < length; i++) {
490             if (documentUserSheets->at(i)->isUserStyleSheet())
491                 tempUserStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
492             else
493                 m_authorStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
494         }
495     }
496
497     if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
498         m_userStyle = tempUserStyle.release();
499
500     // Add rules from elements like SVG's <font-face>
501     if (mappedElementSheet)
502         m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
503
504     // add stylesheets from document
505     unsigned length = styleSheets->length();
506     for (unsigned i = 0; i < length; i++) {
507         StyleSheet* sheet = styleSheets->item(i);
508         if (sheet->isCSSStyleSheet() && !sheet->disabled())
509             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
510     }    
511     // Collect all ids and rules using sibling selectors (:first-child and similar)
512     // in the current set of stylesheets. Style sharing code uses this information to reject
513     // sharing candidates.
514     // Usually there are no sibling rules in the default style but the MathML sheet has some.
515     if (siblingRulesInDefaultStyle)
516         siblingRulesInDefaultStyle->collectFeatures(m_features);
517     m_authorStyle->collectFeatures(m_features);
518     if (m_userStyle)
519         m_userStyle->collectFeatures(m_features);
520
521     m_authorStyle->shrinkToFit();
522     if (m_features.siblingRules)
523         m_features.siblingRules->shrinkToFit();
524
525     if (document->renderer() && document->renderer()->style())
526         document->renderer()->style()->font().update(fontSelector());
527 }
528
529 // This is a simplified style setting function for keyframe styles
530 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
531 {
532     AtomicString s(rule->name());
533     m_keyframesRuleMap.add(s.impl(), rule);
534 }
535
536 CSSStyleSelector::~CSSStyleSelector()
537 {
538     m_fontSelector->clearDocument();
539     deleteAllValues(m_viewportDependentMediaQueryResults);
540 }
541     
542 CSSStyleSelector::Features::Features() 
543     : usesFirstLineRules(false)
544     , usesBeforeAfterRules(false)
545     , usesLinkRules(false)
546 {
547 }
548
549 CSSStyleSelector::Features::~Features()
550 {
551 }
552
553 static CSSStyleSheet* parseUASheet(const String& str)
554 {
555     CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose
556     sheet->parseString(str);
557     return sheet;
558 }
559
560 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
561 {
562     return parseUASheet(String(characters, size));
563 }
564
565 static void loadFullDefaultStyle()
566 {
567     if (simpleDefaultStyleSheet) {
568         ASSERT(defaultStyle);
569         ASSERT(defaultPrintStyle == defaultStyle);
570         delete defaultStyle;
571         simpleDefaultStyleSheet->deref();
572         defaultStyle = new RuleSet;
573         defaultPrintStyle = new RuleSet;
574         simpleDefaultStyleSheet = 0;
575     } else {
576         ASSERT(!defaultStyle);
577         defaultStyle = new RuleSet;
578         defaultPrintStyle = new RuleSet;
579         defaultQuirksStyle = new RuleSet;
580     }
581
582     // Strict-mode rules.
583     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
584     CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
585     defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
586     defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
587
588     // Quirks-mode rules.
589     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
590     CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
591     defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
592 }
593
594 static void loadSimpleDefaultStyle()
595 {
596     ASSERT(!defaultStyle);
597     ASSERT(!simpleDefaultStyleSheet);
598     
599     defaultStyle = new RuleSet;
600     // There are no media-specific rules in the simple default style.
601     defaultPrintStyle = defaultStyle;
602     defaultQuirksStyle = new RuleSet;
603
604     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
605     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
606     
607     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
608 }
609     
610 static void loadViewSourceStyle()
611 {
612     ASSERT(!defaultViewSourceStyle);
613     defaultViewSourceStyle = new RuleSet;
614     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
615 }
616     
617 static inline void collectElementIdentifierHashes(const Element* element, Vector<unsigned, 4>& identifierHashes)
618 {
619     identifierHashes.append(element->localName().impl()->existingHash());
620     if (element->hasID())
621         identifierHashes.append(element->idForStyleResolution().impl()->existingHash());
622     const StyledElement* styledElement = element->isStyledElement() ? static_cast<const StyledElement*>(element) : 0;
623     if (styledElement && styledElement->hasClass()) {
624         const SpaceSplitString& classNames = styledElement->classNames();
625         size_t count = classNames.size();
626         for (size_t i = 0; i < count; ++i)
627             identifierHashes.append(classNames[i].impl()->existingHash());
628     }
629 }
630
631 void CSSStyleSelector::pushParentStackFrame(Element* parent)
632 {
633     ASSERT(m_ancestorIdentifierFilter);
634     ASSERT(m_parentStack.isEmpty() || m_parentStack.last().element == parent->parentOrHostElement());
635     ASSERT(!m_parentStack.isEmpty() || !parent->parentOrHostElement());
636     m_parentStack.append(ParentStackFrame(parent));
637     ParentStackFrame& parentFrame = m_parentStack.last();
638     // Mix tags, class names and ids into some sort of weird bouillabaisse.
639     // The filter is used for fast rejection of child and descendant selectors.
640     collectElementIdentifierHashes(parent, parentFrame.identifierHashes);
641     size_t count = parentFrame.identifierHashes.size();
642     for (size_t i = 0; i < count; ++i)
643         m_ancestorIdentifierFilter->add(parentFrame.identifierHashes[i]);
644 }
645
646 void CSSStyleSelector::popParentStackFrame()
647 {
648     ASSERT(!m_parentStack.isEmpty());
649     ASSERT(m_ancestorIdentifierFilter);
650     const ParentStackFrame& parentFrame = m_parentStack.last();
651     size_t count = parentFrame.identifierHashes.size();
652     for (size_t i = 0; i < count; ++i)
653         m_ancestorIdentifierFilter->remove(parentFrame.identifierHashes[i]);
654     m_parentStack.removeLast();
655     if (m_parentStack.isEmpty()) {
656         ASSERT(m_ancestorIdentifierFilter->likelyEmpty());
657         m_ancestorIdentifierFilter.clear();
658     }
659 }
660
661 void CSSStyleSelector::pushParent(Element* parent)
662 {
663     if (m_parentStack.isEmpty()) {
664         ASSERT(!m_ancestorIdentifierFilter);
665         m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>);
666         // If the element is not the root itself, build the stack starting from the root.
667         if (parent->parentOrHostNode()) {
668             Vector<Element*, 30> ancestors;
669             for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentOrHostElement())
670                 ancestors.append(ancestor);
671             int count = ancestors.size();
672             for (int n = count - 1; n >= 0; --n)
673                 pushParentStackFrame(ancestors[n]);
674             return;
675         }
676     } else if (!parent->parentOrHostElement()) {
677         // We are not always invoked consistently. For example, script execution can cause us to enter
678         // style recalc in the middle of tree building. Reset the stack if we see a new root element.
679         ASSERT(m_ancestorIdentifierFilter);
680         m_ancestorIdentifierFilter->clear();
681         m_parentStack.resize(0);
682     } else {
683         ASSERT(m_ancestorIdentifierFilter);
684         // We may get invoked for some random elements in some wacky cases during style resolve.
685         // Pause maintaining the stack in this case.
686         if (m_parentStack.last().element != parent->parentOrHostElement())
687             return;
688     }
689     pushParentStackFrame(parent);
690 }
691
692 void CSSStyleSelector::popParent(Element* parent)
693 {
694     if (m_parentStack.isEmpty() || m_parentStack.last().element != parent)
695         return;
696     popParentStackFrame();
697 }
698
699 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl)
700 {
701     m_matchedDecls.append(decl);
702 }
703
704 void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
705 {
706     m_matchedRules.clear();
707
708     if (!rules || !m_element)
709         return;
710     
711     // We need to collect the rules for id, class, tag, and everything else into a buffer and
712     // then sort the buffer.
713     if (m_element->hasID())
714         matchRulesForList(rules->getIDRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
715     if (m_element->hasClass()) {
716         ASSERT(m_styledElement);
717         const SpaceSplitString& classNames = m_styledElement->classNames();
718         size_t size = classNames.size();
719         for (size_t i = 0; i < size; ++i)
720             matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
721     }
722     const AtomicString& pseudoId = m_element->shadowPseudoId();
723     if (!pseudoId.isEmpty()) {
724         ASSERT(m_styledElement);
725         matchRulesForList(rules->getPseudoRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
726     }
727     matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
728     matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
729     
730     // If we didn't match any rules, we're done.
731     if (m_matchedRules.isEmpty())
732         return;
733     
734     // Sort the set of matched rules.
735     sortMatchedRules();
736     
737     // Now transfer the set of matched rules over to our list of decls.
738     if (!m_checker.m_collectRulesOnly) {
739         for (unsigned i = 0; i < m_matchedRules.size(); i++)
740             addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
741     } else {
742         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
743             if (!m_ruleList)
744                 m_ruleList = CSSRuleList::create();
745             m_ruleList->append(m_matchedRules[i]->rule());
746         }
747     }
748 }
749
750 inline bool CSSStyleSelector::fastRejectSelector(const RuleData& ruleData) const
751 {
752     ASSERT(m_ancestorIdentifierFilter);
753     const unsigned* descendantSelectorIdentifierHashes = ruleData.descendantSelectorIdentifierHashes();
754     for (unsigned n = 0; n < RuleData::maximumIdentifierCount && descendantSelectorIdentifierHashes[n]; ++n) {
755         if (!m_ancestorIdentifierFilter->mayContain(descendantSelectorIdentifierHashes[n]))
756             return true;
757     }
758     return false;
759 }
760
761 class MatchingUARulesScope {
762 public:
763     MatchingUARulesScope();
764     ~MatchingUARulesScope();
765
766     static bool isMatchingUARules();
767
768 private:
769     static bool m_matchingUARules;
770 };
771
772 MatchingUARulesScope::MatchingUARulesScope()
773 {
774     ASSERT(!m_matchingUARules);
775     m_matchingUARules = true;
776 }
777
778 MatchingUARulesScope::~MatchingUARulesScope()
779 {
780     m_matchingUARules = false;
781 }
782
783 inline bool MatchingUARulesScope::isMatchingUARules()
784 {
785     return m_matchingUARules;
786 }
787
788 bool MatchingUARulesScope::m_matchingUARules = false;
789
790 inline static bool matchesInTreeScope(TreeScope* treeScope, bool ruleReachesIntoShadowDOM)
791 {
792     return MatchingUARulesScope::isMatchingUARules() || treeScope->applyAuthorSheets() || ruleReachesIntoShadowDOM;
793 }
794
795 void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
796 {
797     if (!rules)
798         return;
799     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
800     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
801     bool canUseFastReject = !m_parentStack.isEmpty() && m_parentStack.last().element == m_parentNode;
802
803     unsigned size = rules->size();
804     for (unsigned i = 0; i < size; ++i) {
805         const RuleData& ruleData = rules->at(i);
806         if (canUseFastReject && fastRejectSelector(ruleData))
807             continue;
808         if (checkSelector(ruleData)) {
809             if (!matchesInTreeScope(m_element->treeScope(), m_checker.m_hasUnknownPseudoElements))
810                 continue;
811             // If the rule has no properties to apply, then ignore it in the non-debug mode.
812             CSSStyleRule* rule = ruleData.rule();
813             CSSMutableStyleDeclaration* decl = rule->declaration();
814             if (!decl || (!decl->length() && !includeEmptyRules))
815                 continue;
816             if (m_checker.m_sameOriginOnly && !m_checker.m_document->securityOrigin()->canRequest(rule->baseURL()))
817                 continue; 
818             // If we're matching normal rules, set a pseudo bit if 
819             // we really just matched a pseudo-element.
820             if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) {
821                 if (m_checker.m_collectRulesOnly)
822                     continue;
823                 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
824                     m_style->setHasPseudoStyle(m_dynamicPseudo);
825             } else {
826                 // Update our first/last rule indices in the matched rules array.
827                 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
828                 if (firstRuleIndex == -1)
829                     firstRuleIndex = lastRuleIndex;
830
831                 // Add this rule to our list of matched rules.
832                 addMatchedRule(&ruleData);
833             }
834         }
835     }
836 }
837
838 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
839 {
840     unsigned specificity1 = r1->specificity();
841     unsigned specificity2 = r2->specificity();
842     return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2; 
843 }
844
845 void CSSStyleSelector::sortMatchedRules()
846 {
847     std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
848 }
849
850 inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const
851 {
852     if (!element || !element->isLink())
853         return NotInsideLink;
854     return determineLinkStateSlowCase(element);
855 }
856     
857 inline void CSSStyleSelector::initElement(Element* e)
858 {
859     if (m_element != e) {
860         m_element = e;
861         m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
862         m_elementLinkState = m_checker.determineLinkState(m_element);
863         if (e && e == e->document()->documentElement()) {
864             e->document()->setDirectionSetOnDocumentElement(false);
865             e->document()->setWritingModeSetOnDocumentElement(false);
866         }
867     }
868 }
869
870 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
871 {
872     m_checker.m_pseudoStyle = pseudoID;
873
874     m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0;
875
876     if (parentStyle)
877         m_parentStyle = parentStyle;
878     else
879         m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
880
881     Node* docElement = e ? e->document()->documentElement() : 0;
882     RenderStyle* docStyle = m_checker.m_document->renderStyle();
883     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
884
885     m_style = 0;
886
887     m_matchedDecls.clear();
888
889     m_pendingImageProperties.clear();
890
891     m_ruleList = 0;
892
893     m_fontDirty = false;
894
895     m_forcePseudoClassMask = DoNotForcePseudoClassMask;
896 }
897
898 static inline const AtomicString* linkAttribute(Node* node)
899 {
900     if (!node->isLink())
901         return 0;
902
903     ASSERT(node->isElementNode());
904     Element* element = static_cast<Element*>(node);
905     if (element->isHTMLElement())
906         return &element->fastGetAttribute(hrefAttr);
907
908 #if ENABLE(SVG)
909     if (element->isSVGElement())
910         return &element->fastGetAttribute(XLinkNames::hrefAttr);
911 #endif
912
913     return 0;
914 }
915
916 CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing)
917     : m_document(document)
918     , m_strictParsing(strictParsing)
919     , m_collectRulesOnly(false)
920     , m_sameOriginOnly(false)
921     , m_pseudoStyle(NOPSEUDO)
922     , m_documentIsHTML(document->isHTMLDocument())
923     , m_hasUnknownPseudoElements(false)
924     , m_matchVisitedPseudoClass(false)
925 {
926 }
927
928 EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const
929 {
930     ASSERT(element->isLink());
931     
932     const AtomicString* attr = linkAttribute(element);
933     if (!attr || attr->isNull())
934         return NotInsideLink;
935
936 #if PLATFORM(QT)
937     Vector<UChar, 512> url;
938     visitedURL(m_document->baseURL(), *attr, url);
939     if (url.isEmpty())
940         return InsideUnvisitedLink;
941
942     // If the Qt4.4 interface for the history is used, we will have to fallback
943     // to the old global history.
944     QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface();
945     if (iface)
946         return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink;
947
948     LinkHash hash = visitedLinkHash(url.data(), url.size());
949     if (!hash)
950         return InsideUnvisitedLink;
951 #else
952     LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr);
953     if (!hash)
954         return InsideUnvisitedLink;
955 #endif
956
957     Frame* frame = m_document->frame();
958     if (!frame)
959         return InsideUnvisitedLink;
960
961     Page* page = frame->page();
962     if (!page)
963         return InsideUnvisitedLink;
964
965     m_linksCheckedForVisitedState.add(hash);
966
967 #if USE(PLATFORM_STRATEGIES)
968     return platformStrategies()->visitedLinkStrategy()->isLinkVisited(page, hash) ? InsideVisitedLink : InsideUnvisitedLink;
969 #else
970     return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink;
971 #endif
972 }
973
974 bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
975 {
976     PseudoId dynamicPseudo = NOPSEUDO;
977     return checkSelector(sel, element, dynamicPseudo, false, false) == SelectorMatches;
978 }
979
980 static const unsigned cStyleSearchThreshold = 10;
981 static const unsigned cStyleSearchLevelThreshold = 10;
982
983 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
984 {
985     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
986         return 0;
987     if (!parent || !parent->isStyledElement())
988         return 0;
989     StyledElement* p = static_cast<StyledElement*>(parent);
990     if (p->inlineStyleDecl())
991         return 0;
992     if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
993         return 0;
994
995     RenderStyle* parentStyle = p->renderStyle();
996     unsigned subcount = 0;
997     Node* thisCousin = p;
998     Node* currentNode = p->previousSibling();
999
1000     // Reserve the tries for this level. This effectively makes sure that the algorithm
1001     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
1002     visitedNodeCount += cStyleSearchThreshold;
1003     while (thisCousin) {
1004         while (currentNode) {
1005             ++subcount;
1006             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
1007                 // Adjust for unused reserved tries.
1008                 visitedNodeCount -= cStyleSearchThreshold - subcount;
1009                 return currentNode->lastChild();
1010             }
1011             if (subcount >= cStyleSearchThreshold)
1012                 return 0;
1013             currentNode = currentNode->previousSibling();
1014         }
1015         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
1016         thisCousin = currentNode;
1017     }
1018
1019     return 0;
1020 }
1021
1022 bool CSSStyleSelector::matchesSiblingRules()
1023 {
1024     int firstSiblingRule = -1, lastSiblingRule = -1;
1025     matchRules(m_features.siblingRules.get(), firstSiblingRule, lastSiblingRule, false);
1026     if (m_matchedDecls.isEmpty())
1027         return false;
1028     m_matchedDecls.clear();
1029     return true;
1030 }
1031
1032 bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const
1033 {
1034 #if ENABLE(PROGRESS_TAG)
1035     if (element->hasTagName(progressTag)) {
1036         if (!m_element->hasTagName(progressTag))
1037             return false;
1038         
1039         HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
1040         HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
1041         if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
1042             return false;
1043         
1044         return true;
1045     }
1046 #endif
1047     
1048     HTMLInputElement* thisInputElement = element->toInputElement();
1049     HTMLInputElement* otherInputElement = m_element->toInputElement();
1050     
1051     if (!thisInputElement || !otherInputElement)
1052         return false;
1053     
1054     if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
1055         return false;
1056     if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
1057         return false;
1058     if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
1059         return false;
1060     
1061     if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
1062         return false;
1063     
1064     if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1065         return false;
1066     
1067     if (!m_element->document()->containsValidityStyleRules())
1068         return false;
1069     
1070     bool willValidate = element->willValidate();
1071     
1072     if (willValidate != m_element->willValidate())
1073         return false;
1074     
1075     if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
1076         return false;
1077     
1078     if (element->isInRange() != m_element->isInRange())
1079         return false;
1080     
1081     if (element->isOutOfRange() != m_element->isOutOfRange())
1082         return false;
1083     
1084     return true;
1085 }
1086
1087 bool CSSStyleSelector::canShareStyleWithElement(Node* node) const
1088 {
1089     if (!node->isStyledElement())
1090         return false;
1091
1092     StyledElement* element = static_cast<StyledElement*>(node);
1093     RenderStyle* style = element->renderStyle();
1094
1095     if (!style)
1096         return false;
1097     if (style->unique())
1098         return false;
1099     if (element->tagQName() != m_element->tagQName())
1100         return false;
1101     if (element->hasClass() != m_element->hasClass())
1102         return false;
1103     if (element->inlineStyleDecl())
1104         return false;
1105     if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes())
1106         return false;
1107     if (element->isLink() != m_element->isLink())
1108         return false;
1109     if (style->affectedByAttributeSelectors())
1110         return false;
1111     if (element->hovered() != m_element->hovered())
1112         return false;
1113     if (element->active() != m_element->active())
1114         return false;
1115     if (element->focused() != m_element->focused())
1116         return false;
1117     if (element->shadowPseudoId() != m_element->shadowPseudoId())
1118         return false;
1119     if (element == element->document()->cssTarget())
1120         return false;
1121     if (m_element == m_element->document()->cssTarget())
1122         return false;
1123     if (element->fastGetAttribute(typeAttr) != m_element->fastGetAttribute(typeAttr))
1124         return false;
1125     if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
1126         return false;
1127     if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
1128         return false;
1129     if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
1130         return false;
1131     if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
1132         return false;
1133
1134     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
1135         return false;
1136
1137     bool isControl = element->isFormControlElement();
1138
1139     if (isControl != m_element->isFormControlElement())
1140         return false;
1141
1142     if (isControl && !canShareStyleWithControl(element))
1143         return false;
1144
1145     if (style->transitions() || style->animations())
1146         return false;
1147
1148 #if USE(ACCELERATED_COMPOSITING)
1149     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1150     // See comments in RenderObject::setStyle().
1151     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag))
1152         return false;
1153 #endif
1154
1155     if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto"))
1156         return false;
1157
1158     if (element->hasClass() && m_element->fastGetAttribute(classAttr) != element->fastGetAttribute(classAttr))
1159         return false;
1160
1161     if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()))
1162         return false;
1163
1164     if (element->isLink() && m_elementLinkState != style->insideLink())
1165         return false;
1166
1167     return true;
1168 }
1169     
1170 inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
1171 {
1172     for (; node; node = node->previousSibling()) {
1173         if (!node->isElementNode())
1174             continue;
1175         if (canShareStyleWithElement(node))
1176             break;
1177         if (count++ == cStyleSearchThreshold)
1178             return 0;
1179     }
1180     return node;
1181 }
1182
1183 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
1184 {
1185     return parentStyle->childrenAffectedByPositionalRules() 
1186         || parentStyle->childrenAffectedByFirstChildRules()
1187         || parentStyle->childrenAffectedByLastChildRules() 
1188         || parentStyle->childrenAffectedByDirectAdjacentRules();
1189 }
1190
1191 ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
1192 {
1193     if (!m_styledElement || !m_parentStyle)
1194         return 0;
1195     // If the element has inline style it is probably unique.
1196     if (m_styledElement->inlineStyleDecl())
1197         return 0;
1198     // Ids stop style sharing if they show up in the stylesheets.
1199     if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
1200         return 0;
1201     if (parentStylePreventsSharing(m_parentStyle))
1202         return 0;
1203
1204     // Check previous siblings and their cousins.
1205     unsigned count = 0;
1206     unsigned visitedNodeCount = 0;
1207     Node* shareNode = 0;
1208     Node* cousinList = m_styledElement->previousSibling();
1209     while (cousinList) {
1210         shareNode = findSiblingForStyleSharing(cousinList, count);
1211         if (shareNode)
1212             break;
1213         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1214     }
1215
1216     // If we have exhausted all our budget or our cousins.
1217     if (!shareNode)
1218         return 0;
1219
1220     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1221     if (matchesSiblingRules())
1222         return 0;
1223     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1224     if (parentStylePreventsSharing(m_parentStyle))
1225         return 0;
1226     return shareNode->renderStyle();
1227 }
1228
1229 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
1230 {
1231     MatchingUARulesScope scope;
1232
1233     // First we match rules from the user agent sheet.
1234     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1235         ? defaultPrintStyle : defaultStyle;
1236     matchRules(userAgentStyleSheet, firstUARule, lastUARule, false);
1237
1238     // In quirks mode, we match rules from the quirks user agent sheet.
1239     if (!m_checker.m_strictParsing)
1240         matchRules(defaultQuirksStyle, firstUARule, lastUARule, false);
1241         
1242     // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
1243     if (m_checker.m_document->isViewSource()) {
1244         if (!defaultViewSourceStyle)
1245             loadViewSourceStyle();
1246         matchRules(defaultViewSourceStyle, firstUARule, lastUARule, false);
1247     }
1248 }
1249
1250 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document)
1251 {
1252     Frame* frame = document->frame();
1253
1254     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1255     documentStyle->setDisplay(BLOCK);
1256     documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1257     documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
1258     documentStyle->setPageScaleTransform(frame ? frame->pageScaleFactor() : 1);
1259     documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1260
1261     Element* docElement = document->documentElement();
1262     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1263     if (docElementRenderer) {
1264         // Use the direction and writing-mode of the body to set the
1265         // viewport's direction and writing-mode unless the property is set on the document element.
1266         // If there is no body, then use the document element.
1267         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1268         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1269             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1270         else
1271             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1272         if (bodyRenderer && !document->directionSetOnDocumentElement())
1273             documentStyle->setDirection(bodyRenderer->style()->direction());
1274         else
1275             documentStyle->setDirection(docElementRenderer->style()->direction());
1276     }
1277
1278     FontDescription fontDescription;
1279     fontDescription.setUsePrinterFont(document->printing());
1280     if (Settings* settings = document->settings()) {
1281         fontDescription.setRenderingMode(settings->fontRenderingMode());
1282         if (document->printing() && !settings->shouldPrintBackgrounds())
1283             documentStyle->setForceBackgroundsToWhite(true);
1284         const AtomicString& stdfont = settings->standardFontFamily();
1285         if (!stdfont.isEmpty()) {
1286             fontDescription.firstFamily().setFamily(stdfont);
1287             fontDescription.firstFamily().appendFamily(0);
1288         }
1289         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1290         int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1291         fontDescription.setSpecifiedSize(size);
1292         bool useSVGZoomRules = document->isSVGDocument();
1293         fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1294     }
1295
1296     documentStyle->setFontDescription(fontDescription);
1297     documentStyle->font().update(0);
1298         
1299     return documentStyle.release();
1300 }
1301
1302 static inline bool isAtShadowBoundary(Element* element)
1303 {
1304     if (!element)
1305         return false;
1306
1307     ContainerNode* parentNode = element->parentNode();
1308     return parentNode && parentNode->isShadowRoot();
1309 }
1310
1311 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
1312 // relative units are interpreted according to document root element style, styled only with UA stylesheet
1313
1314 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedPseudoClass)
1315 {
1316     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1317     // will vanish if a style recalc happens during loading.
1318     if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
1319         if (!s_styleNotYetAvailable) {
1320             s_styleNotYetAvailable = RenderStyle::create().releaseRef();
1321             s_styleNotYetAvailable->ref();
1322             s_styleNotYetAvailable->setDisplay(NONE);
1323             s_styleNotYetAvailable->font().update(m_fontSelector);
1324         }
1325         s_styleNotYetAvailable->ref();
1326         e->document()->setHasNodesWithPlaceholderStyle();
1327         return s_styleNotYetAvailable;
1328     }
1329
1330     initElement(e);
1331     initForStyleResolve(e, defaultParent);
1332     if (allowSharing) {
1333         RenderStyle* sharedStyle = locateSharedStyle();
1334         if (sharedStyle)
1335             return sharedStyle;
1336     }
1337
1338     // Compute our style allowing :visited to match first.
1339     RefPtr<RenderStyle> visitedStyle;
1340     if (!matchVisitedPseudoClass && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) {
1341         // Fetch our parent style.
1342         RenderStyle* parentStyle = m_parentStyle;
1343         if (!e->isLink()) {
1344             // Use the parent's visited style if one exists.
1345             RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK);
1346             if (parentVisitedStyle)
1347                 parentStyle = parentVisitedStyle;
1348         }
1349         visitedStyle = styleForElement(e, parentStyle, false, false, true);
1350         initForStyleResolve(e, defaultParent);
1351     }
1352
1353     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1354
1355     m_style = RenderStyle::create();
1356
1357     if (m_parentStyle)
1358         m_style->inheritFrom(m_parentStyle);
1359     else {
1360         m_parentStyle = style();
1361         // Make sure our fonts are initialized if we don't inherit them from our parent style.
1362         m_style->font().update(0);
1363     }
1364
1365     // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
1366     if (isAtShadowBoundary(e))
1367         m_style->setUserModify(RenderStyle::initialUserModify());
1368
1369     if (e->isLink()) {
1370         m_style->setIsLink(true);
1371         m_style->setInsideLink(m_elementLinkState);
1372     }
1373     
1374     if (visitedStyle) {
1375         // Copy any pseudo bits that the visited style has to the primary style so that
1376         // pseudo element styles will continue to work for pseudo elements inside :visited
1377         // links.
1378         for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) {
1379             if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo)))
1380                 m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo));
1381         }
1382         if (m_elementLinkState == InsideUnvisitedLink)
1383             visitedStyle = 0;  // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it.
1384         else
1385             visitedStyle->setStyleType(VISITED_LINK);
1386     }
1387
1388     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) {
1389         loadFullDefaultStyle();
1390         assertNoSiblingRulesInDefaultStyle();
1391     }
1392
1393 #if ENABLE(SVG)
1394     static bool loadedSVGUserAgentSheet;
1395     if (e->isSVGElement() && !loadedSVGUserAgentSheet) {
1396         // SVG rules.
1397         loadedSVGUserAgentSheet = true;
1398         CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
1399         defaultStyle->addRulesFromSheet(svgSheet, screenEval());
1400         defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
1401         assertNoSiblingRulesInDefaultStyle();
1402     }
1403 #endif
1404
1405 #if ENABLE(MATHML)
1406     static bool loadedMathMLUserAgentSheet;
1407     if (e->isMathMLElement() && !loadedMathMLUserAgentSheet) {
1408         // MathML rules.
1409         loadedMathMLUserAgentSheet = true;
1410         CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
1411         defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
1412         defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
1413         // There are some sibling rules here.
1414         collectSiblingRulesInDefaultStyle();
1415     }
1416 #endif
1417
1418 #if ENABLE(VIDEO)
1419     static bool loadedMediaStyleSheet;
1420     if (!loadedMediaStyleSheet && (e->hasTagName(videoTag) || e->hasTagName(audioTag))) {
1421         loadedMediaStyleSheet = true;
1422         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(e->document()->page())->extraMediaControlsStyleSheet();
1423         CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
1424         defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
1425         defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
1426         assertNoSiblingRulesInDefaultStyle();
1427     }
1428 #endif
1429
1430 #if ENABLE(FULLSCREEN_API)
1431     static bool loadedFullScreenStyleSheet;
1432     if (!loadedFullScreenStyleSheet && e->document()->webkitIsFullScreen()) {
1433         loadedFullScreenStyleSheet = true;
1434         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
1435         CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules);
1436         defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval());
1437         defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval());
1438     }
1439 #endif
1440
1441     int firstUARule = -1, lastUARule = -1;
1442     int firstUserRule = -1, lastUserRule = -1;
1443     int firstAuthorRule = -1, lastAuthorRule = -1;
1444     matchUARules(firstUARule, lastUARule);
1445
1446     if (!resolveForRootDefault) {
1447         // 4. Now we check user sheet rules.
1448         if (m_matchAuthorAndUserStyles)
1449             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
1450
1451         // 5. Now check author rules, beginning first with presentational attributes
1452         // mapped from HTML.
1453         if (m_styledElement) {
1454             // Ask if the HTML element has mapped attributes.
1455             if (m_styledElement->hasMappedAttributes()) {
1456                 // Walk our attribute list and add in each decl.
1457                 const NamedNodeMap* map = m_styledElement->attributeMap();
1458                 for (unsigned i = 0; i < map->length(); i++) {
1459                     Attribute* attr = map->attributeItem(i);
1460                     if (attr->isMappedAttribute() && attr->decl()) {
1461                         lastAuthorRule = m_matchedDecls.size();
1462                         if (firstAuthorRule == -1)
1463                             firstAuthorRule = lastAuthorRule;
1464                         addMatchedDeclaration(attr->decl());
1465                     }
1466                 }
1467             }
1468
1469             // Now we check additional mapped declarations.
1470             // Tables and table cells share an additional mapped rule that must be applied
1471             // after all attributes, since their mapped style depends on the values of multiple attributes.
1472             if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
1473                 m_additionalAttributeStyleDecls.clear();
1474                 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
1475                 if (!m_additionalAttributeStyleDecls.isEmpty()) {
1476                     unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
1477                     if (firstAuthorRule == -1)
1478                         firstAuthorRule = m_matchedDecls.size();
1479                     lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
1480                     for (unsigned i = 0; i < additionalDeclsSize; i++)
1481                         addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
1482                 }
1483             }
1484             if (m_styledElement->isHTMLElement()) {
1485                 bool isAuto;
1486                 TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
1487                 if (isAuto)
1488                     addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
1489             }
1490         }
1491     
1492         // 6. Check the rules in author sheets next.
1493         if (m_matchAuthorAndUserStyles)
1494             matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
1495
1496         // 7. Now check our inline style attribute.
1497         if (m_matchAuthorAndUserStyles && m_styledElement) {
1498             CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
1499             if (inlineDecl) {
1500                 lastAuthorRule = m_matchedDecls.size();
1501                 if (firstAuthorRule == -1)
1502                     firstAuthorRule = lastAuthorRule;
1503                 addMatchedDeclaration(inlineDecl);
1504             }
1505         }
1506     }
1507
1508     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1509     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1510     
1511     // Now we have all of the matched rules in the appropriate order.  Walk the rules and apply
1512     // high-priority properties first, i.e., those properties that other properties depend on.
1513     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1514     // and (4) normal important.
1515     m_lineHeightValue = 0;
1516     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1517     if (!resolveForRootDefault) {
1518         applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1519         applyDeclarations<true>(true, firstUserRule, lastUserRule);
1520     }
1521     applyDeclarations<true>(true, firstUARule, lastUARule);
1522     
1523     // If our font got dirtied, go ahead and update it now.
1524     updateFont();
1525
1526     // Line-height is set when we are sure we decided on the font-size
1527     if (m_lineHeightValue)
1528         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1529
1530     // Now do the normal priority UA properties.
1531     applyDeclarations<false>(false, firstUARule, lastUARule);
1532     
1533     // Cache our border and background so that we can examine them later.
1534     cacheBorderAndBackground();
1535     
1536     // Now do the author and user normal priority properties and all the !important properties.
1537     if (!resolveForRootDefault) {
1538         applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1539         applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1540         applyDeclarations<false>(true, firstUserRule, lastUserRule);
1541     }
1542     applyDeclarations<false>(true, firstUARule, lastUARule);
1543
1544     ASSERT(!m_fontDirty);
1545     // If our font got dirtied by one of the non-essential font props, 
1546     // go ahead and update it a second time.
1547     updateFont();
1548
1549     // Clean up our style object's display and text decorations (among other fixups).
1550     adjustRenderStyle(style(), m_parentStyle, e);
1551
1552     // Start loading images referenced by this style.
1553     loadPendingImages();
1554
1555     // If we have first-letter pseudo style, do not share this style
1556     if (m_style->hasPseudoStyle(FIRST_LETTER))
1557         m_style->setUnique();
1558
1559     if (visitedStyle) {
1560         // Add the visited style off the main style.
1561         m_style->addCachedPseudoStyle(visitedStyle.release());
1562     }
1563
1564     if (!matchVisitedPseudoClass)
1565         initElement(0); // Clear out for the next resolve.
1566
1567     // Now return the style.
1568     return m_style.release();
1569 }
1570
1571 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
1572 {
1573     if (keyframeRule->style())
1574         addMatchedDeclaration(keyframeRule->style());
1575
1576     ASSERT(!m_style);
1577
1578     // Create the style
1579     m_style = RenderStyle::clone(elementStyle);
1580
1581     m_lineHeightValue = 0;
1582
1583     // We don't need to bother with !important. Since there is only ever one
1584     // decl, there's nothing to override. So just add the first properties.
1585     if (keyframeRule->style())
1586         applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1587
1588     // If our font got dirtied, go ahead and update it now.
1589     updateFont();
1590
1591     // Line-height is set when we are sure we decided on the font-size
1592     if (m_lineHeightValue)
1593         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1594
1595     // Now do rest of the properties.
1596     if (keyframeRule->style())
1597         applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1598
1599     // If our font got dirtied by one of the non-essential font props,
1600     // go ahead and update it a second time.
1601     updateFont();
1602
1603     // Start loading images referenced by this style.
1604     loadPendingImages();
1605
1606     // Add all the animating properties to the keyframe.
1607     if (keyframeRule->style()) {
1608         CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
1609         for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
1610             int property = (*it).id();
1611             // Timing-function within keyframes is special, because it is not animated; it just
1612             // describes the timing function between this keyframe and the next.
1613             if (property != CSSPropertyWebkitAnimationTimingFunction)
1614                 keyframe.addProperty(property);
1615         }
1616     }
1617
1618     return m_style.release();
1619 }
1620
1621 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1622 {
1623     list.clear();
1624     
1625     // Get the keyframesRule for this name
1626     if (!e || list.animationName().isEmpty())
1627         return;
1628
1629     m_keyframesRuleMap.checkConsistency();
1630    
1631     if (!m_keyframesRuleMap.contains(list.animationName().impl()))
1632         return;
1633         
1634     const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
1635     
1636     // Construct and populate the style for each keyframe
1637     for (unsigned i = 0; i < rule->length(); ++i) {
1638         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1639         initElement(e);
1640         initForStyleResolve(e);
1641         
1642         const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
1643
1644         KeyframeValue keyframe(0, 0);
1645         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
1646
1647         // Add this keyframe style to all the indicated key times
1648         Vector<float> keys;
1649         keyframeRule->getKeys(keys);
1650         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1651             keyframe.setKey(keys[keyIndex]);
1652             list.insert(keyframe);
1653         }
1654     }
1655     
1656     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1657     int initialListSize = list.size();
1658     if (initialListSize > 0 && list[0].key() != 0) {
1659         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1660         keyframeRule->setKeyText("0%");
1661         KeyframeValue keyframe(0, 0);
1662         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1663         list.insert(keyframe);
1664     }
1665
1666     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1667     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1668         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1669         keyframeRule->setKeyText("100%");
1670         KeyframeValue keyframe(1, 0);
1671         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1672         list.insert(keyframe);
1673     }
1674 }
1675
1676 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedPseudoClass)
1677 {
1678     if (!e)
1679         return 0;
1680
1681     initElement(e);
1682
1683     // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it
1684     // off of.
1685     RefPtr<RenderStyle> visitedStyle;
1686     if (!matchVisitedPseudoClass && parentStyle && parentStyle->insideLink()) {
1687         // Fetch our parent style with :visited in effect.
1688         RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK);
1689         visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true);
1690         if (visitedStyle)
1691             visitedStyle->setStyleType(VISITED_LINK);
1692     }
1693
1694     initForStyleResolve(e, parentStyle, pseudo);
1695     m_style = RenderStyle::create();
1696     if (parentStyle)
1697         m_style->inheritFrom(parentStyle);
1698
1699     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1700
1701     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1702     // those rules.
1703     
1704     // Check UA, user and author rules.
1705     int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
1706     matchUARules(firstUARule, lastUARule);
1707
1708     if (m_matchAuthorAndUserStyles) {
1709         matchRules(m_userStyle.get(), firstUserRule, lastUserRule, false);
1710         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, false);
1711     }
1712
1713     if (m_matchedDecls.isEmpty() && !visitedStyle)
1714         return 0;
1715
1716     m_style->setStyleType(pseudo);
1717     
1718     m_lineHeightValue = 0;
1719     
1720     // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1721     m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1722
1723     // High-priority properties.
1724     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1725     applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1726     applyDeclarations<true>(true, firstUserRule, lastUserRule);
1727     applyDeclarations<true>(true, firstUARule, lastUARule);
1728     
1729     // If our font got dirtied, go ahead and update it now.
1730     updateFont();
1731
1732     // Line-height is set when we are sure we decided on the font-size
1733     if (m_lineHeightValue)
1734         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1735     
1736     // Now do the normal priority properties.
1737     applyDeclarations<false>(false, firstUARule, lastUARule);
1738     
1739     // Cache our border and background so that we can examine them later.
1740     cacheBorderAndBackground();
1741     
1742     applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1743     applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1744     applyDeclarations<false>(true, firstUserRule, lastUserRule);
1745     applyDeclarations<false>(true, firstUARule, lastUARule);
1746     
1747     // If our font got dirtied by one of the non-essential font props, 
1748     // go ahead and update it a second time.
1749     updateFont();
1750
1751     // Clean up our style object's display and text decorations (among other fixups).
1752     adjustRenderStyle(style(), parentStyle, 0);
1753
1754     // Start loading images referenced by this style.
1755     loadPendingImages();
1756
1757     // Hang our visited style off m_style.
1758     if (visitedStyle)
1759         m_style->addCachedPseudoStyle(visitedStyle.release());
1760         
1761     // Now return the style.
1762     return m_style.release();
1763 }
1764
1765 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1766 {
1767     initForStyleResolve(m_checker.m_document->documentElement()); // m_rootElementStyle will be set to the document style.
1768
1769     m_style = RenderStyle::create();
1770     m_style->inheritFrom(m_rootElementStyle);
1771
1772     const bool isLeft = isLeftPage(pageIndex);
1773     const bool isFirst = isFirstPage(pageIndex);
1774     const String page = pageName(pageIndex);
1775     matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
1776     matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
1777     matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
1778     m_lineHeightValue = 0;
1779     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1780
1781     // If our font got dirtied, go ahead and update it now.
1782     updateFont();
1783
1784     // Line-height is set when we are sure we decided on the font-size
1785     if (m_lineHeightValue)
1786         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1787
1788     applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1789
1790     // Start loading images referenced by this style.
1791     loadPendingImages();
1792
1793     // Now return the style.
1794     return m_style.release();
1795 }
1796
1797 static void addIntrinsicMargins(RenderStyle* style)
1798 {
1799     // Intrinsic margin value.
1800     const int intrinsicMargin = 2 * style->effectiveZoom();
1801     
1802     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1803     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1804     if (style->width().isIntrinsicOrAuto()) {
1805         if (style->marginLeft().quirk())
1806             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1807         if (style->marginRight().quirk())
1808             style->setMarginRight(Length(intrinsicMargin, Fixed));
1809     }
1810
1811     if (style->height().isAuto()) {
1812         if (style->marginTop().quirk())
1813             style->setMarginTop(Length(intrinsicMargin, Fixed));
1814         if (style->marginBottom().quirk())
1815             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1816     }
1817 }
1818
1819 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1820 {
1821     // Cache our original display.
1822     style->setOriginalDisplay(style->display());
1823
1824     if (style->display() != NONE) {
1825         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1826         // property.
1827         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
1828         // these tags to retain their display types.
1829         if (!m_checker.m_strictParsing && e) {
1830             if (e->hasTagName(tdTag)) {
1831                 style->setDisplay(TABLE_CELL);
1832                 style->setFloating(NoFloat);
1833             }
1834             else if (e->hasTagName(tableTag))
1835                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1836         }
1837
1838         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1839             if (style->whiteSpace() == KHTML_NOWRAP) {
1840                 // Figure out if we are really nowrapping or if we should just
1841                 // use normal instead.  If the width of the cell is fixed, then
1842                 // we don't actually use NOWRAP.
1843                 if (style->width().isFixed())
1844                     style->setWhiteSpace(NORMAL);
1845                 else
1846                     style->setWhiteSpace(NOWRAP);
1847             }
1848         }
1849
1850         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1851         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1852             style->setTextAlign(TAAUTO);
1853
1854         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
1855         // fix a crash where a site tries to position these objects.  They also never honor display.
1856         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1857             style->setPosition(StaticPosition);
1858             style->setDisplay(BLOCK);
1859         }
1860
1861         // Table headers with a text-align of auto will change the text-align to center.
1862         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1863             style->setTextAlign(CENTER);
1864
1865         if (e && e->hasTagName(legendTag))
1866             style->setDisplay(BLOCK);
1867
1868         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1869         // position or float an inline, compact, or run-in.  Cache the original display, since it
1870         // may be needed for positioned elements that have to compute their static normal flow
1871         // positions.  We also force inline-level roots to be block-level.
1872         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1873             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->isFloating() ||
1874              (e && e->document()->documentElement() == e))) {
1875             if (style->display() == INLINE_TABLE)
1876                 style->setDisplay(TABLE);
1877             else if (style->display() == INLINE_BOX)
1878                 style->setDisplay(BOX);
1879             else if (style->display() == LIST_ITEM) {
1880                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1881                 // but only in quirks mode.
1882                 if (!m_checker.m_strictParsing && style->isFloating())
1883                     style->setDisplay(BLOCK);
1884             }
1885             else
1886                 style->setDisplay(BLOCK);
1887         }
1888         
1889         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1890         // clear how that should work.
1891         if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
1892             style->setDisplay(INLINE_BLOCK);
1893         
1894         // After performing the display mutation, check table rows.  We do not honor position:relative on
1895         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
1896         // on some sites).
1897         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1898              || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
1899              style->position() == RelativePosition)
1900             style->setPosition(StaticPosition);
1901
1902         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1903         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1904         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1905             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1906             || style->display() == TABLE_CELL)
1907             style->setWritingMode(parentStyle->writingMode());
1908
1909         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1910         // of block-flow to anything other than TopToBottomWritingMode.
1911         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1912         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1913             style->setWritingMode(TopToBottomWritingMode);
1914     }
1915
1916     // Make sure our z-index value is only applied if the object is positioned.
1917     if (style->position() == StaticPosition)
1918         style->setHasAutoZIndex();
1919
1920     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
1921     // cases where objects that should be blended as a single unit end up with a non-transparent
1922     // object wedged in between them.  Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1923     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f || 
1924         style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect()))
1925         style->setZIndex(0);
1926
1927     // Textarea considers overflow visible as auto.
1928     if (e && e->hasTagName(textareaTag)) {
1929         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1930         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1931     }
1932
1933     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1934     // tables, inline blocks, inline tables, run-ins, or shadow DOM.
1935     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1936         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
1937         style->setTextDecorationsInEffect(style->textDecoration());
1938     else
1939         style->addToTextDecorationsInEffect(style->textDecoration());
1940     
1941     // If either overflow value is not visible, change to auto.
1942     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1943         style->setOverflowY(OMARQUEE);
1944     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1945         style->setOverflowX(OMARQUEE);
1946     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1947         style->setOverflowX(OAUTO);
1948     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1949         style->setOverflowY(OAUTO);
1950
1951     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1952     // FIXME: Eventually table sections will support auto and scroll.
1953     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1954         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1955         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) 
1956             style->setOverflowX(OVISIBLE);
1957         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) 
1958             style->setOverflowY(OVISIBLE);
1959     }
1960
1961     // Menulists should have visible overflow
1962     if (style->appearance() == MenulistPart) {
1963         style->setOverflowX(OVISIBLE);
1964         style->setOverflowY(OVISIBLE);
1965     }
1966
1967     // Cull out any useless layers and also repeat patterns into additional layers.
1968     style->adjustBackgroundLayers();
1969     style->adjustMaskLayers();
1970
1971     // Do the same for animations and transitions.
1972     style->adjustAnimations();
1973     style->adjustTransitions();
1974
1975     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1976     // alter fonts and heights/widths.
1977     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1978         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
1979         // so we have to treat all image buttons as though they were explicitly sized.
1980         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
1981             addIntrinsicMargins(style);
1982     }
1983
1984     // Let the theme also have a crack at adjusting the style.
1985     if (style->hasAppearance())
1986         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1987
1988 #if ENABLE(SVG)
1989     if (e && e->isSVGElement()) {
1990         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1991         if (style->overflowY() == OSCROLL)
1992             style->setOverflowY(OHIDDEN);
1993         else if (style->overflowY() == OAUTO)
1994             style->setOverflowY(OVISIBLE);
1995
1996         if (style->overflowX() == OSCROLL)
1997             style->setOverflowX(OHIDDEN);
1998         else if (style->overflowX() == OAUTO)
1999             style->setOverflowX(OVISIBLE);
2000
2001         // Only the root <svg> element in an SVG document fragment tree honors css position
2002         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
2003             style->setPosition(RenderStyle::initialPosition());
2004     }
2005 #endif
2006 }
2007
2008 void CSSStyleSelector::updateFont()
2009 {
2010     if (!m_fontDirty)
2011         return;
2012
2013     checkForTextSizeAdjust();
2014     checkForGenericFamilyChange(style(), m_parentStyle);
2015     checkForZoomChange(style(), m_parentStyle);
2016     m_style->font().update(m_fontSelector);
2017     m_fontDirty = false;
2018 }
2019
2020 void CSSStyleSelector::cacheBorderAndBackground()
2021 {
2022     m_hasUAAppearance = m_style->hasAppearance();
2023     if (m_hasUAAppearance) {
2024         m_borderData = m_style->border();
2025         m_backgroundData = *m_style->backgroundLayers();
2026         m_backgroundColor = m_style->backgroundColor();
2027     }
2028 }
2029
2030 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude, unsigned forcePseudoClassMask)
2031 {
2032     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude, forcePseudoClassMask);
2033 }
2034
2035 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude, unsigned forcePseudoClassMask)
2036 {
2037     if (!e || !e->document()->haveStylesheetsLoaded())
2038         return 0;
2039
2040     m_checker.m_collectRulesOnly = true;
2041
2042     initElement(e);
2043     initForStyleResolve(e, 0, pseudoId);
2044     m_forcePseudoClassMask = forcePseudoClassMask;
2045
2046     if (rulesToInclude & UAAndUserCSSRules) {
2047         int firstUARule = -1, lastUARule = -1;
2048         // First we match rules from the user agent sheet.
2049         matchUARules(firstUARule, lastUARule);
2050
2051         // Now we check user sheet rules.
2052         if (m_matchAuthorAndUserStyles) {
2053             int firstUserRule = -1, lastUserRule = -1;
2054             matchRules(m_userStyle.get(), firstUserRule, lastUserRule, rulesToInclude & EmptyCSSRules);
2055         }
2056     }
2057
2058     if (m_matchAuthorAndUserStyles) {
2059         m_checker.m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
2060
2061         // Check the rules in author sheets.
2062         int firstAuthorRule = -1, lastAuthorRule = -1;
2063         matchRules(m_authorStyle.get(), firstAuthorRule, lastAuthorRule, rulesToInclude & EmptyCSSRules);
2064
2065         m_checker.m_sameOriginOnly = false;
2066     }
2067
2068     m_checker.m_collectRulesOnly = false;
2069     m_forcePseudoClassMask = DoNotForcePseudoClassMask;
2070    
2071     return m_ruleList.release();
2072 }
2073
2074 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
2075 {
2076     m_dynamicPseudo = NOPSEUDO;
2077     m_checker.m_hasUnknownPseudoElements = false;
2078
2079     // Let the slow path handle SVG as it has some additional rules regarding shadow trees.
2080     if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) {
2081         // We know this selector does not include any pseudo selectors.
2082         if (m_checker.m_pseudoStyle != NOPSEUDO)
2083             return false;
2084         // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
2085         // This is limited to HTML only so we don't need to check the namespace.
2086         if (ruleData.hasTopSelectorMatchingHTMLBasedOnRuleHash() && !ruleData.hasMultipartSelector() && m_element->isHTMLElement())
2087             return true;
2088         return SelectorChecker::fastCheckSelector(ruleData.selector(), m_element);
2089     }
2090
2091     // Slow path.
2092     SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, false, m_forcePseudoClassMask, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
2093     if (match != SelectorMatches)
2094         return false;
2095     if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
2096         return false;
2097     return true;
2098 }
2099     
2100 namespace {
2101
2102 inline bool selectorTagMatches(const Element* element, const CSSSelector* selector)
2103 {
2104     if (!selector->hasTag())
2105         return true;
2106     const AtomicString& localName = selector->tag().localName();
2107     if (localName != starAtom && localName != element->localName())
2108         return false;
2109     const AtomicString& namespaceURI = selector->tag().namespaceURI();
2110     return namespaceURI == starAtom || namespaceURI == element->namespaceURI();
2111 }
2112
2113 inline bool isFastCheckableSelector(const CSSSelector* selector)
2114 {
2115     for (; selector; selector = selector->tagHistory()) {
2116         if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector)
2117             return false;
2118         if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
2119             return false;
2120     }
2121     return true;
2122 }
2123     
2124 template <bool checkValue(const Element*, AtomicStringImpl*)>
2125 inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
2126 {
2127     AtomicStringImpl* value = selector->value().impl();
2128     for (; element; element = element->parentElement()) {
2129         if (checkValue(element, value) && selectorTagMatches(element, selector)) {
2130             if (selector->relation() == CSSSelector::Descendant)
2131                 topChildOrSubselector = 0;
2132             else if (!topChildOrSubselector) {
2133                 ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector);
2134                 topChildOrSubselector = selector;
2135                 topChildOrSubselectorMatchElement = element;
2136             }
2137             if (selector->relation() != CSSSelector::SubSelector)
2138                 element = element->parentElement();
2139             selector = selector->tagHistory();
2140             return true;
2141         }
2142         if (topChildOrSubselector) {
2143             // Child or subselector check failed.
2144             // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match 
2145             // the original element we were checking.
2146             if (!topChildOrSubselectorMatchElement)
2147                 return false;
2148             // There may be other matches down the ancestor chain.
2149             // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors.
2150             selector = topChildOrSubselector;
2151             element = topChildOrSubselectorMatchElement->parentElement();
2152             topChildOrSubselector = 0;
2153             return true;
2154         }
2155     }
2156     return false;
2157 }
2158
2159 inline bool checkClassValue(const Element* element, AtomicStringImpl* value) 
2160 {
2161     return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(value);
2162 }
2163
2164 inline bool checkIDValue(const Element* element, AtomicStringImpl* value) 
2165 {
2166     return element->hasID() && element->idForStyleResolution().impl() == value;
2167 }
2168
2169 inline bool checkTagValue(const Element*, AtomicStringImpl*)
2170 {
2171     return true;
2172 }
2173
2174 }
2175
2176 bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* selector, const Element* element)
2177 {
2178     ASSERT(isFastCheckableSelector(selector));
2179
2180     // The top selector requires tag check only as rule hashes have already handled id and class matches.
2181     if (!selectorTagMatches(element, selector))
2182         return false;
2183
2184     const CSSSelector* topChildOrSubselector = 0;
2185     const Element* topChildOrSubselectorMatchElement = 0;
2186     if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector)
2187         topChildOrSubselector = selector;
2188
2189     if (selector->relation() != CSSSelector::SubSelector)
2190         element = element->parentElement();
2191
2192     selector = selector->tagHistory();
2193
2194     // We know this compound selector has descendant, child and subselector combinators only and all components are simple.
2195     while (selector) {
2196         switch (selector->m_match) {
2197         case CSSSelector::Class:
2198             if (!fastCheckSingleSelector<checkClassValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
2199                 return false;
2200             break;
2201         case CSSSelector::Id:
2202             if (!fastCheckSingleSelector<checkIDValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
2203                 return false;
2204             break;
2205         case CSSSelector::None:
2206             if (!fastCheckSingleSelector<checkTagValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
2207                 return false;
2208             break;
2209         default:
2210             ASSERT_NOT_REACHED();
2211         }
2212     }
2213     return true;
2214 }
2215
2216 // Recursive check of selectors and combinators
2217 // It can return 3 different values:
2218 // * SelectorMatches         - the selector matches the element e
2219 // * SelectorFailsLocally    - the selector fails for the element e
2220 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
2221 CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
2222 {
2223 #if ENABLE(SVG)
2224     // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
2225     // because its contents are not part of the formal document structure.
2226     if (e->isSVGShadowRoot())
2227         return SelectorFailsCompletely;
2228 #endif
2229
2230     // first selector has to match
2231     if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle))
2232         return SelectorFailsLocally;
2233
2234     // The rest of the selectors has to match
2235     CSSSelector::Relation relation = sel->relation();
2236
2237     // Prepare next sel
2238     sel = sel->tagHistory();
2239     if (!sel)
2240         return SelectorMatches;
2241
2242     if (relation != CSSSelector::SubSelector)
2243         // Bail-out if this selector is irrelevant for the pseudoStyle
2244         if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo)
2245             return SelectorFailsCompletely;
2246
2247     // Check for nested links.
2248     if (m_matchVisitedPseudoClass && !isSubSelector) {
2249         RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle();
2250         if (currentStyle && currentStyle->insideLink() && e->isLink()) {
2251             if (encounteredLink)
2252                 m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching.
2253             else
2254                 encounteredLink = true;
2255         }
2256     }
2257
2258     switch (relation) {
2259         case CSSSelector::Descendant:
2260             while (true) {
2261                 ContainerNode* n = e->parentNode();
2262                 if (!n || !n->isElementNode())
2263                     return SelectorFailsCompletely;
2264                 e = static_cast<Element*>(n);
2265                 SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
2266                 if (match != SelectorFailsLocally)
2267                     return match;
2268             }
2269             break;
2270         case CSSSelector::Child:
2271         {
2272             ContainerNode* n = e->parentNode();
2273             if (!n || !n->isElementNode())
2274                 return SelectorFailsCompletely;
2275             e = static_cast<Element*>(n);
2276             return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
2277         }
2278         case CSSSelector::DirectAdjacent:
2279         {
2280             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
2281                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2282                 if (parentStyle)
2283                     parentStyle->setChildrenAffectedByDirectAdjacentRules();
2284             }
2285             Node* n = e->previousSibling();
2286             while (n && !n->isElementNode())
2287                 n = n->previousSibling();
2288             if (!n)
2289                 return SelectorFailsLocally;
2290             e = static_cast<Element*>(n);
2291             m_matchVisitedPseudoClass = false;
2292             return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
2293         }
2294         case CSSSelector::IndirectAdjacent:
2295             if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
2296                 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2297                 if (parentStyle)
2298                     parentStyle->setChildrenAffectedByForwardPositionalRules();
2299             }
2300             while (true) {
2301                 Node* n = e->previousSibling();
2302                 while (n && !n->isElementNode())
2303                     n = n->previousSibling();
2304                 if (!n)
2305                     return SelectorFailsLocally;
2306                 e = static_cast<Element*>(n);
2307                 m_matchVisitedPseudoClass = false;
2308                 SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
2309                 if (match != SelectorFailsLocally)
2310                     return match;
2311             };
2312             break;
2313         case CSSSelector::SubSelector:
2314             // a selector is invalid if something follows a pseudo-element
2315             // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
2316             // to follow the pseudo elements.
2317             if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION &&
2318                 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
2319                 return SelectorFailsCompletely;
2320             return checkSelector(sel, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle);
2321         case CSSSelector::ShadowDescendant:
2322         {
2323             Node* shadowHostNode = e->shadowAncestorNode();
2324             if (shadowHostNode == e || !shadowHostNode->isElementNode())
2325                 return SelectorFailsCompletely;
2326             e = static_cast<Element*>(shadowHostNode);
2327             return checkSelector(sel, e, dynamicPseudo, false, encounteredLink, forcePseudoClassMask);
2328         }
2329     }
2330
2331     return SelectorFailsCompletely;
2332 }
2333
2334 static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
2335 {
2336     set->add(qName.localName().impl());
2337 }
2338
2339 static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
2340 {
2341     // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
2342     // Mozilla treats all other values as case-sensitive, thus so do we.
2343     HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
2344
2345     addLocalNameToSet(attrSet, accept_charsetAttr);
2346     addLocalNameToSet(attrSet, acceptAttr);
2347     addLocalNameToSet(attrSet, alignAttr);
2348     addLocalNameToSet(attrSet, alinkAttr);
2349     addLocalNameToSet(attrSet, axisAttr);
2350     addLocalNameToSet(attrSet, bgcolorAttr);
2351     addLocalNameToSet(attrSet, charsetAttr);
2352     addLocalNameToSet(attrSet, checkedAttr);
2353     addLocalNameToSet(attrSet, clearAttr);
2354     addLocalNameToSet(attrSet, codetypeAttr);
2355     addLocalNameToSet(attrSet, colorAttr);
2356     addLocalNameToSet(attrSet, compactAttr);
2357     addLocalNameToSet(attrSet, declareAttr);
2358     addLocalNameToSet(attrSet, deferAttr);
2359     addLocalNameToSet(attrSet, dirAttr);
2360     addLocalNameToSet(attrSet, disabledAttr);
2361     addLocalNameToSet(attrSet, enctypeAttr);
2362     addLocalNameToSet(attrSet, faceAttr);
2363     addLocalNameToSet(attrSet, frameAttr);
2364     addLocalNameToSet(attrSet, hreflangAttr);
2365     addLocalNameToSet(attrSet, http_equivAttr);
2366     addLocalNameToSet(attrSet, langAttr);
2367     addLocalNameToSet(attrSet, languageAttr);
2368     addLocalNameToSet(attrSet, linkAttr);
2369     addLocalNameToSet(attrSet, mediaAttr);
2370     addLocalNameToSet(attrSet, methodAttr);
2371     addLocalNameToSet(attrSet, multipleAttr);
2372     addLocalNameToSet(attrSet, nohrefAttr);
2373     addLocalNameToSet(attrSet, noresizeAttr);
2374     addLocalNameToSet(attrSet, noshadeAttr);
2375     addLocalNameToSet(attrSet, nowrapAttr);
2376     addLocalNameToSet(attrSet, readonlyAttr);
2377     addLocalNameToSet(attrSet, relAttr);
2378     addLocalNameToSet(attrSet, revAttr);
2379     addLocalNameToSet(attrSet, rulesAttr);
2380     addLocalNameToSet(attrSet, scopeAttr);
2381     addLocalNameToSet(attrSet, scrollingAttr);
2382     addLocalNameToSet(attrSet, selectedAttr);
2383     addLocalNameToSet(attrSet, shapeAttr);
2384     addLocalNameToSet(attrSet, targetAttr);
2385     addLocalNameToSet(attrSet, textAttr);
2386     addLocalNameToSet(attrSet, typeAttr);
2387     addLocalNameToSet(attrSet, valignAttr);
2388     addLocalNameToSet(attrSet, valuetypeAttr);
2389     addLocalNameToSet(attrSet, vlinkAttr);
2390
2391     return attrSet;
2392 }
2393
2394 static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
2395 {
2396     static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
2397     bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
2398     return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
2399 }
2400
2401 static bool attributeQualifiedNameMatches(Attribute* attribute, const QualifiedName& selectorAttr)
2402 {
2403     if (selectorAttr.localName() != attribute->localName())
2404         return false;
2405
2406     return selectorAttr.prefix() == starAtom || selectorAttr.namespaceURI() == attribute->namespaceURI();
2407 }
2408
2409 static bool attributeValueMatches(Attribute* attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive)
2410 {
2411     const AtomicString& value = attributeItem->value();
2412     if (value.isNull())
2413         return false;
2414
2415     switch (match) {
2416     case CSSSelector::Exact:
2417         if (caseSensitive ? selectorValue != value : !equalIgnoringCase(selectorValue, value))
2418             return false;
2419         break;
2420     case CSSSelector::List: {
2421         // Ignore empty selectors or selectors containing spaces
2422         if (selectorValue.contains(' ') || selectorValue.isEmpty())
2423             return false;
2424
2425         unsigned startSearchAt = 0;
2426         while (true) {
2427             size_t foundPos = value.find(selectorValue, startSearchAt, caseSensitive);
2428             if (foundPos == notFound)
2429                 return false;
2430             if (!foundPos || value[foundPos - 1] == ' ') {
2431                 unsigned endStr = foundPos + selectorValue.length();
2432                 if (endStr == value.length() || value[endStr] == ' ')
2433                     break; // We found a match.
2434             }
2435             
2436             // No match. Keep looking.
2437             startSearchAt = foundPos + 1;
2438         }
2439         break;
2440     }
2441     case CSSSelector::Contain:
2442         if (!value.contains(selectorValue, caseSensitive) || selectorValue.isEmpty())
2443             return false;
2444         break;
2445     case CSSSelector::Begin:
2446         if (!value.startsWith(selectorValue, caseSensitive) || selectorValue.isEmpty())
2447             return false;
2448         break;
2449     case CSSSelector::End:
2450         if (!value.endsWith(selectorValue, caseSensitive) || selectorValue.isEmpty())
2451             return false;
2452         break;
2453     case CSSSelector::Hyphen:
2454         if (value.length() < selectorValue.length())
2455             return false;
2456         if (!value.startsWith(selectorValue, caseSensitive))
2457             return false;
2458         // It they start the same, check for exact match or following '-':
2459         if (value.length() != selectorValue.length() && value[selectorValue.length()] != '-')
2460             return false;
2461         break;
2462     case CSSSelector::PseudoClass:
2463     case CSSSelector::PseudoElement:
2464     default:
2465         break;
2466     }
2467
2468     return true;
2469 }
2470
2471 static bool anyAttributeMatches(NamedNodeMap* attributes, CSSSelector::Match match, const QualifiedName& selectorAttr, const AtomicString& selectorValue, bool caseSensitive)
2472 {
2473     for (size_t i = 0; i < attributes->length(); ++i) {
2474         Attribute* attributeItem = attributes->attributeItem(i);
2475
2476         if (!attributeQualifiedNameMatches(attributeItem, selectorAttr))
2477             continue;
2478
2479         if (attributeValueMatches(attributeItem, match, selectorValue, caseSensitive))
2480             return true;
2481     }
2482
2483     return false;
2484 }
2485
2486 bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, unsigned forcePseudoClassMask, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
2487 {
2488     ASSERT(e);
2489     if (!e)
2490         return false;
2491
2492     if (!selectorTagMatches(e, sel))
2493         return false;
2494
2495     if (sel->hasAttribute()) {
2496         if (sel->m_match == CSSSelector::Class)
2497             return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->value());
2498
2499         if (sel->m_match == CSSSelector::Id)
2500             return e->hasID() && e->idForStyleResolution() == sel->value();
2501
2502         const QualifiedName& attr = sel->attribute();
2503
2504         // FIXME: Handle the case were elementStyle is 0.
2505         if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr)))
2506             elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.
2507
2508         NamedNodeMap* attributes = e->attributes(true);
2509         if (!attributes)
2510             return false;
2511
2512         bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr);
2513
2514         if (!anyAttributeMatches(attributes, static_cast<CSSSelector::Match>(sel->m_match), attr, sel->value(), caseSensitive))
2515             return false;
2516     }
2517     
2518     if (sel->m_match == CSSSelector::PseudoClass) {
2519         // Handle :not up front.
2520         if (sel->pseudoType() == CSSSelector::PseudoNot) {
2521             ASSERT(sel->selectorList());
2522             for (CSSSelector* subSel = sel->selectorList()->first(); subSel; subSel = subSel->tagHistory()) {
2523                 // :not cannot nest. I don't really know why this is a
2524                 // restriction in CSS3, but it is, so let's honor it.
2525                 // the parser enforces that this never occurs
2526                 ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot);
2527
2528                 if (!checkOneSelector(subSel, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle))
2529                     return true;
2530             }
2531         } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
2532             // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
2533             // (since there are no elements involved).
2534             return checkScrollbarPseudoClass(sel, dynamicPseudo);
2535         } else if (dynamicPseudo == SELECTION) {
2536             if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
2537                 return !m_document->page()->focusController()->isActive();
2538         }
2539
2540         CSSSelector::PseudoType pseudoType = sel->pseudoType();
2541
2542         // Check forced pseudo class mask first.
2543         if (forcePseudoClassMask != DoNotForcePseudoClassMask) {
2544             switch (pseudoType) {
2545             case CSSSelector::PseudoLink:
2546                 return forcePseudoClassMask & ForceLink;
2547             case CSSSelector::PseudoVisited:
2548                 return forcePseudoClassMask & ForceVisited;
2549             case CSSSelector::PseudoFocus:
2550                 return forcePseudoClassMask & ForceFocus;
2551             case CSSSelector::PseudoHover:
2552                 return forcePseudoClassMask & ForceHover;
2553             case CSSSelector::PseudoActive:
2554                 return forcePseudoClassMask & ForceActive;
2555             default:
2556                 break;
2557             }
2558         }
2559  
2560         // Normal element pseudo class checking.
2561         switch (pseudoType) {
2562             // Pseudo classes:
2563             case CSSSelector::PseudoNot:
2564                 break; // Already handled up above.
2565             case CSSSelector::PseudoEmpty: {
2566                 bool result = true;
2567                 for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
2568                     if (n->isElementNode()) {
2569                         result = false;
2570                         break;
2571                     } else if (n->isTextNode()) {
2572                         Text* textNode = static_cast<Text*>(n);
2573                         if (!textNode->data().isEmpty()) {
2574                             result = false;
2575                             break;
2576                         }
2577                     }
2578                 }
2579                 if (!m_collectRulesOnly) {
2580                     if (elementStyle)
2581                         elementStyle->setEmptyState(result);
2582                     else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
2583                         e->renderStyle()->setEmptyState(result);
2584                 }
2585                 return result;
2586             }
2587             case CSSSelector::PseudoFirstChild: {
2588                 // first-child matches the first child that is an element
2589                 if (e->parentNode() && e->parentNode()->isElementNode()) {
2590                     bool result = false;
2591                     Node* n = e->previousSibling();
2592                     while (n && !n->isElementNode())
2593                         n = n->previousSibling();
2594                     if (!n)
2595                         result = true;
2596                     if (!m_collectRulesOnly) {
2597                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2598                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2599                         if (parentStyle)
2600                             parentStyle->setChildrenAffectedByFirstChildRules();
2601                         if (result && childStyle)
2602                             childStyle->setFirstChildState();
2603                     }
2604                     return result;
2605                 }
2606                 break;
2607             }
2608             case CSSSelector::PseudoFirstOfType: {
2609                 // first-of-type matches the first element of its type
2610                 if (e->parentNode() && e->parentNode()->isElementNode()) {
2611                     bool result = false;
2612                     const QualifiedName& type = e->tagQName();
2613                     Node* n = e->previousSibling();
2614                     while (n) {
2615                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2616                             break;
2617                         n = n->previousSibling();
2618                     }
2619                     if (!n)
2620                         result = true;
2621                     if (!m_collectRulesOnly) {
2622                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2623                         if (parentStyle)
2624                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2625                     }
2626                     return result;
2627                 }
2628                 break;
2629             }
2630             case CSSSelector::PseudoLastChild: {
2631                 // last-child matches the last child that is an element
2632                 if (Element* parentElement = e->parentElement()) {
2633                     bool result = false;
2634                     if (parentElement->isFinishedParsingChildren()) {
2635                         Node* n = e->nextSibling();
2636                         while (n && !n->isElementNode())
2637                             n = n->nextSibling();
2638                         if (!n)
2639                             result = true;
2640                     }
2641                     if (!m_collectRulesOnly) {
2642                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2643                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2644                         if (parentStyle)
2645                             parentStyle->setChildrenAffectedByLastChildRules();
2646                         if (result && childStyle)
2647                             childStyle->setLastChildState();
2648                     }
2649                     return result;
2650                 }
2651                 break;
2652             }
2653             case CSSSelector::PseudoLastOfType: {
2654                 // last-of-type matches the last element of its type
2655                 if (Element* parentElement = e->parentElement()) {
2656                     if (!m_collectRulesOnly) {
2657                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2658                         if (parentStyle)
2659                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2660                     }
2661                     if (!parentElement->isFinishedParsingChildren())
2662                         return false;
2663                     bool result = false;
2664                     const QualifiedName& type = e->tagQName();
2665                     Node* n = e->nextSibling();
2666                     while (n) {
2667                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2668                             break;
2669                         n = n->nextSibling();
2670                     }
2671                     if (!n)
2672                         result = true;
2673                     return result;
2674                 }
2675                 break;
2676             }
2677             case CSSSelector::PseudoOnlyChild: {
2678                 if (Element* parentElement = e->parentElement()) {
2679                     bool firstChild = false;
2680                     bool lastChild = false;
2681                     
2682                     Node* n = e->previousSibling();
2683                     while (n && !n->isElementNode())
2684                         n = n->previousSibling();
2685                     if (!n)
2686                         firstChild = true;
2687                     if (firstChild && parentElement->isFinishedParsingChildren()) {
2688                         n = e->nextSibling();
2689                         while (n && !n->isElementNode())
2690                             n = n->nextSibling();
2691                         if (!n)
2692                             lastChild = true;
2693                     }
2694                     if (!m_collectRulesOnly) {
2695                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2696                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2697                         if (parentStyle) {
2698                             parentStyle->setChildrenAffectedByFirstChildRules();
2699                             parentStyle->setChildrenAffectedByLastChildRules();
2700                         }
2701                         if (firstChild && childStyle)
2702                             childStyle->setFirstChildState();
2703                         if (lastChild && childStyle)
2704                             childStyle->setLastChildState();
2705                     }
2706                     return firstChild && lastChild;
2707                 }
2708                 break;
2709             }
2710             case CSSSelector::PseudoOnlyOfType: {
2711                 // FIXME: This selector is very slow.
2712                 if (Element* parentElement = e->parentElement()) {
2713                     if (!m_collectRulesOnly) {
2714                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2715                         if (parentStyle) {
2716                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2717                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2718                         }
2719                     }
2720                     if (!parentElement->isFinishedParsingChildren())
2721                         return false;
2722                     bool firstChild = false;
2723                     bool lastChild = false;
2724                     const QualifiedName& type = e->tagQName();
2725                     Node* n = e->previousSibling();
2726                     while (n) {
2727                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2728                             break;
2729                         n = n->previousSibling();
2730                     }
2731                     if (!n)
2732                         firstChild = true;
2733                     if (firstChild) {
2734                         n = e->nextSibling();
2735                         while (n) {
2736                             if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2737                                 break;
2738                             n = n->nextSibling();
2739                         }
2740                         if (!n)
2741                             lastChild = true;
2742                     }
2743                     return firstChild && lastChild;
2744                 }
2745                 break;
2746             }
2747             case CSSSelector::PseudoNthChild: {
2748                 if (!sel->parseNth())
2749                     break;
2750                 if (Element* parentElement = e->parentElement()) {
2751                     int count = 1;
2752                     Node* n = e->previousSibling();
2753                     while (n) {
2754                         if (n->isElementNode()) {
2755                             RenderStyle* s = n->renderStyle();
2756                             unsigned index = s ? s->childIndex() : 0;
2757                             if (index) {
2758                                 count += index;
2759                                 break;
2760                             }
2761                             count++;
2762                         }
2763                         n = n->previousSibling();
2764                     }
2765                     
2766                     if (!m_collectRulesOnly) {
2767                         RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2768                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2769                         if (childStyle)
2770                             childStyle->setChildIndex(count);
2771                         if (parentStyle)
2772                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2773                     }
2774                     
2775                     if (sel->matchNth(count))
2776                         return true;
2777                 }
2778                 break;
2779             }
2780             case CSSSelector::PseudoNthOfType: {
2781                 if (!sel->parseNth())
2782                     break;
2783                 if (Element* parentElement = e->parentElement()) {
2784                     int count = 1;
2785                     const QualifiedName& type = e->tagQName();
2786                     Node* n = e->previousSibling();
2787                     while (n) {
2788                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2789                             count++;
2790                         n = n->previousSibling();
2791                     }
2792                     
2793                     if (!m_collectRulesOnly) {
2794                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2795                         if (parentStyle)
2796                             parentStyle->setChildrenAffectedByForwardPositionalRules();
2797                     }
2798
2799                     if (sel->matchNth(count))
2800                         return true;
2801                 }
2802                 break;
2803             }
2804             case CSSSelector::PseudoNthLastChild: {
2805                 if (!sel->parseNth())
2806                     break;
2807                 if (Element* parentElement = e->parentElement()) {
2808                     if (!m_collectRulesOnly) {
2809                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2810                         if (parentStyle)
2811                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2812                     }
2813                     if (!parentElement->isFinishedParsingChildren())
2814                         return false;
2815                     int count = 1;
2816                     Node* n = e->nextSibling();
2817                     while (n) {
2818                         if (n->isElementNode())
2819                             count++;
2820                         n = n->nextSibling();
2821                     }
2822                     if (sel->matchNth(count))
2823                         return true;
2824                 }
2825                 break;
2826             }
2827             case CSSSelector::PseudoNthLastOfType: {
2828                 if (!sel->parseNth())
2829                     break;
2830                 if (Element* parentElement = e->parentElement()) {
2831                     if (!m_collectRulesOnly) {
2832                         RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2833                         if (parentStyle)
2834                             parentStyle->setChildrenAffectedByBackwardPositionalRules();
2835                     }
2836                     if (!parentElement->isFinishedParsingChildren())
2837                         return false;
2838                     int count = 1;
2839                     const QualifiedName& type = e->tagQName();
2840                     Node* n = e->nextSibling();
2841                     while (n) {
2842                         if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2843                             count++;
2844                         n = n->nextSibling();
2845                     }
2846                     if (sel->matchNth(count))
2847                         return true;
2848                 }
2849                 break;
2850             }
2851             case CSSSelector::PseudoTarget:
2852                 if (e == e->document()->cssTarget())
2853                     return true;
2854                 break;
2855             case CSSSelector::PseudoAny:
2856                 for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) {
2857                     if (checkSelector(selector, e, dynamicPseudo, true, encounteredLink, forcePseudoClassMask, elementStyle, elementParentStyle) == SelectorMatches)
2858                         return true;
2859                 }
2860                 break;
2861             case CSSSelector::PseudoAnyLink:
2862                 if (e && e->isLink())
2863                     return true;
2864                 break;
2865             case CSSSelector::PseudoAutofill: {
2866                 if (!e || !e->isFormControlElement())
2867                     break;
2868                 if (HTMLInputElement* inputElement = e->toInputElement())
2869                     return inputElement->isAutofilled();
2870                 break;
2871             }
2872             case CSSSelector::PseudoLink:
2873                 if (e && e->isLink())
2874                     return !m_matchVisitedPseudoClass;
2875                 break;
2876             case CSSSelector::PseudoVisited:
2877                 if (e && e->isLink())
2878                     return m_matchVisitedPseudoClass;
2879                 break;
2880             case CSSSelector::PseudoDrag: {
2881                 if (elementStyle)
2882                     elementStyle->setAffectedByDragRules(true);
2883                 else if (e->renderStyle())
2884                     e->renderStyle()->setAffectedByDragRules(true);
2885                 if (e->renderer() && e->renderer()->isDragging())
2886                     return true;
2887                 break;
2888             }
2889             case CSSSelector::PseudoFocus:
2890                 if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive())
2891                     return true;
2892                 break;
2893             case CSSSelector::PseudoHover: {
2894                 // If we're in quirks mode, then hover should never match anchors with no
2895                 // href and *:hover should not match anything.  This is important for sites like wsj.com.
2896                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2897                     if (elementStyle)
2898                         elementStyle->setAffectedByHoverRules(true);
2899                     else if (e->renderStyle())
2900                         e->renderStyle()->setAffectedByHoverRules(true);
2901                     if (e->hovered())
2902                         return true;
2903                 }
2904                 break;
2905             }
2906             case CSSSelector::PseudoActive:
2907                 // If we're in quirks mode, then :active should never match anchors with no
2908                 // href and *:active should not match anything. 
2909                 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2910                     if (elementStyle)
2911                         elementStyle->setAffectedByActiveRules(true);
2912                     else if (e->renderStyle())
2913                         e->renderStyle()->setAffectedByActiveRules(true);
2914                     if (e->active())
2915                         return true;
2916                 }
2917                 break;
2918             case CSSSelector::PseudoEnabled:
2919                 if (e && e->isFormControlElement())
2920                     return e->isEnabledFormControl();
2921                 break;
2922             case CSSSelector::PseudoFullPageMedia:
2923                 return e && e->document() && e->document()->isMediaDocument();
2924                 break;
2925             case CSSSelector::PseudoDefault:
2926                 return e && e->isDefaultButtonForForm();
2927             case CSSSelector::PseudoDisabled:
2928                 if (e && e->isFormControlElement())
2929                     return !e->isEnabledFormControl();
2930                 break;
2931             case CSSSelector::PseudoReadOnly: {
2932                 if (!e || !e->isFormControlElement())
2933                     return false;
2934                 return e->isTextFormControl() && e->isReadOnlyFormControl();
2935             }
2936             case CSSSelector::PseudoReadWrite: {
2937                 if (!e || !e->isFormControlElement())
2938                     return false;
2939                 return e->isTextFormControl() && !e->isReadOnlyFormControl();
2940             }
2941             case CSSSelector::PseudoOptional:
2942                 return e && e->isOptionalFormControl();
2943             case CSSSelector::PseudoRequired:
2944                 return e && e->isRequiredFormControl();
2945             case CSSSelector::PseudoValid: {
2946                 if (!e)
2947                     return false;
2948                 e->document()->setContainsValidityStyleRules();
2949                 return e->willValidate() && e->isValidFormControlElement();
2950             } case CSSSelector::PseudoInvalid: {
2951                 if (!e)
2952                     return false;
2953                 e->document()->setContainsValidityStyleRules();
2954                 return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue();
2955             } case CSSSelector::PseudoChecked: {
2956                 if (!e || !e->isFormControlElement())
2957                     break;
2958                 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
2959                 // you can't be both checked and indeterminate.  We will behave like WinIE behind the scenes and just
2960                 // obey the CSS spec here in the test for matching the pseudo.
2961                 HTMLInputElement* inputElement = e->toInputElement();
2962                 if (inputElement && inputElement->shouldAppearChecked() && !inputElement->isIndeterminate())
2963                     return true;
2964                 break;
2965             }
2966             case CSSSelector::PseudoIndeterminate: {
2967                 if (!e || !e->isFormControlElement())
2968                     break;
2969                 
2970 #if ENABLE(PROGRESS_TAG)
2971                 if (e->hasTagName(progressTag)) {
2972                     HTMLProgressElement* progress = static_cast<HTMLProgressElement*>(e);
2973                     if (progress && !progress->isDeterminate())
2974                         return true;
2975                     break;
2976                 }
2977 #endif
2978                 
2979                 HTMLInputElement* inputElement = e->toInputElement();
2980                 if (inputElement && inputElement->isIndeterminate())
2981                     return true;
2982                 break;
2983             }
2984             case CSSSelector::PseudoRoot:
2985                 if (e == e->document()->documentElement())
2986                     return true;
2987                 break;
2988             case CSSSelector::PseudoLang: {
2989                 AtomicString value = e->computeInheritedLanguage();
2990                 const AtomicString& argument = sel->argument();
2991                 if (value.isEmpty() || !value.startsWith(argument, false))
2992                     break;
2993                 if (value.length() != argument.length() && value[argument.length()] != '-')
2994                     break;
2995                 return true;
2996             }
2997 #if ENABLE(FULLSCREEN_API)
2998             case CSSSelector::PseudoFullScreen:
2999                 // While a Document is in the fullscreen state, and the document's current fullscreen 
3000                 // element is an element in the document, the 'full-screen' pseudoclass applies to 
3001                 // that element. Also, an <iframe>, <object> or <embed> element whose child browsing 
3002                 // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
3003                 if (e->isFrameElementBase() && static_cast<HTMLFrameElementBase*>(e)->containsFullScreenElement())
3004                     return true;
3005                 if (!e->document()->webkitIsFullScreen())
3006                     return false;
3007                 return e == e->document()->webkitCurrentFullScreenElement();
3008             case CSSSelector::PseudoAnimatingFullScreenTransition:
3009                 if (e != e->document()->webkitCurrentFullScreenElement())
3010                     return false;
3011                 return e->document()->isAnimatingFullScreen();
3012             case CSSSelector::PseudoFullScreenAncestor:
3013                 return e->containsFullScreenElement();
3014             case CSSSelector::PseudoFullScreenDocument:
3015                 // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies 
3016                 // to all elements of that Document.
3017                 if (!e->document()->webkitIsFullScreen())
3018                     return false;
3019                 return true;
3020 #endif
3021             case CSSSelector::PseudoInRange:
3022                 if (!e)
3023                     return false;
3024                 e->document()->setContainsValidityStyleRules();
3025                 return e->isInRange();
3026             case CSSSelector::PseudoOutOfRange:
3027                 if (!e)
3028                     return false;
3029                 e->document()->setContainsValidityStyleRules();
3030                 return e->isOutOfRange();
3031             case CSSSelector::PseudoUnknown:
3032             case CSSSelector::PseudoNotParsed:
3033             default:
3034                 ASSERT_NOT_REACHED();
3035                 break;
3036         }
3037         return false;
3038     }
3039     if (sel->m_match == CSSSelector::PseudoElement) {
3040         if (!elementStyle && !m_collectRulesOnly)
3041             return false;
3042
3043         if (sel->isUnknownPseudoElement()) {
3044             m_hasUnknownPseudoElements = true;
3045             return e->shadowPseudoId() == sel->value();
3046         }
3047
3048         PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType());
3049         if (pseudoId == FIRST_LETTER) {
3050             if (Document* document = e->document())
3051                 document->setUsesFirstLetterRules(true);
3052         }
3053         if (pseudoId != NOPSEUDO)
3054             dynamicPseudo = pseudoId;
3055     }
3056     // ### add the rest of the checks...
3057     return true;
3058 }
3059
3060 bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const
3061 {
3062     RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve();
3063     ScrollbarPart part = RenderScrollbar::partForStyleResolve();
3064
3065     // FIXME: This is a temporary hack for resizers and scrollbar corners.  Eventually :window-inactive should become a real
3066     // pseudo class and just apply to everything.
3067     if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
3068         return !m_document->page()->focusController()->isActive();
3069     
3070     if (!scrollbar)
3071         return false;
3072         
3073     ASSERT(sel->m_match == CSSSelector::PseudoClass);
3074     switch (sel->pseudoType()) {
3075         case CSSSelector::PseudoEnabled:
3076             return scrollbar->enabled();
3077         case CSSSelector::PseudoDisabled:
3078             return !scrollbar->enabled();
3079         case CSSSelector::PseudoHover: {
3080             ScrollbarPart hoveredPart = scrollbar->hoveredPart();
3081             if (part == ScrollbarBGPart)
3082                 return hoveredPart != NoPart;
3083             if (part == TrackBGPart)
3084                 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
3085             return part == hoveredPart;
3086         }
3087         case CSSSelector::PseudoActive: {
3088             ScrollbarPart pressedPart = scrollbar->pressedPart();
3089             if (part == ScrollbarBGPart)
3090                 return pressedPart != NoPart;
3091             if (part == TrackBGPart)
3092                 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
3093             return part == pressedPart;
3094         }
3095         case CSSSelector::PseudoHorizontal:
3096             return scrollbar->orientation() == HorizontalScrollbar;
3097         case CSSSelector::PseudoVertical:
3098             return scrollbar->orientation() == VerticalScrollbar;
3099         case CSSSelector::PseudoDecrement:
3100             return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
3101         case CSSSelector::PseudoIncrement:
3102             return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
3103         case CSSSelector::PseudoStart:
3104             return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
3105         case CSSSelector::PseudoEnd:
3106             return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
3107         case CSSSelector::PseudoDoubleButton: {
3108             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
3109             if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
3110                 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
3111             if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
3112                 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
3113             return false;
3114         } 
3115         case CSSSelector::PseudoSingleButton: {
3116             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
3117             if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
3118                 return buttonsPlacement == ScrollbarButtonsSingle;
3119             return false;
3120         }
3121         case CSSSelector::PseudoNoButton: {
3122             ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
3123             if (part == BackTrackPart)
3124                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
3125             if (part == ForwardTrackPart)
3126                 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
3127             return false;
3128         }
3129         case CSSSelector::PseudoCornerPresent:
3130             return scrollbar->scrollableArea()->isScrollCornerVisible();
3131         default:
3132             return false;
3133     }
3134 }
3135
3136 // -----------------------------------------------------------------
3137
3138 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
3139 {
3140     const AtomicString& selectorNamespace = selector->tag().namespaceURI();
3141     if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
3142         return false;
3143     if (selector->m_match == CSSSelector::None)
3144         return true;
3145     if (selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
3146         return false;
3147     return selector->tag() == starAtom;
3148 }
3149
3150 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
3151     : m_rule(rule)
3152     , m_selector(selector)
3153     , m_specificity(selector->specificity())
3154     , m_position(position)
3155     , m_hasFastCheckableSelector(isFastCheckableSelector(selector))
3156     , m_hasMultipartSelector(selector->tagHistory())
3157     , m_hasTopSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
3158 {
3159     collectDescendantSelectorIdentifierHashes();
3160 }
3161
3162 inline void RuleData::collectIdentifierHashes(const CSSSelector* selector, unsigned& identifierCount)
3163 {
3164     if ((selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class) && !selector->value().isEmpty())
3165         m_descendantSelectorIdentifierHashes[identifierCount++] = selector->value().impl()->existingHash();
3166     if (identifierCount == maximumIdentifierCount)
3167         return;
3168     const AtomicString& localName = selector->tag().localName();
3169     if (localName != starAtom)
3170         m_descendantSelectorIdentifierHashes[identifierCount++] = localName.impl()->existingHash();
3171 }
3172
3173 inline void RuleData::collectDescendantSelectorIdentifierHashes()
3174 {
3175     unsigned identifierCount = 0;
3176     CSSSelector::Relation relation = m_selector->relation();
3177     
3178     // Skip the topmost selector. It is handled quickly by the rule hashes.    
3179     bool skipOverSubselectors = true;
3180     for (const CSSSelector* selector = m_selector->tagHistory(); selector; selector = selector->tagHistory()) {
3181         // Only collect identifiers that match ancestors.
3182         switch (relation) {
3183         case CSSSelector::SubSelector:
3184             if (!skipOverSubselectors)
3185                 collectIdentifierHashes(selector, identifierCount);
3186             break;
3187         case CSSSelector::DirectAdjacent:
3188         case CSSSelector::IndirectAdjacent:
3189         case CSSSelector::ShadowDescendant:
3190             skipOverSubselectors = true;
3191             break;
3192         case CSSSelector::Descendant:
3193         case CSSSelector::Child:
3194             skipOverSubselectors = false;
3195             collectIdentifierHashes(selector, identifierCount);
3196             break;
3197         }
3198         if (identifierCount == maximumIdentifierCount)
3199             return;
3200         relation = selector->relation();
3201     }
3202     m_descendantSelectorIdentifierHashes[identifierCount] = 0;
3203 }
3204
3205 RuleSet::RuleSet()
3206     : m_ruleCount(0)
3207     , m_autoShrinkToFitEnabled(true)
3208 {
3209 }
3210
3211 RuleSet::~RuleSet()
3212
3213     deleteAllValues(m_idRules);
3214     deleteAllValues(m_classRules);
3215     deleteAllValues(m_pseudoRules);
3216     deleteAllValues(m_tagRules);
3217 }
3218
3219
3220 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
3221                               CSSStyleRule* rule, CSSSelector* sel)
3222 {
3223     if (!key) return;
3224     Vector<RuleData>* rules = map.get(key);
3225     if (!rules) {
3226         rules = new Vector<RuleData>;
3227         map.set(key, rules);
3228     }
3229     rules->append(RuleData(rule, sel, m_ruleCount++));
3230 }
3231
3232 void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
3233 {
3234     if (sel->m_match == CSSSelector::Id) {
3235         addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
3236         return;
3237     }
3238     if (sel->m_match == CSSSelector::Class) {
3239         addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
3240         return;
3241     }
3242      
3243     if (sel->isUnknownPseudoElement()) {
3244         addToRuleSet(sel->value().impl(), m_pseudoRules, rule, sel);
3245         return;
3246     }
3247
3248     const AtomicString& localName = sel->tag().localName();
3249     if (localName != starAtom) {
3250         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
3251         return;
3252     }
3253
3254     m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
3255 }
3256
3257 void RuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel)
3258 {
3259     m_pageRules.append(RuleData(rule, sel, m_pageRules.size()));
3260 }
3261
3262 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
3263 {
3264     if (!sheet)
3265         return;
3266
3267     // No media implies "all", but if a media list exists it must
3268     // contain our current medium
3269     if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
3270         return; // the style sheet doesn't apply
3271
3272     int len = sheet->length();
3273
3274     for (int i = 0; i < len; i++) {
3275         StyleBase* item = sheet->item(i);
3276         if (item->isStyleRule())
3277             addStyleRule(static_cast<CSSStyleRule*>(item));
3278         else if (item->isImportRule()) {
3279             CSSImportRule* import = static_cast<CSSImportRule*>(item);
3280             if (!import->media() || medium.eval(import->media(), styleSelector))
3281                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
3282         }
3283         else if (item->isMediaRule()) {
3284             CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
3285             CSSRuleList* rules = r->cssRules();
3286
3287             if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
3288                 // Traverse child elements of the @media rule.
3289                 for (unsigned j = 0; j < rules->length(); j++) {
3290                     CSSRule *childItem = rules->item(j);
3291                     if (childItem->isStyleRule()) {
3292                         // It is a StyleRule, so append it to our list
3293                         addStyleRule(static_cast<CSSStyleRule*>(childItem));
3294                     } else if (childItem->isFontFaceRule() && styleSelector) {
3295                         // Add this font face to our set.
3296                         const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
3297               &nb