Chromium Code Reviews| Index: third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| index 5aec74b02a33daba88c42957303e5647a7751414..590ad2a8cd31c86759a260104baacffbb70c1bab 100644 |
| --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| @@ -313,6 +313,17 @@ public: |
| } |
| }; |
| +class InspectorCSSAgent::StyleEditAction : public InspectorCSSAgent::StyleSheetAction { |
| + WTF_MAKE_NONCOPYABLE(StyleEditAction); |
| +public: |
| + StyleEditAction(const String& name) |
| + : InspectorCSSAgent::StyleSheetAction(name) |
| + { |
| + } |
| + |
| + virtual PassRefPtr<protocol::TypeBuilder::CSS::CSSStyle> takeSerializedStyle() = 0; |
| +}; |
| + |
| class InspectorCSSAgent::SetStyleSheetTextAction final : public InspectorCSSAgent::StyleSheetAction { |
| WTF_MAKE_NONCOPYABLE(SetStyleSheetTextAction); |
| public: |
| @@ -365,7 +376,107 @@ private: |
| String m_oldText; |
| }; |
| -class InspectorCSSAgent::ModifyRuleAction final : public InspectorCSSAgent::StyleSheetAction { |
| +int getMultipleStyleTextsActionId() |
|
dgozman
2016/02/17 23:32:36
static int ...
lushnikov
2016/02/18 01:40:56
Removed.
|
| +{ |
| + static int lastId = 0; |
| + return ++lastId; |
| +} |
| + |
| +class InspectorCSSAgent::SetMultipleStyleTextsAction final : public InspectorCSSAgent::StyleSheetAction { |
|
dgozman
2016/02/17 23:32:36
You can replace this class with a single for loop
lushnikov
2016/02/18 01:40:56
Done.
|
| + WTF_MAKE_NONCOPYABLE(SetMultipleStyleTextsAction); |
| +public: |
| + SetMultipleStyleTextsAction(HeapVector<RefPtrWillBeMember<StyleEditAction>>& actions) |
| + : InspectorCSSAgent::StyleSheetAction("SetMultipleStyleTextsAction") |
| + , m_id(getMultipleStyleTextsActionId()) |
| + , m_actions(actions) |
| + { |
| + } |
| + |
| + bool perform(ExceptionState& exceptionState) override |
| + { |
| + return redo(exceptionState); |
| + } |
| + |
| + bool undo(ExceptionState& exceptionState) override |
| + { |
| + for (size_t i = 0; i < m_actions.size(); ++i) { |
| + RefPtrWillBeMember<StyleEditAction> action = m_actions.at(m_actions.size() - i - 1); |
| + bool success = action->undo(exceptionState); |
| + if (!success) { |
| + for (size_t j = i + 1; j < m_actions.size(); ++j) { |
| + RefPtrWillBeMember<StyleSheetAction> revert = m_actions.at(j); |
| + TrackExceptionState redoExceptionState; |
| + revert->redo(redoExceptionState); |
| + ASSERT(!redoExceptionState.hadException()); |
| + } |
| + return false; |
| + } |
| + } |
| + return true; |
| + } |
| + |
| + bool redo(ExceptionState& exceptionState) override |
| + { |
| + for (size_t i = 0; i < m_actions.size(); ++i) { |
| + RefPtrWillBeMember<StyleEditAction> action = m_actions.at(i); |
| + bool success = action->redo(exceptionState); |
| + if (!success) { |
| + for (size_t j = 0; j < i; ++j) { |
| + RefPtrWillBeMember<StyleSheetAction> revert = m_actions.at(i - j - 1); |
| + TrackExceptionState undoExceptionState; |
| + revert->undo(undoExceptionState); |
| + ASSERT(!undoExceptionState.hadException()); |
| + |
| + } |
| + return false; |
| + } |
| + } |
| + return true; |
| + } |
| + |
| + String mergeId() override |
| + { |
| + if (m_actions.size() == 1) |
| + return String::format("SetMultipleStyleTextsAction Mergeble %s", m_actions.at(0)->mergeId().utf8().data()); |
| + return String::format("SetMultipleStyleTextsAction Non-Mergeble %d", m_id); |
| + } |
| + |
| + void merge(PassRefPtrWillBeRawPtr<Action> action) override |
| + { |
| + ASSERT(action->mergeId() == mergeId()); |
| + |
| + SetMultipleStyleTextsAction* other = static_cast<SetMultipleStyleTextsAction*>(action.get()); |
| + m_actions.at(0)->merge(other->m_actions.at(0)); |
| + } |
| + |
| + PassRefPtr<protocol::TypeBuilder::Array<protocol::TypeBuilder::CSS::CSSStyle>> takeSerializedStyles() |
| + { |
| + RefPtr<protocol::TypeBuilder::Array<protocol::TypeBuilder::CSS::CSSStyle>> result = protocol::TypeBuilder::Array<protocol::TypeBuilder::CSS::CSSStyle>::create(); |
| + for (size_t i = 0; i < m_actions.size(); ++i) |
| + result->addItem(m_actions.at(i)->takeSerializedStyle()); |
| + return result; |
| + } |
| + |
| + bool isNoop() override |
| + { |
| + bool result = true; |
| + for (size_t i = 0; i < m_actions.size(); ++i) |
| + result = result && m_actions.at(i)->isNoop(); |
| + return result; |
| + } |
| + |
| + DEFINE_INLINE_VIRTUAL_TRACE() |
| + { |
| + visitor->trace(m_actions); |
| + InspectorCSSAgent::StyleSheetAction::trace(visitor); |
| + } |
| + |
| +private: |
| + int m_id; |
| + HeapVector<RefPtrWillBeMember<StyleEditAction>> m_actions; |
| +}; |
| + |
| +class InspectorCSSAgent::ModifyRuleAction final : public InspectorCSSAgent::StyleEditAction { |
| WTF_MAKE_NONCOPYABLE(ModifyRuleAction); |
| public: |
| enum Type { |
| @@ -376,7 +487,7 @@ public: |
| }; |
| ModifyRuleAction(Type type, InspectorStyleSheet* styleSheet, const SourceRange& range, const String& text) |
| - : InspectorCSSAgent::StyleSheetAction("ModifyRuleAction") |
| + : InspectorCSSAgent::StyleEditAction("ModifyRuleAction") |
| , m_styleSheet(styleSheet) |
| , m_type(type) |
| , m_newText(text) |
| @@ -435,6 +546,18 @@ public: |
| return result; |
| } |
| + PassRefPtr<protocol::TypeBuilder::CSS::CSSStyle> takeSerializedStyle() override |
| + { |
| + if (m_type != SetStyleText) |
| + return nullptr; |
| + RefPtrWillBeRawPtr<CSSRule> rule = takeRule(); |
| + if (rule->type() == CSSRule::STYLE_RULE) |
| + return m_styleSheet->buildObjectForStyle(toCSSStyleRule(rule.get())->style()); |
| + if (rule->type() == CSSRule::KEYFRAME_RULE) |
| + return m_styleSheet->buildObjectForStyle(toCSSKeyframeRule(rule.get())->style()); |
| + return nullptr; |
| + } |
| + |
| DEFINE_INLINE_VIRTUAL_TRACE() |
| { |
| visitor->trace(m_styleSheet); |
| @@ -471,11 +594,11 @@ private: |
| RefPtrWillBeMember<CSSRule> m_cssRule; |
| }; |
| -class InspectorCSSAgent::SetElementStyleAction final : public InspectorCSSAgent::StyleSheetAction { |
| +class InspectorCSSAgent::SetElementStyleAction final : public InspectorCSSAgent::StyleEditAction { |
| WTF_MAKE_NONCOPYABLE(SetElementStyleAction); |
| public: |
| SetElementStyleAction(InspectorStyleSheetForInlineStyle* styleSheet, const String& text) |
| - : InspectorCSSAgent::StyleSheetAction("SetElementStyleAction") |
| + : InspectorCSSAgent::StyleEditAction("SetElementStyleAction") |
| , m_styleSheet(styleSheet) |
| , m_text(text) |
| { |
| @@ -509,6 +632,11 @@ public: |
| return String::format("SetElementStyleAction:%s", m_styleSheet->id().utf8().data()); |
| } |
| + PassRefPtr<protocol::TypeBuilder::CSS::CSSStyle> takeSerializedStyle() override |
| + { |
| + return m_styleSheet->buildObjectForStyle(m_styleSheet->inlineStyle()); |
| + } |
| + |
| void merge(PassRefPtrWillBeRawPtr<Action> action) override |
| { |
| ASSERT(action->mergeId() == mergeId()); |
| @@ -1203,21 +1331,72 @@ void InspectorCSSAgent::setKeyframeKey(ErrorString* errorString, const String& s |
| *errorString = InspectorDOMAgent::toErrorString(exceptionState); |
| } |
| -void InspectorCSSAgent::setStyleText(ErrorString* errorString, const String& styleSheetId, const RefPtr<JSONObject>& range, const String& text, RefPtr<protocol::TypeBuilder::CSS::CSSStyle>& result) |
| +bool InspectorCSSAgent::multipleStyleTextsActions(ErrorString* errorString, const RefPtr<JSONArray>& edits, HeapVector<RefPtrWillBeMember<StyleEditAction>>* actions) |
| { |
| - FrontendOperationScope scope; |
| - InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); |
| - if (!inspectorStyleSheet) { |
| - *errorString = "Stylesheet not found"; |
| - return; |
| + size_t n = edits->length(); |
| + if (n == 0) { |
| + *errorString = "Edits should not be empty"; |
| + return false; |
| } |
| - SourceRange selectorRange; |
| - if (!jsonRangeToSourceRange(errorString, inspectorStyleSheet, range, &selectorRange)) |
| + |
| + for (size_t i = 0; i < n; ++i) { |
| + RefPtr<JSONObject> edit = edits->get(i)->asObject(); |
| + String styleSheetId; |
| + bool success = edit->getString("styleSheetId", &styleSheetId); |
| + if (!success) { |
| + *errorString = String::format("Could not parse styleSheetId for edit #%zu of %zu", i + 1, n); |
| + return false; |
| + } |
| + InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); |
| + if (!inspectorStyleSheet) { |
| + *errorString = String::format("StyleSheet not found for edit #%zu of %zu", i + 1 , n); |
| + return false; |
| + } |
| + |
| + RefPtr<JSONObject> rangeObject = edit->getObject("range"); |
| + if (!rangeObject) { |
| + *errorString = String::format("Could not parse range object for edit #%zu of %zu", i + 1, n); |
| + return false; |
| + } |
| + |
| + SourceRange range; |
| + if (!jsonRangeToSourceRange(errorString, inspectorStyleSheet, rangeObject, &range)) |
| + return false; |
| + |
| + String text; |
| + success = edit->getString("text", &text); |
| + if (!success) { |
| + *errorString = String::format("Could not parse text for edit #%zu of %zu", i + 1, n); |
| + return false; |
| + } |
| + |
| + if (inspectorStyleSheet->isInlineStyle()) { |
| + InspectorStyleSheetForInlineStyle* inlineStyleSheet = static_cast<InspectorStyleSheetForInlineStyle*>(inspectorStyleSheet); |
| + RefPtrWillBeRawPtr<SetElementStyleAction> action = adoptRefWillBeNoop(new SetElementStyleAction(inlineStyleSheet, text)); |
| + actions->append(action); |
| + } else { |
| + RefPtrWillBeRawPtr<ModifyRuleAction> action = adoptRefWillBeNoop(new ModifyRuleAction(ModifyRuleAction::SetStyleText, static_cast<InspectorStyleSheet*>(inspectorStyleSheet), range, text)); |
| + actions->append(action); |
| + } |
| + } |
| + return true; |
| +} |
| + |
| +void InspectorCSSAgent::setStyleTexts(ErrorString* errorString, const RefPtr<JSONArray>& edits, RefPtr<protocol::TypeBuilder::Array<protocol::TypeBuilder::CSS::CSSStyle>>& result) |
| +{ |
| + FrontendOperationScope scope; |
| + HeapVector<RefPtrWillBeMember<StyleEditAction>> actions; |
| + if (!multipleStyleTextsActions(errorString, edits, &actions)) |
| return; |
| - CSSStyleDeclaration* style = setStyleText(errorString, inspectorStyleSheet, selectorRange, text); |
| - if (style) |
| - result = inspectorStyleSheet->buildObjectForStyle(style); |
| + TrackExceptionState exceptionState; |
| + RefPtrWillBeRawPtr<SetMultipleStyleTextsAction> batchAction = adoptRefWillBeNoop(new SetMultipleStyleTextsAction(actions)); |
| + bool success = m_domAgent->history()->perform(batchAction, exceptionState); |
| + if (!success) { |
| + *errorString = InspectorDOMAgent::toErrorString(exceptionState); |
| + return; |
| + } |
| + result = batchAction->takeSerializedStyles(); |
| } |
| CSSStyleDeclaration* InspectorCSSAgent::setStyleText(ErrorString* errorString, InspectorStyleSheetBase* inspectorStyleSheet, const SourceRange& range, const String& text) |