OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2009 Apple Inc. All rights reserved. |
3 * Copyright (C) 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2011 Google Inc. All rights reserved. |
4 * Copyright (C) 2009 Joseph Pecoraro | 4 * Copyright (C) 2009 Joseph Pecoraro |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * | 9 * |
10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
(...skipping 16 matching lines...) Expand all Loading... | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "core/inspector/InspectorDOMAgent.h" | 31 #include "core/inspector/InspectorDOMAgent.h" |
32 | 32 |
33 #include "bindings/core/v8/BindingSecurity.h" | 33 #include "bindings/core/v8/BindingSecurity.h" |
34 #include "bindings/core/v8/ExceptionState.h" | 34 #include "bindings/core/v8/ExceptionState.h" |
35 #include "bindings/core/v8/V8Node.h" | 35 #include "bindings/core/v8/V8Node.h" |
36 #include "core/InputTypeNames.h" | 36 #include "core/InputTypeNames.h" |
37 #include "core/css/CSSComputedStyleDeclaration.h" | |
38 #include "core/css/CSSVariableData.h" | |
37 #include "core/dom/Attr.h" | 39 #include "core/dom/Attr.h" |
38 #include "core/dom/CharacterData.h" | 40 #include "core/dom/CharacterData.h" |
39 #include "core/dom/ContainerNode.h" | 41 #include "core/dom/ContainerNode.h" |
40 #include "core/dom/DOMException.h" | 42 #include "core/dom/DOMException.h" |
41 #include "core/dom/DOMNodeIds.h" | 43 #include "core/dom/DOMNodeIds.h" |
42 #include "core/dom/Document.h" | 44 #include "core/dom/Document.h" |
43 #include "core/dom/DocumentFragment.h" | 45 #include "core/dom/DocumentFragment.h" |
44 #include "core/dom/DocumentType.h" | 46 #include "core/dom/DocumentType.h" |
45 #include "core/dom/Element.h" | 47 #include "core/dom/Element.h" |
46 #include "core/dom/Node.h" | 48 #include "core/dom/Node.h" |
(...skipping 30 matching lines...) Expand all Loading... | |
77 #include "core/xml/XPathResult.h" | 79 #include "core/xml/XPathResult.h" |
78 #include "platform/PlatformGestureEvent.h" | 80 #include "platform/PlatformGestureEvent.h" |
79 #include "platform/PlatformMouseEvent.h" | 81 #include "platform/PlatformMouseEvent.h" |
80 #include "platform/PlatformTouchEvent.h" | 82 #include "platform/PlatformTouchEvent.h" |
81 #include "wtf/ListHashSet.h" | 83 #include "wtf/ListHashSet.h" |
82 #include "wtf/PtrUtil.h" | 84 #include "wtf/PtrUtil.h" |
83 #include "wtf/text/CString.h" | 85 #include "wtf/text/CString.h" |
84 #include "wtf/text/WTFString.h" | 86 #include "wtf/text/WTFString.h" |
85 #include <memory> | 87 #include <memory> |
86 | 88 |
89 namespace std { | |
90 | |
91 using ComputedStyleArray = | |
92 std::vector<std::unique_ptr<blink::protocol::DOM::ComputedStyleProperty>>; | |
93 | |
94 template <> | |
95 struct equal_to<ComputedStyleArray> { | |
96 bool operator()(const ComputedStyleArray& a, | |
97 const ComputedStyleArray& b) const { | |
98 if (a.size() != b.size()) | |
99 return false; | |
100 for (size_t i = 0; i < a.size(); i++) { | |
101 if (a[i]->getName() != b[i]->getName() || | |
102 a[i]->getValue() != b[i]->getValue()) { | |
103 return false; | |
104 } | |
105 } | |
106 return true; | |
107 } | |
108 }; | |
109 | |
110 template <> | |
111 struct hash<ComputedStyleArray> { | |
112 using argument_type = ComputedStyleArray; | |
113 using result_type = size_t; | |
114 | |
115 static size_t computeHash( | |
116 const blink::protocol::DOM::ComputedStyleProperty* property) { | |
117 size_t h1 = DefaultHash<String>::Hash::hash(property->getName()); | |
118 size_t h2 = DefaultHash<String>::Hash::hash(property->getValue()); | |
119 return h1 ^ (h2 << 1); | |
120 } | |
121 | |
122 size_t operator()(const ComputedStyleArray& array) const { | |
123 if (array.size() == 0) | |
124 return 0; | |
125 size_t h = computeHash(array[0].get()); | |
126 for (size_t i = 1; i < array.size(); i++) { | |
127 size_t h2 = computeHash(array[i].get()); | |
128 h ^= (h2 << 1); | |
129 } | |
130 return h; | |
131 } | |
132 }; | |
133 } // namespace std | |
134 | |
87 namespace blink { | 135 namespace blink { |
88 | 136 |
89 using namespace HTMLNames; | 137 using namespace HTMLNames; |
90 | 138 |
91 namespace DOMAgentState { | 139 namespace DOMAgentState { |
92 static const char domAgentEnabled[] = "domAgentEnabled"; | 140 static const char domAgentEnabled[] = "domAgentEnabled"; |
93 }; | 141 }; |
94 | 142 |
95 namespace { | 143 namespace { |
96 | 144 |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
527 *errorString = "Document is not available"; | 575 *errorString = "Document is not available"; |
528 return; | 576 return; |
529 } | 577 } |
530 | 578 |
531 discardFrontendBindings(); | 579 discardFrontendBindings(); |
532 | 580 |
533 *root = buildObjectForNode(m_document.get(), 2, m_documentNodeToIdMap.get()); | 581 *root = buildObjectForNode(m_document.get(), 2, m_documentNodeToIdMap.get()); |
534 } | 582 } |
535 | 583 |
536 void InspectorDOMAgent::getLayoutTreeNodes( | 584 void InspectorDOMAgent::getLayoutTreeNodes( |
537 ErrorString* errorString, | 585 ErrorString* error_string, |
586 std::unique_ptr<protocol::Array<String>> style_whitelist, | |
538 std::unique_ptr<protocol::Array<protocol::DOM::LayoutTreeNode>>* | 587 std::unique_ptr<protocol::Array<protocol::DOM::LayoutTreeNode>>* |
539 layoutTreeNodes) { | 588 layout_tree_nodes, |
540 layoutTreeNodes->reset(new protocol::Array<protocol::DOM::LayoutTreeNode>); | 589 std::unique_ptr<protocol::Array<protocol::DOM::ComputedStyle>>* |
541 visitLayoutTreeNodes(m_document.get(), *layoutTreeNodes->get()); | 590 computed_styles) { |
591 m_document->updateStyleAndLayoutTree(); | |
592 | |
593 layout_tree_nodes->reset(new protocol::Array<protocol::DOM::LayoutTreeNode>); | |
594 ComputedStylesMap style_to_index_map; | |
595 visitLayoutTreeNodes(m_document.get(), *layout_tree_nodes->get(), | |
596 style_whitelist.get(), style_to_index_map); | |
597 | |
598 std::vector<std::unique_ptr<protocol::DOM::ComputedStyle>> styles( | |
599 style_to_index_map.size()); | |
600 for (ComputedStylesMap::value_type& pair : style_to_index_map) { | |
601 ComputedStyleArray& style = *const_cast<ComputedStyleArray*>(&pair.first); | |
602 using ProtocolStyleArray = | |
603 protocol::Array<blink::protocol::DOM::ComputedStyleProperty>; | |
604 styles[pair.second] = | |
605 protocol::DOM::ComputedStyle::create() | |
606 .setProperties(std::unique_ptr<ProtocolStyleArray>( | |
607 new ProtocolStyleArray(std::move(style)))) | |
608 .build(); | |
609 } | |
610 | |
611 computed_styles->reset( | |
612 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::
| |
613 } | |
614 | |
615 int InspectorDOMAgent::getStyleIndexForNode( | |
616 Node* node, | |
617 protocol::Array<String>* style_whitelist, | |
618 ComputedStylesMap& style_to_index_map) { | |
619 CSSComputedStyleDeclaration* computed_style_info = | |
620 CSSComputedStyleDeclaration::create(node, true); | |
621 ComputedStyleArray style; | |
622 for (size_t i = 0; i < style_whitelist->length(); i++) { | |
623 CSSPropertyID property_id = cssPropertyID(style_whitelist->get(i)); | |
624 if (property_id == CSSPropertyInvalid) | |
625 continue; | |
626 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
| |
627 protocol::DOM::ComputedStyleProperty::create() | |
628 .setName(style_whitelist->get(i)) | |
629 .setValue(computed_style_info->getPropertyValue(property_id)) | |
630 .build()); | |
631 } | |
632 | |
633 ComputedStylesMap::iterator it = style_to_index_map.find(style); | |
634 if (it != style_to_index_map.end()) | |
635 return it->second; | |
636 size_t index = style_to_index_map.size(); | |
637 style_to_index_map.insert(std::make_pair(std::move(style), index)); | |
638 return index; | |
542 } | 639 } |
543 | 640 |
544 void InspectorDOMAgent::visitLayoutTreeNodes( | 641 void InspectorDOMAgent::visitLayoutTreeNodes( |
545 Node* node, | 642 Node* node, |
546 protocol::Array<protocol::DOM::LayoutTreeNode>& layoutTreeNodes) { | 643 protocol::Array<protocol::DOM::LayoutTreeNode>& layout_tree_nodes, |
644 protocol::Array<String>* style_whitelist, | |
645 ComputedStylesMap& style_to_index_map) { | |
547 for (; node; node = NodeTraversal::next(*node)) { | 646 for (; node; node = NodeTraversal::next(*node)) { |
548 // Visit shadow dom nodes. | 647 // Visit shadow dom nodes. |
549 if (node->isElementNode()) { | 648 if (node->isElementNode()) { |
550 const Element* element = toElement(node); | 649 const Element* element = toElement(node); |
551 ElementShadow* elementShadow = element->shadow(); | 650 ElementShadow* elementShadow = element->shadow(); |
552 if (elementShadow) { | 651 if (elementShadow) { |
553 visitLayoutTreeNodes(&elementShadow->youngestShadowRoot(), | 652 visitLayoutTreeNodes(&elementShadow->youngestShadowRoot(), |
554 layoutTreeNodes); | 653 layout_tree_nodes, style_whitelist, |
654 style_to_index_map); | |
555 } | 655 } |
556 } | 656 } |
557 | 657 |
558 // Pierce iframe boundaries. | 658 // Pierce iframe boundaries. |
559 if (node->isFrameOwnerElement()) { | 659 if (node->isFrameOwnerElement()) { |
560 visitLayoutTreeNodes( | 660 Document* content_document = |
561 toHTMLFrameOwnerElement(node)->contentDocument()->documentElement(), | 661 toHTMLFrameOwnerElement(node)->contentDocument(); |
562 layoutTreeNodes); | 662 content_document->updateStyleAndLayoutTree(); |
663 visitLayoutTreeNodes(content_document->documentElement(), | |
664 layout_tree_nodes, style_whitelist, | |
665 style_to_index_map); | |
563 } | 666 } |
564 | 667 |
565 LayoutObject* layoutObject = node->layoutObject(); | 668 LayoutObject* layoutObject = node->layoutObject(); |
566 if (!layoutObject) | 669 if (!layoutObject) |
567 continue; | 670 continue; |
568 | 671 |
569 int backendNodeId = DOMNodeIds::idForNode(node); | 672 int backendNodeId = DOMNodeIds::idForNode(node); |
570 std::unique_ptr<protocol::DOM::LayoutTreeNode> layoutTreeNode = | 673 std::unique_ptr<protocol::DOM::LayoutTreeNode> layoutTreeNode = |
571 protocol::DOM::LayoutTreeNode::create() | 674 protocol::DOM::LayoutTreeNode::create() |
572 .setBackendNodeId(backendNodeId) | 675 .setBackendNodeId(backendNodeId) |
676 .setStyleIndex( | |
677 getStyleIndexForNode(node, style_whitelist, style_to_index_map)) | |
573 .setBoundingBox(buildRectForFloatRect( | 678 .setBoundingBox(buildRectForFloatRect( |
574 node->isElementNode() | 679 node->isElementNode() |
575 ? FloatRect(toElement(node)->boundsInViewport()) | 680 ? FloatRect(toElement(node)->boundsInViewport()) |
576 : layoutObject->absoluteBoundingBoxRect())) | 681 : layoutObject->absoluteBoundingBoxRect())) |
577 .build(); | 682 .build(); |
578 | 683 |
579 if (layoutObject->isText()) { | 684 if (layoutObject->isText()) { |
580 LayoutText* layoutText = toLayoutText(layoutObject); | 685 LayoutText* layoutText = toLayoutText(layoutObject); |
581 layoutTreeNode->setLayoutText(layoutText->text()); | 686 layoutTreeNode->setLayoutText(layoutText->text()); |
582 if (layoutText->hasTextBoxes()) { | 687 if (layoutText->hasTextBoxes()) { |
(...skipping 10 matching lines...) Expand all Loading... | |
593 .setStartCharacterIndex(textBox->start()) | 698 .setStartCharacterIndex(textBox->start()) |
594 .setNumCharacters(textBox->len()) | 699 .setNumCharacters(textBox->len()) |
595 .setBoundingBox(buildRectForFloatRect( | 700 .setBoundingBox(buildRectForFloatRect( |
596 absoluteCoordsTextBoxRect)) | 701 absoluteCoordsTextBoxRect)) |
597 .build()); | 702 .build()); |
598 } | 703 } |
599 layoutTreeNode->setInlineTextNodes(std::move(inlineTextNodes)); | 704 layoutTreeNode->setInlineTextNodes(std::move(inlineTextNodes)); |
600 } | 705 } |
601 } | 706 } |
602 | 707 |
603 layoutTreeNodes.addItem(std::move(layoutTreeNode)); | 708 layout_tree_nodes.addItem(std::move(layoutTreeNode)); |
604 } | 709 } |
605 } | 710 } |
606 | 711 |
607 void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, int depth) { | 712 void InspectorDOMAgent::pushChildNodesToFrontend(int nodeId, int depth) { |
608 Node* node = nodeForId(nodeId); | 713 Node* node = nodeForId(nodeId); |
609 if (!node || (!node->isElementNode() && !node->isDocumentNode() && | 714 if (!node || (!node->isElementNode() && !node->isDocumentNode() && |
610 !node->isDocumentFragment())) | 715 !node->isDocumentFragment())) |
611 return; | 716 return; |
612 | 717 |
613 NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId); | 718 NodeToIdMap* nodeMap = m_idToNodesMap.get(nodeId); |
(...skipping 1752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2366 visitor->trace(m_idToNodesMap); | 2471 visitor->trace(m_idToNodesMap); |
2367 visitor->trace(m_document); | 2472 visitor->trace(m_document); |
2368 visitor->trace(m_revalidateTask); | 2473 visitor->trace(m_revalidateTask); |
2369 visitor->trace(m_searchResults); | 2474 visitor->trace(m_searchResults); |
2370 visitor->trace(m_history); | 2475 visitor->trace(m_history); |
2371 visitor->trace(m_domEditor); | 2476 visitor->trace(m_domEditor); |
2372 InspectorBaseAgent::trace(visitor); | 2477 InspectorBaseAgent::trace(visitor); |
2373 } | 2478 } |
2374 | 2479 |
2375 } // namespace blink | 2480 } // namespace blink |
OLD | NEW |