blob: b2d960998c0f7764705b1df834733699d9d4bab1 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
[email protected]9b159a52013-10-03 17:24:552// 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
Lei Zhangde197672021-04-29 08:11:2413#include "base/containers/contains.h"
Rakina Zata Amni80700402021-09-20 17:18:0314#include "base/debug/dump_without_crashing.h"
Avi Drissmanadac21992023-01-11 23:46:3915#include "base/functional/bind.h"
16#include "base/functional/callback.h"
[email protected]20edca72014-08-14 10:27:5317#include "base/lazy_instance.h"
dcheng9bfa5162016-04-09 01:00:5718#include "base/memory/ptr_util.h"
Peilin Wang427aa6a2023-03-22 17:58:3319#include "base/memory/safe_ref.h"
Peter Kastingd5685942022-09-02 17:52:1720#include "base/ranges/algorithm.h"
Carlos Caballeroede6f8c2021-01-28 11:01:5021#include "base/trace_event/optional_trace_event.h"
Rakina Zata Amni4b1968d2021-09-09 03:29:4722#include "base/trace_event/typed_macros.h"
Pavel Feldman25234722017-10-11 02:49:0623#include "base/unguessable_token.h"
Peilin Wang427aa6a2023-03-22 17:58:3324#include "content/browser/renderer_host/batched_proxy_ipc_sender.h"
danakjc492bf82020-09-09 20:02:4425#include "content/browser/renderer_host/navigation_controller_impl.h"
26#include "content/browser/renderer_host/navigation_entry_impl.h"
27#include "content/browser/renderer_host/navigation_request.h"
28#include "content/browser/renderer_host/navigator.h"
29#include "content/browser/renderer_host/navigator_delegate.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1530#include "content/browser/renderer_host/page_impl.h"
Kevin McNee5f594382021-05-06 23:18:2331#include "content/browser/renderer_host/render_frame_host_delegate.h"
danakjc492bf82020-09-09 20:02:4432#include "content/browser/renderer_host/render_frame_host_factory.h"
33#include "content/browser/renderer_host/render_frame_host_impl.h"
34#include "content/browser/renderer_host/render_frame_proxy_host.h"
Carlos Caballero101ac26b2021-03-24 11:54:0535#include "content/browser/renderer_host/render_view_host_delegate.h"
[email protected]94d0cc12013-12-18 00:07:4136#include "content/browser/renderer_host/render_view_host_factory.h"
37#include "content/browser/renderer_host/render_view_host_impl.h"
Sharon Yang7ce309e2023-01-19 21:39:5738#include "content/common/content_navigation_policy.h"
japhet98e9bd82016-06-28 23:48:4539#include "content/common/content_switches_internal.h"
Peilin Wang427aa6a2023-03-22 17:58:3340#include "content/common/features.h"
Sreeja Kamishetty46f762c2021-02-05 07:52:4641#include "third_party/blink/public/common/features.h"
Kevin McNee43fe8292021-10-04 22:59:4142#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
Blink Reformata30d4232018-04-07 15:31:0643#include "third_party/blink/public/common/frame/frame_policy.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1544#include "third_party/blink/public/common/loader/loader_constants.h"
Ari Chivukula5d15efb2023-01-21 04:33:5245#include "third_party/blink/public/common/storage_key/storage_key.h"
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:5446#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
[email protected]9b159a52013-10-03 17:24:5547
48namespace content {
49
50namespace {
[email protected]20edca72014-08-14 10:27:5351
Rakina Zata Amni4b1968d2021-09-09 03:29:4752using perfetto::protos::pbzero::ChromeTrackEvent;
53
Sharon Yangefe52632022-03-08 23:06:0654// Helper function to collect SiteInstanceGroups involved in rendering a single
55// FrameTree (which is a subset of SiteInstanceGroups in main frame's
56// proxy_hosts_ because of openers).
57std::set<SiteInstanceGroup*> CollectSiteInstanceGroups(FrameTree* tree) {
58 std::set<SiteInstanceGroup*> groups;
Adithya Srinivasan0e9808342022-12-13 18:25:0759 for (FrameTreeNode* node : tree->Nodes())
Sharon Yangefe52632022-03-08 23:06:0660 groups.insert(node->current_frame_host()->GetSiteInstance()->group());
61 return groups;
alexmos3fcd0ca2015-10-23 18:18:3362}
63
Kevin McNee5f594382021-05-06 23:18:2364// If |node| is the placeholder FrameTreeNode for an embedded frame tree,
65// returns the inner tree's main frame's FrameTreeNode. Otherwise, returns null.
66FrameTreeNode* GetInnerTreeMainFrameNode(FrameTreeNode* node) {
Dominic Farolino377edb302021-07-29 05:57:1867 FrameTreeNode* inner_main_frame_tree_node = FrameTreeNode::GloballyFindByID(
68 node->current_frame_host()->inner_tree_main_frame_tree_node_id());
Kevin McNee5f594382021-05-06 23:18:2369
Kevin McNeed459ad42022-09-12 19:24:5970 if (inner_main_frame_tree_node) {
Arthur Sonzognif6785ec2022-12-05 10:11:5071 DCHECK_NE(&node->frame_tree(), &inner_main_frame_tree_node->frame_tree());
Kevin McNee5f594382021-05-06 23:18:2372 }
73
Kevin McNeed459ad42022-09-12 19:24:5974 return inner_main_frame_tree_node;
Kevin McNee5f594382021-05-06 23:18:2375}
76
[email protected]9b159a52013-10-03 17:24:5577} // namespace
78
vmpstr33895d992016-02-24 20:55:2179FrameTree::NodeIterator::NodeIterator(const NodeIterator& other) = default;
80
Fergal Daly55b6d722020-09-11 07:56:3381FrameTree::NodeIterator::~NodeIterator() = default;
dcheng57e39e22016-01-21 00:25:3882
83FrameTree::NodeIterator& FrameTree::NodeIterator::operator++() {
Alex Moshchuk27caae82017-09-11 23:11:1884 if (current_node_ != root_of_subtree_to_skip_) {
Jayson Adams4db0bfe22021-07-15 19:24:0785 // Reserve enough space in the queue to accommodate the nodes we're
86 // going to add, to avoid repeated resize calls.
87 queue_.reserve(queue_.size() + current_node_->child_count());
88
Alex Moshchuk27caae82017-09-11 23:11:1889 for (size_t i = 0; i < current_node_->child_count(); ++i) {
90 FrameTreeNode* child = current_node_->child_at(i);
Kevin McNee5f594382021-05-06 23:18:2391 FrameTreeNode* inner_tree_main_ftn = GetInnerTreeMainFrameNode(child);
Dave Tapuskadda303d2022-10-04 16:56:4892 if (should_descend_into_inner_trees_ && inner_tree_main_ftn) {
93 if (include_delegate_nodes_for_inner_frame_trees_)
94 queue_.push_back(child);
95 queue_.push_back(inner_tree_main_ftn);
96 } else {
97 queue_.push_back(child);
98 }
Kevin McNee5f594382021-05-06 23:18:2399 }
100
101 if (should_descend_into_inner_trees_) {
Jayson Adams4db0bfe22021-07-15 19:24:07102 auto unattached_nodes =
103 current_node_->current_frame_host()
104 ->delegate()
105 ->GetUnattachedOwnedNodes(current_node_->current_frame_host());
106
107 // Reserve enough space in the queue to accommodate the nodes we're
108 // going to add.
109 queue_.reserve(queue_.size() + unattached_nodes.size());
110
111 for (auto* unattached_node : unattached_nodes) {
112 queue_.push_back(unattached_node);
Kevin McNee5f594382021-05-06 23:18:23113 }
Alex Moshchuk27caae82017-09-11 23:11:18114 }
dcheng57e39e22016-01-21 00:25:38115 }
116
Kevin McNee5f594382021-05-06 23:18:23117 AdvanceNode();
118 return *this;
119}
dcheng57e39e22016-01-21 00:25:38120
Kevin McNee5f594382021-05-06 23:18:23121FrameTree::NodeIterator& FrameTree::NodeIterator::AdvanceSkippingChildren() {
122 AdvanceNode();
dcheng57e39e22016-01-21 00:25:38123 return *this;
124}
125
126bool FrameTree::NodeIterator::operator==(const NodeIterator& rhs) const {
127 return current_node_ == rhs.current_node_;
128}
129
Kevin McNee5f594382021-05-06 23:18:23130void FrameTree::NodeIterator::AdvanceNode() {
131 if (!queue_.empty()) {
132 current_node_ = queue_.front();
Jayson Adams4db0bfe22021-07-15 19:24:07133 queue_.pop_front();
Kevin McNee5f594382021-05-06 23:18:23134 } else {
135 current_node_ = nullptr;
136 }
137}
138
139FrameTree::NodeIterator::NodeIterator(
140 const std::vector<FrameTreeNode*>& starting_nodes,
141 const FrameTreeNode* root_of_subtree_to_skip,
Dave Tapuskadda303d2022-10-04 16:56:48142 bool should_descend_into_inner_trees,
143 bool include_delegate_nodes_for_inner_frame_trees)
Kevin McNee5f594382021-05-06 23:18:23144 : current_node_(nullptr),
145 root_of_subtree_to_skip_(root_of_subtree_to_skip),
146 should_descend_into_inner_trees_(should_descend_into_inner_trees),
Dave Tapuskadda303d2022-10-04 16:56:48147 include_delegate_nodes_for_inner_frame_trees_(
148 include_delegate_nodes_for_inner_frame_trees),
Jayson Adams4db0bfe22021-07-15 19:24:07149 queue_(starting_nodes.begin(), starting_nodes.end()) {
Dave Tapuskadda303d2022-10-04 16:56:48150 // If `include_delegate_nodes_for_inner_frame_trees_` is true then
151 // `should_descend_into_inner_trees_` must be true.
152 DCHECK(!include_delegate_nodes_for_inner_frame_trees_ ||
153 should_descend_into_inner_trees_);
Kevin McNee5f594382021-05-06 23:18:23154 AdvanceNode();
155}
dcheng57e39e22016-01-21 00:25:38156
157FrameTree::NodeIterator FrameTree::NodeRange::begin() {
W. James MacLeance3176d2019-10-18 04:01:45158 // We shouldn't be attempting a frame tree traversal while the tree is
Kevin McNee5f594382021-05-06 23:18:23159 // being constructed or destructed.
Peter Kastingd5685942022-09-02 17:52:17160 DCHECK(base::ranges::all_of(starting_nodes_, [](FrameTreeNode* ftn) {
161 return ftn->current_frame_host();
162 }));
Kevin McNee5f594382021-05-06 23:18:23163
164 return NodeIterator(starting_nodes_, root_of_subtree_to_skip_,
Dave Tapuskadda303d2022-10-04 16:56:48165 should_descend_into_inner_trees_,
166 include_delegate_nodes_for_inner_frame_trees_);
dcheng57e39e22016-01-21 00:25:38167}
168
169FrameTree::NodeIterator FrameTree::NodeRange::end() {
Dave Tapuskadda303d2022-10-04 16:56:48170 return NodeIterator({}, nullptr, should_descend_into_inner_trees_,
171 include_delegate_nodes_for_inner_frame_trees_);
dcheng57e39e22016-01-21 00:25:38172}
173
Kevin McNee5f594382021-05-06 23:18:23174FrameTree::NodeRange::NodeRange(
175 const std::vector<FrameTreeNode*>& starting_nodes,
176 const FrameTreeNode* root_of_subtree_to_skip,
Dave Tapuskadda303d2022-10-04 16:56:48177 bool should_descend_into_inner_trees,
178 bool include_delegate_nodes_for_inner_frame_trees)
Kevin McNee5f594382021-05-06 23:18:23179 : starting_nodes_(starting_nodes),
180 root_of_subtree_to_skip_(root_of_subtree_to_skip),
Dave Tapuskadda303d2022-10-04 16:56:48181 should_descend_into_inner_trees_(should_descend_into_inner_trees),
182 include_delegate_nodes_for_inner_frame_trees_(
183 include_delegate_nodes_for_inner_frame_trees) {}
Kevin McNee5f594382021-05-06 23:18:23184
185FrameTree::NodeRange::NodeRange(const NodeRange&) = default;
186FrameTree::NodeRange::~NodeRange() = default;
dcheng57e39e22016-01-21 00:25:38187
Carlos Caballero40b0efd2021-01-26 11:55:00188FrameTree::FrameTree(
189 BrowserContext* browser_context,
Carlos Caballero03262522021-02-05 14:49:58190 Delegate* delegate,
Carlos Caballero40b0efd2021-01-26 11:55:00191 NavigationControllerDelegate* navigation_controller_delegate,
192 NavigatorDelegate* navigator_delegate,
193 RenderFrameHostDelegate* render_frame_delegate,
194 RenderViewHostDelegate* render_view_delegate,
195 RenderWidgetHostDelegate* render_widget_delegate,
Sreeja Kamishetty837a10402021-04-23 12:41:59196 RenderFrameHostManager::Delegate* manager_delegate,
Jeremy Roman2d8dfe132021-07-06 20:51:26197 PageDelegate* page_delegate,
Danil Somsikov259aa65f2022-11-11 20:49:44198 Type type)
Carlos Caballero03262522021-02-05 14:49:58199 : delegate_(delegate),
200 render_frame_delegate_(render_frame_delegate),
[email protected]92404c62013-12-04 16:40:46201 render_view_delegate_(render_view_delegate),
[email protected]fa944cb82013-11-15 17:51:21202 render_widget_delegate_(render_widget_delegate),
203 manager_delegate_(manager_delegate),
Jeremy Roman2d8dfe132021-07-06 20:51:26204 page_delegate_(page_delegate),
Carlos Caballero40b0efd2021-01-26 11:55:00205 navigator_(browser_context,
206 *this,
207 navigator_delegate,
208 navigation_controller_delegate),
Harkiran Bolaria16f2c48d2022-04-22 12:39:57209 type_(type),
thestige62f7382016-11-08 18:31:39210 focused_frame_tree_node_id_(FrameTreeNode::kFrameTreeNodeInvalidId),
David Bokanc3fb5fa2022-07-04 14:55:31211 load_progress_(0.0),
Arthur Sonzognif6785ec2022-12-05 10:11:50212 root_(*this,
Paul Semel3e241042022-10-11 12:57:31213 nullptr,
214 // The top-level frame must always be in a
215 // document scope.
216 blink::mojom::TreeScopeType::kDocument,
217 false,
Paul Semel3e241042022-10-11 12:57:31218 blink::mojom::FrameOwnerProperties(),
219 blink::FrameOwnerElementType::kNone,
220 blink::FramePolicy()) {}
[email protected]9b159a52013-10-03 17:24:55221
222FrameTree::~FrameTree() {
Takashi Toyoshimaea534ef22021-07-21 03:27:59223 is_being_destroyed_ = true;
Carlos Caballero101ac26b2021-03-24 11:54:05224#if DCHECK_IS_ON()
225 DCHECK(was_shut_down_);
226#endif
[email protected]9b159a52013-10-03 17:24:55227}
228
Sharon Yanged884542023-02-02 17:33:44229void FrameTree::ForEachRenderViewHost(
230 base::FunctionRef<void(RenderViewHostImpl*)> on_host) {
231 if (speculative_render_view_host_) {
232 on_host(speculative_render_view_host_.get());
233 }
234
235 for (auto& rvh : render_view_host_map_) {
236 on_host(rvh.second);
237 }
238}
239
Sharon Yang7ce309e2023-01-19 21:39:57240void FrameTree::MakeSpeculativeRVHCurrent() {
241 CHECK(speculative_render_view_host_);
242
243 // The existing RenderViewHost needs to be unregistered first.
244 // Speculative RenderViewHosts are only used for same-SiteInstanceGroup
245 // navigations, so there should be a RenderViewHost of the same
246 // SiteInstanceGroup already in the tree.
247 RenderViewHostMapId speculative_id =
248 speculative_render_view_host_->rvh_map_id();
249 auto it = render_view_host_map_.find(speculative_id);
250 CHECK(it != render_view_host_map_.end());
251 UnregisterRenderViewHost(speculative_id, it->second);
252
253 speculative_render_view_host_->set_is_speculative(false);
254 RegisterRenderViewHost(speculative_id, speculative_render_view_host_.get());
255 speculative_render_view_host_.reset();
256}
257
vishal.b782eb5d2015-04-29 12:22:57258FrameTreeNode* FrameTree::FindByID(int frame_tree_node_id) {
dcheng57e39e22016-01-21 00:25:38259 for (FrameTreeNode* node : Nodes()) {
260 if (node->frame_tree_node_id() == frame_tree_node_id)
261 return node;
262 }
263 return nullptr;
[email protected]9b159a52013-10-03 17:24:55264}
265
nasko479ea5a2015-02-14 00:03:04266FrameTreeNode* FrameTree::FindByRoutingID(int process_id, int routing_id) {
dmazzoni0b5d2482014-09-10 19:45:57267 RenderFrameHostImpl* render_frame_host =
268 RenderFrameHostImpl::FromID(process_id, routing_id);
269 if (render_frame_host) {
270 FrameTreeNode* result = render_frame_host->frame_tree_node();
Arthur Sonzognif6785ec2022-12-05 10:11:50271 if (this == &result->frame_tree())
dmazzoni0b5d2482014-09-10 19:45:57272 return result;
273 }
274
275 RenderFrameProxyHost* render_frame_proxy_host =
276 RenderFrameProxyHost::FromID(process_id, routing_id);
277 if (render_frame_proxy_host) {
278 FrameTreeNode* result = render_frame_proxy_host->frame_tree_node();
Arthur Sonzognif6785ec2022-12-05 10:11:50279 if (this == &result->frame_tree())
dmazzoni0b5d2482014-09-10 19:45:57280 return result;
281 }
282
creis6a93a812015-04-24 23:13:17283 return nullptr;
284}
285
286FrameTreeNode* FrameTree::FindByName(const std::string& name) {
287 if (name.empty())
Paul Semel3e241042022-10-11 12:57:31288 return &root_;
creis6a93a812015-04-24 23:13:17289
dcheng57e39e22016-01-21 00:25:38290 for (FrameTreeNode* node : Nodes()) {
291 if (node->frame_name() == name)
292 return node;
[email protected]9b159a52013-10-03 17:24:55293 }
dcheng57e39e22016-01-21 00:25:38294
295 return nullptr;
296}
297
298FrameTree::NodeRange FrameTree::Nodes() {
Alex Moshchuk27caae82017-09-11 23:11:18299 return NodesExceptSubtree(nullptr);
dcheng57e39e22016-01-21 00:25:38300}
301
kenrb61b6c252016-03-22 17:37:15302FrameTree::NodeRange FrameTree::SubtreeNodes(FrameTreeNode* subtree_root) {
Kevin McNee5f594382021-05-06 23:18:23303 return NodeRange({subtree_root}, nullptr,
Dave Tapuskadda303d2022-10-04 16:56:48304 /*should_descend_into_inner_trees=*/false,
305 /*include_delegate_nodes_for_inner_frame_trees=*/false);
Kevin McNee5f594382021-05-06 23:18:23306}
307
Kevin McNee53f0b2d2021-11-02 18:00:45308FrameTree::NodeRange FrameTree::NodesIncludingInnerTreeNodes() {
Paul Semel3e241042022-10-11 12:57:31309 return NodeRange({&root_}, nullptr,
Dave Tapuskadda303d2022-10-04 16:56:48310 /*should_descend_into_inner_trees=*/true,
311 /*include_delegate_nodes_for_inner_frame_trees=*/false);
Kevin McNee53f0b2d2021-11-02 18:00:45312}
313
Sreeja Kamishettyd64b993d2022-02-14 12:04:42314std::vector<FrameTreeNode*> FrameTree::CollectNodesForIsLoading() {
315 FrameTree::NodeRange node_range = NodesIncludingInnerTreeNodes();
316 FrameTree::NodeIterator node_iter = node_range.begin();
317 std::vector<FrameTreeNode*> nodes;
318
319 DCHECK(node_iter != node_range.end());
Arthur Sonzognif6785ec2022-12-05 10:11:50320 FrameTree* root_loading_tree = root_.frame_tree().LoadingTree();
Sreeja Kamishettyd64b993d2022-02-14 12:04:42321 while (node_iter != node_range.end()) {
322 // Skip over frame trees and children which belong to inner web contents
323 // i.e., when nodes doesn't point to the same loading frame tree.
Arthur Sonzognif6785ec2022-12-05 10:11:50324 if ((*node_iter)->frame_tree().LoadingTree() != root_loading_tree) {
Sreeja Kamishettyd64b993d2022-02-14 12:04:42325 node_iter.AdvanceSkippingChildren();
326 } else {
327 nodes.push_back(*node_iter);
328 ++node_iter;
329 }
330 }
331 return nodes;
332}
333
Kevin McNee5f594382021-05-06 23:18:23334FrameTree::NodeRange FrameTree::SubtreeAndInnerTreeNodes(
Dave Tapuskadda303d2022-10-04 16:56:48335 RenderFrameHostImpl* parent,
336 bool include_delegate_nodes_for_inner_frame_trees) {
Kevin McNee5f594382021-05-06 23:18:23337 std::vector<FrameTreeNode*> starting_nodes;
338 starting_nodes.reserve(parent->child_count());
339 for (size_t i = 0; i < parent->child_count(); ++i) {
340 FrameTreeNode* child = parent->child_at(i);
341 FrameTreeNode* inner_tree_main_ftn = GetInnerTreeMainFrameNode(child);
Dave Tapuskadda303d2022-10-04 16:56:48342 if (inner_tree_main_ftn) {
343 if (include_delegate_nodes_for_inner_frame_trees)
344 starting_nodes.push_back(child);
345 starting_nodes.push_back(inner_tree_main_ftn);
346 } else {
347 starting_nodes.push_back(child);
348 }
Kevin McNee5f594382021-05-06 23:18:23349 }
350 const std::vector<FrameTreeNode*> unattached_owned_nodes =
351 parent->delegate()->GetUnattachedOwnedNodes(parent);
352 starting_nodes.insert(starting_nodes.end(), unattached_owned_nodes.begin(),
353 unattached_owned_nodes.end());
354 return NodeRange(starting_nodes, nullptr,
Dave Tapuskadda303d2022-10-04 16:56:48355 /* should_descend_into_inner_trees */ true,
356 include_delegate_nodes_for_inner_frame_trees);
kenrb61b6c252016-03-22 17:37:15357}
358
Alex Moshchuk27caae82017-09-11 23:11:18359FrameTree::NodeRange FrameTree::NodesExceptSubtree(FrameTreeNode* node) {
Paul Semel3e241042022-10-11 12:57:31360 return NodeRange({&root_}, node, /*should_descend_into_inner_trees=*/false,
Dave Tapuskadda303d2022-10-04 16:56:48361 /*include_delegate_nodes_for_inner_frame_trees=*/false);
[email protected]9b159a52013-10-03 17:24:55362}
363
Sreeja Kamishettyd64b993d2022-02-14 12:04:42364FrameTree* FrameTree::LoadingTree() {
365 // We return the delegate's loading frame tree to infer loading related
366 // states.
367 return delegate_->LoadingTree();
368}
369
Lucas Furukawa Gadani99125822019-01-03 15:41:49370FrameTreeNode* FrameTree::AddFrame(
Alexander Timin381e7e182020-04-28 19:04:03371 RenderFrameHostImpl* parent,
Balazs Engedyba034e72017-10-27 22:26:28372 int process_id,
373 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18374 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
Oksana Zhuravlovafee097c2019-07-26 17:01:30375 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
376 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30377 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
Dominic Farolino12e06d72022-08-05 02:29:49378 mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterfaceProvider>
379 associated_interface_provider_receiver,
Antonio Gomes9d5c1ef2020-04-30 20:56:41380 blink::mojom::TreeScopeType scope,
Balazs Engedyba034e72017-10-27 22:26:28381 const std::string& frame_name,
382 const std::string& frame_unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45383 bool is_created_by_script,
Chris Hamilton3ff6ed0e2021-02-19 03:54:04384 const blink::LocalFrameToken& frame_token,
Balazs Engedyba034e72017-10-27 22:26:28385 const base::UnguessableToken& devtools_frame_token,
Daniel Cheng284c38942022-09-22 23:30:34386 const blink::DocumentToken& document_token,
Luna Luc3fdacdf2017-11-08 04:48:53387 const blink::FramePolicy& frame_policy,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54388 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Ehsan Karamad192a8da2018-10-21 03:48:08389 bool was_discarded,
Kevin McNee43fe8292021-10-04 22:59:41390 blink::FrameOwnerElementType owner_type,
391 bool is_dummy_frame_for_inner_tree) {
nick8814e652015-12-18 01:44:12392 CHECK_NE(new_routing_id, MSG_ROUTING_NONE);
Dominic Farolino4bc10ee2021-08-31 00:37:36393 // Normally this path is for blink adding a child local frame. But both
394 // portals and fenced frames add a dummy child frame that never gets a
395 // corresponding RenderFrameImpl in any renderer process, and therefore its
396 // `frame_remote` is invalid. Also its RenderFrameHostImpl is exempt from
397 // having `RenderFrameCreated()` called on it (see later in this method, as
398 // well as `WebContentsObserverConsistencyChecker::RenderFrameHostChanged()`).
Kevin McNee43fe8292021-10-04 22:59:41399 DCHECK_NE(frame_remote.is_valid(), is_dummy_frame_for_inner_tree);
400 DCHECK_NE(browser_interface_broker_receiver.is_valid(),
401 is_dummy_frame_for_inner_tree);
Dominic Farolino12e06d72022-08-05 02:29:49402 DCHECK_NE(associated_interface_provider_receiver.is_valid(),
403 is_dummy_frame_for_inner_tree);
nick8814e652015-12-18 01:44:12404
dgroganfb22f9a2014-10-20 21:32:32405 // A child frame always starts with an initial empty document, which means
406 // it is in the same SiteInstance as the parent frame. Ensure that the process
407 // which requested a child frame to be added is the same as the process of the
408 // parent node.
Dominic Farolino6caf3032021-10-20 03:50:08409 CHECK_EQ(parent->GetProcess()->GetID(), process_id);
dgroganfb22f9a2014-10-20 21:32:32410
Danil Somsikov259aa65f2022-11-11 20:49:44411 std::unique_ptr<FrameTreeNode> new_node = base::WrapUnique(
Arthur Sonzognif6785ec2022-12-05 10:11:50412 new FrameTreeNode(*this, parent, scope, is_created_by_script,
Danil Somsikov259aa65f2022-11-11 20:49:44413 frame_owner_properties, owner_type, frame_policy));
iclelland098da752017-06-28 13:46:50414
415 // Set sandbox flags and container policy and make them effective immediately,
Charlie Hu5130d25e2021-03-05 21:53:39416 // since initial sandbox flags and permissions policy should apply to the
417 // initial empty document in the frame. This needs to happen before the call
418 // to AddChild so that the effective policy is sent to any newly-created
Dave Tapuska2402595f2022-08-03 16:24:21419 // `blink::RemoteFrame` objects when the RenderFrameHost is created.
Charlie Hu5ffc0152019-12-06 15:59:53420 // SetPendingFramePolicy is necessary here because next navigation on this
421 // frame will need the value of pending frame policy instead of effective
422 // frame policy.
Ian Clellandcdc4f312017-10-13 22:24:12423 new_node->SetPendingFramePolicy(frame_policy);
iclelland098da752017-06-28 13:46:50424
Shubhie Panickerddf2a4e2018-03-06 00:09:06425 if (was_discarded)
426 new_node->set_was_discarded();
427
iclelland098da752017-06-28 13:46:50428 // Add the new node to the FrameTree, creating the RenderFrameHost.
Harkiran Bolaria0b3bdef02022-03-10 13:04:40429 FrameTreeNode* added_node = parent->AddChild(
430 std::move(new_node), new_routing_id, std::move(frame_remote), frame_token,
Danil Somsikov259aa65f2022-11-11 20:49:44431 document_token, devtools_frame_token, frame_policy, frame_name,
432 frame_unique_name);
nick8814e652015-12-18 01:44:12433
Garrett Tanzer34cb92fe2022-09-28 17:50:54434 added_node->SetFencedFramePropertiesIfNeeded();
shivanigithub4cd016a2021-09-20 21:10:30435
Kevin McNee43fe8292021-10-04 22:59:41436 if (browser_interface_broker_receiver.is_valid()) {
437 added_node->current_frame_host()->BindBrowserInterfaceBrokerReceiver(
438 std::move(browser_interface_broker_receiver));
439 }
Oksana Zhuravlovafee097c2019-07-26 17:01:30440
Antonio Sartoridb967c52021-01-20 09:54:30441 if (policy_container_bind_params) {
Antonio Sartoria1fd1432020-11-25 09:10:20442 added_node->current_frame_host()->policy_container_host()->Bind(
Antonio Sartoridb967c52021-01-20 09:54:30443 std::move(policy_container_bind_params));
Antonio Sartoria1fd1432020-11-25 09:10:20444 }
445
Dominic Farolino12e06d72022-08-05 02:29:49446 if (associated_interface_provider_receiver.is_valid()) {
447 added_node->current_frame_host()->BindAssociatedInterfaceProviderReceiver(
448 std::move(associated_interface_provider_receiver));
449 }
450
nasko03ecfad2016-08-02 00:54:06451 // The last committed NavigationEntry may have a FrameNavigationEntry with the
452 // same |frame_unique_name|, since we don't remove FrameNavigationEntries if
453 // their frames are deleted. If there is a stale one, remove it to avoid
454 // conflicts on future updates.
Fergal Daly09d6c762020-05-29 02:05:18455 NavigationEntryImpl* last_committed_entry = static_cast<NavigationEntryImpl*>(
Carlos Caballero40b0efd2021-01-26 11:55:00456 navigator_.controller().GetLastCommittedEntry());
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45457 if (last_committed_entry) {
458 last_committed_entry->RemoveEntryForFrame(
459 added_node, /* only_if_different_position = */ true);
460 }
nasko03ecfad2016-08-02 00:54:06461
nick8814e652015-12-18 01:44:12462 // Now that the new node is part of the FrameTree and has a RenderFrameHost,
463 // we can announce the creation of the initial RenderFrame which already
464 // exists in the renderer process.
Sreeja Kamishetty5b699622021-01-22 12:54:08465 // For consistency with navigating to a new RenderFrameHost case, we dispatch
466 // RenderFrameCreated before RenderFrameHostChanged.
Kevin McNee43fe8292021-10-04 22:59:41467 if (!is_dummy_frame_for_inner_tree) {
Dominic Farolino4bc10ee2021-08-31 00:37:36468 // The outer dummy FrameTreeNode for both portals and fenced frames does not
469 // have a live RenderFrame in the renderer process.
Fergal Dalyf9ea35c2020-12-11 15:26:01470 added_node->current_frame_host()->RenderFrameCreated();
Ehsan Karamad44fc72112019-02-26 18:15:47471 }
Sreeja Kamishetty5b699622021-01-22 12:54:08472
473 // Notify the delegate of the creation of the current RenderFrameHost.
474 // This is only for subframes, as the main frame case is taken care of by
475 // WebContentsImpl::Init.
476 manager_delegate_->NotifySwappedFromRenderManager(
Dave Tapuskae45d6fd2021-09-29 17:03:59477 nullptr, added_node->current_frame_host());
Lucas Furukawa Gadani99125822019-01-03 15:41:49478 return added_node;
[email protected]9b159a52013-10-03 17:24:55479}
480
[email protected]58faf942014-02-20 21:03:58481void FrameTree::RemoveFrame(FrameTreeNode* child) {
Alexander Timin381e7e182020-04-28 19:04:03482 RenderFrameHostImpl* parent = child->parent();
[email protected]58faf942014-02-20 21:03:58483 if (!parent) {
484 NOTREACHED() << "Unexpected RemoveFrame call for main frame.";
485 return;
[email protected]9b159a52013-10-03 17:24:55486 }
487
Alexander Timin381e7e182020-04-28 19:04:03488 parent->RemoveChild(child);
[email protected]9b159a52013-10-03 17:24:55489}
490
Harkiran Bolaria2912a6b32022-02-22 16:43:45491void FrameTree::CreateProxiesForSiteInstance(
492 FrameTreeNode* source,
Charlie Reis37be2682023-01-10 17:04:47493 SiteInstanceImpl* site_instance,
Harkiran Bolaria2912a6b32022-02-22 16:43:45494 const scoped_refptr<BrowsingContextState>&
495 source_new_browsing_context_state) {
Charlie Reis37be2682023-01-10 17:04:47496 SiteInstanceGroup* group = site_instance->group();
Peilin Wang427aa6a2023-03-22 17:58:33497
498 // Will be instantiated and passed to `CreateRenderFrameProxy()` when
499 // `kConsolidatedIPCForProxyCreation` is enabled to batch create proxies
500 // for child frames.
501 std::unique_ptr<BatchedProxyIPCSender> batched_proxy_ipc_sender;
502
alexmos58729042015-06-18 23:20:00503 if (!source || !source->IsMainFrame()) {
Sharon Yang57bde122022-03-01 20:01:12504 RenderViewHostImpl* render_view_host = GetRenderViewHost(group).get();
arthursonzognic5be3842019-07-09 11:49:14505 if (render_view_host) {
Sharon Yang57bde122022-03-01 20:01:12506 root()->render_manager()->EnsureRenderViewInitialized(render_view_host,
507 group);
arthursonzognic5be3842019-07-09 11:49:14508 } else {
Harkiran Bolaria2912a6b32022-02-22 16:43:45509 // Due to the check above, we are creating either an opener proxy (when
510 // source is null) or a main frame proxy due to a subframe navigation
511 // (when source is not a main frame). In the former case, we should use
512 // root's current BrowsingContextState, while in the latter case we should
513 // use BrowsingContextState from the main RenderFrameHost of the subframe
Dave Tapuska2cf1f532022-08-10 15:30:49514 // being navigated. We want to ensure that the `blink::WebView` is created
515 // in the right SiteInstance if it doesn't exist, before creating the
516 // other proxies; if the `blink::WebView` doesn't exist, the only way to
517 // do this is to also create a proxy for the main frame as well.
Peilin Wang427aa6a2023-03-22 17:58:33518 const scoped_refptr<BrowsingContextState>& root_browsing_context_state =
Harkiran Bolaria2912a6b32022-02-22 16:43:45519 source ? source->parent()->GetMainFrame()->browsing_context_state()
Peilin Wang427aa6a2023-03-22 17:58:33520 : root()->current_frame_host()->browsing_context_state();
521
522 // TODO(https://crbug.com/1393697): Batch main frame proxy creation and
523 // pass an instance of `BatchedProxyIPCSender` here instead of nullptr.
524 root()->render_manager()->CreateRenderFrameProxy(
525 site_instance, root_browsing_context_state,
526 /*batched_proxy_ipc_sender=*/nullptr);
527
528 // We only need to use `BatchedProxyIPCSender` when navigating to a new
529 // `SiteInstance`. Proxies do not need to be created when navigating to a
530 // `SiteInstance` that has already been encountered, because site
531 // isolation would guarantee that all nodes already have either proxies
532 // or real frames. Due to the check above, the `render_view_host` does
533 // not exist here, which means we have not seen this `SiteInstance`
534 // before, so we instantiate `batched_proxy_ipc_sender` to consolidate
535 // IPCs for proxy creation.
536 bool should_consolidate_ipcs =
537 base::FeatureList::IsEnabled(kConsolidatedIPCForProxyCreation);
538 if (should_consolidate_ipcs) {
539 base::SafeRef<RenderFrameProxyHost> root_proxy =
540 root_browsing_context_state
541 ->GetRenderFrameProxyHost(site_instance->group())
542 ->GetSafeRef();
543 batched_proxy_ipc_sender =
544 std::make_unique<BatchedProxyIPCSender>(std::move(root_proxy));
545 }
[email protected]82307f6b2014-08-07 03:30:12546 }
547 }
548
Sharon Yang88f064ca2023-03-24 16:25:18549 // Check whether we're in an inner delegate and the group |site_instance| is
550 // in corresponds to the outer delegate. Subframe proxies aren't needed if
551 // this is the case.
552 bool is_site_instance_group_for_outer_delegate = false;
Alex Moshchuk1226b152019-11-08 18:23:45553 RenderFrameProxyHost* outer_delegate_proxy =
554 root()->render_manager()->GetProxyToOuterDelegate();
555 if (outer_delegate_proxy) {
Sharon Yang88f064ca2023-03-24 16:25:18556 is_site_instance_group_for_outer_delegate =
557 (site_instance->group() == outer_delegate_proxy->site_instance_group());
Alex Moshchuk1226b152019-11-08 18:23:45558 }
559
naskoe6edde32014-10-17 15:36:48560 // Proxies are created in the FrameTree in response to a node navigating to a
561 // new SiteInstance. Since |source|'s navigation will replace the currently
Alex Moshchuk27caae82017-09-11 23:11:18562 // loaded document, the entire subtree under |source| will be removed, and
563 // thus proxy creation is skipped for all nodes in that subtree.
564 //
565 // However, a proxy *is* needed for the |source| node itself. This lets
566 // cross-process navigations in |source| start with a proxy and follow a
567 // remote-to-local transition, which avoids race conditions in cases where
568 // other navigations need to reference |source| before it commits. See
569 // https://crbug.com/756790 for more background. Therefore,
570 // NodesExceptSubtree(source) will include |source| in the nodes traversed
571 // (see NodeIterator::operator++).
572 for (FrameTreeNode* node : NodesExceptSubtree(source)) {
dcheng57e39e22016-01-21 00:25:38573 // If a new frame is created in the current SiteInstance, other frames in
574 // that SiteInstance don't need a proxy for the new frame.
Alex Moshchuk27caae82017-09-11 23:11:18575 RenderFrameHostImpl* current_host =
576 node->render_manager()->current_frame_host();
Charlie Reis37be2682023-01-10 17:04:47577 SiteInstanceImpl* current_instance = current_host->GetSiteInstance();
Alex Moshchuk27caae82017-09-11 23:11:18578 if (current_instance != site_instance) {
579 if (node == source && !current_host->IsRenderFrameLive()) {
Fergal Daly6de62f52020-10-14 01:56:44580 // We don't create a proxy at |source| when the current RenderFrameHost
581 // isn't live. This is because either (1) the speculative
Alex Moshchuk27caae82017-09-11 23:11:18582 // RenderFrameHost will be committed immediately, and the proxy
Fergal Daly6de62f52020-10-14 01:56:44583 // destroyed right away, in GetFrameHostForNavigation, which makes the
584 // races above impossible, or (2) the early commit will be skipped due
585 // to ShouldSkipEarlyCommitPendingForCrashedFrame, in which case the
586 // proxy for |source| *is* needed, but it will be created later in
587 // CreateProxiesForNewRenderFrameHost.
588 //
589 // TODO(fergal): Consider creating a proxy for |source| here rather than
590 // in CreateProxiesForNewRenderFrameHost for case (2) above.
Alex Moshchuk27caae82017-09-11 23:11:18591 continue;
592 }
Alex Moshchuk1226b152019-11-08 18:23:45593
594 // Do not create proxies for subframes in the outer delegate's
Sharon Yang88f064ca2023-03-24 16:25:18595 // SiteInstanceGroup, since there is no need to expose these subframes to
596 // the outer delegate. See also comments in CreateProxiesForChildFrame()
597 // and https://crbug.com/1013553.
598 if (!node->IsMainFrame() && is_site_instance_group_for_outer_delegate) {
Alex Moshchuk1226b152019-11-08 18:23:45599 continue;
Sharon Yang88f064ca2023-03-24 16:25:18600 }
Alex Moshchuk1226b152019-11-08 18:23:45601
Harkiran Bolaria2912a6b32022-02-22 16:43:45602 // If |node| is the FrameTreeNode being navigated, we use
603 // |browsing_context_state| (as BrowsingContextState might change for
604 // cross-BrowsingInstance navigations). Otherwise, we should use the
605 // |node|'s current BrowsingContextState.
606 node->render_manager()->CreateRenderFrameProxy(
607 site_instance,
Peilin Wang427aa6a2023-03-22 17:58:33608 node == source ? source_new_browsing_context_state
609 : node->current_frame_host()->browsing_context_state(),
610 batched_proxy_ipc_sender.get());
Alex Moshchuk27caae82017-09-11 23:11:18611 }
dcheng57e39e22016-01-21 00:25:38612 }
Peilin Wang427aa6a2023-03-22 17:58:33613
614 if (batched_proxy_ipc_sender) {
615 batched_proxy_ipc_sender->CreateAllProxies();
616 }
[email protected]82307f6b2014-08-07 03:30:12617}
618
[email protected]9b159a52013-10-03 17:24:55619RenderFrameHostImpl* FrameTree::GetMainFrame() const {
Paul Semel3e241042022-10-11 12:57:31620 return root_.current_frame_host();
[email protected]9b159a52013-10-03 17:24:55621}
622
[email protected]9c9343b2014-03-08 02:56:07623FrameTreeNode* FrameTree::GetFocusedFrame() {
624 return FindByID(focused_frame_tree_node_id_);
625}
626
Sharon Yangefe52632022-03-08 23:06:06627void FrameTree::SetFocusedFrame(FrameTreeNode* node,
628 SiteInstanceGroup* source) {
Rakina Zata Amnicca4889e2021-09-28 23:25:55629 CHECK(node->current_frame_host()->IsActive());
alexmos5357efb2015-12-16 21:44:00630 if (node == GetFocusedFrame())
631 return;
632
Sharon Yangefe52632022-03-08 23:06:06633 std::set<SiteInstanceGroup*> frame_tree_groups =
634 CollectSiteInstanceGroups(this);
alexmosb1dc2162015-11-05 00:59:20635
Sharon Yangefe52632022-03-08 23:06:06636 SiteInstanceGroup* current_group =
637 node->current_frame_host()->GetSiteInstance()->group();
alexmos5357efb2015-12-16 21:44:00638
Sharon Yang7424bda2021-11-04 20:27:43639 // Update the focused frame in all other SiteInstanceGroups. If focus changes
640 // to a cross-group frame, this allows the old focused frame's renderer
alexmosb1dc2162015-11-05 00:59:20641 // process to clear focus from that frame and fire blur events. It also
642 // ensures that the latest focused frame is available in all renderers to
643 // compute document.activeElement.
alexmos5357efb2015-12-16 21:44:00644 //
Sharon Yangefe52632022-03-08 23:06:06645 // We do not notify the |source| SiteInstanceGroup because it already knows
646 // the new focused frame (since it initiated the focus change), and we notify
647 // the new focused frame's SiteInstanceGroup (if it differs from |source|)
648 // separately below.
649 for (auto* group : frame_tree_groups) {
650 if (group != source && group != current_group) {
651 RenderFrameProxyHost* proxy = node->current_frame_host()
652 ->browsing_context_state()
653 ->GetRenderFrameProxyHost(group);
Sharon Yangf92842a2022-03-01 18:21:47654
Rakina Zata Amni80700402021-09-20 17:18:03655 if (proxy) {
656 proxy->SetFocusedFrame();
657 } else {
Sharon Yangf92842a2022-03-01 18:21:47658 base::debug::DumpWithoutCrashing();
Rakina Zata Amni80700402021-09-20 17:18:03659 }
alexmosb1dc2162015-11-05 00:59:20660 }
alexmosca2c6ba2015-10-01 21:52:25661 }
662
Sharon Yangefe52632022-03-08 23:06:06663 // If |node| was focused from a cross-group frame (i.e., via
alexmos5357efb2015-12-16 21:44:00664 // window.focus()), tell its RenderFrame that it should focus.
Sharon Yangefe52632022-03-08 23:06:06665 if (current_group != source)
alexmos5357efb2015-12-16 21:44:00666 node->current_frame_host()->SetFocusedFrame();
667
[email protected]9c9343b2014-03-08 02:56:07668 focused_frame_tree_node_id_ = node->frame_tree_node_id();
alexmos21acae52015-11-07 01:04:43669 node->DidFocus();
dmazzonif27bf892016-03-10 15:51:55670
671 // The accessibility tree data for the root of the frame tree keeps
672 // track of the focused frame too, so update that every time the
673 // focused frame changes.
Kevin McNee582a7d62021-10-12 21:42:22674 root()
675 ->current_frame_host()
676 ->GetOutermostMainFrameOrEmbedder()
677 ->UpdateAXTreeData();
[email protected]9c9343b2014-03-08 02:56:07678}
679
arthursonzognic5be3842019-07-09 11:49:14680scoped_refptr<RenderViewHostImpl> FrameTree::CreateRenderViewHost(
Charlie Reis37be2682023-01-10 17:04:47681 SiteInstanceImpl* site_instance,
avib7348942015-12-25 20:57:10682 int32_t main_frame_routing_id,
Harkiran Bolaria57e2b062022-03-14 10:27:58683 bool renderer_initiated_creation,
Sharon Yang7ce309e2023-01-19 21:39:57684 scoped_refptr<BrowsingContextState> main_browsing_context_state,
685 CreateRenderViewHostCase create_case) {
Harkiran Bolaria57e2b062022-03-14 10:27:58686 if (main_browsing_context_state) {
687 DCHECK(main_browsing_context_state->is_main_frame());
688 }
dcheng29f5a6c2015-08-31 21:43:27689 RenderViewHostImpl* rvh =
690 static_cast<RenderViewHostImpl*>(RenderViewHostFactory::Create(
Charlie Reis37be2682023-01-10 17:04:47691 this, site_instance->group(),
Sharon Yangcadd00b82022-05-13 19:16:33692 site_instance->GetStoragePartitionConfig(), render_view_delegate_,
Dave Tapuska658bfec2022-08-05 14:27:20693 render_widget_delegate_, main_frame_routing_id,
Sharon Yang7ce309e2023-01-19 21:39:57694 renderer_initiated_creation, std::move(main_browsing_context_state),
695 create_case));
696
697 if (ShouldCreateNewHostForAllFrames() &&
698 create_case == CreateRenderViewHostCase::kSpeculative) {
699 set_speculative_render_view_host(rvh->GetWeakPtr());
700 } else {
701 // Register non-speculative RenderViewHosts. If they are speculative, they
702 // will be registered when they become active.
703 RegisterRenderViewHost(rvh->rvh_map_id(), rvh);
704 }
705
arthursonzognic5be3842019-07-09 11:49:14706 return base::WrapRefCounted(rvh);
[email protected]94d0cc12013-12-18 00:07:41707}
708
arthursonzognic5be3842019-07-09 11:49:14709scoped_refptr<RenderViewHostImpl> FrameTree::GetRenderViewHost(
Sharon Yang57bde122022-03-01 20:01:12710 SiteInstanceGroup* group) {
Sharon Yanga2fe85e2022-02-09 21:38:29711 // When called from RenderFrameHostManager::CreateRenderFrameHost, it's
712 // possible that a RenderProcessHost hasn't yet been created, which means
Sharon Yang57bde122022-03-01 20:01:12713 // a SiteInstanceGroup won't have been created yet.
Sharon Yanga2fe85e2022-02-09 21:38:29714 if (!group)
715 return nullptr;
716
717 auto it = render_view_host_map_.find(GetRenderViewHostMapId(group));
arthursonzogni88e54ae2019-04-15 12:57:36718 if (it == render_view_host_map_.end())
719 return nullptr;
alexmos9aa61232016-04-26 21:54:02720
arthursonzognic5be3842019-07-09 11:49:14721 return base::WrapRefCounted(it->second);
[email protected]94d0cc12013-12-18 00:07:41722}
723
Aaron Colwell78b4bde2021-03-16 16:16:09724FrameTree::RenderViewHostMapId FrameTree::GetRenderViewHostMapId(
Sharon Yangc581a0c2021-11-02 18:09:39725 SiteInstanceGroup* site_instance_group) const {
726 return RenderViewHostMapId::FromUnsafeValue(
727 site_instance_group->GetId().value());
Lowell Manners75055a132019-10-11 10:30:29728}
729
Aaron Colwell78b4bde2021-03-16 16:16:09730void FrameTree::RegisterRenderViewHost(RenderViewHostMapId id,
731 RenderViewHostImpl* rvh) {
Rakina Zata Amni4b1968d2021-09-09 03:29:47732 TRACE_EVENT_INSTANT("navigation", "FrameTree::RegisterRenderViewHost",
733 ChromeTrackEvent::kRenderViewHost, *rvh);
Sharon Yang7ce309e2023-01-19 21:39:57734 CHECK(!rvh->is_speculative());
Aaron Colwell78b4bde2021-03-16 16:16:09735 CHECK(!base::Contains(render_view_host_map_, id));
736 render_view_host_map_[id] = rvh;
Sharon Yang7ce309e2023-01-19 21:39:57737 rvh->set_is_registered_with_frame_tree(true);
Aaron Colwell78b4bde2021-03-16 16:16:09738}
739
740void FrameTree::UnregisterRenderViewHost(RenderViewHostMapId id,
Aaron Colwellc4bd7d62021-01-29 04:23:13741 RenderViewHostImpl* rvh) {
Rakina Zata Amni4b1968d2021-09-09 03:29:47742 TRACE_EVENT_INSTANT("navigation", "FrameTree::UnregisterRenderViewHost",
743 ChromeTrackEvent::kRenderViewHost, *rvh);
Sharon Yang7ce309e2023-01-19 21:39:57744 CHECK(!rvh->is_speculative());
Aaron Colwell78b4bde2021-03-16 16:16:09745 auto it = render_view_host_map_.find(id);
arthursonzogni88e54ae2019-04-15 12:57:36746 CHECK(it != render_view_host_map_.end());
arthursonzognic5be3842019-07-09 11:49:14747 CHECK_EQ(it->second, rvh);
748 render_view_host_map_.erase(it);
Sharon Yang7ce309e2023-01-19 21:39:57749 rvh->set_is_registered_with_frame_tree(false);
[email protected]94d0cc12013-12-18 00:07:41750}
751
arthursonzogni0a2007792019-05-28 21:32:48752void FrameTree::FrameUnloading(FrameTreeNode* frame) {
753 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
754 focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
755
756 // Ensure frames that are about to be deleted aren't visible from the other
757 // processes anymore.
Harkiran Bolaria0b3bdef02022-03-10 13:04:40758 frame->GetBrowsingContextStateForSubframe()->ResetProxyHosts();
arthursonzogni0a2007792019-05-28 21:32:48759}
760
dmazzonie950ea232015-03-13 21:39:45761void FrameTree::FrameRemoved(FrameTreeNode* frame) {
nick53d5cbf2015-04-23 22:50:14762 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
thestige62f7382016-11-08 18:31:39763 focused_frame_tree_node_id_ = FrameTreeNode::kFrameTreeNodeInvalidId;
dmazzonie950ea232015-03-13 21:39:45764}
765
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15766double FrameTree::GetLoadProgress() {
Paul Semel3e241042022-10-11 12:57:31767 if (root_.HasNavigation())
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15768 return blink::kInitialLoadProgress;
769
Paul Semel3e241042022-10-11 12:57:31770 return root_.current_frame_host()->GetPage().load_progress();
fdegans1d16355162015-03-26 11:58:34771}
772
Yu Gaoc8c18552022-06-22 14:38:45773bool FrameTree::IsLoadingIncludingInnerFrameTrees() const {
Nate Chapin470dbc62023-04-25 16:34:38774 return GetLoadingState() != LoadingState::NONE;
775}
776
777LoadingState FrameTree::GetLoadingState() const {
778 // The overall loading state for the FrameTree matches the root node's loading
779 // state if the root is loading.
780 if (root_.GetLoadingState() != LoadingState::NONE) {
781 return root_.GetLoadingState();
dcheng57e39e22016-01-21 00:25:38782 }
Nate Chapin470dbc62023-04-25 16:34:38783
784 // Otherwise, check if a subframe is loading without an associated navigation
785 // in the root frame. If so, we are loading, but we don't want to show
786 // loading UI.
787 for (const FrameTreeNode* node_to_check :
788 const_cast<FrameTree*>(this)->CollectNodesForIsLoading()) {
789 if (node_to_check->IsLoading()) {
790 return LoadingState::LOADING_WITHOUT_UI;
791 }
792 }
793 return LoadingState::NONE;
fdegans1d16355162015-03-26 11:58:34794}
795
alexmos3fcd0ca2015-10-23 18:18:33796void FrameTree::ReplicatePageFocus(bool is_focused) {
Dave Tapuska53e6ce12021-08-06 16:08:24797 // Focus loss may occur while this FrameTree is being destroyed. Don't
798 // send the message in this case, as the main frame's RenderFrameHost and
799 // other state has already been cleared.
800 if (is_being_destroyed_)
801 return;
Sharon Yangefe52632022-03-08 23:06:06802 std::set<SiteInstanceGroup*> frame_tree_site_instance_groups =
803 CollectSiteInstanceGroups(this);
alexmos3fcd0ca2015-10-23 18:18:33804
Sharon Yangefe52632022-03-08 23:06:06805 // Send the focus update to main frame's proxies in all SiteInstanceGroups of
alexmos3fcd0ca2015-10-23 18:18:33806 // other frames in this FrameTree. Note that the main frame might also know
Sharon Yangefe52632022-03-08 23:06:06807 // about proxies in SiteInstanceGroups for frames in a different FrameTree
808 // (e.g., for window.open), so we can't just iterate over its proxy_hosts_ in
alexmos3fcd0ca2015-10-23 18:18:33809 // RenderFrameHostManager.
Sharon Yangefe52632022-03-08 23:06:06810 for (auto* group : frame_tree_site_instance_groups)
811 SetPageFocus(group, is_focused);
alexmos0d7e0b09b2015-10-29 22:11:48812}
alexmos3fcd0ca2015-10-23 18:18:33813
Sreeja Kamishetty60e47132022-02-08 12:51:53814bool FrameTree::IsPortal() {
815 return delegate_->IsPortal();
816}
817
Sharon Yangefe52632022-03-08 23:06:06818void FrameTree::SetPageFocus(SiteInstanceGroup* group, bool is_focused) {
Paul Semel3e241042022-10-11 12:57:31819 RenderFrameHostManager* root_manager = root_.render_manager();
alexmos0d7e0b09b2015-10-29 22:11:48820
Adithya Srinivasan47731222021-01-22 15:02:42821 // Portal frame tree should not get page focus.
Sreeja Kamishetty60e47132022-02-08 12:51:53822 DCHECK(!IsPortal() || !is_focused);
Adithya Srinivasan47731222021-01-22 15:02:42823
alexmos0d7e0b09b2015-10-29 22:11:48824 // This is only used to set page-level focus in cross-process subframes, and
Sharon Yangefe52632022-03-08 23:06:06825 // requests to set focus in main frame's SiteInstanceGroup are ignored.
826 if (group != root_manager->current_frame_host()->GetSiteInstance()->group()) {
827 RenderFrameProxyHost* proxy = root_manager->current_frame_host()
828 ->browsing_context_state()
829 ->GetRenderFrameProxyHost(group);
Dave Tapuska82b54012022-07-15 23:26:10830 if (proxy->is_render_frame_proxy_live())
831 proxy->GetAssociatedRemoteFrame()->SetPageFocus(is_focused);
alexmos3fcd0ca2015-10-23 18:18:33832 }
833}
834
W. James MacLeanc07dc41b2022-07-25 18:52:16835void FrameTree::RegisterExistingOriginAsHavingDefaultIsolation(
W. James MacLeanb70fab82020-05-01 18:51:14836 const url::Origin& previously_visited_origin,
837 NavigationRequest* navigation_request_to_exclude) {
W. James MacLeanc07dc41b2022-07-25 18:52:16838 controller().RegisterExistingOriginAsHavingDefaultIsolation(
W. James MacLeanc6dc86c2021-08-12 13:58:37839 previously_visited_origin);
840
Charlie Reis37be2682023-01-10 17:04:47841 std::unordered_set<SiteInstanceImpl*> matching_site_instances;
W. James MacLeanb70fab82020-05-01 18:51:14842
843 // Be sure to visit all RenderFrameHosts associated with this frame that might
844 // have an origin that could script other frames. We skip RenderFrameHosts
845 // that are in the bfcache, assuming there's no way for a frame to join the
846 // BrowsingInstance of a bfcache RFH while it's in the cache.
847 for (auto* frame_tree_node : SubtreeNodes(root())) {
848 auto* frame_host = frame_tree_node->current_frame_host();
W. James MacLeanb70fab82020-05-01 18:51:14849 if (previously_visited_origin == frame_host->GetLastCommittedOrigin())
850 matching_site_instances.insert(frame_host->GetSiteInstance());
851
852 if (frame_host->HasCommittingNavigationRequestForOrigin(
853 previously_visited_origin, navigation_request_to_exclude)) {
854 matching_site_instances.insert(frame_host->GetSiteInstance());
855 }
856
857 auto* spec_frame_host =
858 frame_tree_node->render_manager()->speculative_frame_host();
859 if (spec_frame_host &&
860 spec_frame_host->HasCommittingNavigationRequestForOrigin(
861 previously_visited_origin, navigation_request_to_exclude)) {
862 matching_site_instances.insert(spec_frame_host->GetSiteInstance());
863 }
864
865 auto* navigation_request = frame_tree_node->navigation_request();
866 if (navigation_request &&
867 navigation_request != navigation_request_to_exclude &&
868 navigation_request->HasCommittingOrigin(previously_visited_origin)) {
869 matching_site_instances.insert(frame_host->GetSiteInstance());
870 }
871 }
872
873 // Update any SiteInstances found to contain |origin|.
874 for (auto* site_instance : matching_site_instances) {
Charlie Reis37be2682023-01-10 17:04:47875 site_instance->RegisterAsDefaultOriginIsolation(previously_visited_origin);
W. James MacLeanb70fab82020-05-01 18:51:14876 }
877}
878
Charlie Reis37be2682023-01-10 17:04:47879void FrameTree::Init(SiteInstanceImpl* main_frame_site_instance,
Carlos Caballero40b0efd2021-01-26 11:55:00880 bool renderer_initiated_creation,
Rakina Zata Amniafd3c6582021-11-30 06:19:17881 const std::string& main_frame_name,
Rakina Zata Amni4eb716e2022-04-05 21:32:46882 RenderFrameHostImpl* opener_for_origin,
Danil Somsikov259aa65f2022-11-11 20:49:44883 const blink::FramePolicy& frame_policy,
884 const base::UnguessableToken& devtools_frame_token) {
Carlos Caballero40b0efd2021-01-26 11:55:00885 // blink::FrameTree::SetName always keeps |unique_name| empty in case of a
886 // main frame - let's do the same thing here.
887 std::string unique_name;
Paul Semel3e241042022-10-11 12:57:31888 root_.render_manager()->InitRoot(main_frame_site_instance,
889 renderer_initiated_creation, frame_policy,
Danil Somsikov259aa65f2022-11-11 20:49:44890 main_frame_name, devtools_frame_token);
Paul Semel3e241042022-10-11 12:57:31891 root_.SetFencedFramePropertiesIfNeeded();
Rakina Zata Amniafd3c6582021-11-30 06:19:17892
sbingler1f758842023-02-22 00:23:32893 // The initial empty document should inherit the origin (the origin may
894 // change after the first commit) and other state (such as the
895 // RuntimeFeatureStateReadContext) from its opener, except when they are in
Rakina Zata Amni4eb716e2022-04-05 21:32:46896 // different browsing context groups (`renderer_initiated_creation` will be
sbingler1f758842023-02-22 00:23:32897 // false), where it should use a new opaque origin and default values for the
898 // other state, respectively.
Rakina Zata Amniafd3c6582021-11-30 06:19:17899 // See also https://crbug.com/932067.
900 //
901 // Note that the origin of the new frame might depend on sandbox flags.
902 // Checking sandbox flags of the new frame should be safe at this point,
903 // because the flags should be already inherited when creating the root node.
Rakina Zata Amni4eb716e2022-04-05 21:32:46904 DCHECK(!renderer_initiated_creation || opener_for_origin);
Paul Semel3e241042022-10-11 12:57:31905 root_.current_frame_host()->SetOriginDependentStateOfNewFrame(
sbingler1f758842023-02-22 00:23:32906 renderer_initiated_creation ? opener_for_origin : nullptr);
Rakina Zata Amni2322f4f82022-01-24 13:24:24907
Rakina Zata Amni46087a12022-11-11 08:28:38908 controller().CreateInitialEntry();
Carlos Caballero40b0efd2021-01-26 11:55:00909}
910
Carlos Caballeroede6f8c2021-01-28 11:01:50911void FrameTree::DidAccessInitialMainDocument() {
912 OPTIONAL_TRACE_EVENT0("content", "FrameTree::DidAccessInitialDocument");
913 has_accessed_initial_main_document_ = true;
914 controller().DidAccessInitialMainDocument();
915}
916
Nate Chapin470dbc62023-04-25 16:34:38917void FrameTree::NodeLoadingStateChanged(
918 FrameTreeNode& node,
919 LoadingState previous_frame_tree_loading_state) {
920 LoadingState new_frame_tree_loading_state = GetLoadingState();
921 if (previous_frame_tree_loading_state == new_frame_tree_loading_state) {
Carlos Caballero03262522021-02-05 14:49:58922 return;
Nate Chapin470dbc62023-04-25 16:34:38923 }
Carlos Caballero03262522021-02-05 14:49:58924
Nate Chapin470dbc62023-04-25 16:34:38925 root()->render_manager()->SetIsLoading(new_frame_tree_loading_state !=
926 LoadingState::NONE);
927 delegate_->LoadingStateChanged(new_frame_tree_loading_state);
928 if (previous_frame_tree_loading_state == LoadingState::NONE) {
929 delegate_->DidStartLoading(&node);
930 } else if (new_frame_tree_loading_state == LoadingState::NONE) {
931 delegate_->DidStopLoading();
932 }
Carlos Caballero03262522021-02-05 14:49:58933}
934
Carlos Caballero03262522021-02-05 14:49:58935void FrameTree::DidCancelLoading() {
936 OPTIONAL_TRACE_EVENT0("content", "FrameTree::DidCancelLoading");
937 navigator_.controller().DiscardNonCommittedEntries();
Carlos Caballero03262522021-02-05 14:49:58938}
939
940void FrameTree::StopLoading() {
941 for (FrameTreeNode* node : Nodes())
942 node->StopLoading();
943}
944
Carlos Caballero101ac26b2021-03-24 11:54:05945void FrameTree::Shutdown() {
Dave Tapuskae88286de2021-08-05 19:10:42946 is_being_destroyed_ = true;
Carlos Caballero101ac26b2021-03-24 11:54:05947#if DCHECK_IS_ON()
948 DCHECK(!was_shut_down_);
949 was_shut_down_ = true;
950#endif
951
Paul Semel3e241042022-10-11 12:57:31952 RenderFrameHostManager* root_manager = root_.render_manager();
Carlos Caballero101ac26b2021-03-24 11:54:05953
Carlos Caballerodb7a8f6e2021-04-09 18:17:47954 if (!root_manager->current_frame_host()) {
955 // The page has been transferred out during an activation. There is little
956 // left to do.
Carlos Caballerod1c80432021-04-20 08:16:32957 // TODO(https://crbug.com/1199693): If we decide that pending delete RFHs
Carlos Caballerodb7a8f6e2021-04-09 18:17:47958 // need to be moved along during activation replace this line with a DCHECK
959 // that there are no pending delete instances.
960 root_manager->ClearRFHsPendingShutdown();
Paul Semel3e241042022-10-11 12:57:31961 DCHECK(!root_.navigation_request());
Carlos Caballerodb7a8f6e2021-04-09 18:17:47962 DCHECK(!root_manager->speculative_frame_host());
Paul Semel3e241042022-10-11 12:57:31963 manager_delegate_->OnFrameTreeNodeDestroyed(&root_);
Carlos Caballero101ac26b2021-03-24 11:54:05964 return;
Carlos Caballerodb7a8f6e2021-04-09 18:17:47965 }
Carlos Caballero101ac26b2021-03-24 11:54:05966
967 for (FrameTreeNode* node : Nodes()) {
968 // Delete all RFHs pending shutdown, which will lead the corresponding RVHs
969 // to be shutdown and be deleted as well.
970 node->render_manager()->ClearRFHsPendingShutdown();
Carlos Caballerod1c80432021-04-20 08:16:32971 // TODO(https://crbug.com/1199676): Ban WebUI instance in Prerender pages.
Carlos Caballero101ac26b2021-03-24 11:54:05972 node->render_manager()->ClearWebUIInstances();
973 }
974
975 // Destroy all subframes now. This notifies observers.
976 root_manager->current_frame_host()->ResetChildren();
Harkiran Bolaria0b3bdef02022-03-10 13:04:40977 root_manager->current_frame_host()
978 ->browsing_context_state()
979 ->ResetProxyHosts();
Carlos Caballero101ac26b2021-03-24 11:54:05980
Carlos Caballero101ac26b2021-03-24 11:54:05981 // Manually call the observer methods for the root FrameTreeNode. It is
982 // necessary to manually delete all objects tracking navigations
983 // (NavigationHandle, NavigationRequest) for observers to be properly
984 // notified of these navigations stopping before the WebContents is
985 // destroyed.
986
987 root_manager->current_frame_host()->RenderFrameDeleted();
Rakina Zata Amnif8f2bb62022-11-23 05:54:32988 root_manager->current_frame_host()->ResetOwnedNavigationRequests(
989 NavigationDiscardReason::kWillRemoveFrame);
Carlos Caballero101ac26b2021-03-24 11:54:05990
991 // Do not update state as the FrameTree::Delegate (possibly a WebContents) is
992 // being destroyed.
Paul Semel3e241042022-10-11 12:57:31993 root_.ResetNavigationRequestButKeepState();
Carlos Caballero101ac26b2021-03-24 11:54:05994 if (root_manager->speculative_frame_host()) {
Daniel Chengc3d1e8d2021-06-23 02:11:45995 root_manager->DiscardSpeculativeRenderFrameHostForShutdown();
Carlos Caballero101ac26b2021-03-24 11:54:05996 }
997
Alexander Timin8aeee642021-05-12 08:39:33998 // NavigationRequests restoring the page from bfcache have a reference to the
999 // RFHs stored in the cache, so the cache should be cleared after the
1000 // navigation request is reset.
1001 controller().GetBackForwardCache().Shutdown();
1002
Paul Semel3e241042022-10-11 12:57:311003 manager_delegate_->OnFrameTreeNodeDestroyed(&root_);
Carlos Caballero101ac26b2021-03-24 11:54:051004 render_view_delegate_->RenderViewDeleted(
1005 root_manager->current_frame_host()->render_view_host());
1006}
1007
Dave Tapuskad8b0530f2021-10-19 15:12:311008base::SafeRef<FrameTree> FrameTree::GetSafeRef() {
1009 return weak_ptr_factory_.GetSafeRef();
1010}
1011
Dave Tapuska54c76a032021-10-27 22:10:421012void FrameTree::FocusOuterFrameTrees() {
1013 OPTIONAL_TRACE_EVENT0("content", "FrameTree::FocusOuterFrameTrees");
1014
1015 FrameTree* frame_tree_to_focus = this;
1016 while (true) {
1017 FrameTreeNode* outer_node = FrameTreeNode::GloballyFindByID(
1018 frame_tree_to_focus->delegate()->GetOuterDelegateFrameTreeNodeId());
1019 if (!outer_node || !outer_node->current_frame_host()->IsActive()) {
1020 // Don't set focus on an inactive FrameTreeNode.
1021 return;
1022 }
Arthur Sonzognif6785ec2022-12-05 10:11:501023 outer_node->frame_tree().SetFocusedFrame(outer_node, nullptr);
Dave Tapuska54c76a032021-10-27 22:10:421024
1025 // For a browser initiated focus change, let embedding renderer know of the
1026 // change. Otherwise, if the currently focused element is just across a
1027 // process boundary in focus order, it will not be possible to move across
1028 // that boundary. This is because the target element will already be focused
1029 // (that renderer was not notified) and drop the event.
1030 if (auto* proxy_to_outer_delegate = frame_tree_to_focus->root()
1031 ->render_manager()
1032 ->GetProxyToOuterDelegate()) {
1033 proxy_to_outer_delegate->SetFocusedFrame();
1034 }
Arthur Sonzognif6785ec2022-12-05 10:11:501035 frame_tree_to_focus = &outer_node->frame_tree();
Dave Tapuska54c76a032021-10-27 22:10:421036 }
1037}
1038
Ari Chivukula5d15efb2023-01-21 04:33:521039void FrameTree::RegisterOriginForUnpartitionedSessionStorageAccess(
1040 const url::Origin& origin) {
1041 if (origin.opaque()) {
1042 return;
1043 }
1044 unpartitioned_session_storage_origins_.insert(origin);
1045}
1046
Ari Chivukula9a96a582023-02-03 21:02:291047void FrameTree::UnregisterOriginForUnpartitionedSessionStorageAccess(
1048 const url::Origin& origin) {
1049 unpartitioned_session_storage_origins_.erase(origin);
1050}
1051
Ari Chivukula5d15efb2023-01-21 04:33:521052const blink::StorageKey FrameTree::GetSessionStorageKey(
1053 const blink::StorageKey& storage_key) {
1054 if (unpartitioned_session_storage_origins_.find(storage_key.origin()) !=
1055 unpartitioned_session_storage_origins_.end()) {
1056 // If the storage key matches a participating origin we need to return the
1057 // first-party version for use in binding session storage.
Ari Chivukulac81e13e2023-02-15 20:44:571058 return blink::StorageKey::CreateFirstParty(storage_key.origin());
Ari Chivukula5d15efb2023-01-21 04:33:521059 }
1060 return storage_key;
1061}
1062
[email protected]9b159a52013-10-03 17:24:551063} // namespace content