2b316c38bb0473910afde8e10beb88b8de3dd56a
[WebKit-https.git] / Source / WebCore / inspector / InspectorStyleSheet.h
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 InspectorStyleSheet_h
26 #define InspectorStyleSheet_h
27
28 #include "CSSPropertySourceData.h"
29 #include "CSSStyleDeclaration.h"
30 #include "ExceptionCode.h"
31 #include "InspectorStyleTextEditor.h"
32 #include "InspectorWebTypeBuilders.h"
33 #include <inspector/InspectorValues.h>
34 #include <wtf/HashMap.h>
35 #include <wtf/HashSet.h>
36 #include <wtf/PassRefPtr.h>
37 #include <wtf/RefPtr.h>
38 #include <wtf/Vector.h>
39 #include <wtf/text/WTFString.h>
40
41 class ParsedStyleSheet;
42
43 namespace WebCore {
44
45 class CSSRuleList;
46 class CSSStyleDeclaration;
47 class CSSStyleRule;
48 class CSSStyleSheet;
49 class Document;
50 class Element;
51 class InspectorPageAgent;
52 class InspectorStyleSheet;
53 class Node;
54
55 #if ENABLE(INSPECTOR)
56
57 typedef String ErrorString;
58
59 class InspectorCSSId {
60 public:
61     InspectorCSSId()
62         : m_ordinal(0)
63     {
64     }
65
66     explicit InspectorCSSId(RefPtr<Inspector::InspectorObject> value)
67     {
68         if (!value->getString("styleSheetId", &m_styleSheetId))
69             return;
70         
71         RefPtr<Inspector::InspectorValue> ordinalValue = value->get("ordinal");
72         if (!ordinalValue || !ordinalValue->asNumber(&m_ordinal))
73             m_styleSheetId = "";
74     }
75
76     InspectorCSSId(const String& styleSheetId, unsigned ordinal)
77         : m_styleSheetId(styleSheetId)
78         , m_ordinal(ordinal)
79     {
80     }
81
82     bool isEmpty() const { return m_styleSheetId.isEmpty(); }
83
84     const String& styleSheetId() const { return m_styleSheetId; }
85     unsigned ordinal() const { return m_ordinal; }
86
87     // ID type is either Inspector::TypeBuilder::CSS::CSSStyleId or Inspector::TypeBuilder::CSS::CSSRuleId.
88     template<typename ID>
89     PassRefPtr<ID> asProtocolValue() const
90     {
91         if (isEmpty())
92             return 0;
93
94         RefPtr<ID> result = ID::create()
95             .setStyleSheetId(m_styleSheetId)
96             .setOrdinal(m_ordinal);
97         return result.release();
98     }
99
100 private:
101     String m_styleSheetId;
102     unsigned m_ordinal;
103 };
104
105 struct InspectorStyleProperty {
106     InspectorStyleProperty()
107         : hasSource(false)
108         , disabled(false)
109     {
110     }
111
112     InspectorStyleProperty(CSSPropertySourceData sourceData, bool hasSource, bool disabled)
113         : sourceData(sourceData)
114         , hasSource(hasSource)
115         , disabled(disabled)
116     {
117     }
118
119     void setRawTextFromStyleDeclaration(const String& styleDeclaration)
120     {
121         unsigned start = sourceData.range.start;
122         unsigned end = sourceData.range.end;
123         ASSERT_WITH_SECURITY_IMPLICATION(start < end);
124         ASSERT(end <= styleDeclaration.length());
125         rawText = styleDeclaration.substring(start, end - start);
126     }
127
128     bool hasRawText() const { return !rawText.isEmpty(); }
129
130     CSSPropertySourceData sourceData;
131     bool hasSource;
132     bool disabled;
133     String rawText;
134 };
135
136 class InspectorStyle : public RefCounted<InspectorStyle> {
137 public:
138     static PassRefPtr<InspectorStyle> create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet);
139     virtual ~InspectorStyle();
140
141     CSSStyleDeclaration* cssStyle() const { return m_style.get(); }
142     PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> buildObjectForStyle() const;
143     PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSComputedStyleProperty>> buildArrayForComputedStyle() const;
144     bool hasDisabledProperties() const { return !m_disabledProperties.isEmpty(); }
145     bool setPropertyText(unsigned index, const String& text, bool overwrite, String* oldText, ExceptionCode&);
146     bool toggleProperty(unsigned index, bool disable, ExceptionCode&);
147
148     bool getText(String* result) const;
149     bool setText(const String&, ExceptionCode&);
150
151 private:
152     InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet);
153
154     // FIXME: Remove these aliases and update all the current call sites to use the new public methods.
155     bool styleText(String* result) const { return getText(result); }
156     bool applyStyleText(const String& text) { ExceptionCode ec = 0; return setText(text, ec); }
157
158     bool populateAllProperties(Vector<InspectorStyleProperty>* result) const;
159     PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> styleWithProperties() const;
160     PassRefPtr<CSSRuleSourceData> extractSourceData() const;
161     String shorthandValue(const String& shorthandProperty) const;
162     String shorthandPriority(const String& shorthandProperty) const;
163     Vector<String> longhandProperties(const String& shorthandProperty) const;
164     NewLineAndWhitespace& newLineAndWhitespaceDelimiters() const;
165
166     InspectorCSSId m_styleId;
167     RefPtr<CSSStyleDeclaration> m_style;
168     InspectorStyleSheet* m_parentStyleSheet;
169     Vector<InspectorStyleProperty> m_disabledProperties;
170     mutable std::pair<String, String> m_format;
171     mutable bool m_formatAcquired;
172 };
173
174 class InspectorStyleSheet : public RefCounted<InspectorStyleSheet> {
175 public:
176     class Listener {
177     public:
178         Listener() { }
179         virtual ~Listener() { }
180         virtual void styleSheetChanged(InspectorStyleSheet*) = 0;
181     };
182
183     typedef HashMap<CSSStyleDeclaration*, RefPtr<InspectorStyle>> InspectorStyleMap;
184     static PassRefPtr<InspectorStyleSheet> create(InspectorPageAgent*, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum, const String& documentURL, Listener*);
185     static String styleSheetURL(CSSStyleSheet* pageStyleSheet);
186
187     virtual ~InspectorStyleSheet();
188
189     String id() const { return m_id; }
190     String finalURL() const;
191     CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet.get(); }
192     void reparseStyleSheet(const String&);
193     bool setText(const String&, ExceptionCode&);
194     String ruleSelector(const InspectorCSSId&, ExceptionCode&);
195     bool setRuleSelector(const InspectorCSSId&, const String& selector, ExceptionCode&);
196     CSSStyleRule* addRule(const String& selector, ExceptionCode&);
197     bool deleteRule(const InspectorCSSId&, ExceptionCode&);
198     CSSStyleRule* ruleForId(const InspectorCSSId&) const;
199     PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetBody> buildObjectForStyleSheet();
200     PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetHeader> buildObjectForStyleSheetInfo();
201     PassRefPtr<Inspector::TypeBuilder::CSS::CSSRule> buildObjectForRule(CSSStyleRule*);
202     PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> buildObjectForStyle(CSSStyleDeclaration*);
203     bool setStyleText(const InspectorCSSId&, const String& text, String* oldText, ExceptionCode&);
204     bool setPropertyText(const InspectorCSSId&, unsigned propertyIndex, const String& text, bool overwrite, String* oldPropertyText, ExceptionCode&);
205     bool toggleProperty(const InspectorCSSId&, unsigned propertyIndex, bool disable, ExceptionCode&);
206
207     virtual bool getText(String* result) const;
208     virtual CSSStyleDeclaration* styleForId(const InspectorCSSId&) const;
209     void fireStyleSheetChanged();
210
211     InspectorCSSId ruleId(CSSStyleRule*) const;
212     InspectorCSSId styleId(CSSStyleDeclaration* style) const { return ruleOrStyleId(style); }
213
214 protected:
215     InspectorStyleSheet(InspectorPageAgent*, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum, const String& documentURL, Listener*);
216
217     bool canBind() const { return m_origin != Inspector::TypeBuilder::CSS::StyleSheetOrigin::UserAgent && m_origin != Inspector::TypeBuilder::CSS::StyleSheetOrigin::User; }
218     InspectorCSSId ruleOrStyleId(CSSStyleDeclaration* style) const;
219     virtual Document* ownerDocument() const;
220     virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const;
221     virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const;
222     virtual bool ensureParsedDataReady();
223     virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
224     virtual void rememberInspectorStyle(RefPtr<InspectorStyle> inspectorStyle);
225     virtual void forgetInspectorStyle(CSSStyleDeclaration* style);
226
227     // Also accessed by friend class InspectorStyle.
228     virtual bool setStyleText(CSSStyleDeclaration*, const String&, ExceptionCode&);
229     virtual PassOwnPtr<Vector<size_t>> lineEndings() const;
230
231 private:
232     typedef Vector<RefPtr<CSSStyleRule>> CSSStyleRuleVector;
233     friend class InspectorStyle;
234
235     static void collectFlatRules(PassRefPtr<CSSRuleList>, CSSStyleRuleVector* result);
236     bool checkPageStyleSheet(ExceptionCode&) const;
237     bool ensureText() const;
238     bool ensureSourceData();
239     void ensureFlatRules() const;
240     bool styleSheetTextWithChangedStyle(CSSStyleDeclaration*, const String& newStyleText, String* result);
241     void revalidateStyle(CSSStyleDeclaration*);
242     bool originalStyleSheetText(String* result) const;
243     bool resourceStyleSheetText(String* result) const;
244     bool inlineStyleSheetText(String* result) const;
245     PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSRule>> buildArrayForRuleList(CSSRuleList*);
246     PassRefPtr<Inspector::TypeBuilder::CSS::SelectorList> buildObjectForSelectorList(CSSStyleRule*);
247
248     InspectorPageAgent* m_pageAgent;
249     String m_id;
250     RefPtr<CSSStyleSheet> m_pageStyleSheet;
251     Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum m_origin;
252     String m_documentURL;
253     bool m_isRevalidating;
254     ParsedStyleSheet* m_parsedStyleSheet;
255     InspectorStyleMap m_inspectorStyles;
256     mutable CSSStyleRuleVector m_flatRules;
257     Listener* m_listener;
258 };
259
260 class InspectorStyleSheetForInlineStyle : public InspectorStyleSheet {
261 public:
262     static PassRefPtr<InspectorStyleSheetForInlineStyle> create(InspectorPageAgent*, const String& id, PassRefPtr<Element>, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum, Listener*);
263
264     void didModifyElementAttribute();
265     virtual bool getText(String* result) const;
266     virtual CSSStyleDeclaration* styleForId(const InspectorCSSId& id) const { ASSERT_UNUSED(id, !id.ordinal()); return inlineStyle(); }
267
268 protected:
269     InspectorStyleSheetForInlineStyle(InspectorPageAgent*, const String& id, PassRefPtr<Element>, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum, Listener*);
270
271     virtual Document* ownerDocument() const;
272     virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const { ASSERT_UNUSED(style, style == inlineStyle()); return m_ruleSourceData; }
273     virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const { return 0; }
274     virtual bool ensureParsedDataReady();
275     virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
276     virtual void rememberInspectorStyle(RefPtr<InspectorStyle>) { }
277     virtual void forgetInspectorStyle(CSSStyleDeclaration*) { }
278
279     // Also accessed by friend class InspectorStyle.
280     virtual bool setStyleText(CSSStyleDeclaration*, const String&, ExceptionCode&);
281     virtual PassOwnPtr<Vector<size_t>> lineEndings() const;
282
283 private:
284     CSSStyleDeclaration* inlineStyle() const;
285     const String& elementStyleText() const;
286     bool getStyleAttributeRanges(CSSRuleSourceData* result) const;
287
288     RefPtr<Element> m_element;
289     RefPtr<CSSRuleSourceData> m_ruleSourceData;
290     RefPtr<InspectorStyle> m_inspectorStyle;
291
292     // Contains "style" attribute value.
293     mutable String m_styleText;
294     mutable bool m_isStyleTextValid;
295 };
296
297 #endif
298
299 } // namespace WebCore
300
301 #endif // !defined(InspectorStyleSheet_h)