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