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/inspector/InspectorBaseAgent.h"
31#include "core/inspector/InspectorDOMAgent.h"
32#include "core/inspector/InspectorStyleSheet.h"
33#include "core/frame/ContentSecurityPolicy.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 WebCore {
44
45class ChangeRegionOversetTask;
46struct CSSParserString;
47class CSSRule;
48class CSSRuleList;
49class CSSStyleRule;
50class CSSStyleSheet;
51class Document;
52class Element;
53class InspectorFrontend;
54class InspectorResourceAgent;
55class InstrumentingAgents;
56class MediaList;
57class Node;
58class NodeList;
59class PlatformFontUsage;
60class RenderText;
61class StyleResolver;
62class UpdateRegionLayoutTask;
63
64typedef HashMap<CSSStyleSheet*, RefPtr<InspectorStyleSheet> > CSSStyleSheetToInspectorStyleSheet;
65typedef Vector<RefPtr<StyleSheet> > StyleSheetVector;
66
67class InspectorCSSAgent
68    : public InspectorBaseAgent<InspectorCSSAgent>
69    , public InspectorDOMAgent::DOMListener
70    , public InspectorBackendDispatcher::CSSCommandHandler
71    , public InspectorStyleSheet::Listener {
72    WTF_MAKE_NONCOPYABLE(InspectorCSSAgent);
73public:
74    enum MediaListSource {
75        MediaListSourceLinkedSheet,
76        MediaListSourceInlineSheet,
77        MediaListSourceMediaRule,
78        MediaListSourceImportRule
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 PassOwnPtr<InspectorCSSAgent> create(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorDOMAgent* domAgent, InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent)
101    {
102        return adoptPtr(new InspectorCSSAgent(instrumentingAgents, state, domAgent, pageAgent, resourceAgent));
103    }
104    ~InspectorCSSAgent();
105
106    bool forcePseudoState(Element*, CSSSelector::PseudoType);
107    virtual void setFrontend(InspectorFrontend*);
108    virtual void clearFrontend();
109    virtual void discardAgent();
110    virtual void restore();
111    virtual void enable(ErrorString*, PassRefPtr<EnableCallback>);
112    virtual void disable(ErrorString*);
113    void reset();
114    void didCommitLoad(Frame*, DocumentLoader*);
115    void mediaQueryResultChanged();
116    void didCreateNamedFlow(Document*, NamedFlow*);
117    void willRemoveNamedFlow(Document*, NamedFlow*);
118    void willMutateRules();
119    void didMutateRules(CSSStyleSheet*);
120    void willMutateStyle();
121    void didMutateStyle(CSSStyleDeclaration*, bool);
122
123private:
124    void regionLayoutUpdated(NamedFlow*, int documentNodeId);
125    void regionOversetChanged(NamedFlow*, int documentNodeId);
126
127public:
128    void didUpdateRegionLayout(Document*, NamedFlow*);
129    void didChangeRegionOverset(Document*, NamedFlow*);
130
131    void activeStyleSheetsUpdated(Document*, const StyleSheetVector& newSheets);
132    void frameDetachedFromParent(Frame*);
133
134    virtual void getComputedStyleForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >&);
135    virtual void getPlatformFontsForNode(ErrorString*, int nodeId, String* cssFamilyName, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PlatformFontUsage> >&);
136    virtual void getInlineStylesForNode(ErrorString*, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributes);
137    virtual void getMatchedStylesForNode(ErrorString*, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> >& pseudoIdMatches, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries);
138    virtual void getAllStyleSheets(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> >& styleSheetInfos);
139    virtual void getStyleSheet(ErrorString*, const String& styleSheetId, RefPtr<TypeBuilder::CSS::CSSStyleSheetBody>& result);
140    virtual void getStyleSheetText(ErrorString*, const String& styleSheetId, String* result);
141    virtual void setStyleSheetText(ErrorString*, const String& styleSheetId, const String& text);
142    virtual void setStyleText(ErrorString*, const RefPtr<JSONObject>& styleId, const String& text, RefPtr<TypeBuilder::CSS::CSSStyle>& result);
143    virtual void setPropertyText(ErrorString*, const RefPtr<JSONObject>& styleId, int propertyIndex, const String& text, bool overwrite, RefPtr<TypeBuilder::CSS::CSSStyle>& result);
144    virtual void toggleProperty(ErrorString*, const RefPtr<JSONObject>& styleId, int propertyIndex, bool disable, RefPtr<TypeBuilder::CSS::CSSStyle>& result);
145    virtual void setRuleSelector(ErrorString*, const RefPtr<JSONObject>& ruleId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result);
146    virtual void addRule(ErrorString*, int contextNodeId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result);
147    virtual void getSupportedCSSProperties(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> >& result);
148    virtual void forcePseudoState(ErrorString*, int nodeId, const RefPtr<JSONArray>& forcedPseudoClasses);
149    virtual void getNamedFlowCollection(ErrorString*, int documentNodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> >& result);
150
151    PassRefPtr<TypeBuilder::CSS::CSSMedia> buildMediaObject(const MediaList*, MediaListSource, const String&, CSSStyleSheet*);
152    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSMedia> > buildMediaListChain(CSSRule*);
153
154private:
155    class StyleSheetAction;
156    class SetStyleSheetTextAction;
157    class SetStyleTextAction;
158    class SetPropertyTextAction;
159    class TogglePropertyAction;
160    class SetRuleSelectorAction;
161    class AddRuleAction;
162    class EnableResourceClient;
163
164    InspectorCSSAgent(InstrumentingAgents*, InspectorCompositeState*, InspectorDOMAgent*, InspectorPageAgent*, InspectorResourceAgent*);
165
166    typedef HashMap<String, RefPtr<InspectorStyleSheet> > IdToInspectorStyleSheet;
167    typedef HashMap<Node*, RefPtr<InspectorStyleSheetForInlineStyle> > NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline styles
168    typedef HashMap<RefPtr<Document>, RefPtr<InspectorStyleSheet> > DocumentToViaInspectorStyleSheet; // "via inspector" stylesheets
169    typedef HashMap<int, unsigned> NodeIdToForcedPseudoState;
170
171    void wasEnabled(PassRefPtr<EnableCallback>);
172    void resetNonPersistentData();
173    InspectorStyleSheetForInlineStyle* asInspectorStyleSheet(Element* element);
174    Element* elementForId(ErrorString*, int nodeId);
175    int documentNodeWithRequestedFlowsId(Document*);
176    void collectAllStyleSheets(Vector<InspectorStyleSheet*>&);
177    void collectStyleSheets(CSSStyleSheet*, Vector<InspectorStyleSheet*>&);
178
179    void collectPlatformFontsForRenderer(RenderText*, HashCountedSet<String>*);
180
181    InspectorStyleSheet* bindStyleSheet(CSSStyleSheet*);
182    String unbindStyleSheet(InspectorStyleSheet*);
183    InspectorStyleSheet* viaInspectorStyleSheet(Document*, bool createIfAbsent);
184    InspectorStyleSheet* assertStyleSheetForId(ErrorString*, const String&);
185    TypeBuilder::CSS::StyleSheetOrigin::Enum detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument);
186    bool styleSheetEditInProgress() const { return m_styleSheetsPendingMutation || m_styleDeclarationPendingMutation || m_isSettingStyleSheetText; }
187
188    PassRefPtr<TypeBuilder::CSS::CSSRule> buildObjectForRule(CSSStyleRule*, StyleResolver&);
189    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > buildArrayForRuleList(CSSRuleList*, StyleResolver&);
190    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > buildArrayForMatchedRuleList(CSSRuleList*, StyleResolver&, Element*);
191    PassRefPtr<TypeBuilder::CSS::CSSStyle> buildObjectForAttributesStyle(Element*);
192    PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > buildArrayForRegions(ErrorString*, PassRefPtr<NodeList>, int documentNodeId);
193    PassRefPtr<TypeBuilder::CSS::NamedFlow> buildObjectForNamedFlow(ErrorString*, NamedFlow*, int documentNodeId);
194
195    // InspectorDOMAgent::DOMListener implementation
196    virtual void didRemoveDocument(Document*);
197    virtual void didRemoveDOMNode(Node*);
198    virtual void didModifyDOMAttr(Element*);
199
200    // InspectorStyleSheet::Listener implementation
201    virtual void styleSheetChanged(InspectorStyleSheet*) OVERRIDE;
202    virtual void willReparseStyleSheet() OVERRIDE;
203    virtual void didReparseStyleSheet() OVERRIDE;
204
205    void resetPseudoStates();
206
207    InspectorFrontend::CSS* m_frontend;
208    InspectorDOMAgent* m_domAgent;
209    InspectorPageAgent* m_pageAgent;
210    InspectorResourceAgent* m_resourceAgent;
211
212    IdToInspectorStyleSheet m_idToInspectorStyleSheet;
213    CSSStyleSheetToInspectorStyleSheet m_cssStyleSheetToInspectorStyleSheet;
214    NodeToInspectorStyleSheet m_nodeToInspectorStyleSheet;
215    DocumentToViaInspectorStyleSheet m_documentToInspectorStyleSheet;
216    NodeIdToForcedPseudoState m_nodeIdToForcedPseudoState;
217    HashSet<int> m_namedFlowCollectionsRequested;
218    OwnPtr<UpdateRegionLayoutTask> m_updateRegionLayoutTask;
219    OwnPtr<ChangeRegionOversetTask> m_changeRegionOversetTask;
220
221    int m_lastStyleSheetId;
222    int m_styleSheetsPendingMutation;
223    bool m_styleDeclarationPendingMutation;
224    bool m_creatingViaInspectorStyleSheet;
225    bool m_isSettingStyleSheetText;
226
227    friend class ChangeRegionOversetTask;
228    friend class EnableResourceClient;
229    friend class StyleSheetBinder;
230    friend class UpdateRegionLayoutTask;
231};
232
233
234} // namespace WebCore
235
236#endif // !defined(InspectorCSSAgent_h)
237