diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp | 1072 |
1 files changed, 470 insertions, 602 deletions
diff --git a/chromium/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp b/chromium/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp index 01f60ef60b1..256a1e4f934 100644 --- a/chromium/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp +++ b/chromium/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp @@ -25,16 +25,13 @@ #include "config.h" #include "core/inspector/InspectorStyleSheet.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" -#include "SVGNames.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" #include "bindings/v8/ScriptRegexp.h" +#include "core/CSSPropertyNames.h" #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSMediaRule.h" -#include "core/css/CSSParser.h" -#include "core/css/CSSRule.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSRuleList.h" #include "core/css/CSSStyleRule.h" #include "core/css/CSSStyleSheet.h" @@ -44,14 +41,13 @@ #include "core/css/StyleSheetContents.h" #include "core/dom/Document.h" #include "core/dom/Element.h" -#include "core/dom/Node.h" +#include "core/html/HTMLStyleElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/inspector/ContentSearchUtils.h" #include "core/inspector/InspectorCSSAgent.h" #include "core/inspector/InspectorPageAgent.h" #include "core/inspector/InspectorResourceAgent.h" -#include "core/page/Page.h" -#include "core/page/PageConsole.h" +#include "core/svg/SVGStyleElement.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" #include "wtf/text/StringBuilder.h" @@ -60,96 +56,25 @@ using WebCore::TypeBuilder::Array; using WebCore::RuleSourceDataList; using WebCore::CSSRuleSourceData; +using WebCore::CSSStyleSheet; -class ParsedStyleSheet { - WTF_MAKE_FAST_ALLOCATED; -public: - ParsedStyleSheet(); - - const String& text() const { ASSERT(m_hasText); return m_text; } - void setText(const String& text); - bool hasText() const { return m_hasText; } - void setSourceData(PassOwnPtr<RuleSourceDataList>); - bool hasSourceData() const { return m_sourceData; } - PassRefPtr<WebCore::CSSRuleSourceData> ruleSourceDataAt(unsigned) const; - -private: - void flattenSourceData(RuleSourceDataList*); - - String m_text; - bool m_hasText; - OwnPtr<RuleSourceDataList> m_sourceData; -}; - -ParsedStyleSheet::ParsedStyleSheet() - : m_hasText(false) -{ -} - -void ParsedStyleSheet::setText(const String& text) -{ - m_hasText = true; - m_text = text; - setSourceData(nullptr); -} - -void ParsedStyleSheet::flattenSourceData(RuleSourceDataList* dataList) -{ - for (size_t i = 0; i < dataList->size(); ++i) { - RefPtr<CSSRuleSourceData>& data = dataList->at(i); - if (data->type == CSSRuleSourceData::STYLE_RULE) { - m_sourceData->append(data); - } else if (data->type == CSSRuleSourceData::IMPORT_RULE) { - m_sourceData->append(data); - } else if (data->type == CSSRuleSourceData::MEDIA_RULE) { - m_sourceData->append(data); - flattenSourceData(&data->childRules); - } else if (data->type == CSSRuleSourceData::SUPPORTS_RULE) { - flattenSourceData(&data->childRules); - } - } -} - -void ParsedStyleSheet::setSourceData(PassOwnPtr<RuleSourceDataList> sourceData) -{ - if (!sourceData) { - m_sourceData.clear(); - return; - } - - m_sourceData = adoptPtr(new RuleSourceDataList()); +namespace { - // FIXME: This is a temporary solution to retain the original flat sourceData structure - // containing only style rules, even though CSSParser now provides the full rule source data tree. - // Normally, we should just assign m_sourceData = sourceData; - flattenSourceData(sourceData.get()); -} +using namespace WebCore; -PassRefPtr<WebCore::CSSRuleSourceData> ParsedStyleSheet::ruleSourceDataAt(unsigned index) const +static CSSParserContext parserContextForDocument(Document *document) { - if (!hasSourceData() || index >= m_sourceData->size()) - return 0; - - return m_sourceData->at(index); + return document ? CSSParserContext(*document, 0) : strictCSSParserContext(); } -namespace WebCore { - -static PassOwnPtr<CSSParser> createCSSParser(Document* document) -{ - UseCounter* counter = 0; - return adoptPtr(new CSSParser(document ? CSSParserContext(*document) : strictCSSParserContext(), counter)); -} - -namespace { - -class StyleSheetHandler : public CSSParser::SourceDataHandler { +class StyleSheetHandler FINAL : public CSSParserObserver { public: StyleSheetHandler(const String& parsedText, Document* document, StyleSheetContents* styleSheetContents, RuleSourceDataList* result) : m_parsedText(parsedText) , m_document(document) , m_styleSheetContents(styleSheetContents) , m_result(result) + , m_commentParser(parserContextForDocument(document)) , m_propertyRangeStart(UINT_MAX) , m_selectorRangeStart(UINT_MAX) , m_commentRangeStart(UINT_MAX) @@ -166,22 +91,22 @@ private: virtual void endRuleBody(unsigned, bool) OVERRIDE; virtual void startEndUnknownRule() OVERRIDE { addNewRuleToSourceTree(CSSRuleSourceData::createUnknown()); } virtual void startProperty(unsigned) OVERRIDE; - virtual void endProperty(bool, bool, unsigned, CSSParser::ErrorType) OVERRIDE; + virtual void endProperty(bool, bool, unsigned, CSSParserError) OVERRIDE; virtual void startComment(unsigned) OVERRIDE; virtual void endComment(unsigned) OVERRIDE; - void addNewRuleToSourceTree(PassRefPtr<CSSRuleSourceData>); - PassRefPtr<CSSRuleSourceData> popRuleData(); + void addNewRuleToSourceTree(PassRefPtrWillBeRawPtr<CSSRuleSourceData>); + PassRefPtrWillBeRawPtr<CSSRuleSourceData> popRuleData(); template <typename CharacterType> inline void setRuleHeaderEnd(const CharacterType*, unsigned); void fixUnparsedPropertyRanges(CSSRuleSourceData*); const String& m_parsedText; Document* m_document; StyleSheetContents* m_styleSheetContents; - RuleSourceDataList* m_result; + RawPtrWillBeMember<RuleSourceDataList> m_result; RuleSourceDataList m_currentRuleDataStack; - RefPtr<CSSRuleSourceData> m_currentRuleData; - OwnPtr<CSSParser> m_commentParser; + RefPtrWillBeMember<CSSRuleSourceData> m_currentRuleData; + BisonCSSParser m_commentParser; unsigned m_propertyRangeStart; unsigned m_selectorRangeStart; unsigned m_commentRangeStart; @@ -193,7 +118,7 @@ void StyleSheetHandler::startRuleHeader(CSSRuleSourceData::Type type, unsigned o if (m_currentRuleData) m_currentRuleDataStack.removeLast(); - RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(type); + RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(type); data->ruleHeaderRange.start = offset; m_currentRuleData = data; m_currentRuleDataStack.append(data.release()); @@ -250,7 +175,7 @@ void StyleSheetHandler::endRuleBody(unsigned offset, bool error) ASSERT(!m_currentRuleDataStack.isEmpty()); m_currentRuleDataStack.last()->ruleBodyRange.end = offset; m_propertyRangeStart = UINT_MAX; - RefPtr<CSSRuleSourceData> rule = popRuleData(); + RefPtrWillBeRawPtr<CSSRuleSourceData> rule = popRuleData(); if (error) return; @@ -258,7 +183,7 @@ void StyleSheetHandler::endRuleBody(unsigned offset, bool error) addNewRuleToSourceTree(rule.release()); } -void StyleSheetHandler::addNewRuleToSourceTree(PassRefPtr<CSSRuleSourceData> rule) +void StyleSheetHandler::addNewRuleToSourceTree(PassRefPtrWillBeRawPtr<CSSRuleSourceData> rule) { if (m_currentRuleDataStack.isEmpty()) m_result->append(rule); @@ -266,11 +191,11 @@ void StyleSheetHandler::addNewRuleToSourceTree(PassRefPtr<CSSRuleSourceData> rul m_currentRuleDataStack.last()->childRules.append(rule); } -PassRefPtr<CSSRuleSourceData> StyleSheetHandler::popRuleData() +PassRefPtrWillBeRawPtr<CSSRuleSourceData> StyleSheetHandler::popRuleData() { ASSERT(!m_currentRuleDataStack.isEmpty()); m_currentRuleData.clear(); - RefPtr<CSSRuleSourceData> data = m_currentRuleDataStack.last(); + RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_currentRuleDataStack.last(); m_currentRuleDataStack.removeLast(); return data.release(); } @@ -278,7 +203,7 @@ PassRefPtr<CSSRuleSourceData> StyleSheetHandler::popRuleData() template <typename CharacterType> static inline void fixUnparsedProperties(const CharacterType* characters, CSSRuleSourceData* ruleData) { - Vector<CSSPropertySourceData>& propertyData = ruleData->styleSourceData->propertyData; + WillBeHeapVector<CSSPropertySourceData>& propertyData = ruleData->styleSourceData->propertyData; unsigned size = propertyData.size(); if (!size) return; @@ -340,9 +265,10 @@ void StyleSheetHandler::startProperty(unsigned offset) m_propertyRangeStart = offset; } -void StyleSheetHandler::endProperty(bool isImportant, bool isParsed, unsigned offset, CSSParser::ErrorType errorType) +void StyleSheetHandler::endProperty(bool isImportant, bool isParsed, unsigned offset, CSSParserError errorType) { - if (errorType != CSSParser::NoError) + // FIXME: This is the only place CSSParserError is every read!? + if (errorType != NoCSSError) m_propertyRangeStart = UINT_MAX; if (m_propertyRangeStart == UINT_MAX || m_currentRuleDataStack.isEmpty() || !m_currentRuleDataStack.last()->styleSourceData) @@ -407,16 +333,14 @@ void StyleSheetHandler::endComment(unsigned offset) return; // FIXME: Use the actual rule type rather than STYLE_RULE? - if (!m_commentParser) - m_commentParser = createCSSParser(m_document); RuleSourceDataList sourceData; - // FIXME: Use another subclass of CSSParser::SourceDataHandler and assert that + // FIXME: Use another subclass of BisonCSSParser::SourceDataHandler and assert that // no comments are encountered (will not need m_document and m_styleSheetContents). StyleSheetHandler handler(commentText, m_document, m_styleSheetContents, &sourceData); - RefPtr<MutableStylePropertySet> tempMutableStyle = MutableStylePropertySet::create(); - m_commentParser->parseDeclaration(tempMutableStyle.get(), commentText, &handler, m_styleSheetContents); - Vector<CSSPropertySourceData>& commentPropertyData = sourceData.first()->styleSourceData->propertyData; + RefPtrWillBeRawPtr<MutableStylePropertySet> tempMutableStyle = MutableStylePropertySet::create(); + m_commentParser.parseDeclaration(tempMutableStyle.get(), commentText, &handler, m_styleSheetContents); + WillBeHeapVector<CSSPropertySourceData>& commentPropertyData = sourceData.first()->styleSourceData->propertyData; if (commentPropertyData.size() != 1) return; CSSPropertySourceData& propertyData = commentPropertyData.at(0); @@ -430,6 +354,100 @@ void StyleSheetHandler::endComment(unsigned offset) } // namespace +class ParsedStyleSheet { + WTF_MAKE_FAST_ALLOCATED; +public: + ParsedStyleSheet(CSSStyleSheet* pageStyleSheet); + + const String& text() const { ASSERT(m_hasText); return m_text; } + void setText(const String&); + bool hasText() const { return m_hasText; } + bool ensureSourceData(); + bool hasSourceData() const { return m_sourceData; } + PassRefPtrWillBeRawPtr<WebCore::CSSRuleSourceData> ruleSourceDataAt(unsigned) const; + unsigned ruleCount() { return m_sourceData->size(); } + +private: + void flattenSourceData(RuleSourceDataList*); + void setSourceData(PassOwnPtrWillBeRawPtr<RuleSourceDataList>); + + String m_text; + bool m_hasText; + OwnPtrWillBePersistent<RuleSourceDataList> m_sourceData; + RefPtrWillBePersistent<CSSStyleSheet> m_pageStyleSheet; +}; + +ParsedStyleSheet::ParsedStyleSheet(CSSStyleSheet* pageStyleSheet) + : m_hasText(false) + , m_pageStyleSheet(pageStyleSheet) +{ +} + +void ParsedStyleSheet::setText(const String& text) +{ + m_hasText = true; + m_text = text; + setSourceData(nullptr); +} + +void ParsedStyleSheet::flattenSourceData(RuleSourceDataList* dataList) +{ + for (size_t i = 0; i < dataList->size(); ++i) { + RefPtrWillBeMember<CSSRuleSourceData>& data = dataList->at(i); + if (data->type == CSSRuleSourceData::STYLE_RULE) { + m_sourceData->append(data); + } else if (data->type == CSSRuleSourceData::IMPORT_RULE) { + m_sourceData->append(data); + } else if (data->type == CSSRuleSourceData::MEDIA_RULE) { + m_sourceData->append(data); + flattenSourceData(&data->childRules); + } else if (data->type == CSSRuleSourceData::SUPPORTS_RULE) { + flattenSourceData(&data->childRules); + } + } +} + +bool ParsedStyleSheet::ensureSourceData() +{ + if (hasSourceData()) + return true; + + if (!hasText()) + return false; + + RefPtrWillBeRawPtr<StyleSheetContents> newStyleSheet = StyleSheetContents::create(strictCSSParserContext()); + OwnPtrWillBeRawPtr<RuleSourceDataList> result = adoptPtrWillBeNoop(new RuleSourceDataList()); + StyleSheetHandler handler(text(), m_pageStyleSheet->ownerDocument(), newStyleSheet.get(), result.get()); + BisonCSSParser(parserContextForDocument(m_pageStyleSheet->ownerDocument())).parseSheet(newStyleSheet.get(), text(), TextPosition::minimumPosition(), &handler); + setSourceData(result.release()); + return hasSourceData(); +} + +void ParsedStyleSheet::setSourceData(PassOwnPtrWillBeRawPtr<RuleSourceDataList> sourceData) +{ + if (!sourceData) { + m_sourceData.clear(); + return; + } + + m_sourceData = adoptPtrWillBeNoop(new RuleSourceDataList()); + + // FIXME: This is a temporary solution to retain the original flat sourceData structure + // containing only style rules, even though BisonCSSParser now provides the full rule source data tree. + // Normally, we should just assign m_sourceData = sourceData; + flattenSourceData(sourceData.get()); +} + +PassRefPtrWillBeRawPtr<WebCore::CSSRuleSourceData> ParsedStyleSheet::ruleSourceDataAt(unsigned index) const +{ + if (!hasSourceData() || index >= m_sourceData->size()) + return nullptr; + + return m_sourceData->at(index); +} + +namespace WebCore { + enum MediaListSource { MediaListSourceLinkedSheet, MediaListSourceInlineSheet, @@ -440,7 +458,7 @@ enum MediaListSource { static PassRefPtr<TypeBuilder::CSS::SourceRange> buildSourceRangeObject(const SourceRange& range, Vector<unsigned>* lineEndings) { if (!lineEndings) - return 0; + return nullptr; TextPosition start = TextPosition::fromOffsetAndLineEndings(range.start, *lineEndings); TextPosition end = TextPosition::fromOffsetAndLineEndings(range.end, *lineEndings); @@ -452,13 +470,13 @@ static PassRefPtr<TypeBuilder::CSS::SourceRange> buildSourceRangeObject(const So return result.release(); } -static PassRefPtr<CSSRuleList> asCSSRuleList(CSSStyleSheet* styleSheet) +static PassRefPtrWillBeRawPtr<CSSRuleList> asCSSRuleList(CSSStyleSheet* styleSheet) { if (!styleSheet) - return 0; + return nullptr; - RefPtr<StaticCSSRuleList> list = StaticCSSRuleList::create(); - Vector<RefPtr<CSSRule> >& listRules = list->rules(); + RefPtrWillBeRawPtr<StaticCSSRuleList> list = StaticCSSRuleList::create(); + WillBeHeapVector<RefPtrWillBeMember<CSSRule> >& listRules = list->rules(); for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) { CSSRule* item = styleSheet->item(i); if (item->type() == CSSRule::CHARSET_RULE) @@ -468,10 +486,10 @@ static PassRefPtr<CSSRuleList> asCSSRuleList(CSSStyleSheet* styleSheet) return list.release(); } -static PassRefPtr<CSSRuleList> asCSSRuleList(CSSRule* rule) +static PassRefPtrWillBeRawPtr<CSSRuleList> asCSSRuleList(CSSRule* rule) { if (!rule) - return 0; + return nullptr; if (rule->type() == CSSRule::MEDIA_RULE) return toCSSMediaRule(rule)->cssRules(); @@ -482,15 +500,15 @@ static PassRefPtr<CSSRuleList> asCSSRuleList(CSSRule* rule) if (rule->type() == CSSRule::SUPPORTS_RULE) return toCSSSupportsRule(rule)->cssRules(); - return 0; + return nullptr; } -PassRefPtr<InspectorStyle> InspectorStyle::create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet) +PassRefPtr<InspectorStyle> InspectorStyle::create(const InspectorCSSId& styleId, PassRefPtrWillBeRawPtr<CSSStyleDeclaration> style, InspectorStyleSheetBase* parentStyleSheet) { return adoptRef(new InspectorStyle(styleId, style, parentStyleSheet)); } -InspectorStyle::InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet) +InspectorStyle::InspectorStyle(const InspectorCSSId& styleId, PassRefPtrWillBeRawPtr<CSSStyleDeclaration> style, InspectorStyleSheetBase* parentStyleSheet) : m_styleId(styleId) , m_style(style) , m_parentStyleSheet(parentStyleSheet) @@ -503,12 +521,9 @@ PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::buildObjectForStyle() con { RefPtr<TypeBuilder::CSS::CSSStyle> result = styleWithProperties(); if (!m_styleId.isEmpty()) - result->setStyleId(m_styleId.asProtocolValue<TypeBuilder::CSS::CSSStyleId>()); - - result->setWidth(m_style->getPropertyValue("width")); - result->setHeight(m_style->getPropertyValue("height")); + result->setStyleSheetId(m_styleId.styleSheetId()); - RefPtr<CSSRuleSourceData> sourceData = extractSourceData(); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = extractSourceData(); if (sourceData) result->setRange(buildSourceRangeObject(sourceData->ruleBodyRange, m_parentStyleSheet->lineEndings().get())); @@ -518,10 +533,10 @@ PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::buildObjectForStyle() con PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> > InspectorStyle::buildArrayForComputedStyle() const { RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty>::create(); - Vector<InspectorStyleProperty> properties; + WillBeHeapVector<InspectorStyleProperty> properties; populateAllProperties(properties); - for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) { + for (WillBeHeapVector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) { const CSSPropertySourceData& propertyEntry = it->sourceData; RefPtr<TypeBuilder::CSS::CSSComputedStyleProperty> entry = TypeBuilder::CSS::CSSComputedStyleProperty::create() .setName(propertyEntry.name) @@ -532,118 +547,78 @@ PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> > Insp return result.release(); } -// This method does the following preprocessing of |propertyText| with |overwrite| == false and |index| past the last active property: -// - If the last property (if present) has no closing ";", the ";" is prepended to the current |propertyText| value. -// - A heuristic formatting is attempted to retain the style structure. -// -// The propertyText (if not empty) is checked to be a valid style declaration (containing at least one property). If not, -// the method returns false (denoting an error). -bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, bool overwrite, String* oldText, ExceptionState& exceptionState) +bool InspectorStyle::verifyPropertyText(const String& propertyText, bool canOmitSemicolon) { - ASSERT(m_parentStyleSheet); DEFINE_STATIC_LOCAL(String, bogusPropertyName, ("-webkit-boguz-propertee")); + RefPtrWillBeRawPtr<MutableStylePropertySet> tempMutableStyle = MutableStylePropertySet::create(); + RuleSourceDataList sourceData; + RefPtrWillBeRawPtr<StyleSheetContents> styleSheetContents = StyleSheetContents::create(strictCSSParserContext()); + String declarationText = propertyText + (canOmitSemicolon ? ";" : " ") + bogusPropertyName + ": none"; + StyleSheetHandler handler(declarationText, ownerDocument(), styleSheetContents.get(), &sourceData); + BisonCSSParser(parserContextForDocument(ownerDocument())).parseDeclaration(tempMutableStyle.get(), declarationText, &handler, styleSheetContents.get()); + WillBeHeapVector<CSSPropertySourceData>& propertyData = sourceData.first()->styleSourceData->propertyData; + unsigned propertyCount = propertyData.size(); + + // At least one property + the bogus property added just above should be present. + if (propertyCount < 2) + return false; + + // Check for the proper propertyText termination (the parser could at least restore to the PROPERTY_NAME state). + if (propertyData.at(propertyCount - 1).name != bogusPropertyName) + return false; + + return true; +} + +bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, bool overwrite, ExceptionState& exceptionState) +{ + ASSERT(m_parentStyleSheet); if (!m_parentStyleSheet->ensureParsedDataReady()) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "The parent style sheet's data hasn't been processed."); return false; } if (!propertyText.stripWhiteSpace().isEmpty()) { - RefPtr<MutableStylePropertySet> tempMutableStyle = MutableStylePropertySet::create(); - String declarationText = propertyText + " " + bogusPropertyName + ": none"; - RuleSourceDataList sourceData; - StyleSheetHandler handler(declarationText, ownerDocument(), m_style->parentStyleSheet()->contents(), &sourceData); - createCSSParser(ownerDocument())->parseDeclaration(tempMutableStyle.get(), declarationText, &handler, m_style->parentStyleSheet()->contents()); - Vector<CSSPropertySourceData>& propertyData = sourceData.first()->styleSourceData->propertyData; - unsigned propertyCount = propertyData.size(); - - // At least one property + the bogus property added just above should be present. - if (propertyCount < 2) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return false; - } - - // Check for the proper propertyText termination (the parser could at least restore to the PROPERTY_NAME state). - if (propertyData.at(propertyCount - 1).name != bogusPropertyName) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + if (!verifyPropertyText(propertyText, false) && !verifyPropertyText(propertyText, true)) { + exceptionState.throwDOMException(SyntaxError, "The property '" + propertyText + "' could not be set."); return false; } } - RefPtr<CSSRuleSourceData> sourceData = extractSourceData(); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = extractSourceData(); if (!sourceData) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "The property '" + propertyText + "' could not be set."); return false; } String text; bool success = styleText(&text); if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "The property '" + propertyText + "' could not be set."); return false; } - Vector<InspectorStyleProperty> allProperties; + WillBeHeapVector<InspectorStyleProperty> allProperties; populateAllProperties(allProperties); InspectorStyleTextEditor editor(&allProperties, text, newLineAndWhitespaceDelimiters()); if (overwrite) { if (index >= allProperties.size()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is greater than or equal to the maximum bound (" + String::number(allProperties.size()) + ")."); return false; } - *oldText = allProperties.at(index).rawText; editor.replaceProperty(index, propertyText); - } else + } else { editor.insertProperty(index, propertyText, sourceData->ruleBodyRange.length()); - - return applyStyleText(editor.styleText()); -} - -bool InspectorStyle::toggleProperty(unsigned index, bool disable, ExceptionState& exceptionState) -{ - ASSERT(m_parentStyleSheet); - if (!m_parentStyleSheet->ensureParsedDataReady()) { - exceptionState.throwUninformativeAndGenericDOMException(NoModificationAllowedError); - return false; - } - - RefPtr<CSSRuleSourceData> sourceData = extractSourceData(); - if (!sourceData) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); - return false; - } - - String text; - bool success = styleText(&text); - if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); - return false; - } - - Vector<InspectorStyleProperty> allProperties; - populateAllProperties(allProperties); - if (index >= allProperties.size()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return false; } - InspectorStyleProperty& property = allProperties.at(index); - if (property.sourceData.disabled == disable) - return true; // Idempotent operation. - - InspectorStyleTextEditor editor(&allProperties, text, newLineAndWhitespaceDelimiters()); - if (disable) - editor.disableProperty(index); - else - editor.enableProperty(index); - - return applyStyleText(editor.styleText()); + return m_parentStyleSheet->setStyleText(m_styleId, editor.styleText()); } bool InspectorStyle::styleText(String* result) const { - RefPtr<CSSRuleSourceData> sourceData = extractSourceData(); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = extractSourceData(); if (!sourceData) return false; @@ -657,17 +632,17 @@ bool InspectorStyle::styleText(String* result) const return true; } -void InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>& result) const +void InspectorStyle::populateAllProperties(WillBeHeapVector<InspectorStyleProperty>& result) const { HashSet<String> sourcePropertyNames; - RefPtr<CSSRuleSourceData> sourceData = extractSourceData(); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = extractSourceData(); if (sourceData) { String styleDeclaration; bool isStyleTextKnown = styleText(&styleDeclaration); ASSERT_UNUSED(isStyleTextKnown, isStyleTextKnown); - Vector<CSSPropertySourceData>& sourcePropertyData = sourceData->styleSourceData->propertyData; - for (Vector<CSSPropertySourceData>::const_iterator it = sourcePropertyData.begin(); it != sourcePropertyData.end(); ++it) { + WillBeHeapVector<CSSPropertySourceData>& sourcePropertyData = sourceData->styleSourceData->propertyData; + for (WillBeHeapVector<CSSPropertySourceData>::const_iterator it = sourcePropertyData.begin(); it != sourcePropertyData.end(); ++it) { InspectorStyleProperty p(*it, true); p.setRawTextFromStyleDeclaration(styleDeclaration); result.append(p); @@ -688,23 +663,17 @@ PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithProperties() con { RefPtr<Array<TypeBuilder::CSS::CSSProperty> > propertiesObject = Array<TypeBuilder::CSS::CSSProperty>::create(); RefPtr<Array<TypeBuilder::CSS::ShorthandEntry> > shorthandEntries = Array<TypeBuilder::CSS::ShorthandEntry>::create(); - HashMap<String, RefPtr<TypeBuilder::CSS::CSSProperty> > propertyNameToPreviousActiveProperty; HashSet<String> foundShorthands; - String previousPriority; - String previousStatus; OwnPtr<Vector<unsigned> > lineEndings(m_parentStyleSheet ? m_parentStyleSheet->lineEndings() : PassOwnPtr<Vector<unsigned> >()); - RefPtr<CSSRuleSourceData> sourceData = extractSourceData(); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = extractSourceData(); unsigned ruleBodyRangeStart = sourceData ? sourceData->ruleBodyRange.start : 0; - Vector<InspectorStyleProperty> properties; + WillBeHeapVector<InspectorStyleProperty> properties; populateAllProperties(properties); - for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) { + for (WillBeHeapVector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) { const CSSPropertySourceData& propertyEntry = it->sourceData; const String& name = propertyEntry.name; - const bool disabled = it->sourceData.disabled; - - TypeBuilder::CSS::CSSProperty::Status::Enum status = disabled ? TypeBuilder::CSS::CSSProperty::Status::Disabled : TypeBuilder::CSS::CSSProperty::Status::Active; RefPtr<TypeBuilder::CSS::CSSProperty> property = TypeBuilder::CSS::CSSProperty::create() .setName(name) @@ -717,9 +686,8 @@ PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithProperties() con if (it->hasRawText()) property->setText(it->rawText); - // Default "priority" == "". if (propertyEntry.important) - property->setPriority("important"); + property->setImportant(true); if (it->hasSource) { // The property range is relative to the style body start. // Should be converted into an absolute range (relative to the stylesheet start) @@ -728,66 +696,27 @@ PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithProperties() con absolutePropertyRange.start += ruleBodyRangeStart; absolutePropertyRange.end += ruleBodyRangeStart; property->setRange(buildSourceRangeObject(absolutePropertyRange, lineEndings.get())); - } - if (!disabled) { - if (it->hasSource) { + if (!propertyEntry.disabled) { ASSERT(sourceData); property->setImplicit(false); - - // Parsed property overrides any property with the same name. Non-parsed property overrides - // previous non-parsed property with the same name (if any). - bool shouldInactivate = false; - CSSPropertyID propertyId = cssPropertyID(name); - // Canonicalize property names to treat non-prefixed and vendor-prefixed property names the same (opacity vs. -webkit-opacity). - String canonicalPropertyName = propertyId ? getPropertyNameString(propertyId) : name; - HashMap<String, RefPtr<TypeBuilder::CSS::CSSProperty> >::iterator activeIt = propertyNameToPreviousActiveProperty.find(canonicalPropertyName); - if (activeIt != propertyNameToPreviousActiveProperty.end()) { - if (propertyEntry.parsedOk) { - bool successPriority = activeIt->value->getString(TypeBuilder::CSS::CSSProperty::Priority, &previousPriority); - bool successStatus = activeIt->value->getString(TypeBuilder::CSS::CSSProperty::Status, &previousStatus); - if (successStatus && previousStatus != "inactive") { - if (propertyEntry.important || !successPriority) // Priority not set == "not important". - shouldInactivate = true; - else if (status == TypeBuilder::CSS::CSSProperty::Status::Active) { - // Inactivate a non-important property following the same-named important property. - status = TypeBuilder::CSS::CSSProperty::Status::Inactive; - } - } - } else { - bool previousParsedOk; - bool success = activeIt->value->getBoolean(TypeBuilder::CSS::CSSProperty::ParsedOk, &previousParsedOk); - if (success && !previousParsedOk) - shouldInactivate = true; - } - } else - propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property); - - if (shouldInactivate) { - activeIt->value->setStatus(TypeBuilder::CSS::CSSProperty::Status::Inactive); - propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property); - } - } else { - bool implicit = m_style->isPropertyImplicit(name); - // Default "implicit" == false. - if (implicit) - property->setImplicit(true); - status = TypeBuilder::CSS::CSSProperty::Status::Style; - - String shorthand = m_style->getPropertyShorthand(name); - if (!shorthand.isEmpty()) { - if (foundShorthands.add(shorthand).isNewEntry) { - RefPtr<TypeBuilder::CSS::ShorthandEntry> entry = TypeBuilder::CSS::ShorthandEntry::create() - .setName(shorthand) - .setValue(shorthandValue(shorthand)); - shorthandEntries->addItem(entry); - } + } + property->setDisabled(propertyEntry.disabled); + } else if (!propertyEntry.disabled) { + bool implicit = m_style->isPropertyImplicit(name); + // Default "implicit" == false. + if (implicit) + property->setImplicit(true); + + String shorthand = m_style->getPropertyShorthand(name); + if (!shorthand.isEmpty()) { + if (foundShorthands.add(shorthand).isNewEntry) { + RefPtr<TypeBuilder::CSS::ShorthandEntry> entry = TypeBuilder::CSS::ShorthandEntry::create() + .setName(shorthand) + .setValue(shorthandValue(shorthand)); + shorthandEntries->addItem(entry); } } } - - // Default "status" == "style". - if (status != TypeBuilder::CSS::CSSProperty::Status::Style) - property->setStatus(status); } RefPtr<TypeBuilder::CSS::CSSStyle> result = TypeBuilder::CSS::CSSStyle::create() @@ -796,16 +725,11 @@ PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithProperties() con return result.release(); } -PassRefPtr<CSSRuleSourceData> InspectorStyle::extractSourceData() const +PassRefPtrWillBeRawPtr<CSSRuleSourceData> InspectorStyle::extractSourceData() const { if (!m_parentStyleSheet || !m_parentStyleSheet->ensureParsedDataReady()) - return 0; - return m_parentStyleSheet->ruleSourceDataFor(m_style.get()); -} - -bool InspectorStyle::applyStyleText(const String& text) -{ - return m_parentStyleSheet->setStyleText(m_style.get(), text); + return nullptr; + return m_parentStyleSheet->ruleSourceDataAt(m_styleId.ordinal()); } String InspectorStyle::shorthandValue(const String& shorthandProperty) const @@ -833,36 +757,6 @@ String InspectorStyle::shorthandValue(const String& shorthandProperty) const return value; } -String InspectorStyle::shorthandPriority(const String& shorthandProperty) const -{ - String priority = m_style->getPropertyPriority(shorthandProperty); - if (priority.isEmpty()) { - for (unsigned i = 0; i < m_style->length(); ++i) { - String individualProperty = m_style->item(i); - if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty) - continue; - priority = m_style->getPropertyPriority(individualProperty); - break; - } - } - return priority; -} - -Vector<String> InspectorStyle::longhandProperties(const String& shorthandProperty) const -{ - Vector<String> properties; - HashSet<String> foundProperties; - for (unsigned i = 0; i < m_style->length(); ++i) { - String individualProperty = m_style->item(i); - if (foundProperties.contains(individualProperty) || m_style->getPropertyShorthand(individualProperty) != shorthandProperty) - continue; - - foundProperties.add(individualProperty); - properties.append(individualProperty); - } - return properties; -} - NewLineAndWhitespace& InspectorStyle::newLineAndWhitespaceDelimiters() const { DEFINE_STATIC_LOCAL(String, defaultPrefix, (" ")); @@ -870,8 +764,8 @@ NewLineAndWhitespace& InspectorStyle::newLineAndWhitespaceDelimiters() const if (m_formatAcquired) return m_format; - RefPtr<CSSRuleSourceData> sourceData = extractSourceData(); - Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : 0; + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = extractSourceData(); + WillBeHeapVector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : 0; int propertyCount; if (!sourcePropertyData || !(propertyCount = sourcePropertyData->size())) { m_format.first = "\n"; @@ -930,65 +824,152 @@ NewLineAndWhitespace& InspectorStyle::newLineAndWhitespaceDelimiters() const Document* InspectorStyle::ownerDocument() const { - return m_parentStyleSheet->pageStyleSheet() ? m_parentStyleSheet->pageStyleSheet()->ownerDocument() : 0; + return m_parentStyleSheet->ownerDocument(); } -PassRefPtr<InspectorStyleSheet> InspectorStyleSheet::create(InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener) +InspectorStyleSheetBase::InspectorStyleSheetBase(const String& id, Listener* listener) + : m_id(id) + , m_listener(listener) { - return adoptRef(new InspectorStyleSheet(pageAgent, resourceAgent, id, pageStyleSheet, origin, documentURL, listener)); } -// static -String InspectorStyleSheet::styleSheetURL(CSSStyleSheet* pageStyleSheet) +bool InspectorStyleSheetBase::setPropertyText(const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite, ExceptionState& exceptionState) { - if (pageStyleSheet && !pageStyleSheet->contents()->baseURL().isEmpty()) - return pageStyleSheet->contents()->baseURL().string(); - return emptyString(); + RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id); + if (!inspectorStyle) { + exceptionState.throwDOMException(NotFoundError, "No property could be found for the given ID."); + return false; + } + return inspectorStyle->setPropertyText(propertyIndex, text, overwrite, exceptionState); } -// static -void InspectorStyleSheet::collectFlatRules(PassRefPtr<CSSRuleList> ruleList, CSSRuleVector* result) +bool InspectorStyleSheetBase::getStyleText(const InspectorCSSId& id, String* text) { - if (!ruleList) - return; + RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id); + if (!inspectorStyle) + return false; + return inspectorStyle->styleText(text); +} - for (unsigned i = 0, size = ruleList->length(); i < size; ++i) { - CSSRule* rule = ruleList->item(i); +void InspectorStyleSheetBase::fireStyleSheetChanged() +{ + if (listener()) + listener()->styleSheetChanged(this); +} - // The result->append()'ed types should be exactly the same as in ParsedStyleSheet::flattenSourceData(). - switch (rule->type()) { - case CSSRule::STYLE_RULE: - result->append(rule); +PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyleSheetBase::buildObjectForStyle(CSSStyleDeclaration* style) +{ + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = nullptr; + if (ensureParsedDataReady()) + sourceData = ruleSourceDataAt(styleId(style).ordinal()); + + InspectorCSSId id = styleId(style); + if (id.isEmpty()) { + // Any rule coming from User Agent and not from DefaultStyleSheet will not have id. + // See InspectorCSSAgent::buildObjectForRule for details. + RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(id, style, this); + return inspectorStyle->buildObjectForStyle(); + } + RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id); + RefPtr<TypeBuilder::CSS::CSSStyle> result = inspectorStyle->buildObjectForStyle(); + + // Style text cannot be retrieved without stylesheet, so set cssText here. + if (sourceData) { + String sheetText; + bool success = getText(&sheetText); + if (success) { + const SourceRange& bodyRange = sourceData->ruleBodyRange; + result->setCssText(sheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start)); + } + } + + return result.release(); +} + +PassOwnPtr<Vector<unsigned> > InspectorStyleSheetBase::lineEndings() +{ + String text; + if (!getText(&text)) + return PassOwnPtr<Vector<unsigned> >(); + return WTF::lineEndings(text); +} + +bool InspectorStyleSheetBase::lineNumberAndColumnToOffset(unsigned lineNumber, unsigned columnNumber, unsigned* offset) +{ + OwnPtr<Vector<unsigned> > endings = lineEndings(); + if (lineNumber >= endings->size()) + return false; + unsigned charactersInLine = lineNumber > 0 ? endings->at(lineNumber) - endings->at(lineNumber - 1) - 1 : endings->at(0); + if (columnNumber > charactersInLine) + return false; + TextPosition position(OrdinalNumber::fromZeroBasedInt(lineNumber), OrdinalNumber::fromZeroBasedInt(columnNumber)); + *offset = position.toOffset(*endings).zeroBasedInt(); + return true; +} + +bool InspectorStyleSheetBase::findPropertyByRange(const SourceRange& sourceRange, InspectorCSSId* ruleId, unsigned* propertyIndex, bool* overwrite) +{ + if (!ensureParsedDataReady()) + return false; + for (size_t i = 0; i < ruleCount(); ++i) { + RefPtrWillBeRawPtr<CSSRuleSourceData> ruleSourceData = ruleSourceDataAt(i); + RefPtrWillBeRawPtr<CSSStyleSourceData> styleSourceData = ruleSourceData->styleSourceData; + if (!styleSourceData) continue; - case CSSRule::IMPORT_RULE: - case CSSRule::MEDIA_RULE: - result->append(rule); - break; - default: - break; + if (ruleSourceData->ruleBodyRange.end < sourceRange.start || sourceRange.end < ruleSourceData->ruleBodyRange.start) + continue; + WillBeHeapVector<CSSPropertySourceData>& propertyData = styleSourceData->propertyData; + for (size_t j = 0; j < propertyData.size(); ++j) { + CSSPropertySourceData& property = propertyData.at(j); + unsigned styleStart = ruleSourceData->ruleBodyRange.start; + if (sourceRange.length() && property.range.start + styleStart == sourceRange.start && property.range.end + styleStart == sourceRange.end) { + *ruleId = InspectorCSSId(id(), i); + *propertyIndex = j; + *overwrite = true; + return true; + } + if (!sourceRange.length() && styleStart <= sourceRange.start && sourceRange.start <= property.range.start + styleStart) { + *ruleId = InspectorCSSId(id(), i); + *propertyIndex = j; + *overwrite = false; + return true; + } + } + if (!sourceRange.length() && ruleSourceData->ruleBodyRange.start <= sourceRange.start && sourceRange.start <= ruleSourceData->ruleBodyRange.end) { + *ruleId = InspectorCSSId(id(), i); + *propertyIndex = propertyData.size(); + *overwrite = false; + return true; } - RefPtr<CSSRuleList> childRuleList = asCSSRuleList(rule); - if (childRuleList) - collectFlatRules(childRuleList, result); } + return false; +} + +PassRefPtr<InspectorStyleSheet> InspectorStyleSheet::create(InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent, const String& id, PassRefPtrWillBeRawPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener) +{ + return adoptRef(new InspectorStyleSheet(pageAgent, resourceAgent, id, pageStyleSheet, origin, documentURL, listener)); } -InspectorStyleSheet::InspectorStyleSheet(InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener) - : m_pageAgent(pageAgent) +InspectorStyleSheet::InspectorStyleSheet(InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent, const String& id, PassRefPtrWillBeRawPtr<CSSStyleSheet> pageStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener) + : InspectorStyleSheetBase(id, listener) + , m_pageAgent(pageAgent) , m_resourceAgent(resourceAgent) - , m_id(id) , m_pageStyleSheet(pageStyleSheet) , m_origin(origin) , m_documentURL(documentURL) - , m_isRevalidating(false) - , m_listener(listener) { - m_parsedStyleSheet = new ParsedStyleSheet(); + m_parsedStyleSheet = adoptPtr(new ParsedStyleSheet(m_pageStyleSheet.get())); } InspectorStyleSheet::~InspectorStyleSheet() { - delete m_parsedStyleSheet; +} + +static String styleSheetURL(CSSStyleSheet* pageStyleSheet) +{ + if (pageStyleSheet && !pageStyleSheet->contents()->baseURL().isEmpty()) + return pageStyleSheet->contents()->baseURL().string(); + return emptyString(); } String InspectorStyleSheet::finalURL() const @@ -997,10 +978,13 @@ String InspectorStyleSheet::finalURL() const return url.isEmpty() ? m_documentURL : url; } -void InspectorStyleSheet::reparseStyleSheet(const String& text) +bool InspectorStyleSheet::setText(const String& text, ExceptionState& exceptionState) { - if (m_listener) - m_listener->willReparseStyleSheet(); + m_parsedStyleSheet->setText(text); + m_flatRules.clear(); + + if (listener()) + listener()->willReparseStyleSheet(); { // Have a separate scope for clearRules() (bug 95324). @@ -1013,22 +997,10 @@ void InspectorStyleSheet::reparseStyleSheet(const String& text) m_pageStyleSheet->contents()->parseString(text); } - if (m_listener) - m_listener->didReparseStyleSheet(); + if (listener()) + listener()->didReparseStyleSheet(); fireStyleSheetChanged(); - m_pageStyleSheet->ownerDocument()->styleResolverChanged(RecalcStyleImmediately, FullStyleUpdate); -} - -bool InspectorStyleSheet::setText(const String& text, ExceptionState& exceptionState) -{ - if (!checkPageStyleSheet(exceptionState)) - return false; - if (!m_parsedStyleSheet) - return false; - - m_parsedStyleSheet->setText(text); - m_flatRules.clear(); - + m_pageStyleSheet->ownerDocument()->styleResolverChanged(FullStyleUpdate); return true; } @@ -1036,7 +1008,7 @@ String InspectorStyleSheet::ruleSelector(const InspectorCSSId& id, ExceptionStat { CSSStyleRule* rule = ruleForId(id); if (!rule) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "No rule was found for the given ID."); return ""; } return rule->selectorText(); @@ -1044,23 +1016,21 @@ String InspectorStyleSheet::ruleSelector(const InspectorCSSId& id, ExceptionStat bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String& selector, ExceptionState& exceptionState) { - if (!checkPageStyleSheet(exceptionState)) - return false; CSSStyleRule* rule = ruleForId(id); if (!rule) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "No rule was found for the given ID."); return false; } CSSStyleSheet* styleSheet = rule->parentStyleSheet(); if (!styleSheet || !ensureParsedDataReady()) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "No stylesheet could be found in which to set the selector."); return false; } rule->setSelectorText(selector); - RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(rule->style()); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = ruleSourceDataAt(id.ordinal()); if (!sourceData) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "The selector '" + selector + "' could not be set."); return false; } @@ -1074,23 +1044,21 @@ bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String static bool checkStyleRuleSelector(Document* document, const String& selector) { CSSSelectorList selectorList; - createCSSParser(document)->parseSelector(selector, selectorList); + BisonCSSParser(parserContextForDocument(document)).parseSelector(selector, selectorList); return selectorList.isValid(); } CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionState& exceptionState) { - if (!checkPageStyleSheet(exceptionState)) - return 0; if (!checkStyleRuleSelector(m_pageStyleSheet->ownerDocument(), selector)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The selector '" + selector + "' could not be added."); return 0; } String text; bool success = getText(&text); if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "The selector '" + selector + "' could not be added."); return 0; } StringBuilder styleSheetText; @@ -1109,7 +1077,7 @@ CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionStat // What we just added has to be a CSSStyleRule - we cannot handle other types of rules yet. // If it is not a style rule, pretend we never touched the stylesheet. m_pageStyleSheet->deleteRule(lastRuleIndex, ASSERT_NO_EXCEPTION); - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The selector '" + selector + "' could not be added."); return 0; } @@ -1118,8 +1086,8 @@ CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionStat styleSheetText.append(selector); styleSheetText.appendLiteral(" {}"); - // Using setText() as this operation changes the style sheet rule set. - setText(styleSheetText.toString(), ASSERT_NO_EXCEPTION); + m_parsedStyleSheet->setText(styleSheetText.toString()); + m_flatRules.clear(); fireStyleSheetChanged(); @@ -1128,22 +1096,20 @@ CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionStat bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, ExceptionState& exceptionState) { - if (!checkPageStyleSheet(exceptionState)) - return false; - RefPtr<CSSStyleRule> rule = ruleForId(id); + RefPtrWillBeRawPtr<CSSStyleRule> rule = ruleForId(id); if (!rule) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "No style rule could be found for the provided ID."); return false; } CSSStyleSheet* styleSheet = rule->parentStyleSheet(); if (!styleSheet || !ensureParsedDataReady()) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "No parent stylesheet could be found."); return false; } - RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(rule->style()); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = ruleSourceDataAt(id.ordinal()); if (!sourceData) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "No style rule could be found for the provided ID."); return false; } @@ -1155,44 +1121,27 @@ bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, ExceptionState& e String sheetText = m_parsedStyleSheet->text(); sheetText.remove(sourceData->ruleHeaderRange.start, sourceData->ruleBodyRange.end - sourceData->ruleHeaderRange.start + 1); - setText(sheetText, ASSERT_NO_EXCEPTION); + m_parsedStyleSheet->setText(sheetText); + m_flatRules.clear(); fireStyleSheetChanged(); return true; } CSSStyleRule* InspectorStyleSheet::ruleForId(const InspectorCSSId& id) const { - if (!m_pageStyleSheet) - return 0; - ASSERT(!id.isEmpty()); ensureFlatRules(); return InspectorCSSAgent::asCSSStyleRule(id.ordinal() >= m_flatRules.size() ? 0 : m_flatRules.at(id.ordinal()).get()); } -bool InspectorStyleSheet::fillObjectForStyleSheet(PassRefPtr<TypeBuilder::CSS::CSSStyleSheetBody> prpResult) -{ - CSSStyleSheet* styleSheet = pageStyleSheet(); - if (!styleSheet) - return false; - - RefPtr<TypeBuilder::CSS::CSSStyleSheetBody> result = prpResult; - - String styleSheetText; - bool success = getText(&styleSheetText); - if (success) - result->setText(styleSheetText); - return success; -} - PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObjectForStyleSheetInfo() const { CSSStyleSheet* styleSheet = pageStyleSheet(); if (!styleSheet) - return 0; + return nullptr; Document* document = styleSheet->ownerDocument(); - Frame* frame = document ? document->frame() : 0; + LocalFrame* frame = document ? document->frame() : 0; RefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> result = TypeBuilder::CSS::CSSStyleSheetHeader::create() .setStyleSheetId(id()) @@ -1214,7 +1163,7 @@ PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObje return result.release(); } -PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Selector> > InspectorStyleSheet::selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText) const +PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Selector> > InspectorStyleSheet::selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText) { ScriptRegexp comment("/\\*[^]*?\\*/", TextCaseSensitive, MultilineEnabled); RefPtr<TypeBuilder::Array<TypeBuilder::CSS::Selector> > result = TypeBuilder::Array<TypeBuilder::CSS::Selector>::create(); @@ -1239,9 +1188,9 @@ PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Selector> > InspectorStyleSheet: PassRefPtr<TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule) { - RefPtr<CSSRuleSourceData> sourceData; + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = nullptr; if (ensureParsedDataReady()) - sourceData = ruleSourceDataFor(rule->style()); + sourceData = ruleSourceDataAt(styleId(rule->style()).ordinal()); RefPtr<TypeBuilder::Array<TypeBuilder::CSS::Selector> > selectors; // This intentionally does not rely on the source data to avoid catching the trailing comments (before the declaration starting '{'). @@ -1252,7 +1201,7 @@ PassRefPtr<TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSe else { selectors = TypeBuilder::Array<TypeBuilder::CSS::Selector>::create(); const CSSSelectorList& selectorList = rule->styleRule()->selectorList(); - for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) + for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) selectors->addItem(TypeBuilder::CSS::Selector::create().setValue(selector->selectorText()).release()); } RefPtr<TypeBuilder::CSS::SelectorList> result = TypeBuilder::CSS::SelectorList::create() @@ -1262,114 +1211,34 @@ PassRefPtr<TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSe return result.release(); } +static bool canBind(TypeBuilder::CSS::StyleSheetOrigin::Enum origin) +{ + return origin != TypeBuilder::CSS::StyleSheetOrigin::User_agent && origin != TypeBuilder::CSS::StyleSheetOrigin::User; +} + PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule, PassRefPtr<Array<TypeBuilder::CSS::CSSMedia> > mediaStack) { CSSStyleSheet* styleSheet = pageStyleSheet(); if (!styleSheet) - return 0; + return nullptr; RefPtr<TypeBuilder::CSS::CSSRule> result = TypeBuilder::CSS::CSSRule::create() .setSelectorList(buildObjectForSelectorList(rule)) .setOrigin(m_origin) .setStyle(buildObjectForStyle(rule->style())); - String url = this->url(); - if (!url.isEmpty()) - result->setSourceURL(url); - - if (canBind()) { + if (canBind(m_origin)) { InspectorCSSId id(ruleId(rule)); if (!id.isEmpty()) - result->setRuleId(id.asProtocolValue<TypeBuilder::CSS::CSSRuleId>()); + result->setStyleSheetId(id.styleSheetId()); } - RefPtr<Array<TypeBuilder::CSS::CSSMedia> > mediaArray = Array<TypeBuilder::CSS::CSSMedia>::create(); - if (mediaStack) result->setMedia(mediaStack); return result.release(); } -PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorStyleSheet::buildObjectForStyle(CSSStyleDeclaration* style) -{ - RefPtr<CSSRuleSourceData> sourceData; - if (ensureParsedDataReady()) - sourceData = ruleSourceDataFor(style); - - InspectorCSSId id = ruleOrStyleId(style); - if (id.isEmpty()) { - RefPtr<TypeBuilder::CSS::CSSStyle> bogusStyle = TypeBuilder::CSS::CSSStyle::create() - .setCssProperties(Array<TypeBuilder::CSS::CSSProperty>::create()) - .setShorthandEntries(Array<TypeBuilder::CSS::ShorthandEntry>::create()); - return bogusStyle.release(); - } - RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id); - RefPtr<TypeBuilder::CSS::CSSStyle> result = inspectorStyle->buildObjectForStyle(); - - // Style text cannot be retrieved without stylesheet, so set cssText here. - if (sourceData) { - String sheetText; - bool success = getText(&sheetText); - if (success) { - const SourceRange& bodyRange = sourceData->ruleBodyRange; - result->setCssText(sheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start)); - } - } - - return result.release(); -} - -bool InspectorStyleSheet::setStyleText(const InspectorCSSId& id, const String& text, String* oldText, ExceptionState& exceptionState) -{ - RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id); - if (!inspectorStyle || !inspectorStyle->cssStyle()) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); - return false; - } - - bool success = inspectorStyle->styleText(oldText); - if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); - return false; - } - - success = setStyleText(inspectorStyle->cssStyle(), text); - if (success) - fireStyleSheetChanged(); - else - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return success; -} - -bool InspectorStyleSheet::setPropertyText(const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite, String* oldText, ExceptionState& exceptionState) -{ - RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id); - if (!inspectorStyle) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); - return false; - } - - bool success = inspectorStyle->setPropertyText(propertyIndex, text, overwrite, oldText, exceptionState); - if (success) - fireStyleSheetChanged(); - return success; -} - -bool InspectorStyleSheet::toggleProperty(const InspectorCSSId& id, unsigned propertyIndex, bool disable, ExceptionState& exceptionState) -{ - RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id); - if (!inspectorStyle) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); - return false; - } - - bool success = inspectorStyle->toggleProperty(propertyIndex, disable, exceptionState); - if (success) - fireStyleSheetChanged(); - return success; -} - bool InspectorStyleSheet::getText(String* result) const { if (!ensureText()) @@ -1387,20 +1256,19 @@ CSSStyleDeclaration* InspectorStyleSheet::styleForId(const InspectorCSSId& id) c return rule->style(); } -void InspectorStyleSheet::fireStyleSheetChanged() -{ - if (m_listener) - m_listener->styleSheetChanged(this); -} - PassRefPtr<TypeBuilder::CSS::SourceRange> InspectorStyleSheet::ruleHeaderSourceRange(const CSSRule* rule) { if (!ensureParsedDataReady()) - return 0; + return nullptr; - RefPtr<CSSRuleSourceData> sourceData = m_parsedStyleSheet->ruleSourceDataAt(ruleIndexByRule(rule)); - if (!sourceData) - return 0; + ensureFlatRules(); + size_t index = m_flatRules.find(rule); + // FIXME(lusnikov): m_flatRules are not always aligned with the m_parsedStyleSheet rule source + // datas due to the CSSOM operations that add/remove rules without changing source. + // This is a design issue. See crbug.com/178410 + if (index == kNotFound || index >= m_parsedStyleSheet->ruleCount()) + return nullptr; + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = m_parsedStyleSheet->ruleSourceDataAt(static_cast<unsigned>(index)); return buildSourceRangeObject(sourceData->ruleHeaderRange, lineEndings().get()); } @@ -1408,11 +1276,16 @@ PassRefPtr<InspectorStyle> InspectorStyleSheet::inspectorStyleForId(const Inspec { CSSStyleDeclaration* style = styleForId(id); if (!style) - return 0; + return nullptr; return InspectorStyle::create(id, style, this); } +unsigned InspectorStyleSheet::ruleCount() +{ + return m_parsedStyleSheet->ruleCount(); +} + String InspectorStyleSheet::sourceURL() const { if (!m_sourceURL.isNull()) @@ -1488,7 +1361,7 @@ String InspectorStyleSheet::sourceMapURL() const return m_pageAgent->resourceSourceMapURL(finalURL()); } -InspectorCSSId InspectorStyleSheet::ruleOrStyleId(CSSStyleDeclaration* style) const +InspectorCSSId InspectorStyleSheet::styleId(CSSStyleDeclaration* style) const { unsigned index = ruleIndexByStyle(style); if (index != UINT_MAX) @@ -1496,21 +1369,36 @@ InspectorCSSId InspectorStyleSheet::ruleOrStyleId(CSSStyleDeclaration* style) co return InspectorCSSId(); } -Document* InspectorStyleSheet::ownerDocument() const +bool InspectorStyleSheet::findRuleBySelectorRange(const SourceRange& sourceRange, InspectorCSSId* ruleId) { - return m_pageStyleSheet->ownerDocument(); + if (!ensureParsedDataReady()) + return false; + for (size_t i = 0; i < ruleCount(); ++i) { + RefPtrWillBeRawPtr<CSSRuleSourceData> ruleSourceData = ruleSourceDataAt(i); + if (!ruleSourceData->styleSourceData) + continue; + if (ruleSourceData->ruleHeaderRange.start == sourceRange.start && ruleSourceData->ruleHeaderRange.end == sourceRange.end) { + *ruleId = InspectorCSSId(id(), i); + return true; + } + } + return false; } -PassRefPtr<CSSRuleSourceData> InspectorStyleSheet::ruleSourceDataFor(CSSStyleDeclaration* style) const +const CSSRuleVector& InspectorStyleSheet::flatRules() { - return m_parsedStyleSheet->ruleSourceDataAt(ruleIndexByStyle(style)); + ensureFlatRules(); + return m_flatRules; } -PassOwnPtr<Vector<unsigned> > InspectorStyleSheet::lineEndings() const +Document* InspectorStyleSheet::ownerDocument() const { - if (!m_parsedStyleSheet->hasText()) - return PassOwnPtr<Vector<unsigned> >(); - return WTF::lineEndings(m_parsedStyleSheet->text()); + return m_pageStyleSheet->ownerDocument(); +} + +PassRefPtrWillBeRawPtr<CSSRuleSourceData> InspectorStyleSheet::ruleSourceDataAt(unsigned ruleIndex) const +{ + return m_parsedStyleSheet->ruleSourceDataAt(ruleIndex); } unsigned InspectorStyleSheet::ruleIndexByStyle(CSSStyleDeclaration* pageStyle) const @@ -1524,31 +1412,13 @@ unsigned InspectorStyleSheet::ruleIndexByStyle(CSSStyleDeclaration* pageStyle) c return UINT_MAX; } -unsigned InspectorStyleSheet::ruleIndexByRule(const CSSRule* rule) const -{ - ensureFlatRules(); - size_t index = m_flatRules.find(rule); - return index == kNotFound ? UINT_MAX : static_cast<unsigned>(index); -} - -bool InspectorStyleSheet::checkPageStyleSheet(ExceptionState& exceptionState) const -{ - if (!m_pageStyleSheet) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return false; - } - return true; -} - bool InspectorStyleSheet::ensureParsedDataReady() { - return ensureText() && ensureSourceData(); + return ensureText() && m_parsedStyleSheet->ensureSourceData(); } bool InspectorStyleSheet::ensureText() const { - if (!m_parsedStyleSheet) - return false; if (m_parsedStyleSheet->hasText()) return true; @@ -1561,20 +1431,30 @@ bool InspectorStyleSheet::ensureText() const return success; } -bool InspectorStyleSheet::ensureSourceData() +static void collectFlatRules(PassRefPtrWillBeRawPtr<CSSRuleList> ruleList, CSSRuleVector* result) { - if (m_parsedStyleSheet->hasSourceData()) - return true; + if (!ruleList) + return; - if (!m_parsedStyleSheet->hasText()) - return false; + for (unsigned i = 0, size = ruleList->length(); i < size; ++i) { + CSSRule* rule = ruleList->item(i); - RefPtr<StyleSheetContents> newStyleSheet = StyleSheetContents::create(); - OwnPtr<RuleSourceDataList> result = adoptPtr(new RuleSourceDataList()); - StyleSheetHandler handler(m_parsedStyleSheet->text(), m_pageStyleSheet->ownerDocument(), newStyleSheet.get(), result.get()); - createCSSParser(m_pageStyleSheet->ownerDocument())->parseSheet(newStyleSheet.get(), m_parsedStyleSheet->text(), TextPosition::minimumPosition(), &handler); - m_parsedStyleSheet->setSourceData(result.release()); - return m_parsedStyleSheet->hasSourceData(); + // The result->append()'ed types should be exactly the same as in ParsedStyleSheet::flattenSourceData(). + switch (rule->type()) { + case CSSRule::STYLE_RULE: + result->append(rule); + continue; + case CSSRule::IMPORT_RULE: + case CSSRule::MEDIA_RULE: + result->append(rule); + break; + default: + break; + } + RefPtrWillBeRawPtr<CSSRuleList> childRuleList = asCSSRuleList(rule); + if (childRuleList) + collectFlatRules(childRuleList, result); + } } void InspectorStyleSheet::ensureFlatRules() const @@ -1584,10 +1464,12 @@ void InspectorStyleSheet::ensureFlatRules() const collectFlatRules(asCSSRuleList(pageStyleSheet()), &m_flatRules); } -bool InspectorStyleSheet::setStyleText(CSSStyleDeclaration* style, const String& text) +bool InspectorStyleSheet::setStyleText(const InspectorCSSId& id, const String& text) { - if (!m_pageStyleSheet) + CSSStyleDeclaration* style = styleForId(id); + if (!style) return false; + if (!ensureParsedDataReady()) return false; @@ -1596,14 +1478,12 @@ bool InspectorStyleSheet::setStyleText(CSSStyleDeclaration* style, const String& if (!success) return false; - InspectorCSSId id = ruleOrStyleId(style); - if (id.isEmpty()) - return false; - TrackExceptionState exceptionState; style->setCSSText(text, exceptionState); - if (!exceptionState.hadException()) + if (!exceptionState.hadException()) { m_parsedStyleSheet->setText(patchedStyleSheetText); + fireStyleSheetChanged(); + } return !exceptionState.hadException(); } @@ -1612,11 +1492,10 @@ bool InspectorStyleSheet::styleSheetTextWithChangedStyle(CSSStyleDeclaration* st { if (!style) return false; - if (!ensureParsedDataReady()) return false; - RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(style); + RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = ruleSourceDataAt(styleId(style).ordinal()); unsigned bodyStart = sourceData->ruleBodyRange.start; unsigned bodyEnd = sourceData->ruleBodyRange.end; ASSERT(bodyStart <= bodyEnd); @@ -1631,25 +1510,7 @@ bool InspectorStyleSheet::styleSheetTextWithChangedStyle(CSSStyleDeclaration* st InspectorCSSId InspectorStyleSheet::ruleId(CSSStyleRule* rule) const { - return ruleOrStyleId(rule->style()); -} - -void InspectorStyleSheet::revalidateStyle(CSSStyleDeclaration* pageStyle) -{ - if (m_isRevalidating) - return; - - m_isRevalidating = true; - ensureFlatRules(); - for (unsigned i = 0, size = m_flatRules.size(); i < size; ++i) { - CSSStyleRule* parsedRule = InspectorCSSAgent::asCSSStyleRule(m_flatRules.at(i).get()); - if (parsedRule && parsedRule->style() == pageStyle) { - if (parsedRule->styleRule()->properties()->asText() != pageStyle->cssText()) - setStyleText(pageStyle, pageStyle->cssText()); - break; - } - } - m_isRevalidating = false; + return styleId(rule->style()); } bool InspectorStyleSheet::originalStyleSheetText(String* result) const @@ -1665,7 +1526,7 @@ bool InspectorStyleSheet::resourceStyleSheetText(String* result) const if (m_origin == TypeBuilder::CSS::StyleSheetOrigin::User || m_origin == TypeBuilder::CSS::StyleSheetOrigin::User_agent) return false; - if (!m_pageStyleSheet || !ownerDocument() || !ownerDocument()->frame()) + if (!ownerDocument() || !ownerDocument()->frame()) return false; bool base64Encoded; @@ -1675,29 +1536,26 @@ bool InspectorStyleSheet::resourceStyleSheetText(String* result) const bool InspectorStyleSheet::inlineStyleSheetText(String* result) const { - if (!m_pageStyleSheet) - return false; - Node* ownerNode = m_pageStyleSheet->ownerNode(); - if (!ownerNode || ownerNode->nodeType() != Node::ELEMENT_NODE) + if (!ownerNode || !ownerNode->isElementNode()) return false; - Element* ownerElement = toElement(ownerNode); + Element& ownerElement = toElement(*ownerNode); - if (!ownerElement->hasTagName(HTMLNames::styleTag) && !ownerElement->hasTagName(SVGNames::styleTag)) + if (!isHTMLStyleElement(ownerElement) && !isSVGStyleElement(ownerElement)) return false; - *result = ownerElement->textContent(); + *result = ownerElement.textContent(); return true; } -PassRefPtr<InspectorStyleSheetForInlineStyle> InspectorStyleSheetForInlineStyle::create(InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent, const String& id, PassRefPtr<Element> element, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, Listener* listener) +PassRefPtr<InspectorStyleSheetForInlineStyle> InspectorStyleSheetForInlineStyle::create(const String& id, PassRefPtrWillBeRawPtr<Element> element, Listener* listener) { - return adoptRef(new InspectorStyleSheetForInlineStyle(pageAgent, resourceAgent, id, element, origin, listener)); + return adoptRef(new InspectorStyleSheetForInlineStyle(id, element, listener)); } -InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(InspectorPageAgent* pageAgent, InspectorResourceAgent* resourceAgent, const String& id, PassRefPtr<Element> element, TypeBuilder::CSS::StyleSheetOrigin::Enum origin, Listener* listener) - : InspectorStyleSheet(pageAgent, resourceAgent, id, 0, origin, "", listener) +InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(const String& id, PassRefPtrWillBeRawPtr<Element> element, Listener* listener) + : InspectorStyleSheetBase(id, listener) , m_element(element) - , m_ruleSourceData(0) + , m_ruleSourceData(nullptr) , m_isStyleTextValid(false) { ASSERT(m_element); @@ -1713,6 +1571,16 @@ void InspectorStyleSheetForInlineStyle::didModifyElementAttribute() m_ruleSourceData.clear(); } +bool InspectorStyleSheetForInlineStyle::setText(const String& text, ExceptionState& exceptionState) +{ + bool success = setStyleText(InspectorCSSId(id(), 0), text); + if (!success) + exceptionState.throwDOMException(SyntaxError, "Style sheet text is invalid."); + else + fireStyleSheetChanged(); + return success; +} + bool InspectorStyleSheetForInlineStyle::getText(String* result) const { if (!m_isStyleTextValid) { @@ -1723,8 +1591,11 @@ bool InspectorStyleSheetForInlineStyle::getText(String* result) const return true; } -bool InspectorStyleSheetForInlineStyle::setStyleText(CSSStyleDeclaration* style, const String& text) +bool InspectorStyleSheetForInlineStyle::setStyleText(const InspectorCSSId& id, const String& text) { + CSSStyleDeclaration* style = styleForId(id); + if (!style) + return false; ASSERT_UNUSED(style, style == inlineStyle()); TrackExceptionState exceptionState; @@ -1732,18 +1603,15 @@ bool InspectorStyleSheetForInlineStyle::setStyleText(CSSStyleDeclaration* style, InspectorCSSAgent::InlineStyleOverrideScope overrideScope(m_element->ownerDocument()); m_element->setAttribute("style", AtomicString(text), exceptionState); } - - m_styleText = text; - m_isStyleTextValid = true; - m_ruleSourceData.clear(); + if (!exceptionState.hadException()) { + m_styleText = text; + m_isStyleTextValid = true; + m_ruleSourceData.clear(); + fireStyleSheetChanged(); + } return !exceptionState.hadException(); } -PassOwnPtr<Vector<unsigned> > InspectorStyleSheetForInlineStyle::lineEndings() const -{ - return WTF::lineEndings(elementStyleText()); -} - Document* InspectorStyleSheetForInlineStyle::ownerDocument() const { return &m_element->document(); @@ -1789,22 +1657,22 @@ const String& InspectorStyleSheetForInlineStyle::elementStyleText() const return m_element->getAttribute("style").string(); } -PassRefPtr<CSSRuleSourceData> InspectorStyleSheetForInlineStyle::getStyleAttributeData() const +PassRefPtrWillBeRawPtr<CSSRuleSourceData> InspectorStyleSheetForInlineStyle::getStyleAttributeData() const { if (!m_element->isStyledElement()) - return 0; + return nullptr; if (m_styleText.isEmpty()) { - RefPtr<CSSRuleSourceData> result = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE); + RefPtrWillBeRawPtr<CSSRuleSourceData> result = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE); result->ruleBodyRange.start = 0; result->ruleBodyRange.end = 0; return result.release(); } - RefPtr<MutableStylePropertySet> tempDeclaration = MutableStylePropertySet::create(); + RefPtrWillBeRawPtr<MutableStylePropertySet> tempDeclaration = MutableStylePropertySet::create(); RuleSourceDataList ruleSourceDataResult; - StyleSheetHandler handler(m_styleText, &m_element->document(), m_element->document().elementSheet()->contents(), &ruleSourceDataResult); - createCSSParser(&m_element->document())->parseDeclaration(tempDeclaration.get(), m_styleText, &handler, m_element->document().elementSheet()->contents()); + StyleSheetHandler handler(m_styleText, &m_element->document(), m_element->document().elementSheet().contents(), &ruleSourceDataResult); + BisonCSSParser(parserContextForDocument(&m_element->document())).parseDeclaration(tempDeclaration.get(), m_styleText, &handler, m_element->document().elementSheet().contents()); return ruleSourceDataResult.first().release(); } |