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    auto tempUserStyle = std::make_unique<RuleSet>();
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->ruleCount() > 0 || tempUserStyle->pageRules().size() > 0)
57        m_userStyle = WTF::move(tempUserStyle);
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 std::unique_ptr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules)
69{
70    size_t size = rules.size();
71    if (!size)
72        return nullptr;
73    auto ruleSet = std::make_unique<RuleSet>();
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;
78}
79
80void DocumentRuleSets::resetAuthorStyle()
81{
82    m_authorStyle = std::make_unique<RuleSet>();
83    m_authorStyle->disableAutoShrinkToFit();
84}
85
86void DocumentRuleSets::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet>>& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers, 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        m_authorStyle->addRulesFromSheet(&cssSheet->contents(), *medium, resolver);
97        inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet);
98    }
99    m_authorStyle->shrinkToFit();
100    collectFeatures();
101}
102
103void DocumentRuleSets::collectFeatures()
104{
105    m_features.clear();
106    // Collect all ids and rules using sibling selectors (:first-child and similar)
107    // in the current set of stylesheets. Style sharing code uses this information to reject
108    // sharing candidates.
109    if (CSSDefaultStyleSheets::defaultStyle)
110        m_features.add(CSSDefaultStyleSheets::defaultStyle->features());
111    if (m_authorStyle)
112        m_features.add(m_authorStyle->features());
113    if (m_userStyle)
114        m_features.add(m_userStyle->features());
115
116    m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
117    m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
118}
119
120} // namespace WebCore
121