IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / frame_host / frame_tree.cc
blobf26c46c02360a0eda43722ffe1a1d417709e857a
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.
5 #include "content/browser/frame_host/frame_tree.h"
7 #include <queue>
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 #include "content/browser/renderer_host/render_view_host_factory.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
18 namespace content {
20 namespace {
21 // Used with FrameTree::ForEach() to search for the FrameTreeNode
22 // corresponding to |frame_tree_node_id|.
23 bool FrameTreeNodeForId(int64 frame_tree_node_id,
24 FrameTreeNode** out_node,
25 FrameTreeNode* node) {
26 if (node->frame_tree_node_id() == frame_tree_node_id) {
27 *out_node = node;
28 // Terminate iteration once the node has been found.
29 return false;
31 return true;
34 // TODO(creis): Remove this version along with FrameTreeNode::frame_id().
35 bool FrameTreeNodeForFrameId(int64 frame_id,
36 FrameTreeNode** out_node,
37 FrameTreeNode* node) {
38 if (node->frame_id() == frame_id) {
39 *out_node = node;
40 // Terminate iteration once the node has been found.
41 return false;
43 return true;
46 } // namespace
48 FrameTree::FrameTree(Navigator* navigator,
49 RenderFrameHostDelegate* render_frame_delegate,
50 RenderViewHostDelegate* render_view_delegate,
51 RenderWidgetHostDelegate* render_widget_delegate,
52 RenderFrameHostManager::Delegate* manager_delegate)
53 : render_frame_delegate_(render_frame_delegate),
54 render_view_delegate_(render_view_delegate),
55 render_widget_delegate_(render_widget_delegate),
56 manager_delegate_(manager_delegate),
57 root_(new FrameTreeNode(this,
58 navigator,
59 render_frame_delegate,
60 render_view_delegate,
61 render_widget_delegate,
62 manager_delegate,
63 FrameTreeNode::kInvalidFrameId,
64 std::string())) {
67 FrameTree::~FrameTree() {
70 FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) {
71 FrameTreeNode* node = NULL;
72 ForEach(base::Bind(&FrameTreeNodeForId, frame_tree_node_id, &node));
73 return node;
76 void FrameTree::ForEach(
77 const base::Callback<bool(FrameTreeNode*)>& on_node) const {
78 std::queue<FrameTreeNode*> queue;
79 queue.push(root_.get());
81 while (!queue.empty()) {
82 FrameTreeNode* node = queue.front();
83 queue.pop();
84 if (!on_node.Run(node))
85 break;
87 for (size_t i = 0; i < node->child_count(); ++i)
88 queue.push(node->child_at(i));
92 bool FrameTree::IsFirstNavigationAfterSwap() const {
93 return root_->frame_id() == FrameTreeNode::kInvalidFrameId;
96 void FrameTree::OnFirstNavigationAfterSwap(int main_frame_id) {
97 root_->set_frame_id(main_frame_id);
100 RenderFrameHostImpl* FrameTree::AddFrame(int frame_routing_id,
101 int64 parent_frame_id,
102 int64 frame_id,
103 const std::string& frame_name) {
104 FrameTreeNode* parent = FindByFrameID(parent_frame_id);
105 // TODO(ajwong): Should the renderer be killed here? Would there be a race on
106 // shutdown that might make this case possible?
107 if (!parent)
108 return NULL;
110 scoped_ptr<FrameTreeNode> node(new FrameTreeNode(
111 this, parent->navigator(), render_frame_delegate_, render_view_delegate_,
112 render_widget_delegate_, manager_delegate_, frame_id, frame_name));
113 FrameTreeNode* node_ptr = node.get();
114 // AddChild is what creates the RenderFrameHost.
115 parent->AddChild(node.Pass(), frame_routing_id);
116 return node_ptr->current_frame_host();
119 void FrameTree::RemoveFrame(RenderFrameHostImpl* render_frame_host,
120 int64 parent_frame_id,
121 int64 frame_id) {
122 // If switches::kSitePerProcess is not specified, then the FrameTree only
123 // contains a node for the root element. However, even in this case
124 // frame detachments need to be broadcast outwards.
126 // TODO(ajwong): Move this below the |parent| check after the FrameTree is
127 // guaranteed to be correctly populated even without the
128 // switches::kSitePerProcess flag.
129 FrameTreeNode* parent = FindByFrameID(parent_frame_id);
130 FrameTreeNode* child = FindByFrameID(frame_id);
131 if (!on_frame_removed_.is_null()) {
132 on_frame_removed_.Run(
133 render_frame_host->render_view_host(), frame_id);
136 // TODO(ajwong): Should the renderer be killed here? Would there be a race on
137 // shutdown that might make this case possible?
138 if (!parent || !child)
139 return;
141 parent->RemoveChild(child);
144 void FrameTree::SetFrameUrl(int64 frame_id, const GURL& url) {
145 FrameTreeNode* node = FindByFrameID(frame_id);
146 // TODO(ajwong): Should the renderer be killed here? Would there be a race on
147 // shutdown that might make this case possible?
148 if (!node)
149 return;
151 if (node)
152 node->set_current_url(url);
155 void FrameTree::ResetForMainFrameSwap() {
156 return root_->ResetForMainFrameSwap();
159 RenderFrameHostImpl* FrameTree::GetMainFrame() const {
160 return root_->current_frame_host();
163 void FrameTree::SetFrameRemoveListener(
164 const base::Callback<void(RenderViewHostImpl*, int64)>& on_frame_removed) {
165 on_frame_removed_ = on_frame_removed;
168 void FrameTree::ClearFrameRemoveListenerForTesting() {
169 on_frame_removed_.Reset();
172 RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame(
173 SiteInstance* site_instance,
174 int routing_id,
175 int main_frame_routing_id,
176 bool swapped_out,
177 bool hidden) {
178 DCHECK(main_frame_routing_id != MSG_ROUTING_NONE);
179 RenderViewHostMap::iterator iter =
180 render_view_host_map_.find(site_instance->GetId());
181 CHECK(iter == render_view_host_map_.end());
182 RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
183 RenderViewHostFactory::Create(site_instance,
184 render_view_delegate_,
185 render_widget_delegate_,
186 routing_id,
187 main_frame_routing_id,
188 swapped_out,
189 hidden));
191 render_view_host_map_[site_instance->GetId()] =
192 RenderViewHostRefCount(rvh, 0);
193 return rvh;
196 RenderViewHostImpl* FrameTree::GetRenderViewHostForSubFrame(
197 SiteInstance* site_instance) {
198 RenderViewHostMap::iterator iter =
199 render_view_host_map_.find(site_instance->GetId());
200 // TODO(creis): Mirror the frame tree so this check can't fail.
201 if (iter == render_view_host_map_.end())
202 return NULL;
203 RenderViewHostRefCount rvh_refcount = iter->second;
204 return rvh_refcount.first;
207 void FrameTree::RegisterRenderFrameHost(
208 RenderFrameHostImpl* render_frame_host) {
209 SiteInstance* site_instance =
210 render_frame_host->render_view_host()->GetSiteInstance();
211 RenderViewHostMap::iterator iter =
212 render_view_host_map_.find(site_instance->GetId());
213 CHECK(iter != render_view_host_map_.end());
215 // Increment the refcount.
216 CHECK_GE(iter->second.second, 0);
217 iter->second.second++;
220 void FrameTree::UnregisterRenderFrameHost(
221 RenderFrameHostImpl* render_frame_host) {
222 SiteInstance* site_instance =
223 render_frame_host->render_view_host()->GetSiteInstance();
224 RenderViewHostMap::iterator iter =
225 render_view_host_map_.find(site_instance->GetId());
226 CHECK(iter != render_view_host_map_.end());
228 // Decrement the refcount and shutdown the RenderViewHost if no one else is
229 // using it.
230 CHECK_GT(iter->second.second, 0);
231 iter->second.second--;
232 if (iter->second.second == 0) {
233 iter->second.first->Shutdown();
234 render_view_host_map_.erase(iter);
238 FrameTreeNode* FrameTree::FindByFrameID(int64 frame_id) {
239 FrameTreeNode* node = NULL;
240 ForEach(base::Bind(&FrameTreeNodeForFrameId, frame_id, &node));
241 return node;
244 } // namespace content