1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 *           (C) 2001 Dirk Mueller (mueller@kde.org)
5 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
9 * Copyright (C) 2011 Google Inc. All rights reserved.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB.  If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
25 *
26 */
27
28#ifndef StyleEngine_h
29#define StyleEngine_h
30
31#include "core/css/CSSFontSelectorClient.h"
32#include "core/css/resolver/StyleResolver.h"
33#include "core/dom/Document.h"
34#include "core/dom/DocumentOrderedList.h"
35#include "core/dom/DocumentStyleSheetCollection.h"
36#include "platform/heap/Handle.h"
37#include "wtf/FastAllocBase.h"
38#include "wtf/ListHashSet.h"
39#include "wtf/RefPtr.h"
40#include "wtf/TemporaryChange.h"
41#include "wtf/Vector.h"
42#include "wtf/text/WTFString.h"
43
44namespace blink {
45
46class CSSFontSelector;
47class CSSStyleSheet;
48class Node;
49class RuleFeatureSet;
50class ShadowTreeStyleSheetCollection;
51class StyleRuleFontFace;
52class StyleSheet;
53class StyleSheetContents;
54
55class StyleEngine FINAL : public CSSFontSelectorClient  {
56    WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
57public:
58
59    class IgnoringPendingStylesheet : public TemporaryChange<bool> {
60    public:
61        IgnoringPendingStylesheet(StyleEngine* engine)
62            : TemporaryChange<bool>(engine->m_ignorePendingStylesheets, true)
63        {
64        }
65    };
66
67    friend class IgnoringPendingStylesheet;
68
69    static PassOwnPtrWillBeRawPtr<StyleEngine> create(Document& document) { return adoptPtrWillBeNoop(new StyleEngine(document)); }
70
71    ~StyleEngine();
72
73#if !ENABLE(OILPAN)
74    void detachFromDocument();
75#endif
76
77    const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& styleSheetsForStyleSheetList(TreeScope&);
78    const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& activeAuthorStyleSheets() const;
79
80    const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& documentAuthorStyleSheets() const { return m_authorStyleSheets; }
81    const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& injectedAuthorStyleSheets() const;
82
83    const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > activeStyleSheetsForInspector() const;
84
85    void modifiedStyleSheet(StyleSheet*);
86    void addStyleSheetCandidateNode(Node*, bool createdByParser);
87    void removeStyleSheetCandidateNode(Node*);
88    void removeStyleSheetCandidateNode(Node*, ContainerNode* scopingNode, TreeScope&);
89    void modifiedStyleSheetCandidateNode(Node*);
90    void enableExitTransitionStylesheets();
91    void addXSLStyleSheet(ProcessingInstruction*, bool createdByParser);
92    void removeXSLStyleSheet(ProcessingInstruction*);
93
94    void invalidateInjectedStyleSheetCache();
95    void updateInjectedStyleSheetCache() const;
96
97    void compatibilityModeChanged();
98
99    void addAuthorSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> authorSheet);
100
101    void clearMediaQueryRuleSetStyleSheets();
102    void updateStyleSheetsInImport(DocumentStyleSheetCollector& parentCollector);
103    void updateActiveStyleSheets(StyleResolverUpdateMode);
104
105    String preferredStylesheetSetName() const { return m_preferredStylesheetSetName; }
106    String selectedStylesheetSetName() const { return m_selectedStylesheetSetName; }
107    void setPreferredStylesheetSetName(const String& name) { m_preferredStylesheetSetName = name; }
108    void setSelectedStylesheetSetName(const String& name) { m_selectedStylesheetSetName = name; }
109
110    void selectStylesheetSetName(const String& name)
111    {
112        setPreferredStylesheetSetName(name);
113        setSelectedStylesheetSetName(name);
114    }
115
116    void addPendingSheet();
117    void removePendingSheet(Node* styleSheetCandidateNode);
118
119    bool hasPendingSheets() const { return m_pendingStylesheets > 0; }
120    bool haveStylesheetsLoaded() const { return !hasPendingSheets() || m_ignorePendingStylesheets; }
121    bool ignoringPendingStylesheets() const { return m_ignorePendingStylesheets; }
122
123    unsigned maxDirectAdjacentSelectors() const { return m_maxDirectAdjacentSelectors; }
124    bool usesSiblingRules() const { return m_usesSiblingRules || m_usesSiblingRulesOverride; }
125    void setUsesSiblingRulesOverride(bool b) { m_usesSiblingRulesOverride = b; }
126    bool usesFirstLineRules() const { return m_usesFirstLineRules; }
127    bool usesFirstLetterRules() const { return m_usesFirstLetterRules; }
128    void setUsesFirstLetterRules(bool b) { m_usesFirstLetterRules = b; }
129    bool usesRemUnits() const { return m_usesRemUnits; }
130    void setUsesRemUnit(bool b) { m_usesRemUnits = b; }
131
132    void combineCSSFeatureFlags(const RuleFeatureSet&);
133    void resetCSSFeatureFlags(const RuleFeatureSet&);
134
135    void didRemoveShadowRoot(ShadowRoot*);
136    void appendActiveAuthorStyleSheets();
137
138    StyleResolver* resolver() const
139    {
140        return m_resolver.get();
141    }
142
143    StyleResolver& ensureResolver()
144    {
145        if (!m_resolver) {
146            createResolver();
147        } else if (m_resolver->hasPendingAuthorStyleSheets()) {
148            m_resolver->appendPendingAuthorStyleSheets();
149        }
150        return *m_resolver.get();
151    }
152
153    bool hasResolver() const { return m_resolver.get(); }
154    void clearResolver();
155    void clearMasterResolver();
156
157    CSSFontSelector* fontSelector() { return m_fontSelector.get(); }
158    void removeFontFaceRules(const WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >&);
159    void clearFontCache();
160    // updateGenericFontFamilySettings is used from WebSettingsImpl.
161    void updateGenericFontFamilySettings();
162
163    void didDetach();
164    bool shouldClearResolver() const;
165    void resolverChanged(StyleResolverUpdateMode);
166    unsigned resolverAccessCount() const;
167
168    void markDocumentDirty();
169
170    PassRefPtrWillBeRawPtr<CSSStyleSheet> createSheet(Element*, const String& text, TextPosition startPosition, bool createdByParser);
171    void removeSheet(StyleSheetContents*);
172
173    void addScopedStyleResolver(const ScopedStyleResolver* resolver) { m_scopedStyleResolvers.add(resolver); }
174    void removeScopedStyleResolver(const ScopedStyleResolver* resolver) { m_scopedStyleResolvers.remove(resolver); }
175    bool hasOnlyScopedResolverForDocument() const { return m_scopedStyleResolvers.size() == 1; }
176    void collectScopedStyleFeaturesTo(RuleFeatureSet&) const;
177
178    virtual void trace(Visitor*) OVERRIDE;
179
180private:
181    // CSSFontSelectorClient implementation.
182    virtual void fontsNeedUpdate(CSSFontSelector*) OVERRIDE;
183
184private:
185    StyleEngine(Document&);
186
187    TreeScopeStyleSheetCollection* ensureStyleSheetCollectionFor(TreeScope&);
188    TreeScopeStyleSheetCollection* styleSheetCollectionFor(TreeScope&);
189    bool shouldUpdateDocumentStyleSheetCollection(StyleResolverUpdateMode) const;
190    bool shouldUpdateShadowTreeStyleSheetCollection(StyleResolverUpdateMode) const;
191    bool shouldApplyXSLTransform() const;
192
193    void markTreeScopeDirty(TreeScope&);
194
195    bool isMaster() const { return m_isMaster; }
196    Document* master();
197    Document& document() const { return *m_document; }
198
199    typedef ListHashSet<TreeScope*, 16> TreeScopeSet;
200    static void insertTreeScopeInDocumentOrder(TreeScopeSet&, TreeScope*);
201    void clearMediaQueryRuleSetOnTreeScopeStyleSheets(TreeScopeSet treeScopes);
202
203    void createResolver();
204
205    static PassRefPtrWillBeRawPtr<CSSStyleSheet> parseSheet(Element*, const String& text, TextPosition startPosition, bool createdByParser);
206
207    const DocumentStyleSheetCollection* documentStyleSheetCollection() const
208    {
209        return m_documentStyleSheetCollection.get();
210    }
211
212    DocumentStyleSheetCollection* documentStyleSheetCollection()
213    {
214        return m_documentStyleSheetCollection.get();
215    }
216
217    RawPtrWillBeMember<Document> m_document;
218    bool m_isMaster;
219
220    // Track the number of currently loading top-level stylesheets needed for rendering.
221    // Sheets loaded using the @import directive are not included in this count.
222    // We use this count of pending sheets to detect when we can begin attaching
223    // elements and when it is safe to execute scripts.
224    int m_pendingStylesheets;
225
226    mutable WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > m_injectedAuthorStyleSheets;
227    mutable bool m_injectedStyleSheetCacheValid;
228
229    WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > m_authorStyleSheets;
230
231    OwnPtrWillBeMember<DocumentStyleSheetCollection> m_documentStyleSheetCollection;
232
233    typedef WillBeHeapHashMap<RawPtrWillBeWeakMember<TreeScope>, OwnPtrWillBeMember<ShadowTreeStyleSheetCollection> > StyleSheetCollectionMap;
234    StyleSheetCollectionMap m_styleSheetCollectionMap;
235    typedef WillBeHeapHashSet<RawPtrWillBeMember<const ScopedStyleResolver> > ScopedStyleResolverSet;
236    ScopedStyleResolverSet m_scopedStyleResolvers;
237
238    bool m_documentScopeDirty;
239    TreeScopeSet m_dirtyTreeScopes;
240    TreeScopeSet m_activeTreeScopes;
241
242    String m_preferredStylesheetSetName;
243    String m_selectedStylesheetSetName;
244
245    bool m_usesSiblingRules;
246    bool m_usesSiblingRulesOverride;
247    bool m_usesFirstLineRules;
248    bool m_usesFirstLetterRules;
249    bool m_usesRemUnits;
250    unsigned m_maxDirectAdjacentSelectors;
251
252    bool m_ignorePendingStylesheets;
253    bool m_didCalculateResolver;
254    OwnPtrWillBeMember<StyleResolver> m_resolver;
255
256    RefPtrWillBeMember<CSSFontSelector> m_fontSelector;
257
258    WillBeHeapHashMap<AtomicString, RawPtrWillBeMember<StyleSheetContents> > m_textToSheetCache;
259    WillBeHeapHashMap<RawPtrWillBeMember<StyleSheetContents>, AtomicString> m_sheetToTextCache;
260
261    RefPtrWillBeMember<ProcessingInstruction> m_xslStyleSheet;
262};
263
264}
265
266#endif
267