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 "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 InspectorResourceAgent; 52 class InspectorStyleSheet; 53 54 typedef Vector<RefPtr<CSSRule> > CSSRuleVector; 55 typedef String ErrorString; 56 57 class InspectorCSSId { 58 public: 59 InspectorCSSId() 60 : m_ordinal(0) 61 { 62 } 63 64 explicit InspectorCSSId(PassRefPtr<JSONObject> value) 65 { 66 if (!value->getString("styleSheetId", &m_styleSheetId)) 67 return; 68 69 RefPtr<JSONValue> ordinalValue = value->get("ordinal"); 70 if (!ordinalValue || !ordinalValue->asNumber(&m_ordinal)) 71 m_styleSheetId = ""; 72 } 73 74 InspectorCSSId(const String& styleSheetId, unsigned ordinal) 75 : m_styleSheetId(styleSheetId) 76 , m_ordinal(ordinal) 77 { 78 } 79 80 bool isEmpty() const { return m_styleSheetId.isEmpty(); } 81 82 const String& styleSheetId() const { return m_styleSheetId; } 83 unsigned ordinal() const { return m_ordinal; } 84 85 // ID type is either TypeBuilder::CSS::CSSStyleId or TypeBuilder::CSS::CSSRuleId. 86 template<typename ID> 87 PassRefPtr<ID> asProtocolValue() const 88 { 89 if (isEmpty()) 90 return 0; 91 92 RefPtr<ID> result = ID::create() 93 .setStyleSheetId(m_styleSheetId) 94 .setOrdinal(m_ordinal); 95 return result.release(); 96 } 97 98 private: 99 String m_styleSheetId; 100 unsigned m_ordinal; 101 }; 102 103 struct InspectorStyleProperty { 104 explicit InspectorStyleProperty(CSSPropertySourceData sourceData) 105 : sourceData(sourceData) 106 , hasSource(true) 107 { 108 } 109 110 InspectorStyleProperty(CSSPropertySourceData sourceData, bool hasSource) 111 : sourceData(sourceData) 112 , hasSource(hasSource) 113 { 114 } 115 116 void setRawTextFromStyleDeclaration(const String& styleDeclaration) 117 { 118 unsigned start = sourceData.range.start; 119 unsigned end = sourceData.range.end; 120 ASSERT(start < end); 121 ASSERT(end <= styleDeclaration.length()); 122 rawText = styleDeclaration.substring(start, end - start); 123 } 124 125 bool hasRawText() const { return !rawText.isEmpty(); } 126 127 CSSPropertySourceData sourceData; 128 bool hasSource; 129 String rawText; 130 }; 131 132 class InspectorStyle FINAL : public RefCounted<InspectorStyle> { 133 public: 134 static PassRefPtr<InspectorStyle> create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet); 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*, InspectorResourceAgent*, 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 virtual Document* ownerDocument() const; 184 bool canBind() const { return m_origin != TypeBuilder::CSS::StyleSheetOrigin::User_agent && m_origin != TypeBuilder::CSS::StyleSheetOrigin::User; } 185 CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet.get(); } 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*, InspectorResourceAgent*, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum, const String& documentURL, Listener*); 212 213 InspectorCSSId ruleOrStyleId(CSSStyleDeclaration* style) const; 214 virtual PassRefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration*) const; 215 virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const; 216 virtual unsigned ruleIndexByRule(const CSSRule*) const; 217 virtual bool ensureParsedDataReady(); 218 virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&); 219 virtual String sourceMapURL() const; 220 virtual String sourceURL() const; 221 222 // Also accessed by friend class InspectorStyle. 223 virtual bool setStyleText(CSSStyleDeclaration*, const String&); 224 virtual PassOwnPtr<Vector<unsigned> > lineEndings() const; 225 226 private: 227 friend class InspectorStyle; 228 229 bool checkPageStyleSheet(ExceptionState&) const; 230 bool ensureText() const; 231 bool ensureSourceData(); 232 void ensureFlatRules() const; 233 bool styleSheetTextWithChangedStyle(CSSStyleDeclaration*, const String& newStyleText, String* result); 234 void revalidateStyle(CSSStyleDeclaration*); 235 bool originalStyleSheetText(String* result) const; 236 bool resourceStyleSheetText(String* result) const; 237 bool inlineStyleSheetText(String* result) const; 238 PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Selector> > selectorsFromSource(const CSSRuleSourceData*, const String&) 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 InspectorResourceAgent* m_resourceAgent; 246 String m_id; 247 RefPtr<CSSStyleSheet> m_pageStyleSheet; 248 TypeBuilder::CSS::StyleSheetOrigin::Enum m_origin; 249 String m_documentURL; 250 bool m_isRevalidating; 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*, InspectorResourceAgent*, 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*, InspectorResourceAgent*, 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