1/*
2 * Copyright (C) 2010, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1.  Redistributions of source code must retain the above copyright
8 *     notice, this list of conditions and the following disclaimer.
9 * 2.  Redistributions in binary form must reproduce the above copyright
10 *     notice, this list of conditions and the following disclaimer in the
11 *     documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#ifndef InspectorCSSAgent_h
26#define InspectorCSSAgent_h
27
28#include "core/css/CSSSelector.h"
29#include "core/dom/SecurityContext.h"
30#include "core/frame/csp/ContentSecurityPolicy.h"
31#include "core/inspector/InspectorBaseAgent.h"
32#include "core/inspector/InspectorDOMAgent.h"
33#include "core/inspector/InspectorStyleSheet.h"
34#include "platform/JSONValues.h"
35#include "wtf/HashCountedSet.h"
36#include "wtf/HashMap.h"
37#include "wtf/HashSet.h"
38#include "wtf/PassRefPtr.h"
39#include "wtf/RefPtr.h"
40#include "wtf/Vector.h"
41#include "wtf/text/WTFString.h"
42
43namespace blink {
44
45struct CSSParserString;
46class CSSRule;
47class CSSRuleList;
48class CSSStyleRule;
49class CSSStyleSheet;
50class Document;
51class Element;
52class InspectorFrontend;
53class InspectorResourceAgent;
54class InstrumentingAgents;
55class MediaList;
56class Node;
57class PlatformFontUsage;
58class RenderText;
59class StyleResolver;
60
61class InspectorCSSAgent FINAL
62    : public InspectorBaseAgent<InspectorCSSAgent>
63    , public InspectorDOMAgent::DOMListener
64    , public InspectorBackendDispatcher::CSSCommandHandler
65    , public InspectorStyleSheetBase::Listener {
66    WTF_MAKE_NONCOPYABLE(InspectorCSSAgent);
67    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(InspectorCSSAgent);
68public:
69    enum MediaListSource {
70        MediaListSourceLinkedSheet,
71        MediaListSourceInlineSheet,
72        MediaListSourceMediaRule,
73        MediaListSourceImportRule
74    };
75
76    enum StyleSheetsUpdateType {
77        InitialFrontendLoad = 0,
78        ExistingFrontendRefresh,
79    };
80
81    class InlineStyleOverrideScope {
82    public:
83        InlineStyleOverrideScope(SecurityContext* context)
84            : m_contentSecurityPolicy(context->contentSecurityPolicy())
85        {
86            m_contentSecurityPolicy->setOverrideAllowInlineStyle(true);
87        }
88
89        ~InlineStyleOverrideScope()
90        {
91            m_contentSecurityPolicy->setOverrideAllowInlineStyle(false);
92        }
93
94    private:
95        ContentSecurityPolicy* m_contentSecurityPolicy;
96    };
97
98    static CSSStyleRule* asCSSStyleRule(CSSRule*);
99
100    static PassOwnPtrWillBeRawPtr<InspectorCSSAgent> create(InspectorDOMAgent* domAgent, InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent)
101    {
102        return adoptPtrWillBeNoop(new InspectorCSSAgent(domAgent, pageAgent, resourceAgent));
103    }
104
105    static void collectAllDocumentStyleSheets(Document*, WillBeHeapVector<RawPtrWillBeMember<CSSStyleSheet> >&);
106
107    virtual ~InspectorCSSAgent();
108    virtual void trace(Visitor*) OVERRIDE;
109
110    bool forcePseudoState(Element*, CSSSelector::PseudoType);
111    virtual void setFrontend(InspectorFrontend*) OVERRIDE;
112    virtual void clearFrontend() OVERRIDE;
113    virtual void discardAgent() OVERRIDE;
114    virtual void didCommitLoadForMainFrame() OVERRIDE;
115    virtual void restore() OVERRIDE;
116    virtual void flushPendingFrontendMessages() OVERRIDE;
117    virtual void enable(ErrorString*, PassRefPtrWillBeRawPtr<EnableCallback>) OVERRIDE;
118    virtual void disable(ErrorString*) OVERRIDE;
119    void reset();
120    void mediaQueryResultChanged();
121    void willMutateRules();
122    void didMutateRules(CSSStyleSheet*);
123    void willMutateStyle();
124    void didMutateStyle(CSSStyleDeclaration*, bool);
125
126    void activeStyleSheetsUpdated(Document*);
127    void documentDetached(Document*);
128
129    virtual void getComputedStyleForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >&) OVERRIDE;
130    virtual void getPlatformFontsForNode(ErrorString*, int nodeId, String* cssFamilyName, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PlatformFontUsage> >&) OVERRIDE;
131    virtual void getInlineStylesForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributes) OVERRIDE;
132    virtual void getMatchedStylesForNode(ErrorString*, int nodeId, const bool* excludePseudo, const bool* excludeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> >&, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries) OVERRIDE;
133    virtual void getStyleSheetText(ErrorString*, const String& styleSheetId, String* result) OVERRIDE;
134    virtual void setStyleSheetText(ErrorString*, const String& styleSheetId, const String& text) OVERRIDE;
135
136    virtual void setPropertyText(ErrorString*, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& text, RefPtr<TypeBuilder::CSS::CSSStyle>& result) OVERRIDE;
137    virtual void setRuleSelector(ErrorString*, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result) OVERRIDE;
138    virtual void createStyleSheet(ErrorString*, const String& frameId, TypeBuilder::CSS::StyleSheetId* outStyleSheetId) OVERRIDE;
139    virtual void addRule(ErrorString*, const String& styleSheetId, const String& ruleText, const RefPtr<JSONObject>& location, RefPtr<TypeBuilder::CSS::CSSRule>& result) OVERRIDE;
140    virtual void forcePseudoState(ErrorString*, int nodeId, const RefPtr<JSONArray>& forcedPseudoClasses) OVERRIDE;
141    virtual void getMediaQueries(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSMedia> >& medias) OVERRIDE;
142
143    bool collectMediaQueriesFromRule(CSSRule*, TypeBuilder::Array<TypeBuilder::CSS::CSSMedia>* mediaArray);
144    bool collectMediaQueriesFromStyleSheet(CSSStyleSheet*, TypeBuilder::Array<TypeBuilder::CSS::CSSMedia>* mediaArray);
145    PassRefPtr<TypeBuilder::CSS::CSSMedia> buildMediaObject(const MediaList*, MediaListSource, const String&, CSSStyleSheet*);
146    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSMedia> > buildMediaListChain(CSSRule*);
147
148private:
149    class StyleSheetAction;
150    class SetStyleSheetTextAction;
151    class SetPropertyTextAction;
152    class SetRuleSelectorAction;
153    class AddRuleAction;
154    class InspectorResourceContentLoaderCallback;
155
156    static void collectStyleSheets(CSSStyleSheet*, WillBeHeapVector<RawPtrWillBeMember<CSSStyleSheet> >&);
157
158    InspectorCSSAgent(InspectorDOMAgent*, InspectorPageAgent*, InspectorResourceAgent*);
159
160    typedef WillBeHeapHashMap<String, RefPtrWillBeMember<InspectorStyleSheet> > IdToInspectorStyleSheet;
161    typedef WillBeHeapHashMap<String, RefPtrWillBeMember<InspectorStyleSheetForInlineStyle> > IdToInspectorStyleSheetForInlineStyle;
162    typedef WillBeHeapHashMap<RawPtrWillBeMember<Node>, RefPtrWillBeMember<InspectorStyleSheetForInlineStyle> > NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline styles
163    typedef HashMap<int, unsigned> NodeIdToForcedPseudoState;
164
165    void wasEnabled();
166    void resetNonPersistentData();
167    InspectorStyleSheetForInlineStyle* asInspectorStyleSheet(Element* element);
168    Element* elementForId(ErrorString*, int nodeId);
169
170    void updateActiveStyleSheets(Document*, StyleSheetsUpdateType);
171    void setActiveStyleSheets(Document*, const WillBeHeapVector<RawPtrWillBeMember<CSSStyleSheet> >&, StyleSheetsUpdateType);
172
173    void collectPlatformFontsForRenderer(RenderText*, HashCountedSet<String>*);
174
175    InspectorStyleSheet* bindStyleSheet(CSSStyleSheet*);
176    String unbindStyleSheet(InspectorStyleSheet*);
177    InspectorStyleSheet* viaInspectorStyleSheet(Document*, bool createIfAbsent);
178    InspectorStyleSheet* assertInspectorStyleSheetForId(ErrorString*, const String&);
179    InspectorStyleSheetBase* assertStyleSheetForId(ErrorString*, const String&);
180    TypeBuilder::CSS::StyleSheetOrigin::Enum detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument);
181    bool styleSheetEditInProgress() const { return m_styleSheetsPendingMutation || m_styleDeclarationPendingMutation || m_isSettingStyleSheetText; }
182
183    PassRefPtr<TypeBuilder::CSS::CSSRule> buildObjectForRule(CSSStyleRule*);
184    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > buildArrayForMatchedRuleList(CSSRuleList*, Element*);
185    PassRefPtr<TypeBuilder::CSS::CSSStyle> buildObjectForAttributesStyle(Element*);
186
187    // InspectorDOMAgent::DOMListener implementation
188    virtual void didRemoveDocument(Document*) OVERRIDE;
189    virtual void didRemoveDOMNode(Node*) OVERRIDE;
190    virtual void didModifyDOMAttr(Element*) OVERRIDE;
191
192    // InspectorStyleSheet::Listener implementation
193    virtual void styleSheetChanged(InspectorStyleSheetBase*) OVERRIDE;
194    virtual void willReparseStyleSheet() OVERRIDE;
195    virtual void didReparseStyleSheet() OVERRIDE;
196
197    void resetPseudoStates();
198
199    InspectorFrontend::CSS* m_frontend;
200    RawPtrWillBeMember<InspectorDOMAgent> m_domAgent;
201    RawPtrWillBeMember<InspectorPageAgent> m_pageAgent;
202    RawPtrWillBeMember<InspectorResourceAgent> m_resourceAgent;
203
204    IdToInspectorStyleSheet m_idToInspectorStyleSheet;
205    IdToInspectorStyleSheetForInlineStyle m_idToInspectorStyleSheetForInlineStyle;
206    WillBeHeapHashMap<RawPtrWillBeMember<CSSStyleSheet>, RefPtrWillBeMember<InspectorStyleSheet> > m_cssStyleSheetToInspectorStyleSheet;
207    typedef WillBeHeapHashMap<RawPtrWillBeMember<Document>, OwnPtrWillBeMember<WillBeHeapHashSet<RawPtrWillBeMember<CSSStyleSheet> > > > DocumentStyleSheets;
208    DocumentStyleSheets m_documentToCSSStyleSheets;
209    WillBeHeapHashSet<RawPtrWillBeMember<Document> > m_invalidatedDocuments;
210
211    NodeToInspectorStyleSheet m_nodeToInspectorStyleSheet;
212    WillBeHeapHashMap<RefPtrWillBeMember<Document>, RefPtrWillBeMember<InspectorStyleSheet> > m_documentToViaInspectorStyleSheet; // "via inspector" stylesheets
213    NodeIdToForcedPseudoState m_nodeIdToForcedPseudoState;
214
215    RefPtrWillBeMember<CSSStyleSheet> m_inspectorUserAgentStyleSheet;
216
217    int m_lastStyleSheetId;
218    int m_styleSheetsPendingMutation;
219    bool m_styleDeclarationPendingMutation;
220    bool m_creatingViaInspectorStyleSheet;
221    bool m_isSettingStyleSheetText;
222
223    friend class InspectorResourceContentLoaderCallback;
224    friend class StyleSheetBinder;
225};
226
227
228} // namespace blink
229
230#endif // !defined(InspectorCSSAgent_h)
231