summaryrefslogtreecommitdiff
path: root/Source/WebCore/inspector/InspectorStyleSheet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/inspector/InspectorStyleSheet.cpp')
-rw-r--r--Source/WebCore/inspector/InspectorStyleSheet.cpp1374
1 files changed, 701 insertions, 673 deletions
diff --git a/Source/WebCore/inspector/InspectorStyleSheet.cpp b/Source/WebCore/inspector/InspectorStyleSheet.cpp
index 85cb2c461..b0c725ae2 100644
--- a/Source/WebCore/inspector/InspectorStyleSheet.cpp
+++ b/Source/WebCore/inspector/InspectorStyleSheet.cpp
@@ -23,16 +23,15 @@
*/
#include "config.h"
-
-#if ENABLE(INSPECTOR)
-
#include "InspectorStyleSheet.h"
-#include "CSSHostRule.h"
#include "CSSImportRule.h"
+#include "CSSKeyframesRule.h"
#include "CSSMediaRule.h"
#include "CSSParser.h"
+#include "CSSParserObserver.h"
#include "CSSPropertyNames.h"
+#include "CSSPropertyParser.h"
#include "CSSPropertySourceData.h"
#include "CSSRule.h"
#include "CSSRuleList.h"
@@ -42,30 +41,28 @@
#include "ContentSecurityPolicy.h"
#include "Document.h"
#include "Element.h"
+#include "ExceptionCode.h"
#include "HTMLHeadElement.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "HTMLStyleElement.h"
#include "InspectorCSSAgent.h"
#include "InspectorPageAgent.h"
+#include "MediaList.h"
#include "Node.h"
-#include "SVGNames.h"
+#include "SVGElement.h"
+#include "SVGStyleElement.h"
#include "StyleProperties.h"
#include "StyleResolver.h"
#include "StyleRule.h"
#include "StyleRuleImport.h"
#include "StyleSheetContents.h"
#include "StyleSheetList.h"
-#include "WebKitCSSKeyframesRule.h"
#include <inspector/ContentSearchUtilities.h>
-#include <inspector/InspectorValues.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/Vector.h>
#include <wtf/text/StringBuilder.h>
#include <yarr/RegularExpression.h>
-using Inspector::TypeBuilder::Array;
+using Inspector::Protocol::Array;
using WebCore::RuleSourceDataList;
using WebCore::CSSRuleSourceData;
@@ -78,15 +75,15 @@ public:
void setText(const String& text);
bool hasText() const { return m_hasText; }
RuleSourceDataList* sourceData() const { return m_sourceData.get(); }
- void setSourceData(PassOwnPtr<RuleSourceDataList>);
- bool hasSourceData() const { return m_sourceData; }
- PassRefPtr<WebCore::CSSRuleSourceData> ruleSourceDataAt(unsigned) const;
+ void setSourceData(std::unique_ptr<RuleSourceDataList>);
+ bool hasSourceData() const { return m_sourceData != nullptr; }
+ WebCore::CSSRuleSourceData* ruleSourceDataAt(unsigned) const;
private:
String m_text;
bool m_hasText;
- OwnPtr<RuleSourceDataList> m_sourceData;
+ std::unique_ptr<RuleSourceDataList> m_sourceData;
};
ParsedStyleSheet::ParsedStyleSheet()
@@ -101,52 +98,286 @@ void ParsedStyleSheet::setText(const String& text)
setSourceData(nullptr);
}
-static void flattenSourceData(RuleSourceDataList* dataList, RuleSourceDataList* target)
+static void flattenSourceData(RuleSourceDataList& dataList, RuleSourceDataList& target)
{
- for (size_t i = 0; i < dataList->size(); ++i) {
- RefPtr<CSSRuleSourceData>& data = dataList->at(i);
- if (data->type == CSSRuleSourceData::STYLE_RULE)
- target->append(data);
- else if (data->type == CSSRuleSourceData::MEDIA_RULE)
- flattenSourceData(&data->childRules, target);
-#if ENABLE(SHADOW_DOM)
- else if (data->type == CSSRuleSourceData::HOST_RULE)
- flattenSourceData(&data->childRules, target);
-#endif
-#if ENABLE(CSS3_CONDITIONAL_RULES)
- else if (data->type == CSSRuleSourceData::SUPPORTS_RULE)
- flattenSourceData(&data->childRules, target);
-#endif
+ for (auto& data : dataList) {
+ if (data->type == WebCore::StyleRule::Style)
+ target.append(data.copyRef());
+ else if (data->type == WebCore::StyleRule::Media)
+ flattenSourceData(data->childRules, target);
+ else if (data->type == WebCore::StyleRule::Supports)
+ flattenSourceData(data->childRules, target);
}
}
-void ParsedStyleSheet::setSourceData(PassOwnPtr<RuleSourceDataList> sourceData)
+void ParsedStyleSheet::setSourceData(std::unique_ptr<RuleSourceDataList> sourceData)
{
if (!sourceData) {
- m_sourceData.clear();
+ m_sourceData.reset();
return;
}
- m_sourceData = adoptPtr(new RuleSourceDataList());
+ m_sourceData = std::make_unique<RuleSourceDataList>();
// 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(), m_sourceData.get());
+ flattenSourceData(*sourceData, *m_sourceData);
}
-PassRefPtr<WebCore::CSSRuleSourceData> ParsedStyleSheet::ruleSourceDataAt(unsigned index) const
+WebCore::CSSRuleSourceData* ParsedStyleSheet::ruleSourceDataAt(unsigned index) const
{
if (!hasSourceData() || index >= m_sourceData->size())
return nullptr;
- return m_sourceData->at(index);
+ return m_sourceData->at(index).ptr();
}
using namespace Inspector;
namespace WebCore {
+static CSSParserContext parserContextForDocument(Document* document)
+{
+ return document ? CSSParserContext(*document) : strictCSSParserContext();
+}
+
+class StyleSheetHandler : public CSSParserObserver {
+public:
+ StyleSheetHandler(const String& parsedText, Document* document, RuleSourceDataList* result)
+ : m_parsedText(parsedText)
+ , m_document(document)
+ , m_ruleSourceDataResult(result)
+ {
+ ASSERT(m_ruleSourceDataResult);
+ }
+
+private:
+ void startRuleHeader(StyleRule::Type, unsigned) override;
+ void endRuleHeader(unsigned) override;
+ void observeSelector(unsigned startOffset, unsigned endOffset) override;
+ void startRuleBody(unsigned) override;
+ void endRuleBody(unsigned) override;
+ void observeProperty(unsigned startOffset, unsigned endOffset, bool isImportant, bool isParsed) override;
+ void observeComment(unsigned startOffset, unsigned endOffset) override;
+
+ Ref<CSSRuleSourceData> popRuleData();
+ template <typename CharacterType> inline void setRuleHeaderEnd(const CharacterType*, unsigned);
+ void fixUnparsedPropertyRanges(CSSRuleSourceData*);
+
+ const String& m_parsedText;
+ Document* m_document;
+
+ RuleSourceDataList m_currentRuleDataStack;
+ RefPtr<CSSRuleSourceData> m_currentRuleData;
+ RuleSourceDataList* m_ruleSourceDataResult { nullptr };
+};
+
+void StyleSheetHandler::startRuleHeader(StyleRule::Type type, unsigned offset)
+{
+ // Pop off data for a previous invalid rule.
+ if (m_currentRuleData)
+ m_currentRuleDataStack.removeLast();
+
+ auto data = CSSRuleSourceData::create(type);
+ data->ruleHeaderRange.start = offset;
+ m_currentRuleData = data.copyRef();
+ m_currentRuleDataStack.append(WTFMove(data));
+}
+
+template <typename CharacterType> inline void StyleSheetHandler::setRuleHeaderEnd(const CharacterType* dataStart, unsigned listEndOffset)
+{
+ while (listEndOffset > 1) {
+ if (isHTMLSpace<CharacterType>(*(dataStart + listEndOffset - 1)))
+ --listEndOffset;
+ else
+ break;
+ }
+
+ m_currentRuleDataStack.last()->ruleHeaderRange.end = listEndOffset;
+ if (!m_currentRuleDataStack.last()->selectorRanges.isEmpty())
+ m_currentRuleDataStack.last()->selectorRanges.last().end = listEndOffset;
+}
+
+void StyleSheetHandler::endRuleHeader(unsigned offset)
+{
+ ASSERT(!m_currentRuleDataStack.isEmpty());
+
+ if (m_parsedText.is8Bit())
+ setRuleHeaderEnd<LChar>(m_parsedText.characters8(), offset);
+ else
+ setRuleHeaderEnd<UChar>(m_parsedText.characters16(), offset);
+}
+
+void StyleSheetHandler::observeSelector(unsigned startOffset, unsigned endOffset)
+{
+ ASSERT(m_currentRuleDataStack.size());
+ m_currentRuleDataStack.last()->selectorRanges.append(SourceRange(startOffset, endOffset));
+}
+
+void StyleSheetHandler::startRuleBody(unsigned offset)
+{
+ m_currentRuleData = nullptr;
+ ASSERT(!m_currentRuleDataStack.isEmpty());
+
+ // Skip the rule body opening brace.
+ if (m_parsedText[offset] == '{')
+ ++offset;
+
+ m_currentRuleDataStack.last()->ruleBodyRange.start = offset;
+}
+
+void StyleSheetHandler::endRuleBody(unsigned offset)
+{
+ ASSERT(!m_currentRuleDataStack.isEmpty());
+ m_currentRuleDataStack.last()->ruleBodyRange.end = offset;
+ auto rule = popRuleData();
+ fixUnparsedPropertyRanges(rule.ptr());
+ if (m_currentRuleDataStack.isEmpty())
+ m_ruleSourceDataResult->append(WTFMove(rule));
+ else
+ m_currentRuleDataStack.last()->childRules.append(WTFMove(rule));
+}
+
+Ref<CSSRuleSourceData> StyleSheetHandler::popRuleData()
+{
+ ASSERT(!m_currentRuleDataStack.isEmpty());
+ m_currentRuleData = nullptr;
+ auto data = WTFMove(m_currentRuleDataStack.last());
+ m_currentRuleDataStack.removeLast();
+ return data;
+}
+
+template <typename CharacterType>
+static inline void fixUnparsedProperties(const CharacterType* characters, CSSRuleSourceData* ruleData)
+{
+ Vector<CSSPropertySourceData>& propertyData = ruleData->styleSourceData->propertyData;
+ unsigned size = propertyData.size();
+ if (!size)
+ return;
+
+ unsigned styleStart = ruleData->ruleBodyRange.start;
+
+ CSSPropertySourceData* nextData = &(propertyData.at(0));
+ for (unsigned i = 0; i < size; ++i) {
+ CSSPropertySourceData* currentData = nextData;
+ nextData = i < size - 1 ? &(propertyData.at(i + 1)) : nullptr;
+
+ if (currentData->parsedOk)
+ continue;
+ if (currentData->range.end > 0 && characters[styleStart + currentData->range.end - 1] == ';')
+ continue;
+
+ unsigned propertyEnd;
+ if (!nextData)
+ propertyEnd = ruleData->ruleBodyRange.end - 1;
+ else
+ propertyEnd = styleStart + nextData->range.start - 1;
+
+ while (isHTMLSpace<CharacterType>(characters[propertyEnd]))
+ --propertyEnd;
+
+ // propertyEnd points at the last property text character.
+ unsigned newPropertyEnd = propertyEnd + styleStart + 1;
+ if (currentData->range.end != newPropertyEnd) {
+ currentData->range.end = newPropertyEnd;
+ unsigned valueStart = styleStart + currentData->range.start + currentData->name.length();
+ while (valueStart < propertyEnd && characters[valueStart] != ':')
+ ++valueStart;
+
+ // Shift past the ':'.
+ if (valueStart < propertyEnd)
+ ++valueStart;
+
+ while (valueStart < propertyEnd && isHTMLSpace<CharacterType>(characters[valueStart]))
+ ++valueStart;
+
+ // Need to exclude the trailing ';' from the property value.
+ currentData->value = String(characters + valueStart, propertyEnd - valueStart + (characters[propertyEnd] == ';' ? 0 : 1));
+ }
+ }
+}
+
+void StyleSheetHandler::fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData)
+{
+ if (!ruleData->styleSourceData)
+ return;
+
+ if (m_parsedText.is8Bit()) {
+ fixUnparsedProperties<LChar>(m_parsedText.characters8(), ruleData);
+ return;
+ }
+
+ fixUnparsedProperties<UChar>(m_parsedText.characters16(), ruleData);
+}
+
+void StyleSheetHandler::observeProperty(unsigned startOffset, unsigned endOffset, bool isImportant, bool isParsed)
+{
+ if (m_currentRuleDataStack.isEmpty() || !m_currentRuleDataStack.last()->styleSourceData)
+ return;
+
+ ASSERT(endOffset <= m_parsedText.length());
+
+ // Include semicolon in the property text.
+ if (endOffset < m_parsedText.length() && m_parsedText[endOffset] == ';')
+ ++endOffset;
+
+ ASSERT(startOffset < endOffset);
+ String propertyString = m_parsedText.substring(startOffset, endOffset - startOffset).stripWhiteSpace();
+ if (propertyString.endsWith(';'))
+ propertyString = propertyString.left(propertyString.length() - 1);
+ size_t colonIndex = propertyString.find(':');
+ ASSERT(colonIndex != notFound);
+
+ String name = propertyString.left(colonIndex).stripWhiteSpace();
+ String value = propertyString.substring(colonIndex + 1, propertyString.length()).stripWhiteSpace();
+
+ // FIXME-NEWPARSER: The property range is relative to the declaration start offset, but no
+ // good reason for it, and it complicates fixUnparsedProperties.
+ SourceRange& topRuleBodyRange = m_currentRuleDataStack.last()->ruleBodyRange;
+ m_currentRuleDataStack.last()->styleSourceData->propertyData.append(CSSPropertySourceData(name, value, isImportant, false, isParsed, SourceRange(startOffset - topRuleBodyRange.start, endOffset - topRuleBodyRange.start)));
+}
+
+void StyleSheetHandler::observeComment(unsigned startOffset, unsigned endOffset)
+{
+ ASSERT(endOffset <= m_parsedText.length());
+
+ if (m_currentRuleDataStack.isEmpty() || !m_currentRuleDataStack.last()->ruleHeaderRange.end || !m_currentRuleDataStack.last()->styleSourceData)
+ return;
+
+ // The lexer is not inside a property AND it is scanning a declaration-aware
+ // rule body.
+ String commentText = m_parsedText.substring(startOffset, endOffset - startOffset);
+
+ ASSERT(commentText.startsWith("/*"));
+ commentText = commentText.substring(2);
+
+ // Require well-formed comments.
+ if (!commentText.endsWith("*/"))
+ return;
+ commentText = commentText.substring(0, commentText.length() - 2).stripWhiteSpace();
+ if (commentText.isEmpty())
+ return;
+
+ // FIXME: Use the actual rule type rather than STYLE_RULE?
+ RuleSourceDataList sourceData;
+
+ StyleSheetHandler handler(commentText, m_document, &sourceData);
+ CSSParser::parseDeclarationForInspector(parserContextForDocument(m_document), commentText, handler);
+ Vector<CSSPropertySourceData>& commentPropertyData = sourceData.first()->styleSourceData->propertyData;
+ if (commentPropertyData.size() != 1)
+ return;
+ CSSPropertySourceData& propertyData = commentPropertyData.at(0);
+ bool parsedOk = propertyData.parsedOk || propertyData.name.startsWith("-moz-") || propertyData.name.startsWith("-o-") || propertyData.name.startsWith("-webkit-") || propertyData.name.startsWith("-ms-");
+ if (!parsedOk || propertyData.range.length() != commentText.length())
+ return;
+
+ // FIXME-NEWPARSER: The property range is relative to the declaration start offset, but no
+ // good reason for it, and it complicates fixUnparsedProperties.
+ SourceRange& topRuleBodyRange = m_currentRuleDataStack.last()->ruleBodyRange;
+ m_currentRuleDataStack.last()->styleSourceData->propertyData.append(CSSPropertySourceData(propertyData.name, propertyData.value, false, true, true, SourceRange(startOffset - topRuleBodyRange.start, endOffset - topRuleBodyRange.start)));
+}
+
enum MediaListSource {
MediaListSourceLinkedSheet,
MediaListSourceInlineSheet,
@@ -154,92 +385,85 @@ enum MediaListSource {
MediaListSourceImportRule
};
-static PassRefPtr<Inspector::TypeBuilder::CSS::SourceRange> buildSourceRangeObject(const SourceRange& range, Vector<size_t>* lineEndings)
+static RefPtr<Inspector::Protocol::CSS::SourceRange> buildSourceRangeObject(const SourceRange& range, Vector<size_t>* lineEndings, int* endingLine = nullptr)
{
if (!lineEndings)
return nullptr;
TextPosition start = ContentSearchUtilities::textPositionFromOffset(range.start, *lineEndings);
TextPosition end = ContentSearchUtilities::textPositionFromOffset(range.end, *lineEndings);
- RefPtr<Inspector::TypeBuilder::CSS::SourceRange> result = Inspector::TypeBuilder::CSS::SourceRange::create()
+ if (endingLine)
+ *endingLine = end.m_line.zeroBasedInt();
+
+ return Inspector::Protocol::CSS::SourceRange::create()
.setStartLine(start.m_line.zeroBasedInt())
.setStartColumn(start.m_column.zeroBasedInt())
.setEndLine(end.m_line.zeroBasedInt())
- .setEndColumn(end.m_column.zeroBasedInt());
- return result.release();
+ .setEndColumn(end.m_column.zeroBasedInt())
+ .release();
}
-static PassRefPtr<Inspector::TypeBuilder::CSS::CSSMedia> buildMediaObject(const MediaList* media, MediaListSource mediaListSource, const String& sourceURL)
+static Ref<Inspector::Protocol::CSS::CSSMedia> buildMediaObject(const MediaList* media, MediaListSource mediaListSource, const String& sourceURL)
{
// Make certain compilers happy by initializing |source| up-front.
- Inspector::TypeBuilder::CSS::CSSMedia::Source::Enum source = Inspector::TypeBuilder::CSS::CSSMedia::Source::InlineSheet;
+ Inspector::Protocol::CSS::CSSMedia::Source source = Inspector::Protocol::CSS::CSSMedia::Source::InlineSheet;
switch (mediaListSource) {
case MediaListSourceMediaRule:
- source = Inspector::TypeBuilder::CSS::CSSMedia::Source::MediaRule;
+ source = Inspector::Protocol::CSS::CSSMedia::Source::MediaRule;
break;
case MediaListSourceImportRule:
- source = Inspector::TypeBuilder::CSS::CSSMedia::Source::ImportRule;
+ source = Inspector::Protocol::CSS::CSSMedia::Source::ImportRule;
break;
case MediaListSourceLinkedSheet:
- source = Inspector::TypeBuilder::CSS::CSSMedia::Source::LinkedSheet;
+ source = Inspector::Protocol::CSS::CSSMedia::Source::LinkedSheet;
break;
case MediaListSourceInlineSheet:
- source = Inspector::TypeBuilder::CSS::CSSMedia::Source::InlineSheet;
+ source = Inspector::Protocol::CSS::CSSMedia::Source::InlineSheet;
break;
}
- RefPtr<Inspector::TypeBuilder::CSS::CSSMedia> mediaObject = Inspector::TypeBuilder::CSS::CSSMedia::create()
+ auto mediaObject = Inspector::Protocol::CSS::CSSMedia::create()
.setText(media->mediaText())
- .setSource(source);
+ .setSource(source)
+ .release();
if (!sourceURL.isEmpty()) {
mediaObject->setSourceURL(sourceURL);
mediaObject->setSourceLine(media->queries()->lastLine());
}
- return mediaObject.release();
+ return mediaObject;
}
-static PassRefPtr<CSSRuleList> asCSSRuleList(CSSStyleSheet* styleSheet)
+static RefPtr<CSSRuleList> asCSSRuleList(CSSStyleSheet* styleSheet)
{
if (!styleSheet)
return nullptr;
RefPtr<StaticCSSRuleList> list = StaticCSSRuleList::create();
Vector<RefPtr<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)
- continue;
- listRules.append(item);
- }
- return list.release();
+ for (unsigned i = 0, size = styleSheet->length(); i < size; ++i)
+ listRules.append(styleSheet->item(i));
+ return WTFMove(list);
}
-static PassRefPtr<CSSRuleList> asCSSRuleList(CSSRule* rule)
+static RefPtr<CSSRuleList> asCSSRuleList(CSSRule* rule)
{
if (!rule)
return nullptr;
- if (rule->type() == CSSRule::MEDIA_RULE)
- return static_cast<CSSMediaRule*>(rule)->cssRules();
+ if (is<CSSMediaRule>(*rule))
+ return &downcast<CSSMediaRule>(*rule).cssRules();
- if (rule->type() == CSSRule::WEBKIT_KEYFRAMES_RULE)
- return static_cast<WebKitCSSKeyframesRule*>(rule)->cssRules();
+ if (is<CSSKeyframesRule>(*rule))
+ return &downcast<CSSKeyframesRule>(*rule).cssRules();
-#if ENABLE(SHADOW_DOM)
- if (rule->type() == CSSRule::HOST_RULE)
- return static_cast<CSSHostRule*>(rule)->cssRules();
-#endif
-
-#if ENABLE(CSS3_CONDITIONAL_RULES)
- if (rule->type() == CSSRule::SUPPORTS_RULE)
- return static_cast<CSSSupportsRule*>(rule)->cssRules();
-#endif
+ if (is<CSSSupportsRule>(*rule))
+ return &downcast<CSSSupportsRule>(*rule).cssRules();
return nullptr;
}
-static void fillMediaListChain(CSSRule* rule, Array<Inspector::TypeBuilder::CSS::CSSMedia>* mediaArray)
+static void fillMediaListChain(CSSRule* rule, Array<Inspector::Protocol::CSS::CSSMedia>& mediaArray)
{
MediaList* mediaList;
CSSRule* parentRule = rule;
@@ -247,14 +471,14 @@ static void fillMediaListChain(CSSRule* rule, Array<Inspector::TypeBuilder::CSS:
while (parentRule) {
CSSStyleSheet* parentStyleSheet = nullptr;
bool isMediaRule = true;
- if (parentRule->type() == CSSRule::MEDIA_RULE) {
- CSSMediaRule* mediaRule = static_cast<CSSMediaRule*>(parentRule);
- mediaList = mediaRule->media();
- parentStyleSheet = mediaRule->parentStyleSheet();
- } else if (parentRule->type() == CSSRule::IMPORT_RULE) {
- CSSImportRule* importRule = static_cast<CSSImportRule*>(parentRule);
- mediaList = importRule->media();
- parentStyleSheet = importRule->parentStyleSheet();
+ if (is<CSSMediaRule>(*parentRule)) {
+ CSSMediaRule& mediaRule = downcast<CSSMediaRule>(*parentRule);
+ mediaList = mediaRule.media();
+ parentStyleSheet = mediaRule.parentStyleSheet();
+ } else if (is<CSSImportRule>(*parentRule)) {
+ CSSImportRule& importRule = downcast<CSSImportRule>(*parentRule);
+ mediaList = &importRule.media();
+ parentStyleSheet = importRule.parentStyleSheet();
isMediaRule = false;
} else
mediaList = nullptr;
@@ -264,10 +488,10 @@ static void fillMediaListChain(CSSRule* rule, Array<Inspector::TypeBuilder::CSS:
if (sourceURL.isEmpty())
sourceURL = InspectorDOMAgent::documentURLString(parentStyleSheet->ownerDocument());
} else
- sourceURL = "";
+ sourceURL = emptyString();
if (mediaList && mediaList->length())
- mediaArray->addItem(buildMediaObject(mediaList, isMediaRule ? MediaListSourceMediaRule : MediaListSourceImportRule, sourceURL));
+ mediaArray.addItem(buildMediaObject(mediaList, isMediaRule ? MediaListSourceMediaRule : MediaListSourceImportRule, sourceURL));
if (parentRule->parentRule())
parentRule = parentRule->parentRule();
@@ -282,8 +506,8 @@ static void fillMediaListChain(CSSRule* rule, Array<Inspector::TypeBuilder::CSS:
else if (!styleSheet->contents().baseURL().isEmpty())
sourceURL = styleSheet->contents().baseURL();
else
- sourceURL = "";
- mediaArray->addItem(buildMediaObject(mediaList, styleSheet->ownerNode() ? MediaListSourceLinkedSheet : MediaListSourceInlineSheet, sourceURL));
+ sourceURL = emptyString();
+ mediaArray.addItem(buildMediaObject(mediaList, styleSheet->ownerNode() ? MediaListSourceLinkedSheet : MediaListSourceInlineSheet, sourceURL));
}
parentRule = styleSheet->ownerRule();
if (parentRule)
@@ -294,21 +518,15 @@ static void fillMediaListChain(CSSRule* rule, Array<Inspector::TypeBuilder::CSS:
}
}
-static PassOwnPtr<CSSParser> createCSSParser(Document* document)
+Ref<InspectorStyle> InspectorStyle::create(const InspectorCSSId& styleId, RefPtr<CSSStyleDeclaration>&& style, InspectorStyleSheet* parentStyleSheet)
{
- return adoptPtr(new CSSParser(document ? CSSParserContext(*document) : strictCSSParserContext()));
+ return adoptRef(*new InspectorStyle(styleId, WTFMove(style), parentStyleSheet));
}
-PassRefPtr<InspectorStyle> InspectorStyle::create(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet)
-{
- return adoptRef(new InspectorStyle(styleId, style, parentStyleSheet));
-}
-
-InspectorStyle::InspectorStyle(const InspectorCSSId& styleId, PassRefPtr<CSSStyleDeclaration> style, InspectorStyleSheet* parentStyleSheet)
+InspectorStyle::InspectorStyle(const InspectorCSSId& styleId, RefPtr<CSSStyleDeclaration>&& style, InspectorStyleSheet* parentStyleSheet)
: m_styleId(styleId)
, m_style(style)
, m_parentStyleSheet(parentStyleSheet)
- , m_formatAcquired(false)
{
ASSERT(m_style);
}
@@ -317,11 +535,11 @@ InspectorStyle::~InspectorStyle()
{
}
-PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyle::buildObjectForStyle() const
+RefPtr<Inspector::Protocol::CSS::CSSStyle> InspectorStyle::buildObjectForStyle() const
{
- RefPtr<Inspector::TypeBuilder::CSS::CSSStyle> result = styleWithProperties();
+ Ref<Inspector::Protocol::CSS::CSSStyle> result = styleWithProperties();
if (!m_styleId.isEmpty())
- result->setStyleId(m_styleId.asProtocolValue<Inspector::TypeBuilder::CSS::CSSStyleId>());
+ result->setStyleId(m_styleId.asProtocolValue<Inspector::Protocol::CSS::CSSStyleId>());
result->setWidth(m_style->getPropertyValue("width"));
result->setHeight(m_style->getPropertyValue("height"));
@@ -330,225 +548,116 @@ PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyle::buildObjectFor
if (sourceData)
result->setRange(buildSourceRangeObject(sourceData->ruleBodyRange, m_parentStyleSheet->lineEndings().get()));
- return result.release();
+ return WTFMove(result);
}
-PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSComputedStyleProperty>> InspectorStyle::buildArrayForComputedStyle() const
+Ref<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSComputedStyleProperty>> InspectorStyle::buildArrayForComputedStyle() const
{
- RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSComputedStyleProperty>> result = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSComputedStyleProperty>::create();
+ auto result = Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSComputedStyleProperty>::create();
Vector<InspectorStyleProperty> properties;
populateAllProperties(&properties);
- for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) {
- const CSSPropertySourceData& propertyEntry = it->sourceData;
- RefPtr<Inspector::TypeBuilder::CSS::CSSComputedStyleProperty> entry = Inspector::TypeBuilder::CSS::CSSComputedStyleProperty::create()
+ for (auto& property : properties) {
+ const CSSPropertySourceData& propertyEntry = property.sourceData;
+ auto entry = Inspector::Protocol::CSS::CSSComputedStyleProperty::create()
.setName(propertyEntry.name)
- .setValue(propertyEntry.value);
- result->addItem(entry);
- }
-
- 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, ExceptionCode& ec)
-{
- ASSERT(m_parentStyleSheet);
- DEFINE_STATIC_LOCAL(String, bogusPropertyName, (ASCIILiteral("-webkit-boguz-propertee")));
-
- if (!m_parentStyleSheet->ensureParsedDataReady()) {
- ec = NOT_FOUND_ERR;
- return false;
- }
-
- if (propertyText.stripWhiteSpace().length()) {
- RefPtr<MutableStyleProperties> tempMutableStyle = MutableStyleProperties::create();
- RefPtr<CSSRuleSourceData> sourceData = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE);
- Document* ownerDocument = m_parentStyleSheet->pageStyleSheet() ? m_parentStyleSheet->pageStyleSheet()->ownerDocument() : nullptr;
- createCSSParser(ownerDocument)->parseDeclaration(tempMutableStyle.get(), propertyText + " " + bogusPropertyName + ": none", sourceData, &m_style->parentStyleSheet()->contents());
- Vector<CSSPropertySourceData>& propertyData = sourceData->styleSourceData->propertyData;
- unsigned propertyCount = propertyData.size();
-
- // At least one property + the bogus property added just above should be present.
- if (propertyCount < 2) {
- ec = SYNTAX_ERR;
- return false;
- }
-
- // Check for a proper propertyText termination (the parser could at least restore to the PROPERTY_NAME state).
- if (propertyData.at(propertyCount - 1).name != bogusPropertyName) {
- ec = SYNTAX_ERR;
- return false;
- }
- }
-
- RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
- if (!sourceData) {
- ec = NOT_FOUND_ERR;
- return false;
- }
-
- String text;
- bool success = styleText(&text);
- if (!success) {
- ec = NOT_FOUND_ERR;
- return false;
+ .setValue(propertyEntry.value)
+ .release();
+ result->addItem(WTFMove(entry));
}
- Vector<InspectorStyleProperty> allProperties;
- populateAllProperties(&allProperties);
-
- InspectorStyleTextEditor editor(&allProperties, &m_disabledProperties, text, newLineAndWhitespaceDelimiters());
- if (overwrite) {
- if (index >= allProperties.size()) {
- ec = INDEX_SIZE_ERR;
- return false;
- }
- *oldText = allProperties.at(index).rawText;
- editor.replaceProperty(index, propertyText);
- } else
- editor.insertProperty(index, propertyText, sourceData->ruleBodyRange.length());
-
- return applyStyleText(editor.styleText());
+ return result;
}
-bool InspectorStyle::toggleProperty(unsigned index, bool disable, ExceptionCode& ec)
+ExceptionOr<String> InspectorStyle::text() const
{
- ASSERT(m_parentStyleSheet);
- if (!m_parentStyleSheet->ensureParsedDataReady()) {
- ec = NO_MODIFICATION_ALLOWED_ERR;
- return false;
- }
-
- RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
- if (!sourceData) {
- ec = NOT_FOUND_ERR;
- return false;
- }
-
- String text;
- bool success = styleText(&text);
- if (!success) {
- ec = NOT_FOUND_ERR;
- return false;
- }
-
- Vector<InspectorStyleProperty> allProperties;
- populateAllProperties(&allProperties);
- if (index >= allProperties.size()) {
- ec = INDEX_SIZE_ERR;
- return false;
- }
+ // Precondition: m_parentStyleSheet->ensureParsedDataReady() has been called successfully.
+ auto sourceData = extractSourceData();
+ if (!sourceData)
+ return Exception { NOT_FOUND_ERR };
- InspectorStyleProperty& property = allProperties.at(index);
- if (property.disabled == disable)
- return true; // Idempotent operation.
+ auto result = m_parentStyleSheet->text();
+ if (result.hasException())
+ return result.releaseException();
- InspectorStyleTextEditor editor(&allProperties, &m_disabledProperties, text, newLineAndWhitespaceDelimiters());
- if (disable)
- editor.disableProperty(index);
- else
- editor.enableProperty(index);
-
- return applyStyleText(editor.styleText());
+ auto& bodyRange = sourceData->ruleBodyRange;
+ return result.releaseReturnValue().substring(bodyRange.start, bodyRange.end - bodyRange.start);
}
-bool InspectorStyle::getText(String* result) const
+static String lowercasePropertyName(const String& name)
{
- // Precondition: m_parentStyleSheet->ensureParsedDataReady() has been called successfully.
- RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
- if (!sourceData)
- return false;
-
- String styleSheetText;
- bool success = m_parentStyleSheet->getText(&styleSheetText);
- if (!success)
- return false;
-
- SourceRange& bodyRange = sourceData->ruleBodyRange;
- *result = styleSheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start);
- return true;
+ // Custom properties are case-sensitive.
+ if (name.startsWith("--"))
+ return name;
+ return name.convertToASCIILowercase();
}
-bool InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>* result) const
+void InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>* result) const
{
HashSet<String> sourcePropertyNames;
- unsigned disabledIndex = 0;
- unsigned disabledLength = m_disabledProperties.size();
- InspectorStyleProperty disabledProperty;
- if (disabledIndex < disabledLength)
- disabledProperty = m_disabledProperties.at(disabledIndex);
- RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
- Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : nullptr;
+ auto sourceData = extractSourceData();
+ auto* sourcePropertyData = sourceData ? &sourceData->styleSourceData->propertyData : nullptr;
if (sourcePropertyData) {
- String styleDeclaration;
- bool isStyleTextKnown = styleText(&styleDeclaration);
- ASSERT_UNUSED(isStyleTextKnown, isStyleTextKnown);
- for (Vector<CSSPropertySourceData>::const_iterator it = sourcePropertyData->begin(); it != sourcePropertyData->end(); ++it) {
- while (disabledIndex < disabledLength && disabledProperty.sourceData.range.start <= it->range.start) {
- result->append(disabledProperty);
- if (++disabledIndex < disabledLength)
- disabledProperty = m_disabledProperties.at(disabledIndex);
- }
- InspectorStyleProperty p(*it, true, false);
+ auto styleDeclarationOrException = text();
+ ASSERT(!styleDeclarationOrException.hasException());
+ String styleDeclaration = styleDeclarationOrException.hasException() ? emptyString() : styleDeclarationOrException.releaseReturnValue();
+ for (auto& sourceData : *sourcePropertyData) {
+ // FIXME: <https://webkit.org/b/166787> Web Inspector: Frontend should be made to expect and handle disabled properties
+ if (sourceData.disabled)
+ continue;
+ InspectorStyleProperty p(sourceData, true, sourceData.disabled);
p.setRawTextFromStyleDeclaration(styleDeclaration);
result->append(p);
- sourcePropertyNames.add(it->name.lower());
+ sourcePropertyNames.add(lowercasePropertyName(sourceData.name));
}
}
- while (disabledIndex < disabledLength) {
- disabledProperty = m_disabledProperties.at(disabledIndex++);
- result->append(disabledProperty);
- }
-
for (int i = 0, size = m_style->length(); i < size; ++i) {
String name = m_style->item(i);
- if (sourcePropertyNames.contains(name.lower()))
- continue;
-
- sourcePropertyNames.add(name.lower());
- result->append(InspectorStyleProperty(CSSPropertySourceData(name, m_style->getPropertyValue(name), !m_style->getPropertyPriority(name).isEmpty(), true, SourceRange()), false, false));
+ if (sourcePropertyNames.add(lowercasePropertyName(name)))
+ result->append(InspectorStyleProperty(CSSPropertySourceData(name, m_style->getPropertyValue(name), !m_style->getPropertyPriority(name).isEmpty(), false, true, SourceRange()), false, false));
}
-
- return true;
}
-PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithProperties() const
+Ref<Inspector::Protocol::CSS::CSSStyle> InspectorStyle::styleWithProperties() const
{
Vector<InspectorStyleProperty> properties;
populateAllProperties(&properties);
- RefPtr<Array<Inspector::TypeBuilder::CSS::CSSProperty>> propertiesObject = Array<Inspector::TypeBuilder::CSS::CSSProperty>::create();
- RefPtr<Array<Inspector::TypeBuilder::CSS::ShorthandEntry>> shorthandEntries = Array<Inspector::TypeBuilder::CSS::ShorthandEntry>::create();
- HashMap<String, RefPtr<Inspector::TypeBuilder::CSS::CSSProperty>> propertyNameToPreviousActiveProperty;
+ auto propertiesObject = Array<Inspector::Protocol::CSS::CSSProperty>::create();
+ auto shorthandEntries = Array<Inspector::Protocol::CSS::ShorthandEntry>::create();
+ HashMap<String, RefPtr<Inspector::Protocol::CSS::CSSProperty>> propertyNameToPreviousActiveProperty;
HashSet<String> foundShorthands;
String previousPriority;
String previousStatus;
- OwnPtr<Vector<size_t>> lineEndings(m_parentStyleSheet ? m_parentStyleSheet->lineEndings() : PassOwnPtr<Vector<size_t>>());
- RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
+ std::unique_ptr<Vector<size_t>> lineEndings(m_parentStyleSheet ? m_parentStyleSheet->lineEndings() : nullptr);
+ auto sourceData = extractSourceData();
unsigned ruleBodyRangeStart = sourceData ? sourceData->ruleBodyRange.start : 0;
for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) {
const CSSPropertySourceData& propertyEntry = it->sourceData;
const String& name = propertyEntry.name;
- Inspector::TypeBuilder::CSS::CSSProperty::Status::Enum status = it->disabled ? Inspector::TypeBuilder::CSS::CSSProperty::Status::Disabled : Inspector::TypeBuilder::CSS::CSSProperty::Status::Active;
+ // Visual Studio disagrees with other compilers as to whether 'class' is needed here.
+#if COMPILER(MSVC)
+ enum class Protocol::CSS::CSSPropertyStatus status;
+#else
+ enum Inspector::Protocol::CSS::CSSPropertyStatus status;
+#endif
+ status = it->disabled ? Inspector::Protocol::CSS::CSSPropertyStatus::Disabled : Inspector::Protocol::CSS::CSSPropertyStatus::Active;
+
+ RefPtr<Inspector::Protocol::CSS::CSSProperty> property = Inspector::Protocol::CSS::CSSProperty::create()
+ .setName(name.convertToASCIILowercase())
+ .setValue(propertyEntry.value)
+ .release();
- RefPtr<Inspector::TypeBuilder::CSS::CSSProperty> property = Inspector::TypeBuilder::CSS::CSSProperty::create()
- .setName(name)
- .setValue(propertyEntry.value);
+ propertiesObject->addItem(property.copyRef());
- propertiesObject->addItem(property);
+ CSSPropertyID propertyId = cssPropertyID(name);
// Default "parsedOk" == true.
- if (!propertyEntry.parsedOk)
+ if (!propertyEntry.parsedOk || isInternalCSSProperty(propertyId))
property->setParsedOk(false);
if (it->hasRawText())
property->setText(it->rawText);
@@ -571,25 +680,25 @@ PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithPrope
// 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<Inspector::TypeBuilder::CSS::CSSProperty>>::iterator activeIt = propertyNameToPreviousActiveProperty.find(canonicalPropertyName);
+ HashMap<String, RefPtr<Inspector::Protocol::CSS::CSSProperty>>::iterator activeIt = propertyNameToPreviousActiveProperty.find(canonicalPropertyName);
if (activeIt != propertyNameToPreviousActiveProperty.end()) {
if (propertyEntry.parsedOk) {
- bool successPriority = activeIt->value->getString(Inspector::TypeBuilder::CSS::CSSProperty::Priority, &previousPriority);
- bool successStatus = activeIt->value->getString(Inspector::TypeBuilder::CSS::CSSProperty::Status, &previousStatus);
+ bool successPriority = activeIt->value->getString(Inspector::Protocol::CSS::CSSProperty::Priority, previousPriority);
+ bool successStatus = activeIt->value->getString(Inspector::Protocol::CSS::CSSProperty::Status, previousStatus);
if (successStatus && previousStatus != "inactive") {
if (propertyEntry.important || !successPriority) // Priority not set == "not important".
shouldInactivate = true;
- else if (status == Inspector::TypeBuilder::CSS::CSSProperty::Status::Active) {
+ else if (status == Inspector::Protocol::CSS::CSSPropertyStatus::Active) {
// Inactivate a non-important property following the same-named important property.
- status = Inspector::TypeBuilder::CSS::CSSProperty::Status::Inactive;
+ status = Inspector::Protocol::CSS::CSSPropertyStatus::Inactive;
}
}
} else {
bool previousParsedOk;
- bool success = activeIt->value->getBoolean(Inspector::TypeBuilder::CSS::CSSProperty::ParsedOk, &previousParsedOk);
+ bool success = activeIt->value->getBoolean(Inspector::Protocol::CSS::CSSProperty::ParsedOk, previousParsedOk);
if (success && !previousParsedOk)
shouldInactivate = true;
}
@@ -597,7 +706,7 @@ PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithPrope
propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property);
if (shouldInactivate) {
- activeIt->value->setStatus(Inspector::TypeBuilder::CSS::CSSProperty::Status::Inactive);
+ activeIt->value->setStatus(Inspector::Protocol::CSS::CSSPropertyStatus::Inactive);
propertyNameToPreviousActiveProperty.set(canonicalPropertyName, property);
}
} else {
@@ -605,63 +714,65 @@ PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyle::styleWithPrope
// Default "implicit" == false.
if (implicit)
property->setImplicit(true);
- status = Inspector::TypeBuilder::CSS::CSSProperty::Status::Style;
+ status = Inspector::Protocol::CSS::CSSPropertyStatus::Style;
String shorthand = m_style->getPropertyShorthand(name);
if (!shorthand.isEmpty()) {
if (!foundShorthands.contains(shorthand)) {
foundShorthands.add(shorthand);
- RefPtr<Inspector::TypeBuilder::CSS::ShorthandEntry> entry = Inspector::TypeBuilder::CSS::ShorthandEntry::create()
+ auto entry = Inspector::Protocol::CSS::ShorthandEntry::create()
.setName(shorthand)
- .setValue(shorthandValue(shorthand));
- shorthandEntries->addItem(entry);
+ .setValue(shorthandValue(shorthand))
+ .release();
+ shorthandEntries->addItem(WTFMove(entry));
}
}
}
}
// Default "status" == "style".
- if (status != Inspector::TypeBuilder::CSS::CSSProperty::Status::Style)
+ if (status != Inspector::Protocol::CSS::CSSPropertyStatus::Style)
property->setStatus(status);
}
- RefPtr<Inspector::TypeBuilder::CSS::CSSStyle> result = Inspector::TypeBuilder::CSS::CSSStyle::create()
- .setCssProperties(propertiesObject)
- .setShorthandEntries(shorthandEntries);
- return result.release();
+ return Inspector::Protocol::CSS::CSSStyle::create()
+ .setCssProperties(WTFMove(propertiesObject))
+ .setShorthandEntries(WTFMove(shorthandEntries))
+ .release();
}
-PassRefPtr<CSSRuleSourceData> InspectorStyle::extractSourceData() const
+RefPtr<CSSRuleSourceData> InspectorStyle::extractSourceData() const
{
if (!m_parentStyleSheet || !m_parentStyleSheet->ensureParsedDataReady())
return nullptr;
return m_parentStyleSheet->ruleSourceDataFor(m_style.get());
}
-bool InspectorStyle::setText(const String& text, ExceptionCode& ec)
+ExceptionOr<void> InspectorStyle::setText(const String& text)
{
- return m_parentStyleSheet->setStyleText(m_style.get(), text, ec);
+ return m_parentStyleSheet->setStyleText(m_style.get(), text);
}
String InspectorStyle::shorthandValue(const String& shorthandProperty) const
{
String value = m_style->getPropertyValue(shorthandProperty);
- if (value.isEmpty()) {
- for (unsigned i = 0; i < m_style->length(); ++i) {
- String individualProperty = m_style->item(i);
- if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
- continue;
- if (m_style->isPropertyImplicit(individualProperty))
- continue;
- String individualValue = m_style->getPropertyValue(individualProperty);
- if (individualValue == "initial")
- continue;
- if (value.length())
- value.append(" ");
- value.append(individualValue);
- }
+ if (!value.isEmpty())
+ return value;
+ StringBuilder builder;
+ for (unsigned i = 0; i < m_style->length(); ++i) {
+ String individualProperty = m_style->item(i);
+ if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
+ continue;
+ if (m_style->isPropertyImplicit(individualProperty))
+ continue;
+ String individualValue = m_style->getPropertyValue(individualProperty);
+ if (individualValue == "initial")
+ continue;
+ if (!builder.isEmpty())
+ builder.append(' ');
+ builder.append(individualValue);
}
- return value;
+ return builder.toString();
}
String InspectorStyle::shorthandPriority(const String& shorthandProperty) const
@@ -694,78 +805,11 @@ Vector<String> InspectorStyle::longhandProperties(const String& shorthandPropert
return properties;
}
-NewLineAndWhitespace& InspectorStyle::newLineAndWhitespaceDelimiters() const
+Ref<InspectorStyleSheet> InspectorStyleSheet::create(InspectorPageAgent* pageAgent, const String& id, RefPtr<CSSStyleSheet>&& pageStyleSheet, Inspector::Protocol::CSS::StyleSheetOrigin origin, const String& documentURL, Listener* listener)
{
- DEFINE_STATIC_LOCAL(String, defaultPrefix, (ASCIILiteral(" ")));
-
- if (m_formatAcquired)
- return m_format;
-
- RefPtr<CSSRuleSourceData> sourceData = extractSourceData();
- Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : nullptr;
- int propertyCount;
- if (!sourcePropertyData || !(propertyCount = sourcePropertyData->size())) {
- m_format.first = "\n";
- m_format.second = defaultPrefix;
- return m_format; // Do not remember the default formatting and attempt to acquire it later.
- }
-
- String text;
- bool success = styleText(&text);
- ASSERT_UNUSED(success, success);
-
- m_formatAcquired = true;
-
- String candidatePrefix = defaultPrefix;
- StringBuilder formatLineFeed;
- StringBuilder prefix;
- int scanStart = 0;
- int propertyIndex = 0;
- bool isFullPrefixScanned = false;
- bool lineFeedTerminated = false;
- const UChar* characters = text.deprecatedCharacters();
- while (propertyIndex < propertyCount) {
- const WebCore::CSSPropertySourceData& currentProperty = sourcePropertyData->at(propertyIndex++);
-
- bool processNextProperty = false;
- int scanEnd = currentProperty.range.start;
- for (int i = scanStart; i < scanEnd; ++i) {
- UChar ch = characters[i];
- bool isLineFeed = isHTMLLineBreak(ch);
- if (isLineFeed) {
- if (!lineFeedTerminated)
- formatLineFeed.append(ch);
- prefix.clear();
- } else if (isHTMLSpace(ch))
- prefix.append(ch);
- else {
- candidatePrefix = prefix.toString();
- prefix.clear();
- scanStart = currentProperty.range.end;
- ++propertyIndex;
- processNextProperty = true;
- break;
- }
- if (!isLineFeed && formatLineFeed.length())
- lineFeedTerminated = true;
- }
- if (!processNextProperty) {
- isFullPrefixScanned = true;
- break;
- }
- }
-
- m_format.first = formatLineFeed.toString();
- m_format.second = isFullPrefixScanned ? prefix.toString() : candidatePrefix;
- return m_format;
-}
-
-PassRefPtr<InspectorStyleSheet> InspectorStyleSheet::create(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener)
-{
- return adoptRef(new InspectorStyleSheet(pageAgent, id, pageStyleSheet, origin, documentURL, listener));
+ return adoptRef(*new InspectorStyleSheet(pageAgent, id, WTFMove(pageStyleSheet), origin, documentURL, listener));
}
-// static
String InspectorStyleSheet::styleSheetURL(CSSStyleSheet* pageStyleSheet)
{
if (pageStyleSheet && !pageStyleSheet->contents().baseURL().isEmpty())
@@ -773,13 +817,12 @@ String InspectorStyleSheet::styleSheetURL(CSSStyleSheet* pageStyleSheet)
return emptyString();
}
-InspectorStyleSheet::InspectorStyleSheet(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum origin, const String& documentURL, Listener* listener)
+InspectorStyleSheet::InspectorStyleSheet(InspectorPageAgent* pageAgent, const String& id, RefPtr<CSSStyleSheet>&& pageStyleSheet, Inspector::Protocol::CSS::StyleSheetOrigin origin, const String& documentURL, Listener* listener)
: m_pageAgent(pageAgent)
, m_id(id)
- , m_pageStyleSheet(pageStyleSheet)
+ , m_pageStyleSheet(WTFMove(pageStyleSheet))
, m_origin(origin)
, m_documentURL(documentURL)
- , m_isRevalidating(false)
, m_listener(listener)
{
m_parsedStyleSheet = new ParsedStyleSheet();
@@ -807,103 +850,103 @@ void InspectorStyleSheet::reparseStyleSheet(const String& text)
CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get());
m_pageStyleSheet->contents().parseString(text);
m_pageStyleSheet->clearChildRuleCSSOMWrappers();
- m_inspectorStyles.clear();
fireStyleSheetChanged();
}
+
+ // We just wiped the entire contents of the stylesheet. Clear the mutation flag.
+ m_pageStyleSheet->clearHadRulesMutation();
}
-bool InspectorStyleSheet::setText(const String& text, ExceptionCode& ec)
+ExceptionOr<void> InspectorStyleSheet::setText(const String& text)
{
- if (!checkPageStyleSheet(ec))
- return false;
- if (!m_parsedStyleSheet)
- return false;
+ if (!m_pageStyleSheet)
+ return Exception { NOT_SUPPORTED_ERR };
m_parsedStyleSheet->setText(text);
m_flatRules.clear();
- return true;
+ return { };
}
-String InspectorStyleSheet::ruleSelector(const InspectorCSSId& id, ExceptionCode& ec)
+ExceptionOr<String> InspectorStyleSheet::ruleSelector(const InspectorCSSId& id)
{
CSSStyleRule* rule = ruleForId(id);
- if (!rule) {
- ec = NOT_FOUND_ERR;
- return "";
- }
+ if (!rule)
+ return Exception { NOT_FOUND_ERR };
return rule->selectorText();
}
-bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String& selector, ExceptionCode& ec)
+static bool isValidSelectorListString(const String& selector, Document* document)
{
- if (!checkPageStyleSheet(ec))
- return false;
+ CSSSelectorList selectorList;
+ CSSParser parser(parserContextForDocument(document));
+ parser.parseSelector(selector, selectorList);
+ return selectorList.isValid();
+}
+
+ExceptionOr<void> InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String& selector)
+{
+ if (!m_pageStyleSheet)
+ return Exception { NOT_SUPPORTED_ERR };
+
+ // If the selector is invalid, do not proceed any further.
+ if (!isValidSelectorListString(selector, m_pageStyleSheet->ownerDocument()))
+ return Exception { SYNTAX_ERR };
+
CSSStyleRule* rule = ruleForId(id);
- if (!rule) {
- ec = NOT_FOUND_ERR;
- return false;
- }
+ if (!rule)
+ return Exception { NOT_FOUND_ERR };
+
CSSStyleSheet* styleSheet = rule->parentStyleSheet();
- if (!styleSheet || !ensureParsedDataReady()) {
- ec = NOT_FOUND_ERR;
- return false;
- }
+ if (!styleSheet || !ensureParsedDataReady())
+ return Exception { NOT_FOUND_ERR };
+
+ // If the stylesheet is already mutated at this point, that must mean that our data has been modified
+ // elsewhere. This should never happen as ensureParsedDataReady would return false in that case.
+ ASSERT(!styleSheetMutated());
rule->setSelectorText(selector);
- RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(rule->style());
- if (!sourceData) {
- ec = NOT_FOUND_ERR;
- return false;
- }
+ auto sourceData = ruleSourceDataFor(&rule->style());
+ if (!sourceData)
+ return Exception { NOT_FOUND_ERR };
String sheetText = m_parsedStyleSheet->text();
sheetText.replace(sourceData->ruleHeaderRange.start, sourceData->ruleHeaderRange.length(), selector);
m_parsedStyleSheet->setText(sheetText);
+ m_pageStyleSheet->clearHadRulesMutation();
fireStyleSheetChanged();
- return true;
+ return { };
}
-static bool checkStyleRuleSelector(Document* document, const String& selector)
+ExceptionOr<CSSStyleRule*> InspectorStyleSheet::addRule(const String& selector)
{
- CSSSelectorList selectorList;
- createCSSParser(document)->parseSelector(selector, selectorList);
- return selectorList.isValid();
-}
+ if (!m_pageStyleSheet)
+ return Exception { NOT_SUPPORTED_ERR };
-CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionCode& ec)
-{
- if (!checkPageStyleSheet(ec))
- return nullptr;
- if (!checkStyleRuleSelector(m_pageStyleSheet->ownerDocument(), selector)) {
- ec = SYNTAX_ERR;
- return nullptr;
- }
+ if (!isValidSelectorListString(selector, m_pageStyleSheet->ownerDocument()))
+ return Exception { SYNTAX_ERR };
+
+ auto text = this->text();
+ if (text.hasException())
+ return text.releaseException();
- String text;
- bool success = getText(&text);
- if (!success) {
- ec = NOT_FOUND_ERR;
- return nullptr;
- }
StringBuilder styleSheetText;
- styleSheetText.append(text);
+ styleSheetText.append(text.releaseReturnValue());
- m_pageStyleSheet->addRule(selector, "", ec);
- if (ec)
- return nullptr;
+ auto addRuleResult = m_pageStyleSheet->addRule(selector, emptyString(), std::nullopt);
+ if (addRuleResult.hasException())
+ return addRuleResult.releaseException();
ASSERT(m_pageStyleSheet->length());
unsigned lastRuleIndex = m_pageStyleSheet->length() - 1;
CSSRule* rule = m_pageStyleSheet->item(lastRuleIndex);
ASSERT(rule);
- CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
+ CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(*rule);
if (!styleRule) {
// 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);
- ec = SYNTAX_ERR;
- return nullptr;
+ m_pageStyleSheet->deleteRule(lastRuleIndex);
+ return Exception { SYNTAX_ERR };
}
if (!styleSheetText.isEmpty())
@@ -911,46 +954,41 @@ CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionCode
styleSheetText.append(selector);
styleSheetText.appendLiteral(" {}");
- // Using setText() as this operation changes the style sheet rule set.
- setText(styleSheetText.toString(), ASSERT_NO_EXCEPTION);
+ // Using setText() as this operation changes the stylesheet rule set.
+ setText(styleSheetText.toString());
fireStyleSheetChanged();
return styleRule;
}
-bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, ExceptionCode& ec)
+ExceptionOr<void> InspectorStyleSheet::deleteRule(const InspectorCSSId& id)
{
- if (!checkPageStyleSheet(ec))
- return false;
+ if (!m_pageStyleSheet)
+ return Exception { NOT_SUPPORTED_ERR };
+
RefPtr<CSSStyleRule> rule = ruleForId(id);
- if (!rule) {
- ec = NOT_FOUND_ERR;
- return false;
- }
+ if (!rule)
+ return Exception { NOT_FOUND_ERR };
CSSStyleSheet* styleSheet = rule->parentStyleSheet();
- if (!styleSheet || !ensureParsedDataReady()) {
- ec = NOT_FOUND_ERR;
- return false;
- }
+ if (!styleSheet || !ensureParsedDataReady())
+ return Exception { NOT_FOUND_ERR };
- RefPtr<CSSRuleSourceData> sourceData = ruleSourceDataFor(rule->style());
- if (!sourceData) {
- ec = NOT_FOUND_ERR;
- return false;
- }
+ auto sourceData = ruleSourceDataFor(&rule->style());
+ if (!sourceData)
+ return Exception { NOT_FOUND_ERR };
- styleSheet->deleteRule(id.ordinal(), ec);
- // |rule| MAY NOT be addressed after this line!
+ auto deleteRuleResult = styleSheet->deleteRule(id.ordinal());
+ if (deleteRuleResult.hasException())
+ return deleteRuleResult.releaseException();
- if (ec)
- return false;
+ // |rule| MAY NOT be addressed after this!
String sheetText = m_parsedStyleSheet->text();
sheetText.remove(sourceData->ruleHeaderRange.start, sourceData->ruleBodyRange.end - sourceData->ruleHeaderRange.start + 1);
- setText(sheetText, ASSERT_NO_EXCEPTION);
+ setText(sheetText);
fireStyleSheetChanged();
- return true;
+ return { };
}
CSSStyleRule* InspectorStyleSheet::ruleForId(const InspectorCSSId& id) const
@@ -961,10 +999,9 @@ CSSStyleRule* InspectorStyleSheet::ruleForId(const InspectorCSSId& id) const
ASSERT(!id.isEmpty());
ensureFlatRules();
return id.ordinal() >= m_flatRules.size() ? nullptr : m_flatRules.at(id.ordinal()).get();
-
}
-PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetBody> InspectorStyleSheet::buildObjectForStyleSheet()
+RefPtr<Inspector::Protocol::CSS::CSSStyleSheetBody> InspectorStyleSheet::buildObjectForStyleSheet()
{
CSSStyleSheet* styleSheet = pageStyleSheet();
if (!styleSheet)
@@ -972,19 +1009,19 @@ PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetBody> InspectorStyleSheet::
RefPtr<CSSRuleList> cssRuleList = asCSSRuleList(styleSheet);
- RefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetBody> result = Inspector::TypeBuilder::CSS::CSSStyleSheetBody::create()
+ auto result = Inspector::Protocol::CSS::CSSStyleSheetBody::create()
.setStyleSheetId(id())
- .setRules(buildArrayForRuleList(cssRuleList.get()));
+ .setRules(buildArrayForRuleList(cssRuleList.get()))
+ .release();
- String styleSheetText;
- bool success = getText(&styleSheetText);
- if (success)
- result->setText(styleSheetText);
+ auto styleSheetText = text();
+ if (!styleSheetText.hasException())
+ result->setText(styleSheetText.releaseReturnValue());
- return result.release();
+ return WTFMove(result);
}
-PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObjectForStyleSheetInfo()
+RefPtr<Inspector::Protocol::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObjectForStyleSheetInfo()
{
CSSStyleSheet* styleSheet = pageStyleSheet();
if (!styleSheet)
@@ -992,92 +1029,160 @@ PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet
Document* document = styleSheet->ownerDocument();
Frame* frame = document ? document->frame() : nullptr;
- RefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetHeader> result = Inspector::TypeBuilder::CSS::CSSStyleSheetHeader::create()
+ return Inspector::Protocol::CSS::CSSStyleSheetHeader::create()
.setStyleSheetId(id())
.setOrigin(m_origin)
.setDisabled(styleSheet->disabled())
.setSourceURL(finalURL())
.setTitle(styleSheet->title())
- .setFrameId(m_pageAgent->frameId(frame));
+ .setFrameId(m_pageAgent->frameId(frame))
+ .setIsInline(styleSheet->isInline() && styleSheet->startPosition() != TextPosition())
+ .setStartLine(styleSheet->startPosition().m_line.zeroBasedInt())
+ .setStartColumn(styleSheet->startPosition().m_column.zeroBasedInt())
+ .release();
+}
- return result.release();
+static bool hasDynamicSpecificity(const CSSSelector& simpleSelector)
+{
+ // It is possible that these can have a static specificity if each selector in the list has
+ // equal specificity, but lets always report that they can be dynamic.
+ for (const CSSSelector* selector = &simpleSelector; selector; selector = selector->tagHistory()) {
+ if (selector->match() == CSSSelector::PseudoClass) {
+ CSSSelector::PseudoClassType pseudoClassType = selector->pseudoClassType();
+ if (pseudoClassType == CSSSelector::PseudoClassMatches)
+ return true;
+ if (pseudoClassType == CSSSelector::PseudoClassNthChild || pseudoClassType == CSSSelector::PseudoClassNthLastChild) {
+ if (selector->selectorList())
+ return true;
+ return false;
+ }
+ }
+ }
+
+ return false;
}
-static PassRefPtr<Inspector::TypeBuilder::Array<String>> selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText)
+static Ref<Inspector::Protocol::CSS::CSSSelector> buildObjectForSelectorHelper(const String& selectorText, const CSSSelector& selector, Element* element)
{
- DEFINE_STATIC_LOCAL(JSC::Yarr::RegularExpression, comment, ("/\\*[^]*?\\*/", TextCaseSensitive, JSC::Yarr::MultilineEnabled));
- RefPtr<Inspector::TypeBuilder::Array<String>> result = Inspector::TypeBuilder::Array<String>::create();
- const SelectorRangeList& ranges = sourceData->selectorRanges;
- for (size_t i = 0, size = ranges.size(); i < size; ++i) {
- const SourceRange& range = ranges.at(i);
- String selector = sheetText.substring(range.start, range.length());
+ auto inspectorSelector = Inspector::Protocol::CSS::CSSSelector::create()
+ .setText(selectorText)
+ .release();
+
+ if (element) {
+ bool dynamic = hasDynamicSpecificity(selector);
+ if (dynamic)
+ inspectorSelector->setDynamic(true);
+
+ SelectorChecker::CheckingContext context(SelectorChecker::Mode::CollectingRules);
+ SelectorChecker selectorChecker(element->document());
+
+ unsigned specificity;
+ bool okay = selectorChecker.match(selector, *element, context, specificity);
+ if (!okay)
+ specificity = selector.staticSpecificity(okay);
+
+ if (okay) {
+ auto tuple = Inspector::Protocol::Array<int>::create();
+ tuple->addItem(static_cast<int>((specificity & CSSSelector::idMask) >> 16));
+ tuple->addItem(static_cast<int>((specificity & CSSSelector::classMask) >> 8));
+ tuple->addItem(static_cast<int>(specificity & CSSSelector::elementMask));
+ inspectorSelector->setSpecificity(WTFMove(tuple));
+ }
+ }
+
+ return inspectorSelector;
+}
+
+static Ref<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSSelector>> selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText, const CSSSelectorList& selectorList, Element* element)
+{
+ static NeverDestroyed<JSC::Yarr::RegularExpression> comment("/\\*[^]*?\\*/", TextCaseSensitive, JSC::Yarr::MultilineEnabled);
+
+ auto result = Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSSelector>::create();
+ const CSSSelector* selector = selectorList.first();
+ for (auto& range : sourceData->selectorRanges) {
+ // If we don't have a selector, that means the SourceData for this CSSStyleSheet
+ // no longer matches up with the actual rules in the CSSStyleSheet.
+ ASSERT(selector);
+ if (!selector)
+ break;
+
+ String selectorText = sheetText.substring(range.start, range.length());
// We don't want to see any comments in the selector components, only the meaningful parts.
- replace(selector, comment, "");
- result->addItem(selector.stripWhiteSpace());
+ replace(selectorText, comment, String());
+ result->addItem(buildObjectForSelectorHelper(selectorText.stripWhiteSpace(), *selector, element));
+
+ selector = CSSSelectorList::next(selector);
}
- return result.release();
+ return result;
}
-PassRefPtr<Inspector::TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule)
+Ref<Inspector::Protocol::CSS::CSSSelector> InspectorStyleSheet::buildObjectForSelector(const CSSSelector* selector, Element* element)
+{
+ return buildObjectForSelectorHelper(selector->selectorText(), *selector, element);
+}
+
+Ref<Inspector::Protocol::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule, Element* element, int& endingLine)
{
RefPtr<CSSRuleSourceData> sourceData;
if (ensureParsedDataReady())
- sourceData = ruleSourceDataFor(rule->style());
- RefPtr<Inspector::TypeBuilder::Array<String>> selectors;
+ sourceData = ruleSourceDataFor(&rule->style());
+ RefPtr<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSSelector>> selectors;
// This intentionally does not rely on the source data to avoid catching the trailing comments (before the declaration starting '{').
String selectorText = rule->selectorText();
if (sourceData)
- selectors = selectorsFromSource(sourceData.get(), m_parsedStyleSheet->text());
+ selectors = selectorsFromSource(sourceData.get(), m_parsedStyleSheet->text(), rule->styleRule().selectorList(), element);
else {
- selectors = Inspector::TypeBuilder::Array<String>::create();
- const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
+ selectors = Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSSelector>::create();
+ const CSSSelectorList& selectorList = rule->styleRule().selectorList();
for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
- selectors->addItem(selector->selectorText());
+ selectors->addItem(buildObjectForSelector(selector, element));
}
- RefPtr<Inspector::TypeBuilder::CSS::SelectorList> result = Inspector::TypeBuilder::CSS::SelectorList::create()
- .setSelectors(selectors)
+ auto result = Inspector::Protocol::CSS::SelectorList::create()
+ .setSelectors(WTFMove(selectors))
.setText(selectorText)
.release();
if (sourceData)
- result->setRange(buildSourceRangeObject(sourceData->ruleHeaderRange, lineEndings().get()));
- return result.release();
+ result->setRange(buildSourceRangeObject(sourceData->ruleHeaderRange, lineEndings().get(), &endingLine));
+ return result;
}
-PassRefPtr<Inspector::TypeBuilder::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule)
+RefPtr<Inspector::Protocol::CSS::CSSRule> InspectorStyleSheet::buildObjectForRule(CSSStyleRule* rule, Element* element)
{
CSSStyleSheet* styleSheet = pageStyleSheet();
if (!styleSheet)
return nullptr;
- RefPtr<Inspector::TypeBuilder::CSS::CSSRule> result = Inspector::TypeBuilder::CSS::CSSRule::create()
- .setSelectorList(buildObjectForSelectorList(rule))
- .setSourceLine(rule->styleRule()->sourceLine())
+ int endingLine = 0;
+ auto result = Inspector::Protocol::CSS::CSSRule::create()
+ .setSelectorList(buildObjectForSelectorList(rule, element, endingLine))
+ .setSourceLine(endingLine)
.setOrigin(m_origin)
- .setStyle(buildObjectForStyle(rule->style()));
+ .setStyle(buildObjectForStyle(&rule->style()))
+ .release();
// "sourceURL" is present only for regular rules, otherwise "origin" should be used in the frontend.
- if (m_origin == Inspector::TypeBuilder::CSS::StyleSheetOrigin::Regular)
+ if (m_origin == Inspector::Protocol::CSS::StyleSheetOrigin::Regular)
result->setSourceURL(finalURL());
if (canBind()) {
InspectorCSSId id(ruleId(rule));
if (!id.isEmpty())
- result->setRuleId(id.asProtocolValue<Inspector::TypeBuilder::CSS::CSSRuleId>());
+ result->setRuleId(id.asProtocolValue<Inspector::Protocol::CSS::CSSRuleId>());
}
- RefPtr<Array<Inspector::TypeBuilder::CSS::CSSMedia>> mediaArray = Array<Inspector::TypeBuilder::CSS::CSSMedia>::create();
+ auto mediaArray = Array<Inspector::Protocol::CSS::CSSMedia>::create();
fillMediaListChain(rule, mediaArray.get());
if (mediaArray->length())
- result->setMedia(mediaArray.release());
+ result->setMedia(WTFMove(mediaArray));
- return result.release();
+ return WTFMove(result);
}
-PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyleSheet::buildObjectForStyle(CSSStyleDeclaration* style)
+RefPtr<Inspector::Protocol::CSS::CSSStyle> InspectorStyleSheet::buildObjectForStyle(CSSStyleDeclaration* style)
{
RefPtr<CSSRuleSourceData> sourceData;
if (ensureParsedDataReady())
@@ -1085,83 +1190,50 @@ PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorStyleSheet::buildObje
InspectorCSSId id = ruleOrStyleId(style);
if (id.isEmpty()) {
- RefPtr<Inspector::TypeBuilder::CSS::CSSStyle> bogusStyle = Inspector::TypeBuilder::CSS::CSSStyle::create()
- .setCssProperties(Array<Inspector::TypeBuilder::CSS::CSSProperty>::create())
- .setShorthandEntries(Array<Inspector::TypeBuilder::CSS::ShorthandEntry>::create());
- return bogusStyle.release();
+ return Inspector::Protocol::CSS::CSSStyle::create()
+ .setCssProperties(Array<Inspector::Protocol::CSS::CSSProperty>::create())
+ .setShorthandEntries(Array<Inspector::Protocol::CSS::ShorthandEntry>::create())
+ .release();
}
RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
- RefPtr<Inspector::TypeBuilder::CSS::CSSStyle> result = inspectorStyle->buildObjectForStyle();
+ RefPtr<Inspector::Protocol::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));
+ auto sheetText = text();
+ if (!sheetText.hasException()) {
+ auto& bodyRange = sourceData->ruleBodyRange;
+ result->setCssText(sheetText.releaseReturnValue().substring(bodyRange.start, bodyRange.end - bodyRange.start));
}
}
- return result.release();
+ return result;
}
-bool InspectorStyleSheet::setStyleText(const InspectorCSSId& id, const String& text, String* oldText, ExceptionCode& ec)
+ExceptionOr<void> InspectorStyleSheet::setStyleText(const InspectorCSSId& id, const String& text, String* oldText)
{
- RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
- if (!inspectorStyle) {
- ec = NOT_FOUND_ERR;
- return false;
- }
-
- if (oldText && !inspectorStyle->getText(oldText))
- return false;
+ auto inspectorStyle = inspectorStyleForId(id);
+ if (!inspectorStyle)
+ return Exception { NOT_FOUND_ERR };
- bool success = inspectorStyle->setText(text, ec);
- if (success)
- fireStyleSheetChanged();
- return success;
-}
-
-bool InspectorStyleSheet::setPropertyText(const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite, String* oldText, ExceptionCode& ec)
-{
- RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
- if (!inspectorStyle) {
- ec = NOT_FOUND_ERR;
- return false;
+ if (oldText) {
+ auto result = inspectorStyle->text();
+ if (result.hasException())
+ return result.releaseException();
+ *oldText = result.releaseReturnValue();
}
- bool success = inspectorStyle->setPropertyText(propertyIndex, text, overwrite, oldText, ec);
- if (success)
+ auto result = inspectorStyle->setText(text);
+ if (!result.hasException())
fireStyleSheetChanged();
- return success;
-}
-
-bool InspectorStyleSheet::toggleProperty(const InspectorCSSId& id, unsigned propertyIndex, bool disable, ExceptionCode& ec)
-{
- RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
- if (!inspectorStyle) {
- ec = NOT_FOUND_ERR;
- return false;
- }
-
- bool success = inspectorStyle->toggleProperty(propertyIndex, disable, ec);
- if (success) {
- if (disable)
- rememberInspectorStyle(inspectorStyle);
- else if (!inspectorStyle->hasDisabledProperties())
- forgetInspectorStyle(inspectorStyle->cssStyle());
- fireStyleSheetChanged();
- }
- return success;
+ return result;
}
-bool InspectorStyleSheet::getText(String* result) const
+ExceptionOr<String> InspectorStyleSheet::text() const
{
if (!ensureText())
- return false;
- *result = m_parsedStyleSheet->text();
- return true;
+ return Exception { NOT_FOUND_ERR };
+ return String { m_parsedStyleSheet->text() };
}
CSSStyleDeclaration* InspectorStyleSheet::styleForId(const InspectorCSSId& id) const
@@ -1170,7 +1242,7 @@ CSSStyleDeclaration* InspectorStyleSheet::styleForId(const InspectorCSSId& id) c
if (!rule)
return nullptr;
- return rule->style();
+ return &rule->style();
}
void InspectorStyleSheet::fireStyleSheetChanged()
@@ -1179,28 +1251,13 @@ void InspectorStyleSheet::fireStyleSheetChanged()
m_listener->styleSheetChanged(this);
}
-PassRefPtr<InspectorStyle> InspectorStyleSheet::inspectorStyleForId(const InspectorCSSId& id)
+RefPtr<InspectorStyle> InspectorStyleSheet::inspectorStyleForId(const InspectorCSSId& id)
{
CSSStyleDeclaration* style = styleForId(id);
if (!style)
return nullptr;
- InspectorStyleMap::iterator it = m_inspectorStyles.find(style);
- if (it == m_inspectorStyles.end()) {
- RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(id, style, this);
- return inspectorStyle.release();
- }
- return it->value;
-}
-
-void InspectorStyleSheet::rememberInspectorStyle(RefPtr<InspectorStyle> inspectorStyle)
-{
- m_inspectorStyles.set(inspectorStyle->cssStyle(), inspectorStyle);
-}
-
-void InspectorStyleSheet::forgetInspectorStyle(CSSStyleDeclaration* style)
-{
- m_inspectorStyles.remove(style);
+ return InspectorStyle::create(id, style, this);
}
InspectorCSSId InspectorStyleSheet::ruleOrStyleId(CSSStyleDeclaration* style) const
@@ -1221,10 +1278,10 @@ RefPtr<CSSRuleSourceData> InspectorStyleSheet::ruleSourceDataFor(CSSStyleDeclara
return m_parsedStyleSheet->ruleSourceDataAt(ruleIndexByStyle(style));
}
-PassOwnPtr<Vector<size_t>> InspectorStyleSheet::lineEndings() const
+std::unique_ptr<Vector<size_t>> InspectorStyleSheet::lineEndings() const
{
if (!m_parsedStyleSheet->hasText())
- return PassOwnPtr<Vector<size_t>>();
+ return nullptr;
return ContentSearchUtilities::lineEndings(m_parsedStyleSheet->text());
}
@@ -1232,8 +1289,8 @@ unsigned InspectorStyleSheet::ruleIndexByStyle(CSSStyleDeclaration* pageStyle) c
{
ensureFlatRules();
unsigned index = 0;
- for (unsigned i = 0, size = m_flatRules.size(); i < size; ++i) {
- if (m_flatRules.at(i)->style() == pageStyle)
+ for (auto& rule : m_flatRules) {
+ if (&rule->style() == pageStyle)
return index;
++index;
@@ -1241,18 +1298,15 @@ unsigned InspectorStyleSheet::ruleIndexByStyle(CSSStyleDeclaration* pageStyle) c
return UINT_MAX;
}
-bool InspectorStyleSheet::checkPageStyleSheet(ExceptionCode& ec) const
+bool InspectorStyleSheet::styleSheetMutated() const
{
- if (!m_pageStyleSheet) {
- ec = NOT_SUPPORTED_ERR;
- return false;
- }
- return true;
+ return m_pageStyleSheet && m_pageStyleSheet->hadRulesMutation();
}
bool InspectorStyleSheet::ensureParsedDataReady()
{
- return ensureText() && ensureSourceData();
+ bool allowParsedData = m_origin == Inspector::Protocol::CSS::StyleSheetOrigin::Inspector || !styleSheetMutated();
+ return allowParsedData && ensureText() && ensureSourceData();
}
bool InspectorStyleSheet::ensureText() const
@@ -1280,9 +1334,12 @@ bool InspectorStyleSheet::ensureSourceData()
return false;
RefPtr<StyleSheetContents> newStyleSheet = StyleSheetContents::create();
- OwnPtr<RuleSourceDataList> ruleSourceDataResult = adoptPtr(new RuleSourceDataList());
- createCSSParser(m_pageStyleSheet->ownerDocument())->parseSheet(newStyleSheet.get(), m_parsedStyleSheet->text(), 0, ruleSourceDataResult.get());
- m_parsedStyleSheet->setSourceData(ruleSourceDataResult.release());
+ auto ruleSourceDataResult = std::make_unique<RuleSourceDataList>();
+
+ CSSParserContext context(parserContextForDocument(m_pageStyleSheet->ownerDocument()));
+ StyleSheetHandler handler(m_parsedStyleSheet->text(), m_pageStyleSheet->ownerDocument(), ruleSourceDataResult.get());
+ CSSParser::parseSheetForInspector(context, newStyleSheet.get(), m_parsedStyleSheet->text(), handler);
+ m_parsedStyleSheet->setSourceData(WTFMove(ruleSourceDataResult));
return m_parsedStyleSheet->hasSourceData();
}
@@ -1293,27 +1350,28 @@ void InspectorStyleSheet::ensureFlatRules() const
collectFlatRules(asCSSRuleList(pageStyleSheet()), &m_flatRules);
}
-bool InspectorStyleSheet::setStyleText(CSSStyleDeclaration* style, const String& text, ExceptionCode& ec)
+ExceptionOr<void> InspectorStyleSheet::setStyleText(CSSStyleDeclaration* style, const String& text)
{
if (!m_pageStyleSheet)
- return false;
+ return Exception { NOT_FOUND_ERR };
if (!ensureParsedDataReady())
- return false;
+ return Exception { NOT_FOUND_ERR };
String patchedStyleSheetText;
bool success = styleSheetTextWithChangedStyle(style, text, &patchedStyleSheetText);
if (!success)
- return false;
+ return Exception { NOT_FOUND_ERR };
InspectorCSSId id = ruleOrStyleId(style);
if (id.isEmpty())
- return false;
+ return Exception { NOT_FOUND_ERR };
- style->setCssText(text, ec);
- if (!ec)
- m_parsedStyleSheet->setText(patchedStyleSheetText);
+ auto setCssTextResult = style->setCssText(text);
+ if (setCssTextResult.hasException())
+ return setCssTextResult.releaseException();
- return !ec;
+ m_parsedStyleSheet->setText(patchedStyleSheetText);
+ return { };
}
bool InspectorStyleSheet::styleSheetTextWithChangedStyle(CSSStyleDeclaration* style, const String& newStyleText, String* result)
@@ -1339,30 +1397,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 = m_flatRules.at(i).get();
- if (parsedRule->style() == pageStyle) {
- if (parsedRule->styleRule()->properties().asText() != pageStyle->cssText()) {
- // Clear the disabled properties for the invalid style here.
- m_inspectorStyles.remove(pageStyle);
-
- ExceptionCode ec = 0;
- setStyleText(pageStyle, pageStyle->cssText(), ec);
- }
- break;
- }
- }
- m_isRevalidating = false;
+ return ruleOrStyleId(&rule->style());
}
bool InspectorStyleSheet::originalStyleSheetText(String* result) const
@@ -1375,7 +1410,7 @@ bool InspectorStyleSheet::originalStyleSheetText(String* result) const
bool InspectorStyleSheet::resourceStyleSheetText(String* result) const
{
- if (m_origin == Inspector::TypeBuilder::CSS::StyleSheetOrigin::User || m_origin == Inspector::TypeBuilder::CSS::StyleSheetOrigin::UserAgent)
+ if (m_origin == Inspector::Protocol::CSS::StyleSheetOrigin::User || m_origin == Inspector::Protocol::CSS::StyleSheetOrigin::UserAgent)
return false;
if (!m_pageStyleSheet || !ownerDocument() || !ownerDocument()->frame())
@@ -1383,7 +1418,7 @@ bool InspectorStyleSheet::resourceStyleSheetText(String* result) const
String error;
bool base64Encoded;
- InspectorPageAgent::resourceContent(&error, ownerDocument()->frame(), URL(ParsedURLString, m_pageStyleSheet->href()), result, &base64Encoded);
+ InspectorPageAgent::resourceContent(error, ownerDocument()->frame(), URL(ParsedURLString, m_pageStyleSheet->href()), result, &base64Encoded);
return error.isEmpty() && !base64Encoded;
}
@@ -1393,62 +1428,58 @@ bool InspectorStyleSheet::inlineStyleSheetText(String* result) const
return false;
Node* ownerNode = m_pageStyleSheet->ownerNode();
- if (!ownerNode || !ownerNode->isElementNode())
+ if (!is<Element>(ownerNode))
return false;
- Element* ownerElement = toElement(ownerNode);
+ Element& ownerElement = downcast<Element>(*ownerNode);
- if (!isHTMLStyleElement(ownerElement)
-#if ENABLE(SVG)
- && !ownerElement->hasTagName(SVGNames::styleTag)
-#endif
- )
+ if (!is<HTMLStyleElement>(ownerElement) && !is<SVGStyleElement>(ownerElement))
return false;
- *result = ownerElement->textContent();
+ *result = ownerElement.textContent();
return true;
}
-PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSRule>> InspectorStyleSheet::buildArrayForRuleList(CSSRuleList* ruleList)
+Ref<Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSRule>> InspectorStyleSheet::buildArrayForRuleList(CSSRuleList* ruleList)
{
- RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSRule>> result = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSRule>::create();
+ auto result = Inspector::Protocol::Array<Inspector::Protocol::CSS::CSSRule>::create();
if (!ruleList)
- return result.release();
+ return result;
RefPtr<CSSRuleList> refRuleList = ruleList;
CSSStyleRuleVector rules;
- collectFlatRules(refRuleList, &rules);
+ collectFlatRules(WTFMove(refRuleList), &rules);
- for (unsigned i = 0, size = rules.size(); i < size; ++i)
- result->addItem(buildObjectForRule(rules.at(i).get()));
+ for (auto& rule : rules)
+ result->addItem(buildObjectForRule(rule.get(), nullptr));
- return result.release();
+ return result;
}
-void InspectorStyleSheet::collectFlatRules(PassRefPtr<CSSRuleList> ruleList, CSSStyleRuleVector* result)
+void InspectorStyleSheet::collectFlatRules(RefPtr<CSSRuleList>&& ruleList, CSSStyleRuleVector* result)
{
if (!ruleList)
return;
for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
CSSRule* rule = ruleList->item(i);
- CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
+ CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(*rule);
if (styleRule)
result->append(styleRule);
else {
RefPtr<CSSRuleList> childRuleList = asCSSRuleList(rule);
if (childRuleList)
- collectFlatRules(childRuleList, result);
+ collectFlatRules(WTFMove(childRuleList), result);
}
}
}
-PassRefPtr<InspectorStyleSheetForInlineStyle> InspectorStyleSheetForInlineStyle::create(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<Element> element, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum origin, Listener* listener)
+Ref<InspectorStyleSheetForInlineStyle> InspectorStyleSheetForInlineStyle::create(InspectorPageAgent* pageAgent, const String& id, RefPtr<Element>&& element, Inspector::Protocol::CSS::StyleSheetOrigin origin, Listener* listener)
{
- return adoptRef(new InspectorStyleSheetForInlineStyle(pageAgent, id, element, origin, listener));
+ return adoptRef(*new InspectorStyleSheetForInlineStyle(pageAgent, id, WTFMove(element), origin, listener));
}
-InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(InspectorPageAgent* pageAgent, const String& id, PassRefPtr<Element> element, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum origin, Listener* listener)
- : InspectorStyleSheet(pageAgent, id, nullptr, origin, "", listener)
- , m_element(element)
+InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(InspectorPageAgent* pageAgent, const String& id, RefPtr<Element>&& element, Inspector::Protocol::CSS::StyleSheetOrigin origin, Listener* listener)
+ : InspectorStyleSheet(pageAgent, id, nullptr, origin, String(), listener)
+ , m_element(WTFMove(element))
, m_ruleSourceData(nullptr)
, m_isStyleTextValid(false)
{
@@ -1460,37 +1491,37 @@ InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(InspectorPa
void InspectorStyleSheetForInlineStyle::didModifyElementAttribute()
{
m_isStyleTextValid = false;
- if (m_element->isStyledElement() && m_element->style() != m_inspectorStyle->cssStyle())
+ if (m_element->isStyledElement() && m_element->cssomStyle() != m_inspectorStyle->cssStyle())
m_inspectorStyle = InspectorStyle::create(InspectorCSSId(id(), 0), inlineStyle(), this);
- m_ruleSourceData.clear();
+ m_ruleSourceData = nullptr;
}
-bool InspectorStyleSheetForInlineStyle::getText(String* result) const
+ExceptionOr<String> InspectorStyleSheetForInlineStyle::text() const
{
if (!m_isStyleTextValid) {
m_styleText = elementStyleText();
m_isStyleTextValid = true;
}
- *result = m_styleText;
- return true;
+ return String { m_styleText };
}
-bool InspectorStyleSheetForInlineStyle::setStyleText(CSSStyleDeclaration* style, const String& text, ExceptionCode& ec)
+ExceptionOr<void> InspectorStyleSheetForInlineStyle::setStyleText(CSSStyleDeclaration* style, const String& text)
{
ASSERT_UNUSED(style, style == inlineStyle());
{
- InspectorCSSAgent::InlineStyleOverrideScope overrideScope(&m_element->document());
- m_element->setAttribute("style", text, ec);
+ InspectorCSSAgent::InlineStyleOverrideScope overrideScope(m_element->document());
+ m_element->setAttribute(HTMLNames::styleAttr, text);
}
m_styleText = text;
m_isStyleTextValid = true;
- m_ruleSourceData.clear();
- return !ec;
+ m_ruleSourceData = nullptr;
+
+ return { };
}
-PassOwnPtr<Vector<size_t>> InspectorStyleSheetForInlineStyle::lineEndings() const
+std::unique_ptr<Vector<size_t>> InspectorStyleSheetForInlineStyle::lineEndings() const
{
return ContentSearchUtilities::lineEndings(elementStyleText());
}
@@ -1505,7 +1536,7 @@ bool InspectorStyleSheetForInlineStyle::ensureParsedDataReady()
// The "style" property value can get changed indirectly, e.g. via element.style.borderWidth = "2px".
const String& currentStyleText = elementStyleText();
if (m_styleText != currentStyleText) {
- m_ruleSourceData.clear();
+ m_ruleSourceData = nullptr;
m_styleText = currentStyleText;
m_isStyleTextValid = true;
}
@@ -1513,23 +1544,22 @@ bool InspectorStyleSheetForInlineStyle::ensureParsedDataReady()
if (m_ruleSourceData)
return true;
- m_ruleSourceData = CSSRuleSourceData::create(CSSRuleSourceData::STYLE_RULE);
- bool success = getStyleAttributeRanges(m_ruleSourceData.get());
- if (!success)
+ if (!m_element->isStyledElement())
return false;
+ m_ruleSourceData = ruleSourceData();
return true;
}
-PassRefPtr<InspectorStyle> InspectorStyleSheetForInlineStyle::inspectorStyleForId(const InspectorCSSId& id)
+RefPtr<InspectorStyle> InspectorStyleSheetForInlineStyle::inspectorStyleForId(const InspectorCSSId& id)
{
ASSERT_UNUSED(id, !id.ordinal());
- return m_inspectorStyle;
+ return m_inspectorStyle.copyRef();
}
CSSStyleDeclaration* InspectorStyleSheetForInlineStyle::inlineStyle() const
{
- return m_element->style();
+ return m_element->cssomStyle();
}
const String& InspectorStyleSheetForInlineStyle::elementStyleText() const
@@ -1537,22 +1567,20 @@ const String& InspectorStyleSheetForInlineStyle::elementStyleText() const
return m_element->getAttribute("style").string();
}
-bool InspectorStyleSheetForInlineStyle::getStyleAttributeRanges(CSSRuleSourceData* result) const
+Ref<CSSRuleSourceData> InspectorStyleSheetForInlineStyle::ruleSourceData() const
{
- if (!m_element->isStyledElement())
- return false;
-
if (m_styleText.isEmpty()) {
+ auto result = CSSRuleSourceData::create(StyleRule::Style);
result->ruleBodyRange.start = 0;
result->ruleBodyRange.end = 0;
- return true;
+ return result;
}
- RefPtr<MutableStyleProperties> tempDeclaration = MutableStyleProperties::create();
- createCSSParser(&m_element->document())->parseDeclaration(tempDeclaration.get(), m_styleText, result, &m_element->document().elementSheet().contents());
- return true;
+ CSSParserContext context(parserContextForDocument(&m_element->document()));
+ RuleSourceDataList ruleSourceDataResult;
+ StyleSheetHandler handler(m_styleText, &m_element->document(), &ruleSourceDataResult);
+ CSSParser::parseDeclarationForInspector(context, m_styleText, handler);
+ return WTFMove(ruleSourceDataResult.first());
}
} // namespace WebCore
-
-#endif // ENABLE(INSPECTOR)