| 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 |