blob: 6df53ea83730856e191a6771d23e9daa649a2e0b [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>
Lukasz Anforowicz7bfb2e92017-11-22 17:19:4510#include <set>
dcheng29f5a6c2015-08-31 21:43:2711#include <utility>
[email protected]9b159a52013-10-03 17:24:5512
13#include "base/bind.h"
14#include "base/callback.h"
[email protected]20edca72014-08-14 10:27:5315#include "base/containers/hash_tables.h"
16#include "base/lazy_instance.h"
dcheng9bfa5162016-04-09 01:00:5717#include "base/memory/ptr_util.h"
Pavel Feldman25234722017-10-11 02:49:0618#include "base/unguessable_token.h"
[email protected]d4a8ca482013-10-30 21:06:4019#include "content/browser/frame_host/frame_tree_node.h"
nasko03ecfad2016-08-02 00:54:0620#include "content/browser/frame_host/navigation_controller_impl.h"
21#include "content/browser/frame_host/navigation_entry_impl.h"
[email protected]190b8c52013-11-09 01:35:4422#include "content/browser/frame_host/navigator.h"
[email protected]2a18ee222013-11-21 07:52:4423#include "content/browser/frame_host/render_frame_host_factory.h"
[email protected]d4a8ca482013-10-30 21:06:4024#include "content/browser/frame_host/render_frame_host_impl.h"
dmazzoni0b5d2482014-09-10 19:45:5725#include "content/browser/frame_host/render_frame_proxy_host.h"
[email protected]94d0cc12013-12-18 00:07:4126#include "content/browser/renderer_host/render_view_host_factory.h"
27#include "content/browser/renderer_host/render_view_host_impl.h"
japhet98e9bd82016-06-28 23:48:4528#include "content/common/content_switches_internal.h"
raymes31457802016-07-20 06:08:0929#include "content/common/frame_owner_properties.h"
alexmos3fcd0ca2015-10-23 18:18:3330#include "content/common/input_messages.h"
Kinuko Yasuda75286c02018-02-09 06:09:2131#include "third_party/WebKit/public/common/frame/frame_policy.h"
[email protected]9b159a52013-10-03 17:24:5532
33namespace content {
34
35namespace {
[email protected]20edca72014-08-14 10:27:5336
dcheng57e39e22016-01-21 00:25:3837// Helper function to collect SiteInstances involved in rendering a single
38// FrameTree (which is a subset of SiteInstances in main frame's proxy_hosts_
39// because of openers).
40std::set<SiteInstance*> CollectSiteInstances(FrameTree* tree) {
41 std::set<SiteInstance*> instances;
42 for (FrameTreeNode* node : tree->Nodes())
43 instances.insert(node->current_frame_host()->GetSiteInstance());
44 return instances;
alexmos3fcd0ca2015-10-23 18:18:3345}
46
[email protected]9b159a52013-10-03 17:24:5547} // namespace
48
vmpstr33895d992016-02-24 20:55:2149FrameTree::NodeIterator::NodeIterator(const NodeIterator& other) = default;
50
dcheng57e39e22016-01-21 00:25:3851FrameTree::NodeIterator::~NodeIterator() {}
52
53FrameTree::NodeIterator& FrameTree::NodeIterator::operator++() {
Alex Moshchuk27caae82017-09-11 23:11:1854 if (current_node_ != root_of_subtree_to_skip_) {
55 for (size_t i = 0; i < current_node_->child_count(); ++i) {
56 FrameTreeNode* child = current_node_->child_at(i);
57 queue_.push(child);
58 }
dcheng57e39e22016-01-21 00:25:3859 }
60
61 if (!queue_.empty()) {
62 current_node_ = queue_.front();
63 queue_.pop();
64 } else {
65 current_node_ = nullptr;
66 }
67
68 return *this;
69}
70
71bool FrameTree::NodeIterator::operator==(const NodeIterator& rhs) const {
72 return current_node_ == rhs.current_node_;
73}
74
75FrameTree::NodeIterator::NodeIterator(FrameTreeNode* starting_node,
Alex Moshchuk27caae82017-09-11 23:11:1876 FrameTreeNode* root_of_subtree_to_skip)
77 : current_node_(starting_node),
78 root_of_subtree_to_skip_(root_of_subtree_to_skip) {}
dcheng57e39e22016-01-21 00:25:3879
80FrameTree::NodeIterator FrameTree::NodeRange::begin() {
Alex Moshchuk27caae82017-09-11 23:11:1881 return NodeIterator(root_, root_of_subtree_to_skip_);
dcheng57e39e22016-01-21 00:25:3882}
83
84FrameTree::NodeIterator FrameTree::NodeRange::end() {
85 return NodeIterator(nullptr, nullptr);
86}
87
kenrb61b6c252016-03-22 17:37:1588FrameTree::NodeRange::NodeRange(FrameTreeNode* root,
Alex Moshchuk27caae82017-09-11 23:11:1889 FrameTreeNode* root_of_subtree_to_skip)
90 : root_(root), root_of_subtree_to_skip_(root_of_subtree_to_skip) {}
dcheng57e39e22016-01-21 00:25:3891
[email protected]fa944cb82013-11-15 17:51:2192FrameTree::FrameTree(Navigator* navigator,
[email protected]92404c62013-12-04 16:40:4693 RenderFrameHostDelegate* render_frame_delegate,
[email protected]fa944cb82013-11-15 17:51:2194 RenderViewHostDelegate* render_view_delegate,
95 RenderWidgetHostDelegate* render_widget_delegate,
[email protected]b0936d22013-11-28 06:47:3696 RenderFrameHostManager::Delegate* manager_delegate)
[email protected]92404c62013-12-04 16:40:4697 : render_frame_delegate_(render_frame_delegate),
98 render_view_delegate_(render_view_delegate),
[email protected]fa944cb82013-11-15 17:51:2199 render_widget_delegate_(render_widget_delegate),
100 manager_delegate_(manager_delegate),
[email protected]94d0cc12013-12-18 00:07:41101 root_(new FrameTreeNode(this,
102 navigator,
[email protected]92404c62013-12-04 16:40:46103 render_frame_delegate,
[email protected]fa944cb82013-11-15 17:51:21104 render_widget_delegate,
105 manager_delegate,
xiaochengh98488162016-05-19 15:17:59106 nullptr,
dcheng860817a2015-05-22 03:16:56107 // The top-level frame must always be in a
108 // document scope.
Blink Reformat1c4d759e2017-04-09 16:34:54109 blink::WebTreeScopeType::kDocument,
alexmos6e0ee0c2015-05-01 18:57:34110 std::string(),
lukasza464d8692016-02-22 19:26:32111 std::string(),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45112 false,
Pavel Feldman25234722017-10-11 02:49:06113 base::UnguessableToken::Create(),
raymes31457802016-07-20 06:08:09114 FrameOwnerProperties())),
thestige62f7382016-11-08 18:31:39115 focused_frame_tree_node_id_(FrameTreeNode::kFrameTreeNodeInvalidId),
lazyboy70605c32015-11-03 01:27:31116 load_progress_(0.0) {}
[email protected]9b159a52013-10-03 17:24:55117
118FrameTree::~FrameTree() {
nick70b782d2015-10-06 17:37:04119 delete root_;
120 root_ = nullptr;
[email protected]9b159a52013-10-03 17:24:55121}
122
vishal.b782eb5d2015-04-29 12:22:57123FrameTreeNode* FrameTree::FindByID(int frame_tree_node_id) {
dcheng57e39e22016-01-21 00:25:38124 for (FrameTreeNode* node : Nodes()) {
125 if (node->frame_tree_node_id() == frame_tree_node_id)
126 return node;
127 }
128 return nullptr;
[email protected]9b159a52013-10-03 17:24:55129}
130
nasko479ea5a2015-02-14 00:03:04131FrameTreeNode* FrameTree::FindByRoutingID(int process_id, int routing_id) {
dmazzoni0b5d2482014-09-10 19:45:57132 RenderFrameHostImpl* render_frame_host =
133 RenderFrameHostImpl::FromID(process_id, routing_id);
134 if (render_frame_host) {
135 FrameTreeNode* result = render_frame_host->frame_tree_node();
136 if (this == result->frame_tree())
137 return result;
138 }
139
140 RenderFrameProxyHost* render_frame_proxy_host =
141 RenderFrameProxyHost::FromID(process_id, routing_id);
142 if (render_frame_proxy_host) {
143 FrameTreeNode* result = render_frame_proxy_host->frame_tree_node();
144 if (this == result->frame_tree())
145 return result;
146 }
147
creis6a93a812015-04-24 23:13:17148 return nullptr;
149}
150
151FrameTreeNode* FrameTree::FindByName(const std::string& name) {
152 if (name.empty())
nick70b782d2015-10-06 17:37:04153 return root_;
creis6a93a812015-04-24 23:13:17154
dcheng57e39e22016-01-21 00:25:38155 for (FrameTreeNode* node : Nodes()) {
156 if (node->frame_name() == name)
157 return node;
[email protected]9b159a52013-10-03 17:24:55158 }
dcheng57e39e22016-01-21 00:25:38159
160 return nullptr;
161}
162
163FrameTree::NodeRange FrameTree::Nodes() {
Alex Moshchuk27caae82017-09-11 23:11:18164 return NodesExceptSubtree(nullptr);
dcheng57e39e22016-01-21 00:25:38165}
166
kenrb61b6c252016-03-22 17:37:15167FrameTree::NodeRange FrameTree::SubtreeNodes(FrameTreeNode* subtree_root) {
168 return NodeRange(subtree_root, nullptr);
169}
170
Alex Moshchuk27caae82017-09-11 23:11:18171FrameTree::NodeRange FrameTree::NodesExceptSubtree(FrameTreeNode* node) {
172 return NodeRange(root_, node);
[email protected]9b159a52013-10-03 17:24:55173}
174
Balazs Engedyba034e72017-10-27 22:26:28175bool FrameTree::AddFrame(
176 FrameTreeNode* parent,
177 int process_id,
178 int new_routing_id,
179 service_manager::mojom::InterfaceProviderRequest interface_provider_request,
180 blink::WebTreeScopeType scope,
181 const std::string& frame_name,
182 const std::string& frame_unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45183 bool is_created_by_script,
Balazs Engedyba034e72017-10-27 22:26:28184 const base::UnguessableToken& devtools_frame_token,
Luna Luc3fdacdf2017-11-08 04:48:53185 const blink::FramePolicy& frame_policy,
Shubhie Panickerddf2a4e2018-03-06 00:09:06186 const FrameOwnerProperties& frame_owner_properties,
187 bool was_discarded) {
nick8814e652015-12-18 01:44:12188 CHECK_NE(new_routing_id, MSG_ROUTING_NONE);
189
dgroganfb22f9a2014-10-20 21:32:32190 // A child frame always starts with an initial empty document, which means
191 // it is in the same SiteInstance as the parent frame. Ensure that the process
192 // which requested a child frame to be added is the same as the process of the
193 // parent node.
194 if (parent->current_frame_host()->GetProcess()->GetID() != process_id)
nick8814e652015-12-18 01:44:12195 return false;
dgroganfb22f9a2014-10-20 21:32:32196
iclelland098da752017-06-28 13:46:50197 std::unique_ptr<FrameTreeNode> new_node = base::WrapUnique(new FrameTreeNode(
198 this, parent->navigator(), render_frame_delegate_,
199 render_widget_delegate_, manager_delegate_, parent, scope, frame_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45200 frame_unique_name, is_created_by_script, devtools_frame_token,
201 frame_owner_properties));
iclelland098da752017-06-28 13:46:50202
203 // Set sandbox flags and container policy and make them effective immediately,
204 // since initial sandbox flags and feature policy should apply to the initial
205 // empty document in the frame. This needs to happen before the call to
206 // AddChild so that the effective policy is sent to any newly-created
207 // RenderFrameProxy objects when the RenderFrameHost is created.
Ian Clellandcdc4f312017-10-13 22:24:12208 new_node->SetPendingFramePolicy(frame_policy);
iclelland098da752017-06-28 13:46:50209 new_node->CommitPendingFramePolicy();
210
Shubhie Panickerddf2a4e2018-03-06 00:09:06211 if (was_discarded)
212 new_node->set_was_discarded();
213
iclelland098da752017-06-28 13:46:50214 // Add the new node to the FrameTree, creating the RenderFrameHost.
215 FrameTreeNode* added_node =
216 parent->AddChild(std::move(new_node), process_id, new_routing_id);
nick8814e652015-12-18 01:44:12217
Balazs Engedyba034e72017-10-27 22:26:28218 DCHECK(interface_provider_request.is_pending());
219 added_node->current_frame_host()->BindInterfaceProviderRequest(
220 std::move(interface_provider_request));
221
nasko03ecfad2016-08-02 00:54:06222 // The last committed NavigationEntry may have a FrameNavigationEntry with the
223 // same |frame_unique_name|, since we don't remove FrameNavigationEntries if
224 // their frames are deleted. If there is a stale one, remove it to avoid
225 // conflicts on future updates.
226 NavigationEntryImpl* last_committed_entry = static_cast<NavigationEntryImpl*>(
227 parent->navigator()->GetController()->GetLastCommittedEntry());
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45228 if (last_committed_entry) {
229 last_committed_entry->RemoveEntryForFrame(
230 added_node, /* only_if_different_position = */ true);
231 }
nasko03ecfad2016-08-02 00:54:06232
nick8814e652015-12-18 01:44:12233 // Now that the new node is part of the FrameTree and has a RenderFrameHost,
234 // we can announce the creation of the initial RenderFrame which already
235 // exists in the renderer process.
236 added_node->current_frame_host()->SetRenderFrameCreated(true);
237 return true;
[email protected]9b159a52013-10-03 17:24:55238}
239
[email protected]58faf942014-02-20 21:03:58240void FrameTree::RemoveFrame(FrameTreeNode* child) {
241 FrameTreeNode* parent = child->parent();
242 if (!parent) {
243 NOTREACHED() << "Unexpected RemoveFrame call for main frame.";
244 return;
[email protected]9b159a52013-10-03 17:24:55245 }
246
[email protected]741fd682013-11-08 08:26:55247 parent->RemoveChild(child);
[email protected]9b159a52013-10-03 17:24:55248}
249
[email protected]82307f6b2014-08-07 03:30:12250void FrameTree::CreateProxiesForSiteInstance(
251 FrameTreeNode* source,
252 SiteInstance* site_instance) {
naskob3041b98a42016-03-12 04:43:06253 // Create the RenderFrameProxyHost for the new SiteInstance.
alexmos58729042015-06-18 23:20:00254 if (!source || !source->IsMainFrame()) {
255 RenderViewHostImpl* render_view_host = GetRenderViewHost(site_instance);
[email protected]82307f6b2014-08-07 03:30:12256 if (!render_view_host) {
naskob3041b98a42016-03-12 04:43:06257 root()->render_manager()->CreateRenderFrameProxy(site_instance);
lazyboybb1af562015-02-04 02:36:02258 } else {
alexmos58729042015-06-18 23:20:00259 root()->render_manager()->EnsureRenderViewInitialized(render_view_host,
260 site_instance);
[email protected]82307f6b2014-08-07 03:30:12261 }
262 }
263
naskoe6edde32014-10-17 15:36:48264 // Proxies are created in the FrameTree in response to a node navigating to a
265 // new SiteInstance. Since |source|'s navigation will replace the currently
Alex Moshchuk27caae82017-09-11 23:11:18266 // loaded document, the entire subtree under |source| will be removed, and
267 // thus proxy creation is skipped for all nodes in that subtree.
268 //
269 // However, a proxy *is* needed for the |source| node itself. This lets
270 // cross-process navigations in |source| start with a proxy and follow a
271 // remote-to-local transition, which avoids race conditions in cases where
272 // other navigations need to reference |source| before it commits. See
273 // https://crbug.com/756790 for more background. Therefore,
274 // NodesExceptSubtree(source) will include |source| in the nodes traversed
275 // (see NodeIterator::operator++).
276 for (FrameTreeNode* node : NodesExceptSubtree(source)) {
dcheng57e39e22016-01-21 00:25:38277 // If a new frame is created in the current SiteInstance, other frames in
278 // that SiteInstance don't need a proxy for the new frame.
Alex Moshchuk27caae82017-09-11 23:11:18279 RenderFrameHostImpl* current_host =
280 node->render_manager()->current_frame_host();
281 SiteInstance* current_instance = current_host->GetSiteInstance();
282 if (current_instance != site_instance) {
283 if (node == source && !current_host->IsRenderFrameLive()) {
284 // There's no need to create a proxy at |source| when the current
285 // RenderFrameHost isn't live, as in that case, the pending
286 // RenderFrameHost will be committed immediately, and the proxy
287 // destroyed right away, in GetFrameHostForNavigation. This makes the
288 // race described above not possible.
289 continue;
290 }
dcheng57e39e22016-01-21 00:25:38291 node->render_manager()->CreateRenderFrameProxy(site_instance);
Alex Moshchuk27caae82017-09-11 23:11:18292 }
dcheng57e39e22016-01-21 00:25:38293 }
[email protected]82307f6b2014-08-07 03:30:12294}
295
[email protected]9b159a52013-10-03 17:24:55296RenderFrameHostImpl* FrameTree::GetMainFrame() const {
[email protected]94d0cc12013-12-18 00:07:41297 return root_->current_frame_host();
[email protected]9b159a52013-10-03 17:24:55298}
299
[email protected]9c9343b2014-03-08 02:56:07300FrameTreeNode* FrameTree::GetFocusedFrame() {
301 return FindByID(focused_frame_tree_node_id_);
302}
303
alexmos5357efb2015-12-16 21:44:00304void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
305 if (node == GetFocusedFrame())
306 return;
307
avallee0206f782016-07-28 18:55:33308
dcheng57e39e22016-01-21 00:25:38309 std::set<SiteInstance*> frame_tree_site_instances =
310 CollectSiteInstances(this);
alexmosb1dc2162015-11-05 00:59:20311
alexmos5357efb2015-12-16 21:44:00312 SiteInstance* current_instance =
313 node->current_frame_host()->GetSiteInstance();
314
alexmosb1dc2162015-11-05 00:59:20315 // Update the focused frame in all other SiteInstances. If focus changes to
316 // a cross-process frame, this allows the old focused frame's renderer
317 // process to clear focus from that frame and fire blur events. It also
318 // ensures that the latest focused frame is available in all renderers to
319 // compute document.activeElement.
alexmos5357efb2015-12-16 21:44:00320 //
321 // We do not notify the |source| SiteInstance because it already knows the
322 // new focused frame (since it initiated the focus change), and we notify the
323 // new focused frame's SiteInstance (if it differs from |source|) separately
324 // below.
vmpstr10e0d5f2016-07-21 23:46:09325 for (auto* instance : frame_tree_site_instances) {
alexmos5357efb2015-12-16 21:44:00326 if (instance != source && instance != current_instance) {
alexmosb1dc2162015-11-05 00:59:20327 RenderFrameProxyHost* proxy =
328 node->render_manager()->GetRenderFrameProxyHost(instance);
329 proxy->SetFocusedFrame();
330 }
alexmosca2c6ba2015-10-01 21:52:25331 }
332
alexmos5357efb2015-12-16 21:44:00333 // If |node| was focused from a cross-process frame (i.e., via
334 // window.focus()), tell its RenderFrame that it should focus.
335 if (current_instance != source)
336 node->current_frame_host()->SetFocusedFrame();
337
[email protected]9c9343b2014-03-08 02:56:07338 focused_frame_tree_node_id_ = node->frame_tree_node_id();
alexmos21acae52015-11-07 01:04:43339 node->DidFocus();
dmazzonif27bf892016-03-10 15:51:55340
341 // The accessibility tree data for the root of the frame tree keeps
342 // track of the focused frame too, so update that every time the
343 // focused frame changes.
344 root()->current_frame_host()->UpdateAXTreeData();
[email protected]9c9343b2014-03-08 02:56:07345}
346
[email protected]9b159a52013-10-03 17:24:55347void FrameTree::SetFrameRemoveListener(
[email protected]ae7eeda2014-07-04 01:53:26348 const base::Callback<void(RenderFrameHost*)>& on_frame_removed) {
[email protected]9b159a52013-10-03 17:24:55349 on_frame_removed_ = on_frame_removed;
350}
351
avib7348942015-12-25 20:57:10352RenderViewHostImpl* FrameTree::CreateRenderViewHost(
353 SiteInstance* site_instance,
354 int32_t routing_id,
355 int32_t main_frame_routing_id,
356 bool swapped_out,
357 bool hidden) {
[email protected]94d0cc12013-12-18 00:07:41358 RenderViewHostMap::iterator iter =
359 render_view_host_map_.find(site_instance->GetId());
alexmos9aa61232016-04-26 21:54:02360 if (iter != render_view_host_map_.end())
361 return iter->second;
362
dcheng29f5a6c2015-08-31 21:43:27363 RenderViewHostImpl* rvh =
364 static_cast<RenderViewHostImpl*>(RenderViewHostFactory::Create(
365 site_instance, render_view_delegate_, render_widget_delegate_,
366 routing_id, main_frame_routing_id, swapped_out, hidden));
[email protected]94d0cc12013-12-18 00:07:41367
[email protected]21b41c7e892014-02-28 01:52:24368 render_view_host_map_[site_instance->GetId()] = rvh;
[email protected]94d0cc12013-12-18 00:07:41369 return rvh;
370}
371
[email protected]82307f6b2014-08-07 03:30:12372RenderViewHostImpl* FrameTree::GetRenderViewHost(SiteInstance* site_instance) {
[email protected]94d0cc12013-12-18 00:07:41373 RenderViewHostMap::iterator iter =
374 render_view_host_map_.find(site_instance->GetId());
alexmos9aa61232016-04-26 21:54:02375 if (iter != render_view_host_map_.end())
creise73d58ef2016-03-29 22:12:15376 return iter->second;
alexmos9aa61232016-04-26 21:54:02377
creise73d58ef2016-03-29 22:12:15378 return nullptr;
[email protected]94d0cc12013-12-18 00:07:41379}
380
naskof95ab0e2015-05-23 02:27:24381void FrameTree::AddRenderViewHostRef(RenderViewHostImpl* render_view_host) {
382 SiteInstance* site_instance = render_view_host->GetSiteInstance();
[email protected]94d0cc12013-12-18 00:07:41383 RenderViewHostMap::iterator iter =
384 render_view_host_map_.find(site_instance->GetId());
385 CHECK(iter != render_view_host_map_.end());
naskof95ab0e2015-05-23 02:27:24386 CHECK(iter->second == render_view_host);
[email protected]94d0cc12013-12-18 00:07:41387
[email protected]21b41c7e892014-02-28 01:52:24388 iter->second->increment_ref_count();
[email protected]94d0cc12013-12-18 00:07:41389}
390
naskof95ab0e2015-05-23 02:27:24391void FrameTree::ReleaseRenderViewHostRef(RenderViewHostImpl* render_view_host) {
392 SiteInstance* site_instance = render_view_host->GetSiteInstance();
avib7348942015-12-25 20:57:10393 int32_t site_instance_id = site_instance->GetId();
[email protected]94d0cc12013-12-18 00:07:41394 RenderViewHostMap::iterator iter =
[email protected]21b41c7e892014-02-28 01:52:24395 render_view_host_map_.find(site_instance_id);
alexmos9aa61232016-04-26 21:54:02396
397 CHECK(iter != render_view_host_map_.end());
398 CHECK_EQ(iter->second, render_view_host);
399
400 // Decrement the refcount and shutdown the RenderViewHost if no one else is
401 // using it.
402 CHECK_GT(iter->second->ref_count(), 0);
403 iter->second->decrement_ref_count();
404 if (iter->second->ref_count() == 0) {
405 iter->second->ShutdownAndDestroy();
406 render_view_host_map_.erase(iter);
[email protected]94d0cc12013-12-18 00:07:41407 }
408}
409
dmazzonie950ea232015-03-13 21:39:45410void FrameTree::FrameRemoved(FrameTreeNode* frame) {
nick53d5cbf2015-04-23 22:50:14411 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
thestige62f7382016-11-08 18:31:39412 focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
nick53d5cbf2015-04-23 22:50:14413
dmazzonie950ea232015-03-13 21:39:45414 // No notification for the root frame.
clamy9dbf17e22015-03-31 13:37:08415 if (!frame->parent()) {
nick70b782d2015-10-06 17:37:04416 CHECK_EQ(frame, root_);
dmazzonie950ea232015-03-13 21:39:45417 return;
clamy9dbf17e22015-03-31 13:37:08418 }
dmazzonie950ea232015-03-13 21:39:45419
420 // Notify observers of the frame removal.
421 if (!on_frame_removed_.is_null())
422 on_frame_removed_.Run(frame->current_frame_host());
423}
424
Nate Chapin93536702018-02-07 00:12:21425void FrameTree::UpdateLoadProgress(double progress) {
fdegansa696e5112015-04-17 01:57:59426 if (progress <= load_progress_)
427 return;
428 load_progress_ = progress;
429
430 // Notify the WebContents.
431 root_->navigator()->GetDelegate()->DidChangeLoadProgress();
fdegans1d16355162015-03-26 11:58:34432}
433
434void FrameTree::ResetLoadProgress() {
fdegansa696e5112015-04-17 01:57:59435 load_progress_ = 0.0;
fdegans1d16355162015-03-26 11:58:34436}
437
clamy44e84ce2016-02-22 15:38:25438bool FrameTree::IsLoading() const {
nick931d4452016-03-30 00:59:06439 for (const FrameTreeNode* node : const_cast<FrameTree*>(this)->Nodes()) {
dcheng57e39e22016-01-21 00:25:38440 if (node->IsLoading())
441 return true;
442 }
443 return false;
fdegans1d16355162015-03-26 11:58:34444}
445
alexmos3fcd0ca2015-10-23 18:18:33446void FrameTree::ReplicatePageFocus(bool is_focused) {
dcheng57e39e22016-01-21 00:25:38447 std::set<SiteInstance*> frame_tree_site_instances =
448 CollectSiteInstances(this);
alexmos3fcd0ca2015-10-23 18:18:33449
450 // Send the focus update to main frame's proxies in all SiteInstances of
451 // other frames in this FrameTree. Note that the main frame might also know
452 // about proxies in SiteInstances for frames in a different FrameTree (e.g.,
453 // for window.open), so we can't just iterate over its proxy_hosts_ in
454 // RenderFrameHostManager.
vmpstr10e0d5f2016-07-21 23:46:09455 for (auto* instance : frame_tree_site_instances)
alexmos0d7e0b09b2015-10-29 22:11:48456 SetPageFocus(instance, is_focused);
457}
alexmos3fcd0ca2015-10-23 18:18:33458
alexmos0d7e0b09b2015-10-29 22:11:48459void FrameTree::SetPageFocus(SiteInstance* instance, bool is_focused) {
460 RenderFrameHostManager* root_manager = root_->render_manager();
461
462 // This is only used to set page-level focus in cross-process subframes, and
463 // requests to set focus in main frame's SiteInstance are ignored.
464 if (instance != root_manager->current_frame_host()->GetSiteInstance()) {
alexmos3fcd0ca2015-10-23 18:18:33465 RenderFrameProxyHost* proxy =
alexmos0d7e0b09b2015-10-29 22:11:48466 root_manager->GetRenderFrameProxyHost(instance);
alexmos3fcd0ca2015-10-23 18:18:33467 proxy->Send(new InputMsg_SetFocus(proxy->GetRoutingID(), is_focused));
468 }
469}
470
[email protected]9b159a52013-10-03 17:24:55471} // namespace content