blob: 0090c386d2f494eb52ccc420e81b3a5ce7479fd4 [file] [log] [blame]
[email protected]9b159a52013-10-03 17:24:551// 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
[email protected]d4a8ca482013-10-30 21:06:405#include "content/browser/frame_host/frame_tree.h"
[email protected]9b159a52013-10-03 17:24:556
avib7348942015-12-25 20:57:107#include <stddef.h>
8
[email protected]9b159a52013-10-03 17:24:559#include <queue>
dcheng29f5a6c2015-08-31 21:43:2710#include <utility>
[email protected]9b159a52013-10-03 17:24:5511
12#include "base/bind.h"
13#include "base/callback.h"
[email protected]20edca72014-08-14 10:27:5314#include "base/containers/hash_tables.h"
15#include "base/lazy_instance.h"
dcheng9bfa5162016-04-09 01:00:5716#include "base/memory/ptr_util.h"
[email protected]d4a8ca482013-10-30 21:06:4017#include "content/browser/frame_host/frame_tree_node.h"
[email protected]190b8c52013-11-09 01:35:4418#include "content/browser/frame_host/navigator.h"
[email protected]2a18ee222013-11-21 07:52:4419#include "content/browser/frame_host/render_frame_host_factory.h"
[email protected]d4a8ca482013-10-30 21:06:4020#include "content/browser/frame_host/render_frame_host_impl.h"
dmazzoni0b5d2482014-09-10 19:45:5721#include "content/browser/frame_host/render_frame_proxy_host.h"
[email protected]94d0cc12013-12-18 00:07:4122#include "content/browser/renderer_host/render_view_host_factory.h"
23#include "content/browser/renderer_host/render_view_host_impl.h"
alexmos3fcd0ca2015-10-23 18:18:3324#include "content/common/input_messages.h"
nickac60e75472015-07-31 00:44:3525#include "content/common/site_isolation_policy.h"
dcheng5f60abb2015-05-28 01:39:3626#include "third_party/WebKit/public/web/WebSandboxFlags.h"
[email protected]9b159a52013-10-03 17:24:5527
28namespace content {
29
30namespace {
[email protected]20edca72014-08-14 10:27:5331
dcheng57e39e22016-01-21 00:25:3832// Helper function to collect SiteInstances involved in rendering a single
33// FrameTree (which is a subset of SiteInstances in main frame's proxy_hosts_
34// because of openers).
35std::set<SiteInstance*> CollectSiteInstances(FrameTree* tree) {
36 std::set<SiteInstance*> instances;
37 for (FrameTreeNode* node : tree->Nodes())
38 instances.insert(node->current_frame_host()->GetSiteInstance());
39 return instances;
alexmos3fcd0ca2015-10-23 18:18:3340}
41
[email protected]9b159a52013-10-03 17:24:5542} // namespace
43
vmpstr33895d992016-02-24 20:55:2144FrameTree::NodeIterator::NodeIterator(const NodeIterator& other) = default;
45
dcheng57e39e22016-01-21 00:25:3846FrameTree::NodeIterator::~NodeIterator() {}
47
48FrameTree::NodeIterator& FrameTree::NodeIterator::operator++() {
49 for (size_t i = 0; i < current_node_->child_count(); ++i) {
50 FrameTreeNode* child = current_node_->child_at(i);
51 if (child == node_to_skip_)
52 continue;
53 queue_.push(child);
54 }
55
56 if (!queue_.empty()) {
57 current_node_ = queue_.front();
58 queue_.pop();
59 } else {
60 current_node_ = nullptr;
61 }
62
63 return *this;
64}
65
66bool FrameTree::NodeIterator::operator==(const NodeIterator& rhs) const {
67 return current_node_ == rhs.current_node_;
68}
69
70FrameTree::NodeIterator::NodeIterator(FrameTreeNode* starting_node,
71 FrameTreeNode* node_to_skip)
72 : current_node_(starting_node != node_to_skip ? starting_node : nullptr),
73 node_to_skip_(node_to_skip) {}
74
75FrameTree::NodeIterator FrameTree::NodeRange::begin() {
kenrb61b6c252016-03-22 17:37:1576 return NodeIterator(root_, node_to_skip_);
dcheng57e39e22016-01-21 00:25:3877}
78
79FrameTree::NodeIterator FrameTree::NodeRange::end() {
80 return NodeIterator(nullptr, nullptr);
81}
82
kenrb61b6c252016-03-22 17:37:1583FrameTree::NodeRange::NodeRange(FrameTreeNode* root,
84 FrameTreeNode* node_to_skip)
85 : root_(root), node_to_skip_(node_to_skip) {}
dcheng57e39e22016-01-21 00:25:3886
[email protected]fa944cb82013-11-15 17:51:2187FrameTree::FrameTree(Navigator* navigator,
[email protected]92404c62013-12-04 16:40:4688 RenderFrameHostDelegate* render_frame_delegate,
[email protected]fa944cb82013-11-15 17:51:2189 RenderViewHostDelegate* render_view_delegate,
90 RenderWidgetHostDelegate* render_widget_delegate,
[email protected]b0936d22013-11-28 06:47:3691 RenderFrameHostManager::Delegate* manager_delegate)
[email protected]92404c62013-12-04 16:40:4692 : render_frame_delegate_(render_frame_delegate),
93 render_view_delegate_(render_view_delegate),
[email protected]fa944cb82013-11-15 17:51:2194 render_widget_delegate_(render_widget_delegate),
95 manager_delegate_(manager_delegate),
[email protected]94d0cc12013-12-18 00:07:4196 root_(new FrameTreeNode(this,
97 navigator,
[email protected]92404c62013-12-04 16:40:4698 render_frame_delegate,
[email protected]fa944cb82013-11-15 17:51:2199 render_view_delegate,
100 render_widget_delegate,
101 manager_delegate,
dcheng860817a2015-05-22 03:16:56102 // The top-level frame must always be in a
103 // document scope.
104 blink::WebTreeScopeType::Document,
alexmos6e0ee0c2015-05-01 18:57:34105 std::string(),
lukasza464d8692016-02-22 19:26:32106 std::string(),
lazyboy70605c32015-11-03 01:27:31107 blink::WebFrameOwnerProperties())),
fdegansa696e5112015-04-17 01:57:59108 focused_frame_tree_node_id_(-1),
lazyboy70605c32015-11-03 01:27:31109 load_progress_(0.0) {}
[email protected]9b159a52013-10-03 17:24:55110
111FrameTree::~FrameTree() {
nick70b782d2015-10-06 17:37:04112 delete root_;
113 root_ = nullptr;
[email protected]9b159a52013-10-03 17:24:55114}
115
vishal.b782eb5d2015-04-29 12:22:57116FrameTreeNode* FrameTree::FindByID(int frame_tree_node_id) {
dcheng57e39e22016-01-21 00:25:38117 for (FrameTreeNode* node : Nodes()) {
118 if (node->frame_tree_node_id() == frame_tree_node_id)
119 return node;
120 }
121 return nullptr;
[email protected]9b159a52013-10-03 17:24:55122}
123
nasko479ea5a2015-02-14 00:03:04124FrameTreeNode* FrameTree::FindByRoutingID(int process_id, int routing_id) {
dmazzoni0b5d2482014-09-10 19:45:57125 RenderFrameHostImpl* render_frame_host =
126 RenderFrameHostImpl::FromID(process_id, routing_id);
127 if (render_frame_host) {
128 FrameTreeNode* result = render_frame_host->frame_tree_node();
129 if (this == result->frame_tree())
130 return result;
131 }
132
133 RenderFrameProxyHost* render_frame_proxy_host =
134 RenderFrameProxyHost::FromID(process_id, routing_id);
135 if (render_frame_proxy_host) {
136 FrameTreeNode* result = render_frame_proxy_host->frame_tree_node();
137 if (this == result->frame_tree())
138 return result;
139 }
140
creis6a93a812015-04-24 23:13:17141 return nullptr;
142}
143
144FrameTreeNode* FrameTree::FindByName(const std::string& name) {
145 if (name.empty())
nick70b782d2015-10-06 17:37:04146 return root_;
creis6a93a812015-04-24 23:13:17147
dcheng57e39e22016-01-21 00:25:38148 for (FrameTreeNode* node : Nodes()) {
149 if (node->frame_name() == name)
150 return node;
[email protected]9b159a52013-10-03 17:24:55151 }
dcheng57e39e22016-01-21 00:25:38152
153 return nullptr;
154}
155
156FrameTree::NodeRange FrameTree::Nodes() {
157 return NodesExcept(nullptr);
158}
159
kenrb61b6c252016-03-22 17:37:15160FrameTree::NodeRange FrameTree::SubtreeNodes(FrameTreeNode* subtree_root) {
161 return NodeRange(subtree_root, nullptr);
162}
163
dcheng57e39e22016-01-21 00:25:38164FrameTree::NodeRange FrameTree::NodesExcept(FrameTreeNode* node_to_skip) {
kenrb61b6c252016-03-22 17:37:15165 return NodeRange(root_, node_to_skip);
[email protected]9b159a52013-10-03 17:24:55166}
167
nick8814e652015-12-18 01:44:12168bool FrameTree::AddFrame(
lazyboy70605c32015-11-03 01:27:31169 FrameTreeNode* parent,
170 int process_id,
171 int new_routing_id,
172 blink::WebTreeScopeType scope,
173 const std::string& frame_name,
lukasza464d8692016-02-22 19:26:32174 const std::string& frame_unique_name,
lazyboy70605c32015-11-03 01:27:31175 blink::WebSandboxFlags sandbox_flags,
176 const blink::WebFrameOwnerProperties& frame_owner_properties) {
nick8814e652015-12-18 01:44:12177 CHECK_NE(new_routing_id, MSG_ROUTING_NONE);
178
dgroganfb22f9a2014-10-20 21:32:32179 // A child frame always starts with an initial empty document, which means
180 // it is in the same SiteInstance as the parent frame. Ensure that the process
181 // which requested a child frame to be added is the same as the process of the
182 // parent node.
dgroganfb22f9a2014-10-20 21:32:32183 if (parent->current_frame_host()->GetProcess()->GetID() != process_id)
nick8814e652015-12-18 01:44:12184 return false;
dgroganfb22f9a2014-10-20 21:32:32185
[email protected]5f96f5a62014-01-10 00:05:11186 // AddChild is what creates the RenderFrameHost.
nick8814e652015-12-18 01:44:12187 FrameTreeNode* added_node = parent->AddChild(
dcheng9bfa5162016-04-09 01:00:57188 base::WrapUnique(new FrameTreeNode(
nick8814e652015-12-18 01:44:12189 this, parent->navigator(), render_frame_delegate_,
190 render_view_delegate_, render_widget_delegate_, manager_delegate_,
lukasza464d8692016-02-22 19:26:32191 scope, frame_name, frame_unique_name, frame_owner_properties)),
nick8814e652015-12-18 01:44:12192 process_id, new_routing_id);
193
alexmos6e940102016-01-19 22:47:25194 // Set sandbox flags and make them effective immediately, since initial
195 // sandbox flags should apply to the initial empty document in the frame.
196 added_node->SetPendingSandboxFlags(sandbox_flags);
197 added_node->CommitPendingSandboxFlags();
198
nick8814e652015-12-18 01:44:12199 // Now that the new node is part of the FrameTree and has a RenderFrameHost,
200 // we can announce the creation of the initial RenderFrame which already
201 // exists in the renderer process.
202 added_node->current_frame_host()->SetRenderFrameCreated(true);
203 return true;
[email protected]9b159a52013-10-03 17:24:55204}
205
[email protected]58faf942014-02-20 21:03:58206void FrameTree::RemoveFrame(FrameTreeNode* child) {
207 FrameTreeNode* parent = child->parent();
208 if (!parent) {
209 NOTREACHED() << "Unexpected RemoveFrame call for main frame.";
210 return;
[email protected]9b159a52013-10-03 17:24:55211 }
212
[email protected]741fd682013-11-08 08:26:55213 parent->RemoveChild(child);
[email protected]9b159a52013-10-03 17:24:55214}
215
[email protected]82307f6b2014-08-07 03:30:12216void FrameTree::CreateProxiesForSiteInstance(
217 FrameTreeNode* source,
218 SiteInstance* site_instance) {
naskob3041b98a42016-03-12 04:43:06219 // Create the RenderFrameProxyHost for the new SiteInstance.
alexmos58729042015-06-18 23:20:00220 if (!source || !source->IsMainFrame()) {
221 RenderViewHostImpl* render_view_host = GetRenderViewHost(site_instance);
[email protected]82307f6b2014-08-07 03:30:12222 if (!render_view_host) {
naskob3041b98a42016-03-12 04:43:06223 root()->render_manager()->CreateRenderFrameProxy(site_instance);
lazyboybb1af562015-02-04 02:36:02224 } else {
alexmos58729042015-06-18 23:20:00225 root()->render_manager()->EnsureRenderViewInitialized(render_view_host,
226 site_instance);
[email protected]82307f6b2014-08-07 03:30:12227 }
228 }
229
naskoe6edde32014-10-17 15:36:48230 // Proxies are created in the FrameTree in response to a node navigating to a
231 // new SiteInstance. Since |source|'s navigation will replace the currently
232 // loaded document, the entire subtree under |source| will be removed.
dcheng57e39e22016-01-21 00:25:38233 for (FrameTreeNode* node : NodesExcept(source)) {
234 // If a new frame is created in the current SiteInstance, other frames in
235 // that SiteInstance don't need a proxy for the new frame.
236 SiteInstance* current_instance =
237 node->render_manager()->current_frame_host()->GetSiteInstance();
238 if (current_instance != site_instance)
239 node->render_manager()->CreateRenderFrameProxy(site_instance);
240 }
[email protected]82307f6b2014-08-07 03:30:12241}
242
[email protected]9b159a52013-10-03 17:24:55243RenderFrameHostImpl* FrameTree::GetMainFrame() const {
[email protected]94d0cc12013-12-18 00:07:41244 return root_->current_frame_host();
[email protected]9b159a52013-10-03 17:24:55245}
246
[email protected]9c9343b2014-03-08 02:56:07247FrameTreeNode* FrameTree::GetFocusedFrame() {
248 return FindByID(focused_frame_tree_node_id_);
249}
250
alexmos5357efb2015-12-16 21:44:00251void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
252 if (node == GetFocusedFrame())
253 return;
254
dcheng57e39e22016-01-21 00:25:38255 std::set<SiteInstance*> frame_tree_site_instances =
256 CollectSiteInstances(this);
alexmosb1dc2162015-11-05 00:59:20257
alexmos5357efb2015-12-16 21:44:00258 SiteInstance* current_instance =
259 node->current_frame_host()->GetSiteInstance();
260
alexmosb1dc2162015-11-05 00:59:20261 // Update the focused frame in all other SiteInstances. If focus changes to
262 // a cross-process frame, this allows the old focused frame's renderer
263 // process to clear focus from that frame and fire blur events. It also
264 // ensures that the latest focused frame is available in all renderers to
265 // compute document.activeElement.
alexmos5357efb2015-12-16 21:44:00266 //
267 // We do not notify the |source| SiteInstance because it already knows the
268 // new focused frame (since it initiated the focus change), and we notify the
269 // new focused frame's SiteInstance (if it differs from |source|) separately
270 // below.
alexmosb1dc2162015-11-05 00:59:20271 for (const auto& instance : frame_tree_site_instances) {
alexmos5357efb2015-12-16 21:44:00272 if (instance != source && instance != current_instance) {
alexmosb1dc2162015-11-05 00:59:20273 DCHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
274 RenderFrameProxyHost* proxy =
275 node->render_manager()->GetRenderFrameProxyHost(instance);
276 proxy->SetFocusedFrame();
277 }
alexmosca2c6ba2015-10-01 21:52:25278 }
279
alexmos5357efb2015-12-16 21:44:00280 // If |node| was focused from a cross-process frame (i.e., via
281 // window.focus()), tell its RenderFrame that it should focus.
282 if (current_instance != source)
283 node->current_frame_host()->SetFocusedFrame();
284
[email protected]9c9343b2014-03-08 02:56:07285 focused_frame_tree_node_id_ = node->frame_tree_node_id();
alexmos21acae52015-11-07 01:04:43286 node->DidFocus();
dmazzonif27bf892016-03-10 15:51:55287
288 // The accessibility tree data for the root of the frame tree keeps
289 // track of the focused frame too, so update that every time the
290 // focused frame changes.
291 root()->current_frame_host()->UpdateAXTreeData();
[email protected]9c9343b2014-03-08 02:56:07292}
293
[email protected]9b159a52013-10-03 17:24:55294void FrameTree::SetFrameRemoveListener(
[email protected]ae7eeda2014-07-04 01:53:26295 const base::Callback<void(RenderFrameHost*)>& on_frame_removed) {
[email protected]9b159a52013-10-03 17:24:55296 on_frame_removed_ = on_frame_removed;
297}
298
avib7348942015-12-25 20:57:10299RenderViewHostImpl* FrameTree::CreateRenderViewHost(
300 SiteInstance* site_instance,
301 int32_t routing_id,
302 int32_t main_frame_routing_id,
303 bool swapped_out,
304 bool hidden) {
[email protected]94d0cc12013-12-18 00:07:41305 RenderViewHostMap::iterator iter =
306 render_view_host_map_.find(site_instance->GetId());
[email protected]21b41c7e892014-02-28 01:52:24307 if (iter != render_view_host_map_.end()) {
alexmosb97d6bb62015-09-24 07:31:26308 // If a RenderViewHost is pending deletion for this |site_instance|, it
309 // shouldn't be reused, so put it in the map of RenderViewHosts pending
310 // shutdown. Otherwise, return the existing RenderViewHost for the
311 // SiteInstance. Note that if swapped-out is forbidden, the
312 // RenderViewHost's main frame has already been cleared, so we cannot rely
313 // on checking whether the main frame is pending deletion.
creise73d58ef2016-03-29 22:12:15314 if (root_->render_manager()->IsViewPendingDeletion(iter->second)) {
[email protected]82307f6b2014-08-07 03:30:12315 render_view_host_pending_shutdown_map_.insert(
dcheng29f5a6c2015-08-31 21:43:27316 std::make_pair(site_instance->GetId(), iter->second));
[email protected]82307f6b2014-08-07 03:30:12317 render_view_host_map_.erase(iter);
318 } else {
319 return iter->second;
320 }
[email protected]21b41c7e892014-02-28 01:52:24321 }
dcheng29f5a6c2015-08-31 21:43:27322 RenderViewHostImpl* rvh =
323 static_cast<RenderViewHostImpl*>(RenderViewHostFactory::Create(
324 site_instance, render_view_delegate_, render_widget_delegate_,
325 routing_id, main_frame_routing_id, swapped_out, hidden));
[email protected]94d0cc12013-12-18 00:07:41326
[email protected]21b41c7e892014-02-28 01:52:24327 render_view_host_map_[site_instance->GetId()] = rvh;
[email protected]94d0cc12013-12-18 00:07:41328 return rvh;
329}
330
[email protected]82307f6b2014-08-07 03:30:12331RenderViewHostImpl* FrameTree::GetRenderViewHost(SiteInstance* site_instance) {
[email protected]94d0cc12013-12-18 00:07:41332 RenderViewHostMap::iterator iter =
333 render_view_host_map_.find(site_instance->GetId());
creise73d58ef2016-03-29 22:12:15334 // Don't return the RVH if it is pending deletion.
335 if (iter != render_view_host_map_.end() &&
336 !root_->render_manager()->IsViewPendingDeletion(iter->second)) {
337 return iter->second;
338 }
339 return nullptr;
[email protected]94d0cc12013-12-18 00:07:41340}
341
naskof95ab0e2015-05-23 02:27:24342void FrameTree::AddRenderViewHostRef(RenderViewHostImpl* render_view_host) {
343 SiteInstance* site_instance = render_view_host->GetSiteInstance();
[email protected]94d0cc12013-12-18 00:07:41344 RenderViewHostMap::iterator iter =
345 render_view_host_map_.find(site_instance->GetId());
346 CHECK(iter != render_view_host_map_.end());
naskof95ab0e2015-05-23 02:27:24347 CHECK(iter->second == render_view_host);
[email protected]94d0cc12013-12-18 00:07:41348
[email protected]21b41c7e892014-02-28 01:52:24349 iter->second->increment_ref_count();
[email protected]94d0cc12013-12-18 00:07:41350}
351
naskof95ab0e2015-05-23 02:27:24352void FrameTree::ReleaseRenderViewHostRef(RenderViewHostImpl* render_view_host) {
353 SiteInstance* site_instance = render_view_host->GetSiteInstance();
avib7348942015-12-25 20:57:10354 int32_t site_instance_id = site_instance->GetId();
[email protected]94d0cc12013-12-18 00:07:41355 RenderViewHostMap::iterator iter =
[email protected]21b41c7e892014-02-28 01:52:24356 render_view_host_map_.find(site_instance_id);
naskof95ab0e2015-05-23 02:27:24357 if (iter != render_view_host_map_.end() && iter->second == render_view_host) {
[email protected]21b41c7e892014-02-28 01:52:24358 // Decrement the refcount and shutdown the RenderViewHost if no one else is
359 // using it.
360 CHECK_GT(iter->second->ref_count(), 0);
361 iter->second->decrement_ref_count();
362 if (iter->second->ref_count() == 0) {
avi85a4cef2015-12-18 20:13:37363 iter->second->ShutdownAndDestroy();
[email protected]21b41c7e892014-02-28 01:52:24364 render_view_host_map_.erase(iter);
365 }
366 } else {
367 // The RenderViewHost should be in the list of RenderViewHosts pending
368 // shutdown.
369 bool render_view_host_found = false;
370 std::pair<RenderViewHostMultiMap::iterator,
371 RenderViewHostMultiMap::iterator> result =
372 render_view_host_pending_shutdown_map_.equal_range(site_instance_id);
373 for (RenderViewHostMultiMap::iterator multi_iter = result.first;
374 multi_iter != result.second;
375 ++multi_iter) {
naskof95ab0e2015-05-23 02:27:24376 if (multi_iter->second != render_view_host)
[email protected]21b41c7e892014-02-28 01:52:24377 continue;
378 render_view_host_found = true;
[email protected]21b41c7e892014-02-28 01:52:24379 // Decrement the refcount and shutdown the RenderViewHost if no one else
380 // is using it.
naskof95ab0e2015-05-23 02:27:24381 CHECK_GT(render_view_host->ref_count(), 0);
382 render_view_host->decrement_ref_count();
383 if (render_view_host->ref_count() == 0) {
avi85a4cef2015-12-18 20:13:37384 render_view_host->ShutdownAndDestroy();
[email protected]21b41c7e892014-02-28 01:52:24385 render_view_host_pending_shutdown_map_.erase(multi_iter);
386 }
387 break;
388 }
389 CHECK(render_view_host_found);
[email protected]94d0cc12013-12-18 00:07:41390 }
391}
392
dmazzonie950ea232015-03-13 21:39:45393void FrameTree::FrameRemoved(FrameTreeNode* frame) {
nick53d5cbf2015-04-23 22:50:14394 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
395 focused_frame_tree_node_id_ = -1;
396
dmazzonie950ea232015-03-13 21:39:45397 // No notification for the root frame.
clamy9dbf17e22015-03-31 13:37:08398 if (!frame->parent()) {
nick70b782d2015-10-06 17:37:04399 CHECK_EQ(frame, root_);
dmazzonie950ea232015-03-13 21:39:45400 return;
clamy9dbf17e22015-03-31 13:37:08401 }
dmazzonie950ea232015-03-13 21:39:45402
403 // Notify observers of the frame removal.
404 if (!on_frame_removed_.is_null())
405 on_frame_removed_.Run(frame->current_frame_host());
406}
407
fdegansa696e5112015-04-17 01:57:59408void FrameTree::UpdateLoadProgress() {
fdegans1d16355162015-03-26 11:58:34409 double progress = 0.0;
410 int frame_count = 0;
411
dcheng57e39e22016-01-21 00:25:38412 for (FrameTreeNode* node : Nodes()) {
413 // Ignore the current frame if it has not started loading.
414 if (!node->has_started_loading())
415 continue;
416
417 // Collect progress.
418 progress += node->loading_progress();
419 frame_count++;
420 }
421
fdegans1d16355162015-03-26 11:58:34422 if (frame_count != 0)
423 progress /= frame_count;
fdegansa696e5112015-04-17 01:57:59424
425 if (progress <= load_progress_)
426 return;
427 load_progress_ = progress;
428
429 // Notify the WebContents.
430 root_->navigator()->GetDelegate()->DidChangeLoadProgress();
fdegans1d16355162015-03-26 11:58:34431}
432
433void FrameTree::ResetLoadProgress() {
dcheng57e39e22016-01-21 00:25:38434 for (FrameTreeNode* node : Nodes())
435 node->reset_loading_progress();
fdegansa696e5112015-04-17 01:57:59436 load_progress_ = 0.0;
fdegans1d16355162015-03-26 11:58:34437}
438
clamy44e84ce2016-02-22 15:38:25439bool FrameTree::IsLoading() const {
nick931d4452016-03-30 00:59:06440 for (const FrameTreeNode* node : const_cast<FrameTree*>(this)->Nodes()) {
dcheng57e39e22016-01-21 00:25:38441 if (node->IsLoading())
442 return true;
443 }
444 return false;
fdegans1d16355162015-03-26 11:58:34445}
446
alexmos3fcd0ca2015-10-23 18:18:33447void FrameTree::ReplicatePageFocus(bool is_focused) {
dcheng57e39e22016-01-21 00:25:38448 std::set<SiteInstance*> frame_tree_site_instances =
449 CollectSiteInstances(this);
alexmos3fcd0ca2015-10-23 18:18:33450
451 // Send the focus update to main frame's proxies in all SiteInstances of
452 // other frames in this FrameTree. Note that the main frame might also know
453 // about proxies in SiteInstances for frames in a different FrameTree (e.g.,
454 // for window.open), so we can't just iterate over its proxy_hosts_ in
455 // RenderFrameHostManager.
alexmos0d7e0b09b2015-10-29 22:11:48456 for (const auto& instance : frame_tree_site_instances)
457 SetPageFocus(instance, is_focused);
458}
alexmos3fcd0ca2015-10-23 18:18:33459
alexmos0d7e0b09b2015-10-29 22:11:48460void FrameTree::SetPageFocus(SiteInstance* instance, bool is_focused) {
461 RenderFrameHostManager* root_manager = root_->render_manager();
462
463 // This is only used to set page-level focus in cross-process subframes, and
464 // requests to set focus in main frame's SiteInstance are ignored.
465 if (instance != root_manager->current_frame_host()->GetSiteInstance()) {
alexmos3fcd0ca2015-10-23 18:18:33466 RenderFrameProxyHost* proxy =
alexmos0d7e0b09b2015-10-29 22:11:48467 root_manager->GetRenderFrameProxyHost(instance);
alexmos3fcd0ca2015-10-23 18:18:33468 proxy->Send(new InputMsg_SetFocus(proxy->GetRoutingID(), is_focused));
469 }
470}
471
[email protected]9b159a52013-10-03 17:24:55472} // namespace content