Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1068)

Unified Diff: Source/core/inspector/InspectorStyleSheet.cpp

Issue 441873010: DevTools: [SSP] Implement adding new rule in user stylesheet (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fix compilation error Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/inspector/InspectorStyleSheet.cpp
diff --git a/Source/core/inspector/InspectorStyleSheet.cpp b/Source/core/inspector/InspectorStyleSheet.cpp
index d40c8ca8ecc63b636a5c899d91b6a6e7acc35566..dbe5118c5e5d708769ac405a0d4d88cbe54be2ba 100644
--- a/Source/core/inspector/InspectorStyleSheet.cpp
+++ b/Source/core/inspector/InspectorStyleSheet.cpp
@@ -429,7 +429,6 @@ void ParsedStyleSheet::setSourceData(PassOwnPtrWillBeRawPtr<RuleSourceDataList>
m_sourceData.clear();
return;
}
-
m_sourceData = adoptPtrWillBeNoop(new RuleSourceDataList());
// FIXME: This is a temporary solution to retain the original flat sourceData structure
@@ -1056,60 +1055,147 @@ bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String
return true;
}
-static bool checkStyleRuleSelector(Document* document, const String& selector)
+unsigned InspectorStyleSheet::ruleIndexBySourceRange(const CSSMediaRule* parentMediaRule, const SourceRange& sourceRange)
{
- CSSSelectorList selectorList;
- BisonCSSParser(parserContextForDocument(document)).parseSelector(selector, selectorList);
- return selectorList.isValid();
+ unsigned index = 0;
+ for (size_t i = 0; i < m_flatRules.size(); ++i) {
+ RefPtrWillBeRawPtr<CSSRule> rule = m_flatRules.at(i);
+ if (rule->parentRule() != parentMediaRule)
+ continue;
+ RefPtrWillBeRawPtr<CSSRuleSourceData> ruleSourceData = m_parsedStyleSheet->ruleSourceDataAt(i);
+ if (ruleSourceData->ruleBodyRange.end < sourceRange.start)
+ ++index;
+ }
+ return index;
}
-CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionState& exceptionState)
+CSSStyleRule* InspectorStyleSheet::insertCSSOMRuleInStyleSheet(const SourceRange& sourceRange, const String& ruleText, ExceptionState& exceptionState)
{
- if (!checkStyleRuleSelector(m_pageStyleSheet->ownerDocument(), selector)) {
- exceptionState.throwDOMException(SyntaxError, "The selector '" + selector + "' could not be added.");
+ unsigned index = ruleIndexBySourceRange(nullptr, sourceRange);
+ m_pageStyleSheet->insertRule(ruleText, index, exceptionState);
+ CSSRule* rule = m_pageStyleSheet->item(index);
+ CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
+ if (!styleRule) {
+ m_pageStyleSheet->deleteRule(index, ASSERT_NO_EXCEPTION);
+ exceptionState.throwDOMException(SyntaxError, "The rule '" + ruleText + "' could not be added in style sheet.");
+ return 0;
+ }
+ return styleRule;
+}
+
+CSSStyleRule* InspectorStyleSheet::insertCSSOMRuleInMediaRule(CSSMediaRule* mediaRule, const SourceRange& sourceRange, const String& ruleText, ExceptionState& exceptionState)
+{
+ unsigned index = ruleIndexBySourceRange(mediaRule, sourceRange);
+ mediaRule->insertRule(ruleText, index, exceptionState);
+ CSSRule* rule = mediaRule->item(index);
+ CSSStyleRule* styleRule = InspectorCSSAgent::asCSSStyleRule(rule);
+ if (!styleRule) {
+ mediaRule->deleteRule(index, ASSERT_NO_EXCEPTION);
+ exceptionState.throwDOMException(SyntaxError, "The rule '" + ruleText + "' could not be added in media rule.");
+ return 0;
+ }
+ return styleRule;
+}
+
+CSSStyleRule* InspectorStyleSheet::insertCSSOMRuleBySourceRange(const SourceRange& sourceRange, const String& ruleText, ExceptionState& exceptionState)
+{
+ int containingRuleIndex = -1;
+ unsigned containingRuleLength = 0;
+ for (size_t i = 0; i < m_parsedStyleSheet->ruleCount(); ++i) {
+ RefPtrWillBeRawPtr<CSSRuleSourceData> ruleSourceData = m_parsedStyleSheet->ruleSourceDataAt(i);
+ if (ruleSourceData->ruleHeaderRange.start < sourceRange.start && sourceRange.start < ruleSourceData->ruleBodyRange.start) {
+ exceptionState.throwDOMException(NotFoundError, "Cannot insert rule inside rule selector.");
+ return 0;
+ }
+ if (sourceRange.start < ruleSourceData->ruleBodyRange.start || ruleSourceData->ruleBodyRange.end < sourceRange.start)
+ continue;
+ if (containingRuleIndex == -1 || containingRuleLength > ruleSourceData->ruleBodyRange.length()) {
+ containingRuleIndex = i;
+ containingRuleLength = ruleSourceData->ruleBodyRange.length();
+ }
+ }
+ if (containingRuleIndex == -1)
+ return insertCSSOMRuleInStyleSheet(sourceRange, ruleText, exceptionState);
+ RefPtrWillBeRawPtr<CSSRule> rule = m_flatRules.at(containingRuleIndex);
+ if (rule->type() != CSSRule::MEDIA_RULE) {
+ exceptionState.throwDOMException(NotFoundError, "Cannot insert rule in non-media rule.");
+ return 0;
+ }
+ return insertCSSOMRuleInMediaRule(toCSSMediaRule(rule.get()), sourceRange, ruleText, exceptionState);
+}
+
+bool InspectorStyleSheet::verifyRuleText(const String& ruleText)
+{
+ DEFINE_STATIC_LOCAL(String, bogusPropertyName, ("-webkit-boguz-propertee"));
+ RefPtrWillBeRawPtr<MutableStylePropertySet> tempMutableStyle = MutableStylePropertySet::create();
+ RuleSourceDataList sourceData;
+ RefPtrWillBeRawPtr<StyleSheetContents> styleSheetContents = StyleSheetContents::create(strictCSSParserContext());
+ String text = ruleText + " div { " + bogusPropertyName + ": none; }";
+ StyleSheetHandler handler(text, ownerDocument(), styleSheetContents.get(), &sourceData);
+ BisonCSSParser(parserContextForDocument(ownerDocument())).parseSheet(styleSheetContents.get(), text, TextPosition::minimumPosition(), &handler);
+ unsigned ruleCount = sourceData.size();
+
+ // Exactly two rules should be parsed.
+ if (ruleCount != 2)
+ return false;
+
+ // Added rule must be style rule.
+ if (!sourceData.at(0)->styleSourceData)
+ return false;
+
+ WillBeHeapVector<CSSPropertySourceData>& propertyData = sourceData.at(1)->styleSourceData->propertyData;
+ unsigned propertyCount = propertyData.size();
+
+ // Exactly one property should be in rule.
+ if (propertyCount != 1)
+ return false;
+
+ // Check for the property name.
+ if (propertyData.at(0).name != bogusPropertyName)
+ return false;
+
+ return true;
+}
+
+CSSStyleRule* InspectorStyleSheet::addRule(const String& ruleText, const SourceRange& location, ExceptionState& exceptionState)
+{
+ if (!ensureParsedDataReady()) {
+ exceptionState.throwDOMException(NotFoundError, "Cannot parse style sheet.");
+ return 0;
+ }
+
+ if (location.start != location.end) {
+ exceptionState.throwDOMException(NotFoundError, "Source range must be collapsed.");
+ return 0;
+ }
+
+ if (!verifyRuleText(ruleText)) {
+ exceptionState.throwDOMException(SyntaxError, "Rule text is not valid.");
return 0;
}
String text;
bool success = getText(&text);
if (!success) {
- exceptionState.throwDOMException(NotFoundError, "The selector '" + selector + "' could not be added.");
+ exceptionState.throwDOMException(NotFoundError, "The rule '" + ruleText + "' could not be added.");
return 0;
}
- StringBuilder styleSheetText;
- styleSheetText.append(text);
- m_pageStyleSheet->addRule(selector, "", exceptionState);
+ ensureFlatRules();
+ CSSStyleRule* styleRule = insertCSSOMRuleBySourceRange(location, ruleText, exceptionState);
if (exceptionState.hadException())
return 0;
- ASSERT(m_pageStyleSheet->length());
- unsigned lastRuleIndex = m_pageStyleSheet->length() - 1;
- CSSRule* rule = m_pageStyleSheet->item(lastRuleIndex);
- ASSERT(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);
- exceptionState.throwDOMException(SyntaxError, "The selector '" + selector + "' could not be added.");
- return 0;
- }
- if (!styleSheetText.isEmpty())
- styleSheetText.append('\n');
+ text.insert(ruleText, location.start);
- styleSheetText.append(selector);
- styleSheetText.appendLiteral(" {}");
- m_parsedStyleSheet->setText(styleSheetText.toString());
+ m_parsedStyleSheet->setText(text);
m_flatRules.clear();
fireStyleSheetChanged();
-
return styleRule;
}
-bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, ExceptionState& exceptionState)
+bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, const String& oldText, ExceptionState& exceptionState)
{
RefPtrWillBeRawPtr<CSSStyleRule> rule = ruleForId(id);
if (!rule) {
@@ -1128,15 +1214,31 @@ bool InspectorStyleSheet::deleteRule(const InspectorCSSId& id, ExceptionState& e
return false;
}
- styleSheet->deleteRule(id.ordinal(), exceptionState);
+ CSSRule* parentRule = rule->parentRule();
+ if (parentRule) {
+ if (parentRule->type() != CSSRule::MEDIA_RULE) {
+ exceptionState.throwDOMException(NotFoundError, "Cannot remove rule from non-media rule.");
+ return false;
+ }
+ CSSMediaRule* parentMediaRule = toCSSMediaRule(parentRule);
+ size_t index = 0;
+ while (index < parentMediaRule->length() && parentMediaRule->item(index) != rule)
+ ++index;
+ ASSERT(index < parentMediaRule->length());
+ parentMediaRule->deleteRule(index, exceptionState);
+ } else {
+ size_t index = 0;
+ while (index < styleSheet->length() && styleSheet->item(index) != rule)
+ ++index;
+ ASSERT(index < styleSheet->length());
+ styleSheet->deleteRule(index, exceptionState);
+ }
// |rule| MAY NOT be addressed after this line!
if (exceptionState.hadException())
return false;
- String sheetText = m_parsedStyleSheet->text();
- sheetText.remove(sourceData->ruleHeaderRange.start, sourceData->ruleBodyRange.end - sourceData->ruleHeaderRange.start + 1);
- m_parsedStyleSheet->setText(sheetText);
+ m_parsedStyleSheet->setText(oldText);
m_flatRules.clear();
fireStyleSheetChanged();
return true;
« no previous file with comments | « Source/core/inspector/InspectorStyleSheet.h ('k') | Source/devtools/front_end/elements/StylesSidebarPane.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698