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)); |
} |
} |