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