blob: 13bffe27440cce642063b0e1e794e3f7d0fe9f21 [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
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_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/lazy_instance.h"
dcheng9bfa5162016-04-09 01:00:5716#include "base/memory/ptr_util.h"
Lowell Manners75055a132019-10-11 10:30:2917#include "base/stl_util.h"
Carlos Caballeroede6f8c2021-01-28 11:01:5018#include "base/trace_event/optional_trace_event.h"
Pavel Feldman25234722017-10-11 02:49:0619#include "base/unguessable_token.h"
danakjc492bf82020-09-09 20:02:4420#include "content/browser/renderer_host/frame_tree_node.h"
21#include "content/browser/renderer_host/navigation_controller_impl.h"
22#include "content/browser/renderer_host/navigation_entry_impl.h"
23#include "content/browser/renderer_host/navigation_request.h"
24#include "content/browser/renderer_host/navigator.h"
25#include "content/browser/renderer_host/navigator_delegate.h"
26#include "content/browser/renderer_host/render_frame_host_factory.h"
27#include "content/browser/renderer_host/render_frame_host_impl.h"
28#include "content/browser/renderer_host/render_frame_proxy_host.h"
[email protected]94d0cc12013-12-18 00:07:4129#include "content/browser/renderer_host/render_view_host_factory.h"
30#include "content/browser/renderer_host/render_view_host_impl.h"
japhet98e9bd82016-06-28 23:48:4531#include "content/common/content_switches_internal.h"
alexmos3fcd0ca2015-10-23 18:18:3332#include "content/common/input_messages.h"
Sreeja Kamishetty46f762c2021-02-05 07:52:4633#include "third_party/blink/public/common/features.h"
Blink Reformata30d4232018-04-07 15:31:0634#include "third_party/blink/public/common/frame/frame_policy.h"
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:5435#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
[email protected]9b159a52013-10-03 17:24:5536
37namespace content {
38
39namespace {
[email protected]20edca72014-08-14 10:27:5340
dcheng57e39e22016-01-21 00:25:3841// Helper function to collect SiteInstances involved in rendering a single
42// FrameTree (which is a subset of SiteInstances in main frame's proxy_hosts_
43// because of openers).
44std::set<SiteInstance*> CollectSiteInstances(FrameTree* tree) {
45 std::set<SiteInstance*> instances;
46 for (FrameTreeNode* node : tree->Nodes())
47 instances.insert(node->current_frame_host()->GetSiteInstance());
48 return instances;
alexmos3fcd0ca2015-10-23 18:18:3349}
50
[email protected]9b159a52013-10-03 17:24:5551} // namespace
52
vmpstr33895d992016-02-24 20:55:2153FrameTree::NodeIterator::NodeIterator(const NodeIterator& other) = default;
54
Fergal Daly55b6d722020-09-11 07:56:3355FrameTree::NodeIterator::~NodeIterator() = default;
dcheng57e39e22016-01-21 00:25:3856
57FrameTree::NodeIterator& FrameTree::NodeIterator::operator++() {
Alex Moshchuk27caae82017-09-11 23:11:1858 if (current_node_ != root_of_subtree_to_skip_) {
59 for (size_t i = 0; i < current_node_->child_count(); ++i) {
60 FrameTreeNode* child = current_node_->child_at(i);
61 queue_.push(child);
62 }
dcheng57e39e22016-01-21 00:25:3863 }
64
65 if (!queue_.empty()) {
66 current_node_ = queue_.front();
67 queue_.pop();
68 } else {
69 current_node_ = nullptr;
70 }
71
72 return *this;
73}
74
75bool FrameTree::NodeIterator::operator==(const NodeIterator& rhs) const {
76 return current_node_ == rhs.current_node_;
77}
78
79FrameTree::NodeIterator::NodeIterator(FrameTreeNode* starting_node,
Alex Moshchuk27caae82017-09-11 23:11:1880 FrameTreeNode* root_of_subtree_to_skip)
81 : current_node_(starting_node),
82 root_of_subtree_to_skip_(root_of_subtree_to_skip) {}
dcheng57e39e22016-01-21 00:25:3883
84FrameTree::NodeIterator FrameTree::NodeRange::begin() {
W. James MacLeance3176d2019-10-18 04:01:4585 // We shouldn't be attempting a frame tree traversal while the tree is
86 // being constructed.
87 DCHECK(root_->current_frame_host());
Alex Moshchuk27caae82017-09-11 23:11:1888 return NodeIterator(root_, root_of_subtree_to_skip_);
dcheng57e39e22016-01-21 00:25:3889}
90
91FrameTree::NodeIterator FrameTree::NodeRange::end() {
92 return NodeIterator(nullptr, nullptr);
93}
94
kenrb61b6c252016-03-22 17:37:1595FrameTree::NodeRange::NodeRange(FrameTreeNode* root,
Alex Moshchuk27caae82017-09-11 23:11:1896 FrameTreeNode* root_of_subtree_to_skip)
97 : root_(root), root_of_subtree_to_skip_(root_of_subtree_to_skip) {}
dcheng57e39e22016-01-21 00:25:3898
Carlos Caballero40b0efd2021-01-26 11:55:0099FrameTree::FrameTree(
100 BrowserContext* browser_context,
Carlos Caballero03262522021-02-05 14:49:58101 Delegate* delegate,
Carlos Caballero40b0efd2021-01-26 11:55:00102 NavigationControllerDelegate* navigation_controller_delegate,
103 NavigatorDelegate* navigator_delegate,
104 RenderFrameHostDelegate* render_frame_delegate,
105 RenderViewHostDelegate* render_view_delegate,
106 RenderWidgetHostDelegate* render_widget_delegate,
107 RenderFrameHostManager::Delegate* manager_delegate)
Carlos Caballero03262522021-02-05 14:49:58108 : delegate_(delegate),
109 render_frame_delegate_(render_frame_delegate),
[email protected]92404c62013-12-04 16:40:46110 render_view_delegate_(render_view_delegate),
[email protected]fa944cb82013-11-15 17:51:21111 render_widget_delegate_(render_widget_delegate),
112 manager_delegate_(manager_delegate),
Carlos Caballero40b0efd2021-01-26 11:55:00113 navigator_(browser_context,
114 *this,
115 navigator_delegate,
116 navigation_controller_delegate),
[email protected]94d0cc12013-12-18 00:07:41117 root_(new FrameTreeNode(this,
xiaochengh98488162016-05-19 15:17:59118 nullptr,
dcheng860817a2015-05-22 03:16:56119 // The top-level frame must always be in a
120 // document scope.
Antonio Gomes9d5c1ef2020-04-30 20:56:41121 blink::mojom::TreeScopeType::kDocument,
alexmos6e0ee0c2015-05-01 18:57:34122 std::string(),
lukasza464d8692016-02-22 19:26:32123 std::string(),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45124 false,
Pavel Feldman25234722017-10-11 02:49:06125 base::UnguessableToken::Create(),
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54126 blink::mojom::FrameOwnerProperties(),
Antonio Gomes58d38062020-04-30 01:50:14127 blink::mojom::FrameOwnerElementType::kNone)),
thestige62f7382016-11-08 18:31:39128 focused_frame_tree_node_id_(FrameTreeNode::kFrameTreeNodeInvalidId),
lazyboy70605c32015-11-03 01:27:31129 load_progress_(0.0) {}
[email protected]9b159a52013-10-03 17:24:55130
131FrameTree::~FrameTree() {
nick70b782d2015-10-06 17:37:04132 delete root_;
133 root_ = nullptr;
[email protected]9b159a52013-10-03 17:24:55134}
135
vishal.b782eb5d2015-04-29 12:22:57136FrameTreeNode* FrameTree::FindByID(int frame_tree_node_id) {
dcheng57e39e22016-01-21 00:25:38137 for (FrameTreeNode* node : Nodes()) {
138 if (node->frame_tree_node_id() == frame_tree_node_id)
139 return node;
140 }
141 return nullptr;
[email protected]9b159a52013-10-03 17:24:55142}
143
nasko479ea5a2015-02-14 00:03:04144FrameTreeNode* FrameTree::FindByRoutingID(int process_id, int routing_id) {
dmazzoni0b5d2482014-09-10 19:45:57145 RenderFrameHostImpl* render_frame_host =
146 RenderFrameHostImpl::FromID(process_id, routing_id);
147 if (render_frame_host) {
148 FrameTreeNode* result = render_frame_host->frame_tree_node();
149 if (this == result->frame_tree())
150 return result;
151 }
152
153 RenderFrameProxyHost* render_frame_proxy_host =
154 RenderFrameProxyHost::FromID(process_id, routing_id);
155 if (render_frame_proxy_host) {
156 FrameTreeNode* result = render_frame_proxy_host->frame_tree_node();
157 if (this == result->frame_tree())
158 return result;
159 }
160
creis6a93a812015-04-24 23:13:17161 return nullptr;
162}
163
164FrameTreeNode* FrameTree::FindByName(const std::string& name) {
165 if (name.empty())
nick70b782d2015-10-06 17:37:04166 return root_;
creis6a93a812015-04-24 23:13:17167
dcheng57e39e22016-01-21 00:25:38168 for (FrameTreeNode* node : Nodes()) {
169 if (node->frame_name() == name)
170 return node;
[email protected]9b159a52013-10-03 17:24:55171 }
dcheng57e39e22016-01-21 00:25:38172
173 return nullptr;
174}
175
176FrameTree::NodeRange FrameTree::Nodes() {
Alex Moshchuk27caae82017-09-11 23:11:18177 return NodesExceptSubtree(nullptr);
dcheng57e39e22016-01-21 00:25:38178}
179
kenrb61b6c252016-03-22 17:37:15180FrameTree::NodeRange FrameTree::SubtreeNodes(FrameTreeNode* subtree_root) {
181 return NodeRange(subtree_root, nullptr);
182}
183
Alex Moshchuk27caae82017-09-11 23:11:18184FrameTree::NodeRange FrameTree::NodesExceptSubtree(FrameTreeNode* node) {
185 return NodeRange(root_, node);
[email protected]9b159a52013-10-03 17:24:55186}
187
Lucas Furukawa Gadani99125822019-01-03 15:41:49188FrameTreeNode* FrameTree::AddFrame(
Alexander Timin381e7e182020-04-28 19:04:03189 RenderFrameHostImpl* parent,
Balazs Engedyba034e72017-10-27 22:26:28190 int process_id,
191 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18192 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
Oksana Zhuravlovafee097c2019-07-26 17:01:30193 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
194 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30195 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
Antonio Gomes9d5c1ef2020-04-30 20:56:41196 blink::mojom::TreeScopeType scope,
Balazs Engedyba034e72017-10-27 22:26:28197 const std::string& frame_name,
198 const std::string& frame_unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45199 bool is_created_by_script,
Dave Tapuska84449382020-05-01 00:39:04200 const base::UnguessableToken& frame_token,
Balazs Engedyba034e72017-10-27 22:26:28201 const base::UnguessableToken& devtools_frame_token,
Luna Luc3fdacdf2017-11-08 04:48:53202 const blink::FramePolicy& frame_policy,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54203 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Ehsan Karamad192a8da2018-10-21 03:48:08204 bool was_discarded,
Antonio Gomes58d38062020-04-30 01:50:14205 blink::mojom::FrameOwnerElementType owner_type) {
nick8814e652015-12-18 01:44:12206 CHECK_NE(new_routing_id, MSG_ROUTING_NONE);
danakj0bdfacd2021-01-20 19:27:18207 // Normally this path is for blink adding a child local frame. But portals are
208 // making a remote frame, as the local frame is only created in a nested
209 // FrameTree.
210 DCHECK_NE(frame_remote.is_valid(),
211 owner_type == blink::mojom::FrameOwnerElementType::kPortal);
nick8814e652015-12-18 01:44:12212
dgroganfb22f9a2014-10-20 21:32:32213 // A child frame always starts with an initial empty document, which means
214 // it is in the same SiteInstance as the parent frame. Ensure that the process
215 // which requested a child frame to be added is the same as the process of the
216 // parent node.
Alexander Timin381e7e182020-04-28 19:04:03217 if (parent->GetProcess()->GetID() != process_id)
Lucas Furukawa Gadani99125822019-01-03 15:41:49218 return nullptr;
dgroganfb22f9a2014-10-20 21:32:32219
iclelland098da752017-06-28 13:46:50220 std::unique_ptr<FrameTreeNode> new_node = base::WrapUnique(new FrameTreeNode(
Fergal Daly09d6c762020-05-29 02:05:18221 this, parent, scope, frame_name, frame_unique_name, is_created_by_script,
222 devtools_frame_token, frame_owner_properties, owner_type));
iclelland098da752017-06-28 13:46:50223
224 // Set sandbox flags and container policy and make them effective immediately,
225 // since initial sandbox flags and feature policy should apply to the initial
226 // empty document in the frame. This needs to happen before the call to
227 // AddChild so that the effective policy is sent to any newly-created
228 // RenderFrameProxy objects when the RenderFrameHost is created.
Charlie Hu5ffc0152019-12-06 15:59:53229 // SetPendingFramePolicy is necessary here because next navigation on this
230 // frame will need the value of pending frame policy instead of effective
231 // frame policy.
Ian Clellandcdc4f312017-10-13 22:24:12232 new_node->SetPendingFramePolicy(frame_policy);
Charlie Hu5ffc0152019-12-06 15:59:53233 new_node->CommitFramePolicy(frame_policy);
iclelland098da752017-06-28 13:46:50234
Shubhie Panickerddf2a4e2018-03-06 00:09:06235 if (was_discarded)
236 new_node->set_was_discarded();
237
iclelland098da752017-06-28 13:46:50238 // Add the new node to the FrameTree, creating the RenderFrameHost.
danakj0bdfacd2021-01-20 19:27:18239 FrameTreeNode* added_node =
240 parent->AddChild(std::move(new_node), process_id, new_routing_id,
241 std::move(frame_remote), frame_token);
nick8814e652015-12-18 01:44:12242
Oksana Zhuravlovafee097c2019-07-26 17:01:30243 DCHECK(browser_interface_broker_receiver.is_valid());
244 added_node->current_frame_host()->BindBrowserInterfaceBrokerReceiver(
245 std::move(browser_interface_broker_receiver));
246
Antonio Sartoridb967c52021-01-20 09:54:30247 if (policy_container_bind_params) {
Antonio Sartoria1fd1432020-11-25 09:10:20248 added_node->current_frame_host()->policy_container_host()->Bind(
Antonio Sartoridb967c52021-01-20 09:54:30249 std::move(policy_container_bind_params));
Antonio Sartoria1fd1432020-11-25 09:10:20250 }
251
nasko03ecfad2016-08-02 00:54:06252 // The last committed NavigationEntry may have a FrameNavigationEntry with the
253 // same |frame_unique_name|, since we don't remove FrameNavigationEntries if
254 // their frames are deleted. If there is a stale one, remove it to avoid
255 // conflicts on future updates.
Fergal Daly09d6c762020-05-29 02:05:18256 NavigationEntryImpl* last_committed_entry = static_cast<NavigationEntryImpl*>(
Carlos Caballero40b0efd2021-01-26 11:55:00257 navigator_.controller().GetLastCommittedEntry());
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45258 if (last_committed_entry) {
259 last_committed_entry->RemoveEntryForFrame(
260 added_node, /* only_if_different_position = */ true);
261 }
nasko03ecfad2016-08-02 00:54:06262
nick8814e652015-12-18 01:44:12263 // Now that the new node is part of the FrameTree and has a RenderFrameHost,
264 // we can announce the creation of the initial RenderFrame which already
265 // exists in the renderer process.
Sreeja Kamishetty5b699622021-01-22 12:54:08266 // For consistency with navigating to a new RenderFrameHost case, we dispatch
267 // RenderFrameCreated before RenderFrameHostChanged.
Ehsan Karamad44fc72112019-02-26 18:15:47268 if (added_node->frame_owner_element_type() !=
Antonio Gomes58d38062020-04-30 01:50:14269 blink::mojom::FrameOwnerElementType::kPortal) {
Ehsan Karamad44fc72112019-02-26 18:15:47270 // Portals do not have a live RenderFrame in the renderer process.
Fergal Dalyf9ea35c2020-12-11 15:26:01271 added_node->current_frame_host()->RenderFrameCreated();
Ehsan Karamad44fc72112019-02-26 18:15:47272 }
Sreeja Kamishetty5b699622021-01-22 12:54:08273
274 // Notify the delegate of the creation of the current RenderFrameHost.
275 // This is only for subframes, as the main frame case is taken care of by
276 // WebContentsImpl::Init.
277 manager_delegate_->NotifySwappedFromRenderManager(
278 nullptr, added_node->current_frame_host(), false /* is_main_frame */);
Lucas Furukawa Gadani99125822019-01-03 15:41:49279 return added_node;
[email protected]9b159a52013-10-03 17:24:55280}
281
[email protected]58faf942014-02-20 21:03:58282void FrameTree::RemoveFrame(FrameTreeNode* child) {
Alexander Timin381e7e182020-04-28 19:04:03283 RenderFrameHostImpl* parent = child->parent();
[email protected]58faf942014-02-20 21:03:58284 if (!parent) {
285 NOTREACHED() << "Unexpected RemoveFrame call for main frame.";
286 return;
[email protected]9b159a52013-10-03 17:24:55287 }
288
Alexander Timin381e7e182020-04-28 19:04:03289 parent->RemoveChild(child);
[email protected]9b159a52013-10-03 17:24:55290}
291
Aran Gilman37d11632019-10-08 23:07:15292void FrameTree::CreateProxiesForSiteInstance(FrameTreeNode* source,
293 SiteInstance* site_instance) {
naskob3041b98a42016-03-12 04:43:06294 // Create the RenderFrameProxyHost for the new SiteInstance.
alexmos58729042015-06-18 23:20:00295 if (!source || !source->IsMainFrame()) {
arthursonzognic5be3842019-07-09 11:49:14296 RenderViewHostImpl* render_view_host =
297 GetRenderViewHost(site_instance).get();
298 if (render_view_host) {
alexmos58729042015-06-18 23:20:00299 root()->render_manager()->EnsureRenderViewInitialized(render_view_host,
300 site_instance);
arthursonzognic5be3842019-07-09 11:49:14301 } else {
302 root()->render_manager()->CreateRenderFrameProxy(site_instance);
[email protected]82307f6b2014-08-07 03:30:12303 }
304 }
305
Alex Moshchuk1226b152019-11-08 18:23:45306 // Check whether we're in an inner delegate and |site_instance| corresponds
307 // to the outer delegate. Subframe proxies aren't needed if this is the
308 // case.
309 bool is_site_instance_for_outer_delegate = false;
310 RenderFrameProxyHost* outer_delegate_proxy =
311 root()->render_manager()->GetProxyToOuterDelegate();
312 if (outer_delegate_proxy) {
313 is_site_instance_for_outer_delegate =
314 (site_instance == outer_delegate_proxy->GetSiteInstance());
315 }
316
naskoe6edde32014-10-17 15:36:48317 // Proxies are created in the FrameTree in response to a node navigating to a
318 // new SiteInstance. Since |source|'s navigation will replace the currently
Alex Moshchuk27caae82017-09-11 23:11:18319 // loaded document, the entire subtree under |source| will be removed, and
320 // thus proxy creation is skipped for all nodes in that subtree.
321 //
322 // However, a proxy *is* needed for the |source| node itself. This lets
323 // cross-process navigations in |source| start with a proxy and follow a
324 // remote-to-local transition, which avoids race conditions in cases where
325 // other navigations need to reference |source| before it commits. See
326 // https://crbug.com/756790 for more background. Therefore,
327 // NodesExceptSubtree(source) will include |source| in the nodes traversed
328 // (see NodeIterator::operator++).
329 for (FrameTreeNode* node : NodesExceptSubtree(source)) {
dcheng57e39e22016-01-21 00:25:38330 // If a new frame is created in the current SiteInstance, other frames in
331 // that SiteInstance don't need a proxy for the new frame.
Alex Moshchuk27caae82017-09-11 23:11:18332 RenderFrameHostImpl* current_host =
333 node->render_manager()->current_frame_host();
334 SiteInstance* current_instance = current_host->GetSiteInstance();
335 if (current_instance != site_instance) {
336 if (node == source && !current_host->IsRenderFrameLive()) {
Fergal Daly6de62f52020-10-14 01:56:44337 // We don't create a proxy at |source| when the current RenderFrameHost
338 // isn't live. This is because either (1) the speculative
Alex Moshchuk27caae82017-09-11 23:11:18339 // RenderFrameHost will be committed immediately, and the proxy
Fergal Daly6de62f52020-10-14 01:56:44340 // destroyed right away, in GetFrameHostForNavigation, which makes the
341 // races above impossible, or (2) the early commit will be skipped due
342 // to ShouldSkipEarlyCommitPendingForCrashedFrame, in which case the
343 // proxy for |source| *is* needed, but it will be created later in
344 // CreateProxiesForNewRenderFrameHost.
345 //
346 // TODO(fergal): Consider creating a proxy for |source| here rather than
347 // in CreateProxiesForNewRenderFrameHost for case (2) above.
Alex Moshchuk27caae82017-09-11 23:11:18348 continue;
349 }
Alex Moshchuk1226b152019-11-08 18:23:45350
351 // Do not create proxies for subframes in the outer delegate's
352 // SiteInstance, since there is no need to expose these subframes to the
353 // outer delegate. See also comments in CreateProxiesForChildFrame() and
354 // https://crbug.com/1013553.
355 if (!node->IsMainFrame() && is_site_instance_for_outer_delegate)
356 continue;
357
dcheng57e39e22016-01-21 00:25:38358 node->render_manager()->CreateRenderFrameProxy(site_instance);
Alex Moshchuk27caae82017-09-11 23:11:18359 }
dcheng57e39e22016-01-21 00:25:38360 }
[email protected]82307f6b2014-08-07 03:30:12361}
362
[email protected]9b159a52013-10-03 17:24:55363RenderFrameHostImpl* FrameTree::GetMainFrame() const {
[email protected]94d0cc12013-12-18 00:07:41364 return root_->current_frame_host();
[email protected]9b159a52013-10-03 17:24:55365}
366
[email protected]9c9343b2014-03-08 02:56:07367FrameTreeNode* FrameTree::GetFocusedFrame() {
368 return FindByID(focused_frame_tree_node_id_);
369}
370
alexmos5357efb2015-12-16 21:44:00371void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
372 if (node == GetFocusedFrame())
373 return;
374
dcheng57e39e22016-01-21 00:25:38375 std::set<SiteInstance*> frame_tree_site_instances =
376 CollectSiteInstances(this);
alexmosb1dc2162015-11-05 00:59:20377
alexmos5357efb2015-12-16 21:44:00378 SiteInstance* current_instance =
379 node->current_frame_host()->GetSiteInstance();
380
alexmosb1dc2162015-11-05 00:59:20381 // Update the focused frame in all other SiteInstances. If focus changes to
382 // a cross-process frame, this allows the old focused frame's renderer
383 // process to clear focus from that frame and fire blur events. It also
384 // ensures that the latest focused frame is available in all renderers to
385 // compute document.activeElement.
alexmos5357efb2015-12-16 21:44:00386 //
387 // We do not notify the |source| SiteInstance because it already knows the
388 // new focused frame (since it initiated the focus change), and we notify the
389 // new focused frame's SiteInstance (if it differs from |source|) separately
390 // below.
vmpstr10e0d5f2016-07-21 23:46:09391 for (auto* instance : frame_tree_site_instances) {
alexmos5357efb2015-12-16 21:44:00392 if (instance != source && instance != current_instance) {
alexmosb1dc2162015-11-05 00:59:20393 RenderFrameProxyHost* proxy =
394 node->render_manager()->GetRenderFrameProxyHost(instance);
395 proxy->SetFocusedFrame();
396 }
alexmosca2c6ba2015-10-01 21:52:25397 }
398
alexmos5357efb2015-12-16 21:44:00399 // If |node| was focused from a cross-process frame (i.e., via
400 // window.focus()), tell its RenderFrame that it should focus.
401 if (current_instance != source)
402 node->current_frame_host()->SetFocusedFrame();
403
[email protected]9c9343b2014-03-08 02:56:07404 focused_frame_tree_node_id_ = node->frame_tree_node_id();
alexmos21acae52015-11-07 01:04:43405 node->DidFocus();
dmazzonif27bf892016-03-10 15:51:55406
407 // The accessibility tree data for the root of the frame tree keeps
408 // track of the focused frame too, so update that every time the
409 // focused frame changes.
Daniel Libby50d1c1e2020-10-21 20:30:04410 root()->current_frame_host()->GetOutermostMainFrame()->UpdateAXTreeData();
[email protected]9c9343b2014-03-08 02:56:07411}
412
arthursonzognic5be3842019-07-09 11:49:14413scoped_refptr<RenderViewHostImpl> FrameTree::CreateRenderViewHost(
avib7348942015-12-25 20:57:10414 SiteInstance* site_instance,
avib7348942015-12-25 20:57:10415 int32_t main_frame_routing_id,
danakj08eb51d2020-12-30 20:15:23416 bool swapped_out,
417 bool renderer_initiated_creation) {
dcheng29f5a6c2015-08-31 21:43:27418 RenderViewHostImpl* rvh =
419 static_cast<RenderViewHostImpl*>(RenderViewHostFactory::Create(
Carlos Caballero00d9c862021-01-22 12:37:34420 this, site_instance, render_view_delegate_, render_widget_delegate_,
danakj08eb51d2020-12-30 20:15:23421 main_frame_routing_id, swapped_out, renderer_initiated_creation));
arthursonzognic5be3842019-07-09 11:49:14422 return base::WrapRefCounted(rvh);
[email protected]94d0cc12013-12-18 00:07:41423}
424
arthursonzognic5be3842019-07-09 11:49:14425scoped_refptr<RenderViewHostImpl> FrameTree::GetRenderViewHost(
426 SiteInstance* site_instance) {
arthursonzogni88e54ae2019-04-15 12:57:36427 auto it = render_view_host_map_.find(site_instance->GetId());
428 if (it == render_view_host_map_.end())
429 return nullptr;
alexmos9aa61232016-04-26 21:54:02430
arthursonzognic5be3842019-07-09 11:49:14431 return base::WrapRefCounted(it->second);
[email protected]94d0cc12013-12-18 00:07:41432}
433
Aaron Colwellc4bd7d62021-01-29 04:23:13434void FrameTree::RegisterRenderViewHost(SiteInstance* site_instance,
435 RenderViewHostImpl* rvh) {
436 CHECK(!base::Contains(render_view_host_map_, site_instance->GetId()));
437 render_view_host_map_[site_instance->GetId()] = rvh;
Lowell Manners75055a132019-10-11 10:30:29438}
439
Aaron Colwellc4bd7d62021-01-29 04:23:13440void FrameTree::UnregisterRenderViewHost(SiteInstance* site_instance,
441 RenderViewHostImpl* rvh) {
442 auto it = render_view_host_map_.find(site_instance->GetId());
arthursonzogni88e54ae2019-04-15 12:57:36443 CHECK(it != render_view_host_map_.end());
arthursonzognic5be3842019-07-09 11:49:14444 CHECK_EQ(it->second, rvh);
445 render_view_host_map_.erase(it);
[email protected]94d0cc12013-12-18 00:07:41446}
447
arthursonzogni0a2007792019-05-28 21:32:48448void FrameTree::FrameUnloading(FrameTreeNode* frame) {
449 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
450 focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
451
452 // Ensure frames that are about to be deleted aren't visible from the other
453 // processes anymore.
454 frame->render_manager()->ResetProxyHosts();
455}
456
dmazzonie950ea232015-03-13 21:39:45457void FrameTree::FrameRemoved(FrameTreeNode* frame) {
nick53d5cbf2015-04-23 22:50:14458 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
thestige62f7382016-11-08 18:31:39459 focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
dmazzonie950ea232015-03-13 21:39:45460}
461
fdegans1d16355162015-03-26 11:58:34462void FrameTree::ResetLoadProgress() {
fdegansa696e5112015-04-17 01:57:59463 load_progress_ = 0.0;
fdegans1d16355162015-03-26 11:58:34464}
465
clamy44e84ce2016-02-22 15:38:25466bool FrameTree::IsLoading() const {
nick931d4452016-03-30 00:59:06467 for (const FrameTreeNode* node : const_cast<FrameTree*>(this)->Nodes()) {
dcheng57e39e22016-01-21 00:25:38468 if (node->IsLoading())
469 return true;
470 }
471 return false;
fdegans1d16355162015-03-26 11:58:34472}
473
alexmos3fcd0ca2015-10-23 18:18:33474void FrameTree::ReplicatePageFocus(bool is_focused) {
dcheng57e39e22016-01-21 00:25:38475 std::set<SiteInstance*> frame_tree_site_instances =
476 CollectSiteInstances(this);
alexmos3fcd0ca2015-10-23 18:18:33477
478 // Send the focus update to main frame's proxies in all SiteInstances of
479 // other frames in this FrameTree. Note that the main frame might also know
480 // about proxies in SiteInstances for frames in a different FrameTree (e.g.,
481 // for window.open), so we can't just iterate over its proxy_hosts_ in
482 // RenderFrameHostManager.
vmpstr10e0d5f2016-07-21 23:46:09483 for (auto* instance : frame_tree_site_instances)
alexmos0d7e0b09b2015-10-29 22:11:48484 SetPageFocus(instance, is_focused);
485}
alexmos3fcd0ca2015-10-23 18:18:33486
alexmos0d7e0b09b2015-10-29 22:11:48487void FrameTree::SetPageFocus(SiteInstance* instance, bool is_focused) {
488 RenderFrameHostManager* root_manager = root_->render_manager();
489
Adithya Srinivasan47731222021-01-22 15:02:42490 // Portal frame tree should not get page focus.
491 DCHECK(!GetMainFrame()->InsidePortal() || !is_focused);
492
alexmos0d7e0b09b2015-10-29 22:11:48493 // This is only used to set page-level focus in cross-process subframes, and
494 // requests to set focus in main frame's SiteInstance are ignored.
495 if (instance != root_manager->current_frame_host()->GetSiteInstance()) {
alexmos3fcd0ca2015-10-23 18:18:33496 RenderFrameProxyHost* proxy =
alexmos0d7e0b09b2015-10-29 22:11:48497 root_manager->GetRenderFrameProxyHost(instance);
Julie Jeongeun Kim2002cb32020-01-17 11:37:29498 proxy->GetAssociatedRemoteFrame()->SetPageFocus(is_focused);
alexmos3fcd0ca2015-10-23 18:18:33499 }
500}
501
W. James MacLeanb70fab82020-05-01 18:51:14502void FrameTree::RegisterExistingOriginToPreventOptInIsolation(
503 const url::Origin& previously_visited_origin,
504 NavigationRequest* navigation_request_to_exclude) {
505 std::unordered_set<SiteInstance*> matching_site_instances;
506
507 // Be sure to visit all RenderFrameHosts associated with this frame that might
508 // have an origin that could script other frames. We skip RenderFrameHosts
509 // that are in the bfcache, assuming there's no way for a frame to join the
510 // BrowsingInstance of a bfcache RFH while it's in the cache.
511 for (auto* frame_tree_node : SubtreeNodes(root())) {
512 auto* frame_host = frame_tree_node->current_frame_host();
513
514 if (previously_visited_origin == frame_host->GetLastCommittedOrigin())
515 matching_site_instances.insert(frame_host->GetSiteInstance());
516
517 if (frame_host->HasCommittingNavigationRequestForOrigin(
518 previously_visited_origin, navigation_request_to_exclude)) {
519 matching_site_instances.insert(frame_host->GetSiteInstance());
520 }
521
522 auto* spec_frame_host =
523 frame_tree_node->render_manager()->speculative_frame_host();
524 if (spec_frame_host &&
525 spec_frame_host->HasCommittingNavigationRequestForOrigin(
526 previously_visited_origin, navigation_request_to_exclude)) {
527 matching_site_instances.insert(spec_frame_host->GetSiteInstance());
528 }
529
530 auto* navigation_request = frame_tree_node->navigation_request();
531 if (navigation_request &&
532 navigation_request != navigation_request_to_exclude &&
533 navigation_request->HasCommittingOrigin(previously_visited_origin)) {
534 matching_site_instances.insert(frame_host->GetSiteInstance());
535 }
536 }
537
538 // Update any SiteInstances found to contain |origin|.
539 for (auto* site_instance : matching_site_instances) {
540 static_cast<SiteInstanceImpl*>(site_instance)
541 ->PreventOptInOriginIsolation(previously_visited_origin);
542 }
543}
544
Carlos Caballero40b0efd2021-01-26 11:55:00545void FrameTree::Init(SiteInstance* main_frame_site_instance,
546 bool renderer_initiated_creation,
Sreeja Kamishetty3699c35f2021-02-12 15:10:58547 const std::string& main_frame_name,
548 bool is_prerendering) {
Carlos Caballero40b0efd2021-01-26 11:55:00549 // blink::FrameTree::SetName always keeps |unique_name| empty in case of a
550 // main frame - let's do the same thing here.
551 std::string unique_name;
552 root_->SetFrameName(main_frame_name, unique_name);
Sreeja Kamishetty3699c35f2021-02-12 15:10:58553 is_prerendering_ = is_prerendering;
554 root_->render_manager()->InitRoot(main_frame_site_instance,
555 renderer_initiated_creation);
Carlos Caballero40b0efd2021-01-26 11:55:00556}
557
Carlos Caballeroede6f8c2021-01-28 11:01:50558void FrameTree::DidAccessInitialMainDocument() {
559 OPTIONAL_TRACE_EVENT0("content", "FrameTree::DidAccessInitialDocument");
560 has_accessed_initial_main_document_ = true;
561 controller().DidAccessInitialMainDocument();
562}
563
Sreeja Kamishetty3699c35f2021-02-12 15:10:58564void FrameTree::ActivatePrerenderedFrameTree() {
565 DCHECK(is_prerendering_ && blink::features::IsPrerender2Enabled());
566 is_prerendering_ = false;
567 GetMainFrame()->OnPrerenderedPageActivated();
Sreeja Kamishetty46f762c2021-02-05 07:52:46568}
569
Carlos Caballero03262522021-02-05 14:49:58570void FrameTree::DidStartLoadingNode(FrameTreeNode& node,
571 bool to_different_document,
572 bool was_previously_loading) {
573 // Any main frame load to a new document should reset the load progress since
574 // it will replace the current page and any frames. The WebContents will
575 // be notified when DidChangeLoadProgress is called.
576 if (to_different_document && node.IsMainFrame())
577 ResetLoadProgress();
578
579 if (was_previously_loading)
580 return;
581
582 root()->render_manager()->SetIsLoading(IsLoading());
583 delegate_->DidStartLoading(&node, to_different_document);
584}
585
586void FrameTree::DidStopLoadingNode(FrameTreeNode& node) {
587 if (IsLoading())
588 return;
589
590 root()->render_manager()->SetIsLoading(false);
591 delegate_->DidStopLoading();
592}
593
594void FrameTree::DidChangeLoadProgressForNode(FrameTreeNode& node,
595 double load_progress) {
596 if (!node.IsMainFrame())
597 return;
598 if (load_progress <= load_progress_)
599 return;
600 load_progress_ = load_progress;
601
602 // Notify the WebContents.
603 delegate_->DidChangeLoadProgress();
604}
605
606void FrameTree::DidCancelLoading() {
607 OPTIONAL_TRACE_EVENT0("content", "FrameTree::DidCancelLoading");
608 navigator_.controller().DiscardNonCommittedEntries();
609 // TODO(https://crbug.com/1170277): This should not be needed as we already
610 // send a notification in
611 // NavigationControllerImpl::DiscardNonCommittedEntries().
612 navigator_.controller().delegate()->NotifyNavigationStateChanged(
613 INVALIDATE_TYPE_URL);
614}
615
616void FrameTree::StopLoading() {
617 for (FrameTreeNode* node : Nodes())
618 node->StopLoading();
619}
620
[email protected]9b159a52013-10-03 17:24:55621} // namespace content