1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 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 * Copyright (C) 2013 Google Inc. All rights reserved.
12 *
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
17 *
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 * Library General Public License for more details.
22 *
23 * You should have received a copy of the GNU Library General Public License
24 * along with this library; see the file COPYING.LIB.  If not, write to
25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
27 */
28
29#include "config.h"
30#include "DocumentRuleSets.h"
31
32#include "CSSDefaultStyleSheets.h"
33#include "CSSStyleSheet.h"
34#include "DocumentStyleSheetCollection.h"
35#include "MediaQueryEvaluator.h"
36#include "StyleResolver.h"
37#include "StyleSheetContents.h"
38
39namespace WebCore {
40
41DocumentRuleSets::DocumentRuleSets()
42{
43}
44
45DocumentRuleSets::~DocumentRuleSets()
46{
47}
48
49void DocumentRuleSets::initUserStyle(DocumentStyleSheetCollection* styleSheetCollection, const MediaQueryEvaluator& medium, StyleResolver& resolver)
50{
51    OwnPtr<RuleSet> tempUserStyle = RuleSet::create();
52    if (CSSStyleSheet* pageUserSheet = styleSheetCollection->pageUserSheet())
53        tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), medium, &resolver);
54    collectRulesFromUserStyleSheets(styleSheetCollection->injectedUserStyleSheets(), *tempUserStyle, medium, resolver);
55    collectRulesFromUserStyleSheets(styleSheetCollection->documentUserStyleSheets(), *tempUserStyle, medium, resolver);
56    if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
57        m_userStyle = tempUserStyle.release();
58}
59
60void DocumentRuleSets::collectRulesFromUserStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& userSheets, RuleSet& userStyle, const MediaQueryEvaluator& medium, StyleResolver& resolver)
61{
62    for (unsigned i = 0; i < userSheets.size(); ++i) {
63        ASSERT(userSheets[i]->contents()->isUserStyleSheet());
64        userStyle.addRulesFromSheet(userSheets[i]->contents(), medium, &resolver);
65    }
66}
67
68static PassOwnPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules)
69{
70    size_t size = rules.size();
71    if (!size)
72        return nullptr;
73    OwnPtr<RuleSet> ruleSet = RuleSet::create();
74    for (size_t i = 0; i < size; ++i)
75        ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState);
76    ruleSet->shrinkToFit();
77    return ruleSet.release();
78}
79
80void DocumentRuleSets::resetAuthorStyle()
81{
82    m_authorStyle = RuleSet::create();
83    m_authorStyle->disableAutoShrinkToFit();
84}
85
86void DocumentRuleSets::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers, bool isViewSource, StyleResolver* resolver)
87{
88    // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
89    // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
90    unsigned size = styleSheets.size();
91    for (unsigned i = firstNew; i < size; ++i) {
92        CSSStyleSheet* cssSheet = styleSheets[i].get();
93        ASSERT(!cssSheet->disabled());
94        if (cssSheet->mediaQueries() && !medium->eval(cssSheet->mediaQueries(), resolver))
95            continue;
96        StyleSheetContents* sheet = cssSheet->contents();
97#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
98        if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
99            // FIXME: Remove a dependency to calling a StyleResolver's member function.
100            // If we can avoid calling resolver->ensureScopeResolver() here, we don't have to include "StyleResolver.h".
101            // https://bugs.webkit.org/show_bug.cgi?id=108890
102            resolver->ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *medium, resolver, scope);
103            continue;
104        }
105#endif
106        m_authorStyle->addRulesFromSheet(sheet, *medium, resolver);
107        inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet);
108    }
109    m_authorStyle->shrinkToFit();
110    collectFeatures(isViewSource, resolver->scopeResolver());
111}
112
113void DocumentRuleSets::collectFeatures(bool isViewSource, StyleScopeResolver* scopeResolver)
114{
115    m_features.clear();
116    // Collect all ids and rules using sibling selectors (:first-child and similar)
117    // in the current set of stylesheets. Style sharing code uses this information to reject
118    // sharing candidates.
119    if (CSSDefaultStyleSheets::defaultStyle)
120        m_features.add(CSSDefaultStyleSheets::defaultStyle->features());
121    if (m_authorStyle)
122        m_features.add(m_authorStyle->features());
123    if (isViewSource)
124        m_features.add(CSSDefaultStyleSheets::viewSourceStyle()->features());
125
126    if (scopeResolver)
127        scopeResolver->collectFeaturesTo(m_features);
128    if (m_userStyle)
129        m_features.add(m_userStyle->features());
130
131    m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
132    m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
133}
134
135} // namespace WebCore
136