Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(390)

Side by Side Diff: headless/public/util/dom_tree_extractor.cc

Issue 2385653003: Add a utility class for extracting details of the DOM (Closed)
Patch Set: Refactor Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "headless/public/util/dom_tree_extractor.h"
6
7 #include "base/bind.h"
8 #include "base/json/json_writer.h"
9 #include "headless/public/headless_devtools_client.h"
10
11 namespace headless {
12
13 DomTreeExtractor::DomTreeExtractor(HeadlessDevToolsClient* devtools_client)
14 : child_nodes_fetched_(false),
15 dom_observer_registered_(false),
16 work_in_progress_(false),
17 devtools_client_(devtools_client),
18 weak_factory_(this) {}
19
20 DomTreeExtractor::~DomTreeExtractor() {
21 if (dom_observer_registered_)
22 devtools_client_->GetDOM()->RemoveObserver(this);
23 }
24
25 void DomTreeExtractor::ExtractDomTree(DomResultCB callback) {
26 DCHECK(!work_in_progress_);
27 work_in_progress_ = true;
28
29 callback_ = std::move(callback);
30
31 // Fetching the DOM nodes is a two step process. First we fetch the Document
32 // (which only contains a few nodes) and then we fetch all it's children
Sami 2016/10/03 10:42:18 s/it's/its/
alex clarke (OOO till 29th) 2016/10/19 16:23:26 Acknowledged.
33 // including any iframe content documents.
34 devtools_client_->GetDOM()->GetDocument(base::Bind(
35 &DomTreeExtractor::OnRootDocumentFetched, weak_factory_.GetWeakPtr()));
36
37 devtools_client_->GetDOM()->GetExperimental()->GetLayoutTreeNodes(
38 dom::GetLayoutTreeNodesParams::Builder().Build(),
39 base::Bind(&DomTreeExtractor::OnLayoutTreeNodesFetched,
40 weak_factory_.GetWeakPtr()));
41 }
42
43 void DomTreeExtractor::OnRootDocumentFetched(
44 std::unique_ptr<dom::GetDocumentResult> result) {
45 dom_tree_.document_result_ = std::move(result);
46
47 DCHECK(!dom_observer_registered_);
48 devtools_client_->GetDOM()->AddObserver(this);
49 dom_observer_registered_ = true;
50
51 devtools_client_->GetDOM()->RequestChildNodes(
Sami 2016/10/03 10:42:18 Curious: does this work on a document that is comp
alex clarke (OOO till 29th) 2016/10/19 16:23:26 It would have. Anyway it's gone now, since we can
52 dom::RequestChildNodesParams::Builder()
53 .SetNodeId(dom_tree_.document_result_->GetRoot()->GetNodeId())
54 .SetDepth(-1)
55 .SetTraverseFrames(true)
56 .Build());
57 }
58
59 void DomTreeExtractor::OnLayoutTreeNodesFetched(
60 std::unique_ptr<dom::GetLayoutTreeNodesResult> result) {
61 dom_tree_.layout_tree_result_ = std::move(result);
62 MaybeExtractDomTree();
63 }
64
65 void DomTreeExtractor::OnSetChildNodes(const dom::SetChildNodesParams& params) {
66 // Ignore nodes we're not looking for.
67 if (params.GetParentId() !=
68 dom_tree_.document_result_->GetRoot()->GetNodeId()) {
69 LOG(WARNING) << "Received unexpected child nodes for parent id "
70 << params.GetParentId();
71 return;
72 }
73
74 // Move the missing children into the |dom_tree_.document_result_|.
75 dom::Node* parent_node =
76 const_cast<dom::Node*>(dom_tree_.document_result_->GetRoot());
77 std::vector<std::unique_ptr<dom::Node>>* child_nodes =
78 const_cast<std::vector<std::unique_ptr<dom::Node>>*>(params.GetNodes());
79 parent_node->SetChildren(std::move(*child_nodes));
80
81 if (dom_observer_registered_)
82 devtools_client_->GetDOM()->RemoveObserver(this);
83 dom_observer_registered_ = false;
84
85 child_nodes_fetched_ = true;
86 MaybeExtractDomTree();
87 }
88
89 void DomTreeExtractor::MaybeExtractDomTree() {
90 if (dom_tree_.document_result_ && dom_tree_.layout_tree_result_ &&
91 child_nodes_fetched_) {
92 EnumerateNodes(dom_tree_.document_result_->GetRoot());
93 ExtractLayoutTreeNodes();
94
95 child_nodes_fetched_ = false;
96 work_in_progress_ = false;
97
98 callback_.Run(std::move(dom_tree_));
99 }
100 }
101
102 void DomTreeExtractor::EnumerateNodes(const dom::Node* node) {
103 // Allocate an index and record the node pointer.
104 size_t index = dom_tree_.node_id_to_index_.size();
105 dom_tree_.node_id_to_index_[node->GetNodeId()] = index;
106 dom_tree_.dom_nodes_.push_back(node);
107
108 if (node->HasContentDocument())
109 EnumerateNodes(node->GetContentDocument());
110
111 if (node->HasChildren()) {
112 for (const std::unique_ptr<dom::Node>& child : *node->GetChildren()) {
113 EnumerateNodes(child.get());
114 }
115 }
116 }
117
118 void DomTreeExtractor::ExtractLayoutTreeNodes() {
119 dom_tree_.layout_tree_nodes_.reserve(
120 dom_tree_.layout_tree_result_->GetLayoutTreeNodes()->size());
121
122 // Only extract layout tree nodes that map to a DOM node.
123 for (const std::unique_ptr<dom::LayoutTreeNode>& layout_node :
124 *dom_tree_.layout_tree_result_->GetLayoutTreeNodes()) {
125 std::unordered_map<NodeId, size_t>::const_iterator it =
126 dom_tree_.node_id_to_index_.find(layout_node->GetBackendNodeId());
127 if (it == dom_tree_.node_id_to_index_.end())
128 continue;
129
130 dom_tree_.layout_tree_nodes_.push_back(layout_node.get());
131 }
132 }
133
134 DomTreeExtractor::DomTree::DomTree() {}
135 DomTreeExtractor::DomTree::~DomTree() {}
136
137 DomTreeExtractor::DomTree::DomTree(DomTree&& other) {
Sami 2016/10/03 10:42:18 Could this be "= default"?
alex clarke (OOO till 29th) 2016/10/19 16:23:26 Done.
138 dom_nodes_ = std::move(other.dom_nodes_);
139 node_id_to_index_ = std::move(other.node_id_to_index_);
140 layout_tree_nodes_ = std::move(other.layout_tree_nodes_);
141 document_result_ = std::move(other.document_result_);
142 layout_tree_result_ = std::move(other.layout_tree_result_);
143 }
144
145 } // namespace headless
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698