frame_tree.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 3// found in the LICENSE file. 4 5#include "content/browser/frame_host/frame_tree.h" 6 7#include <queue> 8 9#include "base/bind.h" 10#include "base/callback.h" 11#include "content/browser/frame_host/frame_tree_node.h" 12#include "content/browser/frame_host/navigator.h" 13#include "content/browser/frame_host/render_frame_host_factory.h" 14#include "content/browser/frame_host/render_frame_host_impl.h" 15 16namespace content { 17 18namespace { 19// Used with FrameTree::ForEach() to search for the FrameTreeNode 20// corresponding to |frame_tree_node_id|. 21bool FrameTreeNodeForId(int64 frame_tree_node_id, 22 FrameTreeNode** out_node, 23 FrameTreeNode* node) { 24 if (node->frame_tree_node_id() == frame_tree_node_id) { 25 *out_node = node; 26 // Terminate iteration once the node has been found. 27 return false; 28 } 29 return true; 30} 31 32// TODO(creis): Remove this version along with FrameTreeNode::frame_id(). 33bool FrameTreeNodeForFrameId(int64 frame_id, 34 FrameTreeNode** out_node, 35 FrameTreeNode* node) { 36 if (node->frame_id() == frame_id) { 37 *out_node = node; 38 // Terminate iteration once the node has been found. 39 return false; 40 } 41 return true; 42} 43 44} // namespace 45 46FrameTree::FrameTree(Navigator* navigator, 47 RenderViewHostDelegate* render_view_delegate, 48 RenderWidgetHostDelegate* render_widget_delegate, 49 RenderFrameHostManager::Delegate* manager_delegate) 50 : render_view_delegate_(render_view_delegate), 51 render_widget_delegate_(render_widget_delegate), 52 manager_delegate_(manager_delegate), 53 root_(new FrameTreeNode(navigator, 54 render_view_delegate, 55 render_widget_delegate, 56 manager_delegate, 57 FrameTreeNode::kInvalidFrameId, 58 std::string(), 59 scoped_ptr<RenderFrameHostImpl>())) { 60} 61 62FrameTree::~FrameTree() { 63} 64 65FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) { 66 FrameTreeNode* node = NULL; 67 ForEach(base::Bind(&FrameTreeNodeForId, frame_tree_node_id, &node)); 68 return node; 69} 70 71void FrameTree::ForEach( 72 const base::Callback<bool(FrameTreeNode*)>& on_node) const { 73 std::queue<FrameTreeNode*> queue; 74 queue.push(root_.get()); 75 76 while (!queue.empty()) { 77 FrameTreeNode* node = queue.front(); 78 queue.pop(); 79 if (!on_node.Run(node)) 80 break; 81 82 for (size_t i = 0; i < node->child_count(); ++i) 83 queue.push(node->child_at(i)); 84 } 85} 86 87bool FrameTree::IsFirstNavigationAfterSwap() const { 88 return root_->frame_id() == FrameTreeNode::kInvalidFrameId; 89} 90 91void FrameTree::OnFirstNavigationAfterSwap(int main_frame_id) { 92 root_->set_frame_id(main_frame_id); 93} 94 95void FrameTree::AddFrame(int render_frame_host_id, 96 int64 parent_frame_id, 97 int64 frame_id, 98 const std::string& frame_name) { 99 FrameTreeNode* parent = FindByFrameID(parent_frame_id); 100 // TODO(ajwong): Should the renderer be killed here? Would there be a race on 101 // shutdown that might make this case possible? 102 if (!parent) 103 return; 104 105 parent->AddChild(CreateNode(frame_id, frame_name, render_frame_host_id, 106 parent->navigator(), 107 parent->render_frame_host()->GetProcess())); 108} 109 110void FrameTree::RemoveFrame(int64 parent_frame_id, int64 frame_id) { 111 // If switches::kSitePerProcess is not specified, then the FrameTree only 112 // contains a node for the root element. However, even in this case 113 // frame detachments need to be broadcast outwards. 114 // 115 // TODO(ajwong): Move this below the |parent| check after the FrameTree is 116 // guaranteed to be correctly populated even without the 117 // switches::kSitePerProcess flag. 118 FrameTreeNode* parent = FindByFrameID(parent_frame_id); 119 FrameTreeNode* child = FindByFrameID(frame_id); 120 if (!on_frame_removed_.is_null()) { 121 on_frame_removed_.Run( 122 root_->render_frame_host()->render_view_host(), frame_id); 123 } 124 125 // TODO(ajwong): Should the renderer be killed here? Would there be a race on 126 // shutdown that might make this case possible? 127 if (!parent || !child) 128 return; 129 130 parent->RemoveChild(child); 131} 132 133void FrameTree::SetFrameUrl(int64 frame_id, const GURL& url) { 134 FrameTreeNode* node = FindByFrameID(frame_id); 135 // TODO(ajwong): Should the renderer be killed here? Would there be a race on 136 // shutdown that might make this case possible? 137 if (!node) 138 return; 139 140 if (node) 141 node->set_current_url(url); 142} 143 144void FrameTree::SwapMainFrame(RenderFrameHostImpl* render_frame_host) { 145 return root_->ResetForMainFrame(render_frame_host); 146} 147 148RenderFrameHostImpl* FrameTree::GetMainFrame() const { 149 return root_->render_frame_host(); 150} 151 152void FrameTree::SetFrameRemoveListener( 153 const base::Callback<void(RenderViewHostImpl*, int64)>& on_frame_removed) { 154 on_frame_removed_ = on_frame_removed; 155} 156 157FrameTreeNode* FrameTree::FindByFrameID(int64 frame_id) { 158 FrameTreeNode* node = NULL; 159 ForEach(base::Bind(&FrameTreeNodeForFrameId, frame_id, &node)); 160 return node; 161} 162 163scoped_ptr<FrameTreeNode> FrameTree::CreateNode( 164 int64 frame_id, 165 const std::string& frame_name, 166 int render_frame_host_id, 167 Navigator* navigator, 168 RenderProcessHost* render_process_host) { 169 scoped_ptr<RenderFrameHostImpl> render_frame_host( 170 RenderFrameHostFactory::Create( 171 root_->render_frame_host()->render_view_host(), 172 this, 173 render_frame_host_id, 174 false)); 175 176 return make_scoped_ptr(new FrameTreeNode(navigator, 177 render_view_delegate_, render_widget_delegate_, manager_delegate_, 178 frame_id, frame_name, render_frame_host.Pass())); 179} 180 181} // namespace content 182