OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/frame_host/frame_tree.h" | 5 #include "content/browser/frame_host/frame_tree.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 FrameTreeNode** out_node, | 24 FrameTreeNode** out_node, |
25 FrameTreeNode* node) { | 25 FrameTreeNode* node) { |
26 if (node->frame_tree_node_id() == frame_tree_node_id) { | 26 if (node->frame_tree_node_id() == frame_tree_node_id) { |
27 *out_node = node; | 27 *out_node = node; |
28 // Terminate iteration once the node has been found. | 28 // Terminate iteration once the node has been found. |
29 return false; | 29 return false; |
30 } | 30 } |
31 return true; | 31 return true; |
32 } | 32 } |
33 | 33 |
34 // TODO(creis): Remove this version along with FrameTreeNode::frame_id(). | 34 bool FrameTreeNodeForRoutingId(int routing_id, |
35 bool FrameTreeNodeForFrameId(int64 frame_id, | 35 int process_id, |
36 FrameTreeNode** out_node, | 36 FrameTreeNode** out_node, |
37 FrameTreeNode* node) { | 37 FrameTreeNode* node) { |
38 if (node->frame_id() == frame_id) { | 38 // TODO(creis): Look through the swapped out RFHs as well. |
| 39 if (node->current_frame_host()->GetProcess()->GetID() == process_id && |
| 40 node->current_frame_host()->GetRoutingID() == routing_id) { |
39 *out_node = node; | 41 *out_node = node; |
40 // Terminate iteration once the node has been found. | 42 // Terminate iteration once the node has been found. |
41 return false; | 43 return false; |
42 } | 44 } |
43 return true; | 45 return true; |
44 } | 46 } |
45 | 47 |
46 // Iterate over the FrameTree to reset any node affected by the loss of the | 48 // Iterate over the FrameTree to reset any node affected by the loss of the |
47 // given RenderViewHost's process. | 49 // given RenderViewHost's process. |
48 bool ResetNodesForNewProcess(RenderViewHost* render_view_host, | 50 bool ResetNodesForNewProcess(RenderViewHost* render_view_host, |
(...skipping 13 matching lines...) Expand all Loading... |
62 : render_frame_delegate_(render_frame_delegate), | 64 : render_frame_delegate_(render_frame_delegate), |
63 render_view_delegate_(render_view_delegate), | 65 render_view_delegate_(render_view_delegate), |
64 render_widget_delegate_(render_widget_delegate), | 66 render_widget_delegate_(render_widget_delegate), |
65 manager_delegate_(manager_delegate), | 67 manager_delegate_(manager_delegate), |
66 root_(new FrameTreeNode(this, | 68 root_(new FrameTreeNode(this, |
67 navigator, | 69 navigator, |
68 render_frame_delegate, | 70 render_frame_delegate, |
69 render_view_delegate, | 71 render_view_delegate, |
70 render_widget_delegate, | 72 render_widget_delegate, |
71 manager_delegate, | 73 manager_delegate, |
72 FrameTreeNode::kInvalidFrameId, | |
73 std::string())) { | 74 std::string())) { |
74 } | 75 } |
75 | 76 |
76 FrameTree::~FrameTree() { | 77 FrameTree::~FrameTree() { |
77 } | 78 } |
78 | 79 |
79 FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) { | 80 FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) { |
80 FrameTreeNode* node = NULL; | 81 FrameTreeNode* node = NULL; |
81 ForEach(base::Bind(&FrameTreeNodeForId, frame_tree_node_id, &node)); | 82 ForEach(base::Bind(&FrameTreeNodeForId, frame_tree_node_id, &node)); |
82 return node; | 83 return node; |
83 } | 84 } |
84 | 85 |
| 86 FrameTreeNode* FrameTree::FindByRoutingID(int routing_id, int process_id) { |
| 87 FrameTreeNode* node = NULL; |
| 88 ForEach( |
| 89 base::Bind(&FrameTreeNodeForRoutingId, routing_id, process_id, &node)); |
| 90 return node; |
| 91 } |
| 92 |
85 void FrameTree::ForEach( | 93 void FrameTree::ForEach( |
86 const base::Callback<bool(FrameTreeNode*)>& on_node) const { | 94 const base::Callback<bool(FrameTreeNode*)>& on_node) const { |
87 std::queue<FrameTreeNode*> queue; | 95 std::queue<FrameTreeNode*> queue; |
88 queue.push(root_.get()); | 96 queue.push(root_.get()); |
89 | 97 |
90 while (!queue.empty()) { | 98 while (!queue.empty()) { |
91 FrameTreeNode* node = queue.front(); | 99 FrameTreeNode* node = queue.front(); |
92 queue.pop(); | 100 queue.pop(); |
93 if (!on_node.Run(node)) | 101 if (!on_node.Run(node)) |
94 break; | 102 break; |
95 | 103 |
96 for (size_t i = 0; i < node->child_count(); ++i) | 104 for (size_t i = 0; i < node->child_count(); ++i) |
97 queue.push(node->child_at(i)); | 105 queue.push(node->child_at(i)); |
98 } | 106 } |
99 } | 107 } |
100 | 108 |
101 bool FrameTree::IsFirstNavigationAfterSwap() const { | 109 RenderFrameHostImpl* FrameTree::AddFrame(FrameTreeNode* parent, |
102 return root_->frame_id() == FrameTreeNode::kInvalidFrameId; | 110 int new_routing_id, |
103 } | |
104 | |
105 void FrameTree::OnFirstNavigationAfterSwap(int main_frame_id) { | |
106 root_->set_frame_id(main_frame_id); | |
107 } | |
108 | |
109 RenderFrameHostImpl* FrameTree::AddFrame(int frame_routing_id, | |
110 int64 parent_frame_id, | |
111 int64 frame_id, | |
112 const std::string& frame_name) { | 111 const std::string& frame_name) { |
113 FrameTreeNode* parent = FindByFrameID(parent_frame_id); | |
114 // TODO(ajwong): Should the renderer be killed here? Would there be a race on | |
115 // shutdown that might make this case possible? | |
116 if (!parent) | |
117 return NULL; | |
118 | |
119 scoped_ptr<FrameTreeNode> node(new FrameTreeNode( | 112 scoped_ptr<FrameTreeNode> node(new FrameTreeNode( |
120 this, parent->navigator(), render_frame_delegate_, render_view_delegate_, | 113 this, parent->navigator(), render_frame_delegate_, render_view_delegate_, |
121 render_widget_delegate_, manager_delegate_, frame_id, frame_name)); | 114 render_widget_delegate_, manager_delegate_, frame_name)); |
122 FrameTreeNode* node_ptr = node.get(); | 115 FrameTreeNode* node_ptr = node.get(); |
123 // AddChild is what creates the RenderFrameHost. | 116 // AddChild is what creates the RenderFrameHost. |
124 parent->AddChild(node.Pass(), frame_routing_id); | 117 parent->AddChild(node.Pass(), new_routing_id); |
125 return node_ptr->current_frame_host(); | 118 return node_ptr->current_frame_host(); |
126 } | 119 } |
127 | 120 |
128 void FrameTree::RemoveFrame(RenderFrameHostImpl* render_frame_host, | 121 void FrameTree::RemoveFrame(FrameTreeNode* child) { |
129 int64 parent_frame_id, | 122 FrameTreeNode* parent = child->parent(); |
130 int64 frame_id) { | 123 if (!parent) { |
131 // If switches::kSitePerProcess is not specified, then the FrameTree only | 124 NOTREACHED() << "Unexpected RemoveFrame call for main frame."; |
132 // contains a node for the root element. However, even in this case | 125 return; |
133 // frame detachments need to be broadcast outwards. | 126 } |
134 // | 127 |
135 // TODO(ajwong): Move this below the |parent| check after the FrameTree is | 128 // Notify observers of the frame removal. |
136 // guaranteed to be correctly populated even without the | 129 RenderFrameHostImpl* render_frame_host = child->current_frame_host(); |
137 // switches::kSitePerProcess flag. | |
138 FrameTreeNode* parent = FindByFrameID(parent_frame_id); | |
139 FrameTreeNode* child = FindByFrameID(frame_id); | |
140 if (!on_frame_removed_.is_null()) { | 130 if (!on_frame_removed_.is_null()) { |
141 on_frame_removed_.Run( | 131 on_frame_removed_.Run( |
142 render_frame_host->render_view_host(), frame_id); | 132 render_frame_host->render_view_host(), |
| 133 render_frame_host->GetRoutingID()); |
143 } | 134 } |
144 | 135 |
145 // TODO(ajwong): Should the renderer be killed here? Would there be a race on | |
146 // shutdown that might make this case possible? | |
147 if (!parent || !child) | |
148 return; | |
149 | |
150 parent->RemoveChild(child); | 136 parent->RemoveChild(child); |
151 } | 137 } |
152 | 138 |
153 void FrameTree::SetFrameUrl(int64 frame_id, const GURL& url) { | |
154 FrameTreeNode* node = FindByFrameID(frame_id); | |
155 // TODO(ajwong): Should the renderer be killed here? Would there be a race on | |
156 // shutdown that might make this case possible? | |
157 if (!node) | |
158 return; | |
159 | |
160 if (node) | |
161 node->set_current_url(url); | |
162 } | |
163 | |
164 void FrameTree::ResetForMainFrameSwap() { | 139 void FrameTree::ResetForMainFrameSwap() { |
165 root_->ResetForNewProcess(); | 140 root_->ResetForNewProcess(); |
166 } | 141 } |
167 | 142 |
168 void FrameTree::RenderProcessGone(RenderViewHost* render_view_host) { | 143 void FrameTree::RenderProcessGone(RenderViewHost* render_view_host) { |
169 // Walk the full tree looking for nodes that may be affected. Once a frame | 144 // Walk the full tree looking for nodes that may be affected. Once a frame |
170 // crashes, all of its child FrameTreeNodes go away. | 145 // crashes, all of its child FrameTreeNodes go away. |
171 // Note that the helper function may call ResetForNewProcess on a node, which | 146 // Note that the helper function may call ResetForNewProcess on a node, which |
172 // clears its children before we iterate over them. That's ok, because | 147 // clears its children before we iterate over them. That's ok, because |
173 // ForEach does not add a node's children to the queue until after visiting | 148 // ForEach does not add a node's children to the queue until after visiting |
174 // the node itself. | 149 // the node itself. |
175 ForEach(base::Bind(&ResetNodesForNewProcess, render_view_host)); | 150 ForEach(base::Bind(&ResetNodesForNewProcess, render_view_host)); |
176 } | 151 } |
177 | 152 |
178 RenderFrameHostImpl* FrameTree::GetMainFrame() const { | 153 RenderFrameHostImpl* FrameTree::GetMainFrame() const { |
179 return root_->current_frame_host(); | 154 return root_->current_frame_host(); |
180 } | 155 } |
181 | 156 |
182 void FrameTree::SetFrameRemoveListener( | 157 void FrameTree::SetFrameRemoveListener( |
183 const base::Callback<void(RenderViewHostImpl*, int64)>& on_frame_removed) { | 158 const base::Callback<void(RenderViewHostImpl*, int)>& on_frame_removed) { |
184 on_frame_removed_ = on_frame_removed; | 159 on_frame_removed_ = on_frame_removed; |
185 } | 160 } |
186 | 161 |
187 void FrameTree::ClearFrameRemoveListenerForTesting() { | |
188 on_frame_removed_.Reset(); | |
189 } | |
190 | |
191 RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame( | 162 RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame( |
192 SiteInstance* site_instance, | 163 SiteInstance* site_instance, |
193 int routing_id, | 164 int routing_id, |
194 int main_frame_routing_id, | 165 int main_frame_routing_id, |
195 bool swapped_out, | 166 bool swapped_out, |
196 bool hidden) { | 167 bool hidden) { |
197 DCHECK(main_frame_routing_id != MSG_ROUTING_NONE); | 168 DCHECK(main_frame_routing_id != MSG_ROUTING_NONE); |
198 RenderViewHostMap::iterator iter = | 169 RenderViewHostMap::iterator iter = |
199 render_view_host_map_.find(site_instance->GetId()); | 170 render_view_host_map_.find(site_instance->GetId()); |
200 if (iter != render_view_host_map_.end()) { | 171 if (iter != render_view_host_map_.end()) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 if (rvh->ref_count() == 0) { | 251 if (rvh->ref_count() == 0) { |
281 rvh->Shutdown(); | 252 rvh->Shutdown(); |
282 render_view_host_pending_shutdown_map_.erase(multi_iter); | 253 render_view_host_pending_shutdown_map_.erase(multi_iter); |
283 } | 254 } |
284 break; | 255 break; |
285 } | 256 } |
286 CHECK(render_view_host_found); | 257 CHECK(render_view_host_found); |
287 } | 258 } |
288 } | 259 } |
289 | 260 |
290 FrameTreeNode* FrameTree::FindByFrameID(int64 frame_id) { | |
291 FrameTreeNode* node = NULL; | |
292 ForEach(base::Bind(&FrameTreeNodeForFrameId, frame_id, &node)); | |
293 return node; | |
294 } | |
295 | |
296 } // namespace content | 261 } // namespace content |
OLD | NEW |