Web Inspector: implement undo for setOuterHTML via undo-ing nested primitive commands.
[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 "ExceptionCode.h"
30 #include "InspectorStyleTextEditor.h"
31 #include "InspectorValues.h"
32 #include "PlatformString.h"
33
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
40 class ParsedStyleSheet;
41
42 namespace WebCore {
43
44 class CSSRuleList;
45 class CSSStyleDeclaration;
46 class CSSStyleSheet;
47 class Document;
48 class Element;
49 class InspectorStyleSheet;
50 class Node;
51
52 #if ENABLE(INSPECTOR)
53
54 typedef String ErrorString;
55
56 class InspectorCSSId {
57 public:
58     InspectorCSSId() { }
59
60     explicit InspectorCSSId(RefPtr<InspectorObject> value)
61     {
62         if (!value->getString("styleSheetId", &m_styleSheetId))
63             return;
64         
65         RefPtr<InspectorValue> ordinalValue = value->get("ordinal");
66         if (!ordinalValue || !ordinalValue->asNumber(&m_ordinal))
67             m_styleSheetId = "";
68     }
69
70     InspectorCSSId(const String& styleSheetId, unsigned ordinal)
71         : m_styleSheetId(styleSheetId)
72         , m_ordinal(ordinal)
73     {
74     }
75
76     bool isEmpty() const { return m_styleSheetId.isEmpty(); }
77
78     const String& styleSheetId() const { return m_styleSheetId; }
79     unsigned ordinal() const { return m_ordinal; }
80
81     PassRefPtr<InspectorValue> asInspectorValue() const
82     {
83         if (isEmpty())
84             return InspectorValue::null();
85
86         RefPtr<InspectorObject> result = InspectorObject::create();
87         result->setString("styleSheetId", m_styleSheetId);
88         result->setNumber("ordinal", m_ordinal);
89         return result.release();
90     }
91
92 private:
93     String m_styleSheetId;
94     unsigned m_ordinal;
95 };
96
97 struct InspectorStyleProperty {
98     InspectorStyleProperty()
99     {
100     }
101
102     InspectorStyleProperty(CSSPropertySourceData sourceData, bool hasSource, bool disabled)
103         : sourceData(sourceData)
104         , hasSource(hasSource)
105         , disabled(disabled)
106     {
107     }
108
109     void setRawTextFromStyleDeclaration(const String& styleDeclaration)
110     {
111         unsigned start = sourceData.range.start;
112         unsigned end = sourceData.range.end;
113         ASSERT(start < end);
114         ASSERT(end <= styleDeclaration.length());
115         rawText = styleDeclaration.substring(start, end - start);
116     }
117
118     bool hasRawText() const { return !rawText.isEmpty(); }
119
120     CSSPropertySourceData sourceData;
121     bool hasSource;
122     bool disabled;
123     String rawText;
124 };
125
126 class InspectorStyle : public RefCounted<InspectorStyle> {
127 public:
128     static PassRefPtr<InspectorStyle> create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet);
129     virtual ~InspectorStyle();
130
131     CSSStyleDeclaration* cssStyle() const { return m_style.get(); }
132     PassRefPtr<InspectorObject> buildObjectForStyle() const;
133     PassRefPtr<InspectorArray> buildArrayForComputedStyle() const;
134     bool hasDisabledProperties() const { return !m_disabledProperties.isEmpty(); }
135     bool setPropertyText(unsigned index, const String& text, bool overwrite, String* oldText, ExceptionCode&);
136     bool toggleProperty(unsigned index, bool disable, ExceptionCode&);
137
138 private:
139     InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet);
140
141     bool styleText(String* result) const;
142     bool populateAllProperties(Vector<InspectorStyleProperty>* result) const;
143     void populateObjectWithStyleProperties(InspectorObject* result) const;
144     bool applyStyleText(const String&);
145     String shorthandValue(const String& shorthandProperty) const;
146     String shorthandPriority(const String& shorthandProperty) const;
147     Vector<String> longhandProperties(const String& shorthandProperty) const;
148     NewLineAndWhitespace& newLineAndWhitespaceDelimiters() const;
149
150     InspectorCSSId m_styleId;
151     RefPtr<CSSStyleDeclaration> m_style;
152     InspectorStyleSheet* m_parentStyleSheet;
153     Vector<InspectorStyleProperty> m_disabledProperties;
154     mutable std::pair<String, String> m_format;
155     mutable bool m_formatAcquired;
156 };
157
158 class InspectorStyleSheet : public RefCounted<InspectorStyleSheet> {
159 public:
160     typedef HashMap<CSSStyleDeclaration*, RefPtr<InspectorStyle> > InspectorStyleMap;
161     static PassRefPtr<InspectorStyleSheet> create(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL);
162     static String styleSheetURL(CSSStyleSheet* pageStyleSheet);
163
164     virtual ~InspectorStyleSheet();
165
166     String id() const { return m_id; }
167     String finalURL() const;
168     CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet.get(); }
169     void reparseStyleSheet(const String&);
170     bool setText(const String&);
171     bool setRuleSelector(const InspectorCSSId&, const String& selector);
172     CSSStyleRule* addRule(const String& selector);
173     CSSStyleRule* ruleForId(const InspectorCSSId&) const;
174     PassRefPtr<InspectorObject> buildObjectForStyleSheet();
175     PassRefPtr<InspectorObject> buildObjectForStyleSheetInfo();
176     PassRefPtr<InspectorObject> buildObjectForRule(CSSStyleRule*);
177     PassRefPtr<InspectorObject> buildObjectForStyle(CSSStyleDeclaration*);
178     bool setPropertyText(const InspectorCSSId&, unsigned propertyIndex, const String& text, bool overwrite, String* oldPropertyText, ExceptionCode&);
179     bool toggleProperty(const InspectorCSSId&, unsigned propertyIndex, bool disable, ExceptionCode&);
180
181     virtual bool getText(String* result) const;
182     virtual CSSStyleDeclaration* styleForId(const InspectorCSSId&) const;
183
184 protected:
185     InspectorStyleSheet(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL);
186
187     bool canBind() const { return m_origin != "userAgent" && m_origin != "user"; }
188     InspectorCSSId ruleOrStyleId(CSSStyleDeclaration* style) const;
189     virtual Document* ownerDocument() const;
190     virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const;
191     virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const;
192     virtual bool ensureParsedDataReady();
193     virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
194     virtual void rememberInspectorStyle(RefPtr<InspectorStyle> inspectorStyle);
195     virtual void forgetInspectorStyle(CSSStyleDeclaration* style);
196
197     // Also accessed by friend class InspectorStyle.
198     virtual bool setStyleText(CSSStyleDeclaration*, const String&);
199
200 private:
201     static void fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData, const String& styleSheetText);
202     static void collectFlatRules(PassRefPtr<CSSRuleList>, Vector<CSSStyleRule*>* result);
203     bool ensureText() const;
204     bool ensureSourceData();
205     void ensureFlatRules() const;
206     bool styleSheetTextWithChangedStyle(CSSStyleDeclaration*, const String& newStyleText, String* result);
207     InspectorCSSId ruleId(CSSStyleRule* rule) const;
208     InspectorCSSId styleId(CSSStyleDeclaration* style) const { return ruleOrStyleId(style); }
209     void revalidateStyle(CSSStyleDeclaration*);
210     bool originalStyleSheetText(String* result) const;
211     bool resourceStyleSheetText(String* result) const;
212     bool inlineStyleSheetText(String* result) const;
213     PassRefPtr<InspectorArray> buildArrayForRuleList(CSSRuleList*);
214
215     String m_id;
216     RefPtr<CSSStyleSheet> m_pageStyleSheet;
217     String m_origin;
218     String m_documentURL;
219     bool m_isRevalidating;
220     ParsedStyleSheet* m_parsedStyleSheet;
221     InspectorStyleMap m_inspectorStyles;
222     mutable Vector<CSSStyleRule*> m_flatRules;
223
224     friend class InspectorStyle;
225 };
226
227 class InspectorStyleSheetForInlineStyle : public InspectorStyleSheet {
228 public:
229     static PassRefPtr<InspectorStyleSheetForInlineStyle> create(const String& id, PassRefPtr<Element> element, const String& origin);
230
231     void didModifyElementAttribute();
232     virtual bool getText(String* result) const;
233     virtual CSSStyleDeclaration* styleForId(const InspectorCSSId& id) const { ASSERT_UNUSED(id, !id.ordinal()); return inlineStyle(); }
234
235 protected:
236     InspectorStyleSheetForInlineStyle(const String& id, PassRefPtr<Element> element, const String& origin);
237
238     virtual Document* ownerDocument() const;
239     virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const { ASSERT_UNUSED(style, style == inlineStyle()); return m_ruleSourceData; }
240     virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const { return 0; }
241     virtual bool ensureParsedDataReady();
242     virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
243     virtual void rememberInspectorStyle(RefPtr<InspectorStyle>) { }
244     virtual void forgetInspectorStyle(CSSStyleDeclaration*) { }
245
246     // Also accessed by friend class InspectorStyle.
247     virtual bool setStyleText(CSSStyleDeclaration*, const String&);
248
249 private:
250     CSSStyleDeclaration* inlineStyle() const;
251     const String& elementStyleText() const;
252     bool getStyleAttributeRanges(RefPtr<CSSStyleSourceData>* result) const;
253
254     RefPtr<Element> m_element;
255     RefPtr<CSSRuleSourceData> m_ruleSourceData;
256     RefPtr<InspectorStyle> m_inspectorStyle;
257
258     // Contains "style" attribute value.
259     mutable String m_styleText;
260     mutable bool m_isStyleTextValid;
261 };
262
263 #endif
264
265 } // namespace WebCore
266
267 #endif // !defined(InspectorStyleSheet_h)