Chromium Code Reviews| Index: third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| index 54d1faaea05b0e39848554cfbc80de5ba69c6d69..c1285a30c5145ef7012673e94a0af23b31766eaf 100644 |
| --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp |
| @@ -34,6 +34,8 @@ |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "bindings/core/v8/V8Node.h" |
| #include "core/InputTypeNames.h" |
| +#include "core/css/CSSComputedStyleDeclaration.h" |
| +#include "core/css/CSSVariableData.h" |
| #include "core/dom/Attr.h" |
| #include "core/dom/CharacterData.h" |
| #include "core/dom/ContainerNode.h" |
| @@ -84,6 +86,52 @@ |
| #include "wtf/text/WTFString.h" |
| #include <memory> |
| +namespace std { |
| + |
| +using ComputedStyleArray = |
| + std::vector<std::unique_ptr<blink::protocol::DOM::ComputedStyleProperty>>; |
| + |
| +template <> |
| +struct equal_to<ComputedStyleArray> { |
| + bool operator()(const ComputedStyleArray& a, |
| + const ComputedStyleArray& b) const { |
| + if (a.size() != b.size()) |
| + return false; |
| + for (size_t i = 0; i < a.size(); i++) { |
| + if (a[i]->getName() != b[i]->getName() || |
| + a[i]->getValue() != b[i]->getValue()) { |
| + return false; |
| + } |
| + } |
| + return true; |
| + } |
| +}; |
| + |
| +template <> |
| +struct hash<ComputedStyleArray> { |
| + using argument_type = ComputedStyleArray; |
| + using result_type = size_t; |
| + |
| + static size_t computeHash( |
| + const blink::protocol::DOM::ComputedStyleProperty* property) { |
| + size_t h1 = DefaultHash<String>::Hash::hash(property->getName()); |
| + size_t h2 = DefaultHash<String>::Hash::hash(property->getValue()); |
| + return h1 ^ (h2 << 1); |
| + } |
| + |
| + size_t operator()(const ComputedStyleArray& array) const { |
| + if (array.size() == 0) |
| + return 0; |
| + size_t h = computeHash(array[0].get()); |
| + for (size_t i = 1; i < array.size(); i++) { |
| + size_t h2 = computeHash(array[i].get()); |
| + h ^= (h2 << 1); |
| + } |
| + return h; |
| + } |
| +}; |
| +} // namespace std |
| + |
| namespace blink { |
| using namespace HTMLNames; |
| @@ -534,16 +582,67 @@ void InspectorDOMAgent::getDocument( |
| } |
| void InspectorDOMAgent::getLayoutTreeNodes( |
| - ErrorString* errorString, |
| + ErrorString* error_string, |
| + std::unique_ptr<protocol::Array<String>> style_whitelist, |
| std::unique_ptr<protocol::Array<protocol::DOM::LayoutTreeNode>>* |
| - layoutTreeNodes) { |
| - layoutTreeNodes->reset(new protocol::Array<protocol::DOM::LayoutTreeNode>); |
| - visitLayoutTreeNodes(m_document.get(), *layoutTreeNodes->get()); |
| + layout_tree_nodes, |
| + std::unique_ptr<protocol::Array<protocol::DOM::ComputedStyle>>* |
| + computed_styles) { |
| + m_document->updateStyleAndLayoutTree(); |
| + |
| + layout_tree_nodes->reset(new protocol::Array<protocol::DOM::LayoutTreeNode>); |
| + ComputedStylesMap style_to_index_map; |
| + visitLayoutTreeNodes(m_document.get(), *layout_tree_nodes->get(), |
| + style_whitelist.get(), style_to_index_map); |
| + |
| + std::vector<std::unique_ptr<protocol::DOM::ComputedStyle>> styles( |
| + style_to_index_map.size()); |
| + for (ComputedStylesMap::value_type& pair : style_to_index_map) { |
| + ComputedStyleArray& style = *const_cast<ComputedStyleArray*>(&pair.first); |
| + using ProtocolStyleArray = |
| + protocol::Array<blink::protocol::DOM::ComputedStyleProperty>; |
| + styles[pair.second] = |
| + protocol::DOM::ComputedStyle::create() |
| + .setProperties(std::unique_ptr<ProtocolStyleArray>( |
| + new ProtocolStyleArray(std::move(style)))) |
| + .build(); |
| + } |
| + |
| + computed_styles->reset( |
| + new protocol::Array<protocol::DOM::ComputedStyle>(std::move(styles))); |
|
dgozman
2016/10/12 21:00:40
Can just use addItem above, directly constructing
alex clarke (OOO till 29th)
2016/10/13 20:25:10
The problem with that is:
for (ComputedStylesMap::
|
| +} |
| + |
| +int InspectorDOMAgent::getStyleIndexForNode( |
| + Node* node, |
| + protocol::Array<String>* style_whitelist, |
| + ComputedStylesMap& style_to_index_map) { |
| + CSSComputedStyleDeclaration* computed_style_info = |
| + CSSComputedStyleDeclaration::create(node, true); |
| + ComputedStyleArray style; |
| + for (size_t i = 0; i < style_whitelist->length(); i++) { |
| + CSSPropertyID property_id = cssPropertyID(style_whitelist->get(i)); |
| + if (property_id == CSSPropertyInvalid) |
| + continue; |
| + style.push_back( |
|
dgozman
2016/10/12 21:00:40
Since all the keys in all ComputedStyleArray insta
alex clarke (OOO till 29th)
2016/10/13 20:25:10
Right, in the spirit of that it seems simplest to
|
| + protocol::DOM::ComputedStyleProperty::create() |
| + .setName(style_whitelist->get(i)) |
| + .setValue(computed_style_info->getPropertyValue(property_id)) |
| + .build()); |
| + } |
| + |
| + ComputedStylesMap::iterator it = style_to_index_map.find(style); |
| + if (it != style_to_index_map.end()) |
| + return it->second; |
| + size_t index = style_to_index_map.size(); |
| + style_to_index_map.insert(std::make_pair(std::move(style), index)); |
| + return index; |
| } |
| void InspectorDOMAgent::visitLayoutTreeNodes( |
| Node* node, |
| - protocol::Array<protocol::DOM::LayoutTreeNode>& layoutTreeNodes) { |
| + protocol::Array<protocol::DOM::LayoutTreeNode>& layout_tree_nodes, |
| + protocol::Array<String>* style_whitelist, |
| + ComputedStylesMap& style_to_index_map) { |
| for (; node; node = NodeTraversal::next(*node)) { |
| // Visit shadow dom nodes. |
| if (node->isElementNode()) { |
| @@ -551,15 +650,19 @@ void InspectorDOMAgent::visitLayoutTreeNodes( |
| ElementShadow* elementShadow = element->shadow(); |
| if (elementShadow) { |
| visitLayoutTreeNodes(&elementShadow->youngestShadowRoot(), |
| - layoutTreeNodes); |
| + layout_tree_nodes, style_whitelist, |
| + style_to_index_map); |
| } |
| } |
| // Pierce iframe boundaries. |
| if (node->isFrameOwnerElement()) { |
| - visitLayoutTreeNodes( |
| - toHTMLFrameOwnerElement(node)->contentDocument()->documentElement(), |
| - layoutTreeNodes); |
| + Document* content_document = |
| + toHTMLFrameOwnerElement(node)->contentDocument(); |
| + content_document->updateStyleAndLayoutTree(); |
| + visitLayoutTreeNodes(content_document->documentElement(), |
| + layout_tree_nodes, style_whitelist, |
| + style_to_index_map); |
| } |
| LayoutObject* layoutObject = node->layoutObject(); |
| @@ -570,6 +673,8 @@ void InspectorDOMAgent::visitLayoutTreeNodes( |
| std::unique_ptr<protocol::DOM::LayoutTreeNode> layoutTreeNode = |
| protocol::DOM::LayoutTreeNode::create() |
| .setBackendNodeId(backendNodeId) |
| + .setStyleIndex( |
| + getStyleIndexForNode(node, style_whitelist, style_to_index_map)) |
| .setBoundingBox(buildRectForFloatRect( |
| node->isElementNode() |
| ? FloatRect(toElement(node)->boundsInViewport()) |
| @@ -600,7 +705,7 @@ void InspectorDOMAgent::visitLayoutTreeNodes( |
| } |
| } |
| - layoutTreeNodes.addItem(std::move(layoutTreeNode)); |
| + layout_tree_nodes.addItem(std::move(layoutTreeNode)); |
| } |
| } |