Index: Source/core/inspector/InspectorCSSAgent.cpp |
diff --git a/Source/core/inspector/InspectorCSSAgent.cpp b/Source/core/inspector/InspectorCSSAgent.cpp |
index 09b3a882864f1167f861819cd8709cd95414bd79..e7859c5d0b37ecdf23ce9ac939264a2db7e4ff00 100644 |
--- a/Source/core/inspector/InspectorCSSAgent.cpp |
+++ b/Source/core/inspector/InspectorCSSAgent.cpp |
@@ -94,6 +94,32 @@ String createShorthandValue(Document* document, const String& shorthand, const S |
return style->getPropertyValue(shorthand); |
} |
+PassRefPtrWillBeRawPtr<CSSRuleList> filterDuplicateRules(RefPtrWillBeRawPtr<CSSRuleList> ruleList) |
+{ |
+ RefPtrWillBeRawPtr<StaticCSSRuleList> uniqRuleList = StaticCSSRuleList::create(); |
+ if (!ruleList) |
+ return uniqRuleList.release(); |
+ |
+ HashSet<CSSStyleRule*> uniqRulesSet; |
+ |
+ Vector<RefPtrWillBeRawPtr<CSSRule>> uniqRules; |
+ for (unsigned i = ruleList->length(); i > 0; --i) { |
+ CSSRule* rule = ruleList->item(i - 1); |
+ if (!rule || rule->type() != CSSRule::STYLE_RULE) |
+ continue; |
+ |
+ CSSStyleRule* styleRule = toCSSStyleRule(rule); |
+ if (uniqRulesSet.contains(styleRule)) |
+ continue; |
+ uniqRulesSet.add(styleRule); |
+ uniqRules.append(styleRule); |
+ } |
+ |
+ for (unsigned i = uniqRules.size(); i > 0; --i) |
+ uniqRuleList->rules().append(uniqRules[i - 1]); |
+ return uniqRuleList.release(); |
+} |
+ |
} // namespace |
namespace CSSAgentState { |
@@ -1393,18 +1419,10 @@ PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > InspectorCSSAgent:: |
if (!ruleList) |
return result.release(); |
- HashSet<CSSStyleRule*> uniqRulesSet; |
- Vector<CSSStyleRule*> uniqRules; |
- for (unsigned i = ruleList->length(); i > 0; --i) { |
- CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i - 1)); |
- if (uniqRulesSet.contains(rule)) |
- continue; |
- uniqRulesSet.add(rule); |
- uniqRules.append(rule); |
- } |
+ RefPtrWillBeRawPtr<CSSRuleList> uniqRules = filterDuplicateRules(ruleList); |
- for (unsigned i = uniqRules.size(); i > 0; --i) { |
- CSSStyleRule* rule = uniqRules.at(i - 1); |
+ for (unsigned i = 0; i < uniqRules->length(); ++i) { |
+ CSSStyleRule* rule = asCSSStyleRule(uniqRules->item(i)); |
RefPtr<TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule); |
if (!ruleObject) |
continue; |
@@ -1515,11 +1533,9 @@ void InspectorCSSAgent::resetPseudoStates() |
document->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Inspector)); |
} |
-PassRefPtrWillBeRawPtr<CSSStyleDeclaration> InspectorCSSAgent::findEffectiveDeclaration(Element* element, CSSPropertyID propertyId) |
+PassRefPtrWillBeRawPtr<CSSRuleList> InspectorCSSAgent::matchedRulesList(Element* element) |
{ |
PseudoId elementPseudoId = element->pseudoId(); |
- CSSStyleDeclaration* inlineStyle = element->style(); |
- |
if (elementPseudoId) { |
element = element->parentOrShadowHostElement(); |
if (!element) |
@@ -1531,8 +1547,17 @@ PassRefPtrWillBeRawPtr<CSSStyleDeclaration> InspectorCSSAgent::findEffectiveDecl |
if (!ownerDocument->isActive()) |
return nullptr; |
- String longhand = getPropertyNameString(propertyId); |
+ StyleResolver& styleResolver = ownerDocument->ensureStyleResolver(); |
+ element->updateDistribution(); |
+ return filterDuplicateRules(styleResolver.pseudoCSSRulesForElement(element, elementPseudoId, StyleResolver::AllCSSRules)); |
+} |
+PassRefPtrWillBeRawPtr<CSSStyleDeclaration> InspectorCSSAgent::findEffectiveDeclaration(CSSPropertyID propertyId, CSSRuleList* ruleList, CSSStyleDeclaration* inlineStyle) |
+{ |
+ if (!ruleList && !inlineStyle) |
+ return nullptr; |
+ |
+ String longhand = getPropertyNameString(propertyId); |
RefPtrWillBeRawPtr<CSSStyleDeclaration> foundStyle = nullptr; |
bool isImportant = false; |
@@ -1541,10 +1566,6 @@ PassRefPtrWillBeRawPtr<CSSStyleDeclaration> InspectorCSSAgent::findEffectiveDecl |
isImportant = inlineStyle->getPropertyPriority(longhand) == "important"; |
} |
- StyleResolver& styleResolver = ownerDocument->ensureStyleResolver(); |
- element->updateDistribution(); |
- RefPtrWillBeRawPtr<CSSRuleList> ruleList = styleResolver.pseudoCSSRulesForElement(element, elementPseudoId, StyleResolver::AllCSSRules); |
- |
for (unsigned i = 0, size = ruleList ? ruleList->length() : 0; i < size; ++i) { |
if (isImportant) |
break; |
@@ -1571,39 +1592,16 @@ PassRefPtrWillBeRawPtr<CSSStyleDeclaration> InspectorCSSAgent::findEffectiveDecl |
return foundStyle.release(); |
} |
-void InspectorCSSAgent::setCSSPropertyValue(ErrorString* errorString, Element* element, CSSPropertyID propertyId, const String& value) |
+void InspectorCSSAgent::setCSSPropertyValue(ErrorString* errorString, Element* element, RefPtrWillBeRawPtr<CSSStyleDeclaration> style, CSSPropertyID propertyId, const String& value, bool forceImportant) |
{ |
- Document* ownerDocument = element->ownerDocument(); |
- if (!ownerDocument->isActive()) { |
- *errorString = "Can't edit a node from a non-active document"; |
- return; |
- } |
- |
- Vector<StylePropertyShorthand, 4> shorthands; |
- getMatchingShorthandsForLonghand(propertyId, &shorthands); |
- |
- String shorthand = shorthands.size() > 0 ? getPropertyNameString(shorthands[0].id()) : String(); |
- String longhand = getPropertyNameString(propertyId); |
- |
- RefPtrWillBeRawPtr<CSSStyleDeclaration> foundStyle = findEffectiveDeclaration(element, propertyId); |
- CSSStyleDeclaration* inlineStyle = element->style(); |
- if (!foundStyle || !foundStyle->parentStyleSheet()) |
- foundStyle = inlineStyle; |
- |
- if (!foundStyle) { |
- *errorString = "Can't find a style to edit"; |
- return; |
- } |
- |
InspectorStyleSheetBase* inspectorStyleSheet = nullptr; |
RefPtrWillBeRawPtr<CSSRuleSourceData> sourceData = nullptr; |
- if (foundStyle != inlineStyle) { |
- InspectorStyleSheet* styleSheet = bindStyleSheet(foundStyle->parentStyleSheet()); |
+ // An absence of the parent rule means that given style is an inline style. |
+ if (style->parentRule()) { |
+ InspectorStyleSheet* styleSheet = bindStyleSheet(style->parentStyleSheet()); |
inspectorStyleSheet = styleSheet; |
- sourceData = styleSheet->sourceDataForRule(foundStyle->parentRule()); |
- } |
- |
- if (!sourceData) { |
+ sourceData = styleSheet->sourceDataForRule(style->parentRule()); |
+ } else { |
InspectorStyleSheetForInlineStyle* inlineStyleSheet = asInspectorStyleSheet(element); |
inspectorStyleSheet = inlineStyleSheet; |
sourceData = inlineStyleSheet->ruleSourceData(); |
@@ -1614,6 +1612,12 @@ void InspectorCSSAgent::setCSSPropertyValue(ErrorString* errorString, Element* e |
return; |
} |
+ Vector<StylePropertyShorthand, 4> shorthands; |
+ getMatchingShorthandsForLonghand(propertyId, &shorthands); |
+ |
+ String shorthand = shorthands.size() > 0 ? getPropertyNameString(shorthands[0].id()) : String(); |
+ String longhand = getPropertyNameString(propertyId); |
+ |
int foundIndex = -1; |
WillBeHeapVector<CSSPropertySourceData> properties = sourceData->styleSourceData->propertyData; |
for (unsigned i = 0; i < properties.size(); ++i) { |
@@ -1638,8 +1642,7 @@ void InspectorCSSAgent::setCSSPropertyValue(ErrorString* errorString, Element* e |
String styleText = styleSheetText.substring(bodyRange.start, bodyRange.length()); |
SourceRange changeRange; |
if (foundIndex == -1) { |
- bool isImportant = inlineStyle->getPropertyPriority(longhand) == "important"; |
- String newPropertyText = "\n" + longhand + ": " + value + (isImportant ? " !important" : "") + ";"; |
+ String newPropertyText = "\n" + longhand + ": " + value + (forceImportant ? " !important" : "") + ";"; |
if (!styleText.isEmpty() && !styleText.stripWhiteSpace().endsWith(';')) |
newPropertyText = ";" + newPropertyText; |
styleText.append(newPropertyText); |
@@ -1649,11 +1652,11 @@ void InspectorCSSAgent::setCSSPropertyValue(ErrorString* errorString, Element* e |
CSSPropertySourceData declaration = properties[foundIndex]; |
String newValueText; |
if (declaration.name == shorthand) |
- newValueText = createShorthandValue(ownerDocument, shorthand, declaration.value, longhand, value); |
+ newValueText = createShorthandValue(element->ownerDocument(), shorthand, declaration.value, longhand, value); |
else |
newValueText = value; |
- String newPropertyText = declaration.name + ": " + newValueText + (declaration.important ? " !important" : "") + ";"; |
+ String newPropertyText = declaration.name + ": " + newValueText + (declaration.important || forceImportant ? " !important" : "") + ";"; |
styleText.replace(declaration.range.start - bodyRange.start, declaration.range.length(), newPropertyText); |
changeRange.start = declaration.range.start; |
changeRange.end = changeRange.start + newPropertyText.length(); |
@@ -1667,6 +1670,7 @@ void InspectorCSSAgent::setCSSPropertyValue(ErrorString* errorString, Element* e |
void InspectorCSSAgent::setEffectivePropertyValueForNode(ErrorString* errorString, int nodeId, const String& propertyName, const String& value) |
{ |
+ // TODO: move testing from CSSAgent to layout editor. |
Element* element = elementForId(errorString, nodeId); |
if (!element) |
return; |
@@ -1676,7 +1680,26 @@ void InspectorCSSAgent::setEffectivePropertyValueForNode(ErrorString* errorStrin |
*errorString = "Invalid property name"; |
return; |
} |
- setCSSPropertyValue(errorString, element, cssPropertyID(propertyName), value); |
+ |
+ Document* ownerDocument = element->ownerDocument(); |
+ if (!ownerDocument->isActive()) { |
+ *errorString = "Can't edit a node from a non-active document"; |
+ return; |
+ } |
+ |
+ CSSPropertyID propertyId = cssPropertyID(propertyName); |
+ CSSStyleDeclaration* inlineStyle = element->style(); |
+ RefPtrWillBeRawPtr<CSSRuleList> ruleList = matchedRulesList(element); |
+ RefPtrWillBeRawPtr<CSSStyleDeclaration> foundStyle = findEffectiveDeclaration(propertyId, ruleList.get(), inlineStyle); |
+ if (!foundStyle || !foundStyle->parentStyleSheet()) |
+ foundStyle = inlineStyle; |
+ |
+ if (!foundStyle) { |
+ *errorString = "Can't find a style to edit"; |
+ return; |
+ } |
+ |
+ setCSSPropertyValue(errorString, element, foundStyle.get(), propertyId, value); |
} |
DEFINE_TRACE(InspectorCSSAgent) |