blob: d2360afc2f412071fe82d73ac0dd82cc5244b463 [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
Peter Kasting1557e5f2025-01-28 01:14:089#include <algorithm>
[email protected]9b159a52013-10-03 17:24:5510#include <queue>
Lukasz Anforowicz7bfb2e92017-11-22 17:19:4511#include <set>
dcheng29f5a6c2015-08-31 21:43:2712#include <utility>
[email protected]9b159a52013-10-03 17:24:5513
Lei Zhangde197672021-04-29 08:11:2414#include "base/containers/contains.h"
Lei Zhang302bc3fa2025-06-04 20:10:3415#include "base/debug/crash_logging.h"
Rakina Zata Amni80700402021-09-20 17:18:0316#include "base/debug/dump_without_crashing.h"
Avi Drissmanadac21992023-01-11 23:46:3917#include "base/functional/bind.h"
18#include "base/functional/callback.h"
[email protected]20edca72014-08-14 10:27:5319#include "base/lazy_instance.h"
dcheng9bfa5162016-04-09 01:00:5720#include "base/memory/ptr_util.h"
Ali Hijazie63cbaf62023-12-20 19:29:3521#include "base/memory/raw_ptr.h"
Peilin Wang427aa6a2023-03-22 17:58:3322#include "base/memory/safe_ref.h"
Thomas Lukaszewicz0ef0f45f2025-02-18 17:59:4223#include "base/metrics/histogram_functions.h"
Carlos Caballeroede6f8c2021-01-28 11:01:5024#include "base/trace_event/optional_trace_event.h"
Rakina Zata Amni4b1968d2021-09-09 03:29:4725#include "base/trace_event/typed_macros.h"
Peter Kasting3b811ffd2025-01-29 22:20:1626#include "base/types/cxx23_from_range.h"
Pavel Feldman25234722017-10-11 02:49:0627#include "base/unguessable_token.h"
Peilin Wang427aa6a2023-03-22 17:58:3328#include "content/browser/renderer_host/batched_proxy_ipc_sender.h"
danakjc492bf82020-09-09 20:02:4429#include "content/browser/renderer_host/navigation_controller_impl.h"
30#include "content/browser/renderer_host/navigation_entry_impl.h"
31#include "content/browser/renderer_host/navigation_request.h"
32#include "content/browser/renderer_host/navigator.h"
33#include "content/browser/renderer_host/navigator_delegate.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1534#include "content/browser/renderer_host/page_impl.h"
Kevin McNee5f594382021-05-06 23:18:2335#include "content/browser/renderer_host/render_frame_host_delegate.h"
danakjc492bf82020-09-09 20:02:4436#include "content/browser/renderer_host/render_frame_host_factory.h"
37#include "content/browser/renderer_host/render_frame_host_impl.h"
38#include "content/browser/renderer_host/render_frame_proxy_host.h"
Carlos Caballero101ac26b2021-03-24 11:54:0539#include "content/browser/renderer_host/render_view_host_delegate.h"
[email protected]94d0cc12013-12-18 00:07:4140#include "content/browser/renderer_host/render_view_host_factory.h"
41#include "content/browser/renderer_host/render_view_host_impl.h"
Sharon Yang7ce309e2023-01-19 21:39:5742#include "content/common/content_navigation_policy.h"
japhet98e9bd82016-06-28 23:48:4543#include "content/common/content_switches_internal.h"
Peilin Wang427aa6a2023-03-22 17:58:3344#include "content/common/features.h"
Tom Sepezcc69c442025-07-17 02:00:3045#include "ipc/constants.mojom.h"
Sreeja Kamishetty46f762c2021-02-05 07:52:4646#include "third_party/blink/public/common/features.h"
Kevin McNee43fe8292021-10-04 22:59:4147#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
Blink Reformata30d4232018-04-07 15:31:0648#include "third_party/blink/public/common/frame/frame_policy.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1549#include "third_party/blink/public/common/loader/loader_constants.h"
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:5450#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
[email protected]9b159a52013-10-03 17:24:5551
52namespace content {
53
54namespace {
[email protected]20edca72014-08-14 10:27:5355
Rakina Zata Amni4b1968d2021-09-09 03:29:4756using perfetto::protos::pbzero::ChromeTrackEvent;
57
Sharon Yangefe52632022-03-08 23:06:0658// Helper function to collect SiteInstanceGroups involved in rendering a single
59// FrameTree (which is a subset of SiteInstanceGroups in main frame's
60// proxy_hosts_ because of openers).
61std::set<SiteInstanceGroup*> CollectSiteInstanceGroups(FrameTree* tree) {
62 std::set<SiteInstanceGroup*> groups;
Adithya Srinivasan0e9808342022-12-13 18:25:0763 for (FrameTreeNode* node : tree->Nodes())
Sharon Yangefe52632022-03-08 23:06:0664 groups.insert(node->current_frame_host()->GetSiteInstance()->group());
65 return groups;
alexmos3fcd0ca2015-10-23 18:18:3366}
67
Kevin McNee5f594382021-05-06 23:18:2368// If |node| is the placeholder FrameTreeNode for an embedded frame tree,
69// returns the inner tree's main frame's FrameTreeNode. Otherwise, returns null.
70FrameTreeNode* GetInnerTreeMainFrameNode(FrameTreeNode* node) {
Dominic Farolino377edb302021-07-29 05:57:1871 FrameTreeNode* inner_main_frame_tree_node = FrameTreeNode::GloballyFindByID(
72 node->current_frame_host()->inner_tree_main_frame_tree_node_id());
Kevin McNee5f594382021-05-06 23:18:2373
Kevin McNeed459ad42022-09-12 19:24:5974 if (inner_main_frame_tree_node) {
Arthur Sonzognif6785ec2022-12-05 10:11:5075 DCHECK_NE(&node->frame_tree(), &inner_main_frame_tree_node->frame_tree());
Kevin McNee5f594382021-05-06 23:18:2376 }
77
Kevin McNeed459ad42022-09-12 19:24:5978 return inner_main_frame_tree_node;
Kevin McNee5f594382021-05-06 23:18:2379}
80
[email protected]9b159a52013-10-03 17:24:5581} // namespace
82
vmpstr33895d992016-02-24 20:55:2183FrameTree::NodeIterator::NodeIterator(const NodeIterator& other) = default;
84
Fergal Daly55b6d722020-09-11 07:56:3385FrameTree::NodeIterator::~NodeIterator() = default;
dcheng57e39e22016-01-21 00:25:3886
87FrameTree::NodeIterator& FrameTree::NodeIterator::operator++() {
Alex Moshchuk27caae82017-09-11 23:11:1888 if (current_node_ != root_of_subtree_to_skip_) {
Jayson Adams4db0bfe22021-07-15 19:24:0789 // Reserve enough space in the queue to accommodate the nodes we're
90 // going to add, to avoid repeated resize calls.
91 queue_.reserve(queue_.size() + current_node_->child_count());
92
Alex Moshchuk27caae82017-09-11 23:11:1893 for (size_t i = 0; i < current_node_->child_count(); ++i) {
94 FrameTreeNode* child = current_node_->child_at(i);
Kevin McNee5f594382021-05-06 23:18:2395 FrameTreeNode* inner_tree_main_ftn = GetInnerTreeMainFrameNode(child);
Dave Tapuskadda303d2022-10-04 16:56:4896 if (should_descend_into_inner_trees_ && inner_tree_main_ftn) {
97 if (include_delegate_nodes_for_inner_frame_trees_)
98 queue_.push_back(child);
99 queue_.push_back(inner_tree_main_ftn);
100 } else {
101 queue_.push_back(child);
102 }
Kevin McNee5f594382021-05-06 23:18:23103 }
104
105 if (should_descend_into_inner_trees_) {
Jayson Adams4db0bfe22021-07-15 19:24:07106 auto unattached_nodes =
107 current_node_->current_frame_host()
108 ->delegate()
109 ->GetUnattachedOwnedNodes(current_node_->current_frame_host());
110
111 // Reserve enough space in the queue to accommodate the nodes we're
112 // going to add.
113 queue_.reserve(queue_.size() + unattached_nodes.size());
114
115 for (auto* unattached_node : unattached_nodes) {
116 queue_.push_back(unattached_node);
Kevin McNee5f594382021-05-06 23:18:23117 }
Alex Moshchuk27caae82017-09-11 23:11:18118 }
dcheng57e39e22016-01-21 00:25:38119 }
120
Kevin McNee5f594382021-05-06 23:18:23121 AdvanceNode();
122 return *this;
123}
dcheng57e39e22016-01-21 00:25:38124
Kevin McNee5f594382021-05-06 23:18:23125FrameTree::NodeIterator& FrameTree::NodeIterator::AdvanceSkippingChildren() {
126 AdvanceNode();
dcheng57e39e22016-01-21 00:25:38127 return *this;
128}
129
130bool FrameTree::NodeIterator::operator==(const NodeIterator& rhs) const {
131 return current_node_ == rhs.current_node_;
132}
133
Kevin McNee5f594382021-05-06 23:18:23134void FrameTree::NodeIterator::AdvanceNode() {
135 if (!queue_.empty()) {
136 current_node_ = queue_.front();
Jayson Adams4db0bfe22021-07-15 19:24:07137 queue_.pop_front();
Kevin McNee5f594382021-05-06 23:18:23138 } else {
139 current_node_ = nullptr;
140 }
141}
142
143FrameTree::NodeIterator::NodeIterator(
Ali Hijazie63cbaf62023-12-20 19:29:35144 const std::vector<raw_ptr<FrameTreeNode, VectorExperimental>>&
145 starting_nodes,
Kevin McNee5f594382021-05-06 23:18:23146 const FrameTreeNode* root_of_subtree_to_skip,
Dave Tapuskadda303d2022-10-04 16:56:48147 bool should_descend_into_inner_trees,
148 bool include_delegate_nodes_for_inner_frame_trees)
Kevin McNee5f594382021-05-06 23:18:23149 : current_node_(nullptr),
150 root_of_subtree_to_skip_(root_of_subtree_to_skip),
151 should_descend_into_inner_trees_(should_descend_into_inner_trees),
Dave Tapuskadda303d2022-10-04 16:56:48152 include_delegate_nodes_for_inner_frame_trees_(
153 include_delegate_nodes_for_inner_frame_trees),
Alan Zhaoadbc4f72024-11-08 01:59:36154 queue_(base::from_range, starting_nodes) {
Dave Tapuskadda303d2022-10-04 16:56:48155 // If `include_delegate_nodes_for_inner_frame_trees_` is true then
156 // `should_descend_into_inner_trees_` must be true.
157 DCHECK(!include_delegate_nodes_for_inner_frame_trees_ ||
158 should_descend_into_inner_trees_);
Kevin McNee5f594382021-05-06 23:18:23159 AdvanceNode();
160}
dcheng57e39e22016-01-21 00:25:38161
162FrameTree::NodeIterator FrameTree::NodeRange::begin() {
W. James MacLeance3176d2019-10-18 04:01:45163 // We shouldn't be attempting a frame tree traversal while the tree is
Kevin McNee5f594382021-05-06 23:18:23164 // being constructed or destructed.
Peter Kasting1557e5f2025-01-28 01:14:08165 DCHECK(std::ranges::all_of(starting_nodes_, [](FrameTreeNode* ftn) {
Peter Kastingd5685942022-09-02 17:52:17166 return ftn->current_frame_host();
167 }));
Kevin McNee5f594382021-05-06 23:18:23168
169 return NodeIterator(starting_nodes_, root_of_subtree_to_skip_,
Dave Tapuskadda303d2022-10-04 16:56:48170 should_descend_into_inner_trees_,
171 include_delegate_nodes_for_inner_frame_trees_);
dcheng57e39e22016-01-21 00:25:38172}
173
174FrameTree::NodeIterator FrameTree::NodeRange::end() {
Dave Tapuskadda303d2022-10-04 16:56:48175 return NodeIterator({}, nullptr, should_descend_into_inner_trees_,
176 include_delegate_nodes_for_inner_frame_trees_);
dcheng57e39e22016-01-21 00:25:38177}
178
Kevin McNee5f594382021-05-06 23:18:23179FrameTree::NodeRange::NodeRange(
Ali Hijazie63cbaf62023-12-20 19:29:35180 const std::vector<raw_ptr<FrameTreeNode, VectorExperimental>>&
181 starting_nodes,
Kevin McNee5f594382021-05-06 23:18:23182 const FrameTreeNode* root_of_subtree_to_skip,
Dave Tapuskadda303d2022-10-04 16:56:48183 bool should_descend_into_inner_trees,
184 bool include_delegate_nodes_for_inner_frame_trees)
Kevin McNee5f594382021-05-06 23:18:23185 : starting_nodes_(starting_nodes),
186 root_of_subtree_to_skip_(root_of_subtree_to_skip),
Dave Tapuskadda303d2022-10-04 16:56:48187 should_descend_into_inner_trees_(should_descend_into_inner_trees),
188 include_delegate_nodes_for_inner_frame_trees_(
189 include_delegate_nodes_for_inner_frame_trees) {}
Kevin McNee5f594382021-05-06 23:18:23190
191FrameTree::NodeRange::NodeRange(const NodeRange&) = default;
192FrameTree::NodeRange::~NodeRange() = default;
dcheng57e39e22016-01-21 00:25:38193
Carlos Caballero40b0efd2021-01-26 11:55:00194FrameTree::FrameTree(
195 BrowserContext* browser_context,
Carlos Caballero03262522021-02-05 14:49:58196 Delegate* delegate,
Carlos Caballero40b0efd2021-01-26 11:55:00197 NavigationControllerDelegate* navigation_controller_delegate,
198 NavigatorDelegate* navigator_delegate,
199 RenderFrameHostDelegate* render_frame_delegate,
200 RenderViewHostDelegate* render_view_delegate,
201 RenderWidgetHostDelegate* render_widget_delegate,
Sreeja Kamishetty837a10402021-04-23 12:41:59202 RenderFrameHostManager::Delegate* manager_delegate,
Jeremy Roman2d8dfe132021-07-06 20:51:26203 PageDelegate* page_delegate,
Danil Somsikov259aa65f2022-11-11 20:49:44204 Type type)
Carlos Caballero03262522021-02-05 14:49:58205 : delegate_(delegate),
206 render_frame_delegate_(render_frame_delegate),
[email protected]92404c62013-12-04 16:40:46207 render_view_delegate_(render_view_delegate),
[email protected]fa944cb82013-11-15 17:51:21208 render_widget_delegate_(render_widget_delegate),
209 manager_delegate_(manager_delegate),
Jeremy Roman2d8dfe132021-07-06 20:51:26210 page_delegate_(page_delegate),
Carlos Caballero40b0efd2021-01-26 11:55:00211 navigator_(browser_context,
212 *this,
213 navigator_delegate,
214 navigation_controller_delegate),
Harkiran Bolaria16f2c48d2022-04-22 12:39:57215 type_(type),
Arthur Sonzognif6785ec2022-12-05 10:11:50216 root_(*this,
Paul Semel3e241042022-10-11 12:57:31217 nullptr,
218 // The top-level frame must always be in a
219 // document scope.
220 blink::mojom::TreeScopeType::kDocument,
221 false,
Paul Semel3e241042022-10-11 12:57:31222 blink::mojom::FrameOwnerProperties(),
223 blink::FrameOwnerElementType::kNone,
224 blink::FramePolicy()) {}
[email protected]9b159a52013-10-03 17:24:55225
226FrameTree::~FrameTree() {
Takashi Toyoshimaea534ef22021-07-21 03:27:59227 is_being_destroyed_ = true;
Carlos Caballero101ac26b2021-03-24 11:54:05228#if DCHECK_IS_ON()
229 DCHECK(was_shut_down_);
230#endif
[email protected]9b159a52013-10-03 17:24:55231}
232
Sharon Yanged884542023-02-02 17:33:44233void FrameTree::ForEachRenderViewHost(
234 base::FunctionRef<void(RenderViewHostImpl*)> on_host) {
235 if (speculative_render_view_host_) {
236 on_host(speculative_render_view_host_.get());
237 }
238
239 for (auto& rvh : render_view_host_map_) {
240 on_host(rvh.second);
241 }
242}
243
Sharon Yang7ce309e2023-01-19 21:39:57244void FrameTree::MakeSpeculativeRVHCurrent() {
245 CHECK(speculative_render_view_host_);
246
247 // The existing RenderViewHost needs to be unregistered first.
248 // Speculative RenderViewHosts are only used for same-SiteInstanceGroup
249 // navigations, so there should be a RenderViewHost of the same
250 // SiteInstanceGroup already in the tree.
251 RenderViewHostMapId speculative_id =
252 speculative_render_view_host_->rvh_map_id();
253 auto it = render_view_host_map_.find(speculative_id);
254 CHECK(it != render_view_host_map_.end());
255 UnregisterRenderViewHost(speculative_id, it->second);
256
257 speculative_render_view_host_->set_is_speculative(false);
258 RegisterRenderViewHost(speculative_id, speculative_render_view_host_.get());
259 speculative_render_view_host_.reset();
260}
261
Avi Drissmanbd153642024-09-03 18:58:05262FrameTreeNode* FrameTree::FindByID(FrameTreeNodeId frame_tree_node_id) {
dcheng57e39e22016-01-21 00:25:38263 for (FrameTreeNode* node : Nodes()) {
264 if (node->frame_tree_node_id() == frame_tree_node_id)
265 return node;
266 }
267 return nullptr;
[email protected]9b159a52013-10-03 17:24:55268}
269
nasko479ea5a2015-02-14 00:03:04270FrameTreeNode* FrameTree::FindByRoutingID(int process_id, int routing_id) {
dmazzoni0b5d2482014-09-10 19:45:57271 RenderFrameHostImpl* render_frame_host =
272 RenderFrameHostImpl::FromID(process_id, routing_id);
273 if (render_frame_host) {
274 FrameTreeNode* result = render_frame_host->frame_tree_node();
Arthur Sonzognif6785ec2022-12-05 10:11:50275 if (this == &result->frame_tree())
dmazzoni0b5d2482014-09-10 19:45:57276 return result;
277 }
278
279 RenderFrameProxyHost* render_frame_proxy_host =
280 RenderFrameProxyHost::FromID(process_id, routing_id);
281 if (render_frame_proxy_host) {
282 FrameTreeNode* result = render_frame_proxy_host->frame_tree_node();
Arthur Sonzognif6785ec2022-12-05 10:11:50283 if (this == &result->frame_tree())
dmazzoni0b5d2482014-09-10 19:45:57284 return result;
285 }
286
creis6a93a812015-04-24 23:13:17287 return nullptr;
288}
289
290FrameTreeNode* FrameTree::FindByName(const std::string& name) {
291 if (name.empty())
Paul Semel3e241042022-10-11 12:57:31292 return &root_;
creis6a93a812015-04-24 23:13:17293
dcheng57e39e22016-01-21 00:25:38294 for (FrameTreeNode* node : Nodes()) {
295 if (node->frame_name() == name)
296 return node;
[email protected]9b159a52013-10-03 17:24:55297 }
dcheng57e39e22016-01-21 00:25:38298
299 return nullptr;
300}
301
302FrameTree::NodeRange FrameTree::Nodes() {
Alex Moshchuk27caae82017-09-11 23:11:18303 return NodesExceptSubtree(nullptr);
dcheng57e39e22016-01-21 00:25:38304}
305
kenrb61b6c252016-03-22 17:37:15306FrameTree::NodeRange FrameTree::SubtreeNodes(FrameTreeNode* subtree_root) {
Kevin McNee5f594382021-05-06 23:18:23307 return NodeRange({subtree_root}, nullptr,
Dave Tapuskadda303d2022-10-04 16:56:48308 /*should_descend_into_inner_trees=*/false,
309 /*include_delegate_nodes_for_inner_frame_trees=*/false);
Kevin McNee5f594382021-05-06 23:18:23310}
311
Kevin McNee53f0b2d2021-11-02 18:00:45312FrameTree::NodeRange FrameTree::NodesIncludingInnerTreeNodes() {
Paul Semel3e241042022-10-11 12:57:31313 return NodeRange({&root_}, nullptr,
Dave Tapuskadda303d2022-10-04 16:56:48314 /*should_descend_into_inner_trees=*/true,
315 /*include_delegate_nodes_for_inner_frame_trees=*/false);
Kevin McNee53f0b2d2021-11-02 18:00:45316}
317
Sreeja Kamishettyd64b993d2022-02-14 12:04:42318std::vector<FrameTreeNode*> FrameTree::CollectNodesForIsLoading() {
319 FrameTree::NodeRange node_range = NodesIncludingInnerTreeNodes();
320 FrameTree::NodeIterator node_iter = node_range.begin();
321 std::vector<FrameTreeNode*> nodes;
322
Daniel Cheng4d54f0a2025-05-26 22:59:12323 CHECK(node_iter != node_range.end());
Arthur Sonzognif6785ec2022-12-05 10:11:50324 FrameTree* root_loading_tree = root_.frame_tree().LoadingTree();
Sreeja Kamishettyd64b993d2022-02-14 12:04:42325 while (node_iter != node_range.end()) {
326 // Skip over frame trees and children which belong to inner web contents
327 // i.e., when nodes doesn't point to the same loading frame tree.
Arthur Sonzognif6785ec2022-12-05 10:11:50328 if ((*node_iter)->frame_tree().LoadingTree() != root_loading_tree) {
Sreeja Kamishettyd64b993d2022-02-14 12:04:42329 node_iter.AdvanceSkippingChildren();
330 } else {
331 nodes.push_back(*node_iter);
332 ++node_iter;
333 }
334 }
335 return nodes;
336}
337
Kevin McNee5f594382021-05-06 23:18:23338FrameTree::NodeRange FrameTree::SubtreeAndInnerTreeNodes(
Dave Tapuskadda303d2022-10-04 16:56:48339 RenderFrameHostImpl* parent,
340 bool include_delegate_nodes_for_inner_frame_trees) {
Ali Hijazie63cbaf62023-12-20 19:29:35341 std::vector<raw_ptr<FrameTreeNode, VectorExperimental>> starting_nodes;
Kevin McNee5f594382021-05-06 23:18:23342 starting_nodes.reserve(parent->child_count());
343 for (size_t i = 0; i < parent->child_count(); ++i) {
344 FrameTreeNode* child = parent->child_at(i);
345 FrameTreeNode* inner_tree_main_ftn = GetInnerTreeMainFrameNode(child);
Dave Tapuskadda303d2022-10-04 16:56:48346 if (inner_tree_main_ftn) {
347 if (include_delegate_nodes_for_inner_frame_trees)
348 starting_nodes.push_back(child);
349 starting_nodes.push_back(inner_tree_main_ftn);
350 } else {
351 starting_nodes.push_back(child);
352 }
Kevin McNee5f594382021-05-06 23:18:23353 }
354 const std::vector<FrameTreeNode*> unattached_owned_nodes =
355 parent->delegate()->GetUnattachedOwnedNodes(parent);
356 starting_nodes.insert(starting_nodes.end(), unattached_owned_nodes.begin(),
357 unattached_owned_nodes.end());
358 return NodeRange(starting_nodes, nullptr,
Dave Tapuskadda303d2022-10-04 16:56:48359 /* should_descend_into_inner_trees */ true,
360 include_delegate_nodes_for_inner_frame_trees);
kenrb61b6c252016-03-22 17:37:15361}
362
Alex Moshchuk27caae82017-09-11 23:11:18363FrameTree::NodeRange FrameTree::NodesExceptSubtree(FrameTreeNode* node) {
Paul Semel3e241042022-10-11 12:57:31364 return NodeRange({&root_}, node, /*should_descend_into_inner_trees=*/false,
Dave Tapuskadda303d2022-10-04 16:56:48365 /*include_delegate_nodes_for_inner_frame_trees=*/false);
[email protected]9b159a52013-10-03 17:24:55366}
367
Sreeja Kamishettyd64b993d2022-02-14 12:04:42368FrameTree* FrameTree::LoadingTree() {
369 // We return the delegate's loading frame tree to infer loading related
370 // states.
371 return delegate_->LoadingTree();
372}
373
Lucas Furukawa Gadani99125822019-01-03 15:41:49374FrameTreeNode* FrameTree::AddFrame(
Alexander Timin381e7e182020-04-28 19:04:03375 RenderFrameHostImpl* parent,
Balazs Engedyba034e72017-10-27 22:26:28376 int process_id,
377 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18378 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
Oksana Zhuravlovafee097c2019-07-26 17:01:30379 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
380 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30381 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
Dominic Farolino12e06d72022-08-05 02:29:49382 mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterfaceProvider>
383 associated_interface_provider_receiver,
Antonio Gomes9d5c1ef2020-04-30 20:56:41384 blink::mojom::TreeScopeType scope,
Balazs Engedyba034e72017-10-27 22:26:28385 const std::string& frame_name,
386 const std::string& frame_unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45387 bool is_created_by_script,
Chris Hamilton3ff6ed0e2021-02-19 03:54:04388 const blink::LocalFrameToken& frame_token,
Balazs Engedyba034e72017-10-27 22:26:28389 const base::UnguessableToken& devtools_frame_token,
Daniel Cheng284c38942022-09-22 23:30:34390 const blink::DocumentToken& document_token,
Luna Luc3fdacdf2017-11-08 04:48:53391 const blink::FramePolicy& frame_policy,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54392 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Ehsan Karamad192a8da2018-10-21 03:48:08393 bool was_discarded,
Kevin McNee43fe8292021-10-04 22:59:41394 blink::FrameOwnerElementType owner_type,
395 bool is_dummy_frame_for_inner_tree) {
Tom Sepezcc69c442025-07-17 02:00:30396 CHECK_NE(new_routing_id, IPC::mojom::kRoutingIdNone);
Jeremy Romanc0c69be2023-11-21 19:14:52397 // Normally this path is for blink adding a child local frame. But fenced
398 // frames add a dummy child frame that never gets a corresponding
399 // RenderFrameImpl in any renderer process, and therefore its `frame_remote`
400 // is invalid. Also its RenderFrameHostImpl is exempt from having
401 // `RenderFrameCreated()` called on it (see later in this method, as well as
402 // `WebContentsObserverConsistencyChecker::RenderFrameHostChanged()`).
Kevin McNee43fe8292021-10-04 22:59:41403 DCHECK_NE(frame_remote.is_valid(), is_dummy_frame_for_inner_tree);
404 DCHECK_NE(browser_interface_broker_receiver.is_valid(),
405 is_dummy_frame_for_inner_tree);
Dominic Farolino12e06d72022-08-05 02:29:49406 DCHECK_NE(associated_interface_provider_receiver.is_valid(),
407 is_dummy_frame_for_inner_tree);
nick8814e652015-12-18 01:44:12408
dgroganfb22f9a2014-10-20 21:32:32409 // A child frame always starts with an initial empty document, which means
410 // it is in the same SiteInstance as the parent frame. Ensure that the process
411 // which requested a child frame to be added is the same as the process of the
412 // parent node.
Emily Andrewsd15fd762024-12-10 20:41:54413 CHECK_EQ(parent->GetProcess()->GetDeprecatedID(), process_id);
dgroganfb22f9a2014-10-20 21:32:32414
Danil Somsikov259aa65f2022-11-11 20:49:44415 std::unique_ptr<FrameTreeNode> new_node = base::WrapUnique(
Arthur Sonzognif6785ec2022-12-05 10:11:50416 new FrameTreeNode(*this, parent, scope, is_created_by_script,
Danil Somsikov259aa65f2022-11-11 20:49:44417 frame_owner_properties, owner_type, frame_policy));
iclelland098da752017-06-28 13:46:50418
419 // Set sandbox flags and container policy and make them effective immediately,
Charlie Hu5130d25e2021-03-05 21:53:39420 // since initial sandbox flags and permissions policy should apply to the
421 // initial empty document in the frame. This needs to happen before the call
422 // to AddChild so that the effective policy is sent to any newly-created
Dave Tapuska2402595f2022-08-03 16:24:21423 // `blink::RemoteFrame` objects when the RenderFrameHost is created.
Charlie Hu5ffc0152019-12-06 15:59:53424 // SetPendingFramePolicy is necessary here because next navigation on this
425 // frame will need the value of pending frame policy instead of effective
426 // frame policy.
Ian Clellandcdc4f312017-10-13 22:24:12427 new_node->SetPendingFramePolicy(frame_policy);
iclelland098da752017-06-28 13:46:50428
Shubhie Panickerddf2a4e2018-03-06 00:09:06429 if (was_discarded)
430 new_node->set_was_discarded();
431
iclelland098da752017-06-28 13:46:50432 // Add the new node to the FrameTree, creating the RenderFrameHost.
Harkiran Bolaria0b3bdef02022-03-10 13:04:40433 FrameTreeNode* added_node = parent->AddChild(
434 std::move(new_node), new_routing_id, std::move(frame_remote), frame_token,
Danil Somsikov259aa65f2022-11-11 20:49:44435 document_token, devtools_frame_token, frame_policy, frame_name,
436 frame_unique_name);
nick8814e652015-12-18 01:44:12437
Garrett Tanzer34cb92fe2022-09-28 17:50:54438 added_node->SetFencedFramePropertiesIfNeeded();
shivanigithub4cd016a2021-09-20 21:10:30439
Kevin McNee43fe8292021-10-04 22:59:41440 if (browser_interface_broker_receiver.is_valid()) {
441 added_node->current_frame_host()->BindBrowserInterfaceBrokerReceiver(
442 std::move(browser_interface_broker_receiver));
443 }
Oksana Zhuravlovafee097c2019-07-26 17:01:30444
Antonio Sartoridb967c52021-01-20 09:54:30445 if (policy_container_bind_params) {
Antonio Sartoria1fd1432020-11-25 09:10:20446 added_node->current_frame_host()->policy_container_host()->Bind(
Antonio Sartoridb967c52021-01-20 09:54:30447 std::move(policy_container_bind_params));
Antonio Sartoria1fd1432020-11-25 09:10:20448 }
449
Dominic Farolino12e06d72022-08-05 02:29:49450 if (associated_interface_provider_receiver.is_valid()) {
451 added_node->current_frame_host()->BindAssociatedInterfaceProviderReceiver(
452 std::move(associated_interface_provider_receiver));
453 }
454
nasko03ecfad2016-08-02 00:54:06455 // The last committed NavigationEntry may have a FrameNavigationEntry with the
456 // same |frame_unique_name|, since we don't remove FrameNavigationEntries if
457 // their frames are deleted. If there is a stale one, remove it to avoid
458 // conflicts on future updates.
Fergal Daly09d6c762020-05-29 02:05:18459 NavigationEntryImpl* last_committed_entry = static_cast<NavigationEntryImpl*>(
Carlos Caballero40b0efd2021-01-26 11:55:00460 navigator_.controller().GetLastCommittedEntry());
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45461 if (last_committed_entry) {
462 last_committed_entry->RemoveEntryForFrame(
463 added_node, /* only_if_different_position = */ true);
464 }
nasko03ecfad2016-08-02 00:54:06465
nick8814e652015-12-18 01:44:12466 // Now that the new node is part of the FrameTree and has a RenderFrameHost,
467 // we can announce the creation of the initial RenderFrame which already
468 // exists in the renderer process.
Sreeja Kamishetty5b699622021-01-22 12:54:08469 // For consistency with navigating to a new RenderFrameHost case, we dispatch
470 // RenderFrameCreated before RenderFrameHostChanged.
Kevin McNee43fe8292021-10-04 22:59:41471 if (!is_dummy_frame_for_inner_tree) {
Jeremy Romanc0c69be2023-11-21 19:14:52472 // The outer dummy FrameTreeNode for fenced frames does not have a live
473 // RenderFrame in the renderer process.
Fergal Dalyf9ea35c2020-12-11 15:26:01474 added_node->current_frame_host()->RenderFrameCreated();
Ehsan Karamad44fc72112019-02-26 18:15:47475 }
Sreeja Kamishetty5b699622021-01-22 12:54:08476
477 // Notify the delegate of the creation of the current RenderFrameHost.
478 // This is only for subframes, as the main frame case is taken care of by
479 // WebContentsImpl::Init.
480 manager_delegate_->NotifySwappedFromRenderManager(
Dave Tapuskae45d6fd2021-09-29 17:03:59481 nullptr, added_node->current_frame_host());
Lucas Furukawa Gadani99125822019-01-03 15:41:49482 return added_node;
[email protected]9b159a52013-10-03 17:24:55483}
484
[email protected]58faf942014-02-20 21:03:58485void FrameTree::RemoveFrame(FrameTreeNode* child) {
Alexander Timin381e7e182020-04-28 19:04:03486 RenderFrameHostImpl* parent = child->parent();
[email protected]58faf942014-02-20 21:03:58487 if (!parent) {
Peter Boströmfc7ddc182024-10-31 19:37:21488 NOTREACHED() << "Unexpected RemoveFrame call for main frame.";
[email protected]9b159a52013-10-03 17:24:55489 }
490
Alexander Timin381e7e182020-04-28 19:04:03491 parent->RemoveChild(child);
[email protected]9b159a52013-10-03 17:24:55492}
493
Sharon Yangdcc5f252024-05-09 18:27:23494void FrameTree::CreateProxiesForSiteInstanceGroup(
Harkiran Bolaria2912a6b32022-02-22 16:43:45495 FrameTreeNode* source,
Sharon Yangdcc5f252024-05-09 18:27:23496 SiteInstanceGroup* site_instance_group,
Harkiran Bolaria2912a6b32022-02-22 16:43:45497 const scoped_refptr<BrowsingContextState>&
Alex Moshchukd0d759c22025-05-09 18:18:35498 source_new_browsing_context_state,
499 const std::optional<base::UnguessableToken>& navigation_metrics_token) {
Peilin Wangfc543212024-03-27 16:17:21500 // Will be instantiated with the root proxy later and passed to
501 // `CreateRenderFrameProxy()` to batch create proxies for child frames.
Peilin Wang427aa6a2023-03-22 17:58:33502 std::unique_ptr<BatchedProxyIPCSender> batched_proxy_ipc_sender;
503
alexmos58729042015-06-18 23:20:00504 if (!source || !source->IsMainFrame()) {
Sharon Yangdcc5f252024-05-09 18:27:23505 RenderViewHostImpl* render_view_host =
506 GetRenderViewHost(site_instance_group).get();
arthursonzognic5be3842019-07-09 11:49:14507 if (render_view_host) {
Sharon Yangdcc5f252024-05-09 18:27:23508 root()->render_manager()->EnsureRenderViewInitialized(
Alex Moshchukd0d759c22025-05-09 18:18:35509 render_view_host, site_instance_group, navigation_metrics_token);
arthursonzognic5be3842019-07-09 11:49:14510 } else {
Harkiran Bolaria2912a6b32022-02-22 16:43:45511 // Due to the check above, we are creating either an opener proxy (when
512 // source is null) or a main frame proxy due to a subframe navigation
513 // (when source is not a main frame). In the former case, we should use
514 // root's current BrowsingContextState, while in the latter case we should
515 // use BrowsingContextState from the main RenderFrameHost of the subframe
Dave Tapuska2cf1f532022-08-10 15:30:49516 // being navigated. We want to ensure that the `blink::WebView` is created
Sharon Yangdcc5f252024-05-09 18:27:23517 // in the right SiteInstanceGroup if it doesn't exist, before creating the
Dave Tapuska2cf1f532022-08-10 15:30:49518 // other proxies; if the `blink::WebView` doesn't exist, the only way to
519 // do this is to also create a proxy for the main frame as well.
Peilin Wang427aa6a2023-03-22 17:58:33520 const scoped_refptr<BrowsingContextState>& root_browsing_context_state =
Harkiran Bolaria2912a6b32022-02-22 16:43:45521 source ? source->parent()->GetMainFrame()->browsing_context_state()
Peilin Wang427aa6a2023-03-22 17:58:33522 : root()->current_frame_host()->browsing_context_state();
523
Alison Gale770f3fc2024-04-27 00:39:58524 // TODO(crbug.com/40248300): Batch main frame proxy creation and
Peilin Wang427aa6a2023-03-22 17:58:33525 // pass an instance of `BatchedProxyIPCSender` here instead of nullptr.
526 root()->render_manager()->CreateRenderFrameProxy(
Sharon Yangdcc5f252024-05-09 18:27:23527 site_instance_group, root_browsing_context_state,
Alex Moshchukd0d759c22025-05-09 18:18:35528 navigation_metrics_token,
Peilin Wang427aa6a2023-03-22 17:58:33529 /*batched_proxy_ipc_sender=*/nullptr);
530
531 // We only need to use `BatchedProxyIPCSender` when navigating to a new
Sharon Yangdcc5f252024-05-09 18:27:23532 // SiteInstanceGroup. Proxies do not need to be created when navigating to
533 // a SiteInstanceGroup that has already been encountered, because site
Peilin Wang427aa6a2023-03-22 17:58:33534 // isolation would guarantee that all nodes already have either proxies
535 // or real frames. Due to the check above, the `render_view_host` does
Sharon Yangdcc5f252024-05-09 18:27:23536 // not exist here, which means we have not seen this SiteInstanceGroup
Peilin Wang427aa6a2023-03-22 17:58:33537 // before, so we instantiate `batched_proxy_ipc_sender` to consolidate
538 // IPCs for proxy creation.
Peilin Wangfc543212024-03-27 16:17:21539 base::SafeRef<RenderFrameProxyHost> root_proxy =
540 root_browsing_context_state
Sharon Yangdcc5f252024-05-09 18:27:23541 ->GetRenderFrameProxyHost(site_instance_group)
Peilin Wangfc543212024-03-27 16:17:21542 ->GetSafeRef();
Alex Moshchukd0d759c22025-05-09 18:18:35543 batched_proxy_ipc_sender = std::make_unique<BatchedProxyIPCSender>(
544 std::move(root_proxy), navigation_metrics_token);
[email protected]82307f6b2014-08-07 03:30:12545 }
546 }
547
Sharon Yangdcc5f252024-05-09 18:27:23548 // Check whether we're in an inner delegate and the |site_instance_group|
549 // corresponds to the outer delegate. Subframe proxies aren't needed if this
550 // is the case.
Sharon Yang88f064ca2023-03-24 16:25:18551 bool is_site_instance_group_for_outer_delegate = false;
Alex Moshchuk1226b152019-11-08 18:23:45552 RenderFrameProxyHost* outer_delegate_proxy =
553 root()->render_manager()->GetProxyToOuterDelegate();
554 if (outer_delegate_proxy) {
Sharon Yang88f064ca2023-03-24 16:25:18555 is_site_instance_group_for_outer_delegate =
Sharon Yangdcc5f252024-05-09 18:27:23556 (site_instance_group == outer_delegate_proxy->site_instance_group());
Alex Moshchuk1226b152019-11-08 18:23:45557 }
558
naskoe6edde32014-10-17 15:36:48559 // Proxies are created in the FrameTree in response to a node navigating to a
Sharon Yangdcc5f252024-05-09 18:27:23560 // new SiteInstanceGroup. Since |source|'s navigation will replace the
561 // currently loaded document, the entire subtree under |source| will be
562 // removed, and thus proxy creation is skipped for all nodes in that subtree.
Alex Moshchuk27caae82017-09-11 23:11:18563 //
Sharon Yangdcc5f252024-05-09 18:27:23564 // However, a proxy *is* needed for the |source| node if it is
565 // cross-SiteInstanceGroup from the current node. This lets cross-process
566 // navigations in |source| start with a proxy and follow a remote-to-local
567 // transition, which avoids race conditions in cases where other navigations
568 // need to reference |source| before it commits. See https://crbug.com/756790
569 // for more background. Therefore, NodesExceptSubtree(source) will include
570 // |source| in the nodes traversed (see NodeIterator::operator++).
Alex Moshchuk27caae82017-09-11 23:11:18571 for (FrameTreeNode* node : NodesExceptSubtree(source)) {
Sharon Yangdcc5f252024-05-09 18:27:23572 // If a new frame is created in the current SiteInstanceGroup, other frames
573 // in that SiteInstanceGroup don't need a proxy for the new frame.
Alex Moshchuk27caae82017-09-11 23:11:18574 RenderFrameHostImpl* current_host =
575 node->render_manager()->current_frame_host();
Sharon Yangdcc5f252024-05-09 18:27:23576 SiteInstanceGroup* current_group = current_host->GetSiteInstance()->group();
577
578 // Check that the proxy is for a different SiteInstanceGroup. This ensures
579 // that a navigation within a SiteInstanceGroup does not cause proxies to be
580 // created. That then allows the Blink side to do a local to local frame
581 // transition within the same process.
582 if (current_group != site_instance_group) {
Alex Moshchuk27caae82017-09-11 23:11:18583 if (node == source && !current_host->IsRenderFrameLive()) {
Fergal Daly6de62f52020-10-14 01:56:44584 // We don't create a proxy at |source| when the current RenderFrameHost
585 // isn't live. This is because either (1) the speculative
Alex Moshchuk27caae82017-09-11 23:11:18586 // RenderFrameHost will be committed immediately, and the proxy
Fergal Daly6de62f52020-10-14 01:56:44587 // destroyed right away, in GetFrameHostForNavigation, which makes the
588 // races above impossible, or (2) the early commit will be skipped due
589 // to ShouldSkipEarlyCommitPendingForCrashedFrame, in which case the
590 // proxy for |source| *is* needed, but it will be created later in
591 // CreateProxiesForNewRenderFrameHost.
592 //
593 // TODO(fergal): Consider creating a proxy for |source| here rather than
594 // in CreateProxiesForNewRenderFrameHost for case (2) above.
Alex Moshchuk27caae82017-09-11 23:11:18595 continue;
596 }
Alex Moshchuk1226b152019-11-08 18:23:45597
598 // Do not create proxies for subframes in the outer delegate's
Sharon Yang88f064ca2023-03-24 16:25:18599 // SiteInstanceGroup, since there is no need to expose these subframes to
600 // the outer delegate. See also comments in CreateProxiesForChildFrame()
601 // and https://crbug.com/1013553.
602 if (!node->IsMainFrame() && is_site_instance_group_for_outer_delegate) {
Alex Moshchuk1226b152019-11-08 18:23:45603 continue;
Sharon Yang88f064ca2023-03-24 16:25:18604 }
Alex Moshchuk1226b152019-11-08 18:23:45605
Harkiran Bolaria2912a6b32022-02-22 16:43:45606 // If |node| is the FrameTreeNode being navigated, we use
607 // |browsing_context_state| (as BrowsingContextState might change for
608 // cross-BrowsingInstance navigations). Otherwise, we should use the
609 // |node|'s current BrowsingContextState.
610 node->render_manager()->CreateRenderFrameProxy(
Sharon Yangdcc5f252024-05-09 18:27:23611 site_instance_group,
Peilin Wang427aa6a2023-03-22 17:58:33612 node == source ? source_new_browsing_context_state
613 : node->current_frame_host()->browsing_context_state(),
Alex Moshchukd0d759c22025-05-09 18:18:35614 navigation_metrics_token, batched_proxy_ipc_sender.get());
Alex Moshchuk27caae82017-09-11 23:11:18615 }
dcheng57e39e22016-01-21 00:25:38616 }
Peilin Wang427aa6a2023-03-22 17:58:33617
618 if (batched_proxy_ipc_sender) {
619 batched_proxy_ipc_sender->CreateAllProxies();
620 }
[email protected]82307f6b2014-08-07 03:30:12621}
622
[email protected]9b159a52013-10-03 17:24:55623RenderFrameHostImpl* FrameTree::GetMainFrame() const {
Paul Semel3e241042022-10-11 12:57:31624 return root_.current_frame_host();
[email protected]9b159a52013-10-03 17:24:55625}
626
[email protected]9c9343b2014-03-08 02:56:07627FrameTreeNode* FrameTree::GetFocusedFrame() {
628 return FindByID(focused_frame_tree_node_id_);
629}
630
Sharon Yangefe52632022-03-08 23:06:06631void FrameTree::SetFocusedFrame(FrameTreeNode* node,
632 SiteInstanceGroup* source) {
Rakina Zata Amnicca4889e2021-09-28 23:25:55633 CHECK(node->current_frame_host()->IsActive());
alexmos5357efb2015-12-16 21:44:00634 if (node == GetFocusedFrame())
635 return;
636
Sharon Yangefe52632022-03-08 23:06:06637 std::set<SiteInstanceGroup*> frame_tree_groups =
638 CollectSiteInstanceGroups(this);
alexmosb1dc2162015-11-05 00:59:20639
Sharon Yangefe52632022-03-08 23:06:06640 SiteInstanceGroup* current_group =
641 node->current_frame_host()->GetSiteInstance()->group();
alexmos5357efb2015-12-16 21:44:00642
Sharon Yang7424bda2021-11-04 20:27:43643 // Update the focused frame in all other SiteInstanceGroups. If focus changes
644 // to a cross-group frame, this allows the old focused frame's renderer
alexmosb1dc2162015-11-05 00:59:20645 // process to clear focus from that frame and fire blur events. It also
646 // ensures that the latest focused frame is available in all renderers to
647 // compute document.activeElement.
alexmos5357efb2015-12-16 21:44:00648 //
Sharon Yangefe52632022-03-08 23:06:06649 // We do not notify the |source| SiteInstanceGroup because it already knows
650 // the new focused frame (since it initiated the focus change), and we notify
651 // the new focused frame's SiteInstanceGroup (if it differs from |source|)
652 // separately below.
653 for (auto* group : frame_tree_groups) {
654 if (group != source && group != current_group) {
655 RenderFrameProxyHost* proxy = node->current_frame_host()
656 ->browsing_context_state()
657 ->GetRenderFrameProxyHost(group);
Sharon Yangf92842a2022-03-01 18:21:47658
Rakina Zata Amni80700402021-09-20 17:18:03659 if (proxy) {
660 proxy->SetFocusedFrame();
661 } else {
Sharon Yangf92842a2022-03-01 18:21:47662 base::debug::DumpWithoutCrashing();
Rakina Zata Amni80700402021-09-20 17:18:03663 }
alexmosb1dc2162015-11-05 00:59:20664 }
alexmosca2c6ba2015-10-01 21:52:25665 }
666
Sharon Yangefe52632022-03-08 23:06:06667 // If |node| was focused from a cross-group frame (i.e., via
alexmos5357efb2015-12-16 21:44:00668 // window.focus()), tell its RenderFrame that it should focus.
Sharon Yangefe52632022-03-08 23:06:06669 if (current_group != source)
alexmos5357efb2015-12-16 21:44:00670 node->current_frame_host()->SetFocusedFrame();
671
[email protected]9c9343b2014-03-08 02:56:07672 focused_frame_tree_node_id_ = node->frame_tree_node_id();
alexmos21acae52015-11-07 01:04:43673 node->DidFocus();
dmazzonif27bf892016-03-10 15:51:55674
675 // The accessibility tree data for the root of the frame tree keeps
676 // track of the focused frame too, so update that every time the
677 // focused frame changes.
Kevin McNee582a7d62021-10-12 21:42:22678 root()
679 ->current_frame_host()
680 ->GetOutermostMainFrameOrEmbedder()
681 ->UpdateAXTreeData();
[email protected]9c9343b2014-03-08 02:56:07682}
683
arthursonzognic5be3842019-07-09 11:49:14684scoped_refptr<RenderViewHostImpl> FrameTree::CreateRenderViewHost(
Sharon Yangeb76ee22023-11-29 00:42:09685 SiteInstanceGroup* site_instance_group,
avib7348942015-12-25 20:57:10686 int32_t main_frame_routing_id,
Harkiran Bolaria57e2b062022-03-14 10:27:58687 bool renderer_initiated_creation,
Sharon Yang7ce309e2023-01-19 21:39:57688 scoped_refptr<BrowsingContextState> main_browsing_context_state,
Khushal Sagar402d1c9f2023-11-15 22:21:48689 CreateRenderViewHostCase create_case,
Arthur Sonzognic686e8f2024-01-11 08:36:37690 std::optional<viz::FrameSinkId> frame_sink_id) {
Harkiran Bolaria57e2b062022-03-14 10:27:58691 if (main_browsing_context_state) {
692 DCHECK(main_browsing_context_state->is_main_frame());
693 }
dcheng29f5a6c2015-08-31 21:43:27694 RenderViewHostImpl* rvh =
695 static_cast<RenderViewHostImpl*>(RenderViewHostFactory::Create(
Sharon Yangeb76ee22023-11-29 00:42:09696 this, site_instance_group,
697 site_instance_group->GetStoragePartitionConfig(),
698 render_view_delegate_, render_widget_delegate_, main_frame_routing_id,
Sharon Yang7ce309e2023-01-19 21:39:57699 renderer_initiated_creation, std::move(main_browsing_context_state),
Khushal Sagar402d1c9f2023-11-15 22:21:48700 create_case, frame_sink_id));
Sharon Yang7ce309e2023-01-19 21:39:57701
Rakina Zata Amnidf9988fa12024-07-30 02:00:50702 if (create_case == CreateRenderViewHostCase::kSpeculative) {
Sharon Yang7ce309e2023-01-19 21:39:57703 set_speculative_render_view_host(rvh->GetWeakPtr());
704 } else {
705 // Register non-speculative RenderViewHosts. If they are speculative, they
706 // will be registered when they become active.
707 RegisterRenderViewHost(rvh->rvh_map_id(), rvh);
708 }
709
arthursonzognic5be3842019-07-09 11:49:14710 return base::WrapRefCounted(rvh);
[email protected]94d0cc12013-12-18 00:07:41711}
712
arthursonzognic5be3842019-07-09 11:49:14713scoped_refptr<RenderViewHostImpl> FrameTree::GetRenderViewHost(
Sharon Yang57bde122022-03-01 20:01:12714 SiteInstanceGroup* group) {
Sharon Yanga2fe85e2022-02-09 21:38:29715 // When called from RenderFrameHostManager::CreateRenderFrameHost, it's
716 // possible that a RenderProcessHost hasn't yet been created, which means
Sharon Yang57bde122022-03-01 20:01:12717 // a SiteInstanceGroup won't have been created yet.
Sharon Yanga2fe85e2022-02-09 21:38:29718 if (!group)
719 return nullptr;
720
721 auto it = render_view_host_map_.find(GetRenderViewHostMapId(group));
arthursonzogni88e54ae2019-04-15 12:57:36722 if (it == render_view_host_map_.end())
723 return nullptr;
alexmos9aa61232016-04-26 21:54:02724
arthursonzognic5be3842019-07-09 11:49:14725 return base::WrapRefCounted(it->second);
[email protected]94d0cc12013-12-18 00:07:41726}
727
Aaron Colwell78b4bde2021-03-16 16:16:09728FrameTree::RenderViewHostMapId FrameTree::GetRenderViewHostMapId(
Sharon Yangc581a0c2021-11-02 18:09:39729 SiteInstanceGroup* site_instance_group) const {
730 return RenderViewHostMapId::FromUnsafeValue(
731 site_instance_group->GetId().value());
Lowell Manners75055a132019-10-11 10:30:29732}
733
Aaron Colwell78b4bde2021-03-16 16:16:09734void FrameTree::RegisterRenderViewHost(RenderViewHostMapId id,
735 RenderViewHostImpl* rvh) {
Rakina Zata Amni4b1968d2021-09-09 03:29:47736 TRACE_EVENT_INSTANT("navigation", "FrameTree::RegisterRenderViewHost",
737 ChromeTrackEvent::kRenderViewHost, *rvh);
Sharon Yang7ce309e2023-01-19 21:39:57738 CHECK(!rvh->is_speculative());
Rakina Zata Amni89b8aa32024-09-20 03:36:54739 bool rvh_id_already_in_map = base::Contains(render_view_host_map_, id);
740 bool rfh_in_bfcache =
741 controller()
742 .GetBackForwardCache()
743 .IsRenderFrameHostWithSIGInBackForwardCacheForDebugging(
744 rvh->site_instance_group()->GetId());
745 bool rfph_in_bfcache =
746 controller()
747 .GetBackForwardCache()
748 .IsRenderFrameProxyHostWithSIGInBackForwardCacheForDebugging(
749 rvh->site_instance_group()->GetId());
750 bool rvh_in_bfcache =
751 controller()
752 .GetBackForwardCache()
753 .IsRenderViewHostWithMapIdInBackForwardCacheForDebugging(*rvh);
754 // We're seeing cases where an RVH being restored from BFCache has the same
755 // ID as an RVH already in the map, where the 2 RVHs are different but one
756 // was in BFCache and one isn't.
757 // To investigate, detect if any of these cases happen:
758 // 1) A RenderViewHost with the same ID as `rvh` is already in the map
759 // 2) A RenderFrameHost with the same SIG ID as `rvh` is in BFCache
760 // 3) A RenderFrameProxyHost with the same SIG ID as `rvh` is in BFCache
761 // 4) A RenderViewHost with the same ID as `rvh` is in BFCache
762 // These cases shouldn't be possible. Note that when checking #2-#4 for
763 // a RenderViewHost that is getting out of BFCache, we are guaranteed to not
764 // accidentally match to the RVH/RFPH/RFH of the page being restored,
765 // because we can only get here after the StoredPage is taken out of the
766 // BFCache and thus won't be iterated over in the functions above.
767 // See the linked bug below for more details.
768 if (rvh_id_already_in_map || rfh_in_bfcache || rfph_in_bfcache ||
769 rvh_in_bfcache) {
Rakina Zata Amni9b7ea7052024-09-04 20:40:58770 // TODO(https://crbug.com/354382462): Remove crash keys once investigation
771 // is done.
Rakina Zata Amni89b8aa32024-09-20 03:36:54772 SCOPED_CRASH_KEY_BOOL("rvh-double", "in_map", rvh_id_already_in_map);
773 SCOPED_CRASH_KEY_BOOL("rvh-double", "rfh_in_bfcache", rfh_in_bfcache);
774 SCOPED_CRASH_KEY_BOOL("rvh-double", "rfph_in_bfcache", rfph_in_bfcache);
775 SCOPED_CRASH_KEY_BOOL("rvh-double", "rvh_in_bfcache", rvh_in_bfcache);
776 SCOPED_CRASH_KEY_BOOL("rvh-double", "passed_renderer_created",
Rakina Zata Amnid3006032024-09-12 00:53:53777 rvh->renderer_view_created());
Rakina Zata Amnid3006032024-09-12 00:53:53778 SCOPED_CRASH_KEY_NUMBER("rvh-double", "passed_rvh_main_id",
779 rvh->main_frame_routing_id());
780 SCOPED_CRASH_KEY_NUMBER("rvh-double", "root_routing_id",
781 root()->current_frame_host()->GetRoutingID());
Rakina Zata Amnid3006032024-09-12 00:53:53782 SCOPED_CRASH_KEY_NUMBER("rvh-double", "passed_rvh_ptr",
783 reinterpret_cast<size_t>(rvh));
Rakina Zata Amni89b8aa32024-09-20 03:36:54784 SCOPED_CRASH_KEY_BOOL("rvh-double", "passed_rvh_bfcache",
785 rvh->is_in_back_forward_cache());
786 SCOPED_CRASH_KEY_BOOL("rvh-double", "frame_tree_primary", is_primary());
787
788 if (rvh_id_already_in_map) {
789 SCOPED_CRASH_KEY_BOOL(
790 "rvh-double", "mapped_rvh_registered",
791 render_view_host_map_[id]->is_registered_with_frame_tree());
792 SCOPED_CRASH_KEY_NUMBER(
793 "rvh-double", "mapped_rvh_main_id",
794 render_view_host_map_[id]->main_frame_routing_id());
795 SCOPED_CRASH_KEY_NUMBER(
796 "rvh-double", "map_rvh_ptr",
797 reinterpret_cast<size_t>(render_view_host_map_[id]));
798 SCOPED_CRASH_KEY_BOOL(
799 "rvh-double", "map_rvh_bfcache",
800 render_view_host_map_[id]->is_in_back_forward_cache());
801 SCOPED_CRASH_KEY_BOOL("rvh-double", "mapped_renderer_created",
802 render_view_host_map_[id]->renderer_view_created());
803 CHECK_EQ(rvh, render_view_host_map_[id]);
804 }
Rakina Zata Amni9b7ea7052024-09-04 20:40:58805 }
Aaron Colwell78b4bde2021-03-16 16:16:09806 render_view_host_map_[id] = rvh;
Sharon Yang7ce309e2023-01-19 21:39:57807 rvh->set_is_registered_with_frame_tree(true);
Aaron Colwell78b4bde2021-03-16 16:16:09808}
809
810void FrameTree::UnregisterRenderViewHost(RenderViewHostMapId id,
Aaron Colwellc4bd7d62021-01-29 04:23:13811 RenderViewHostImpl* rvh) {
Rakina Zata Amni4b1968d2021-09-09 03:29:47812 TRACE_EVENT_INSTANT("navigation", "FrameTree::UnregisterRenderViewHost",
813 ChromeTrackEvent::kRenderViewHost, *rvh);
Sharon Yang7ce309e2023-01-19 21:39:57814 CHECK(!rvh->is_speculative());
Aaron Colwell78b4bde2021-03-16 16:16:09815 auto it = render_view_host_map_.find(id);
arthursonzogni88e54ae2019-04-15 12:57:36816 CHECK(it != render_view_host_map_.end());
arthursonzognic5be3842019-07-09 11:49:14817 CHECK_EQ(it->second, rvh);
818 render_view_host_map_.erase(it);
Sharon Yang7ce309e2023-01-19 21:39:57819 rvh->set_is_registered_with_frame_tree(false);
[email protected]94d0cc12013-12-18 00:07:41820}
821
arthursonzogni0a2007792019-05-28 21:32:48822void FrameTree::FrameUnloading(FrameTreeNode* frame) {
823 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
Avi Drissmanbd153642024-09-03 18:58:05824 focused_frame_tree_node_id_ = FrameTreeNodeId();
arthursonzogni0a2007792019-05-28 21:32:48825
826 // Ensure frames that are about to be deleted aren't visible from the other
827 // processes anymore.
Harkiran Bolaria0b3bdef02022-03-10 13:04:40828 frame->GetBrowsingContextStateForSubframe()->ResetProxyHosts();
arthursonzogni0a2007792019-05-28 21:32:48829}
830
dmazzonie950ea232015-03-13 21:39:45831void FrameTree::FrameRemoved(FrameTreeNode* frame) {
nick53d5cbf2015-04-23 22:50:14832 if (frame->frame_tree_node_id() == focused_frame_tree_node_id_)
Avi Drissmanbd153642024-09-03 18:58:05833 focused_frame_tree_node_id_ = FrameTreeNodeId();
dmazzonie950ea232015-03-13 21:39:45834}
835
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15836double FrameTree::GetLoadProgress() {
Paul Semel3e241042022-10-11 12:57:31837 if (root_.HasNavigation())
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15838 return blink::kInitialLoadProgress;
839
Paul Semel3e241042022-10-11 12:57:31840 return root_.current_frame_host()->GetPage().load_progress();
fdegans1d16355162015-03-26 11:58:34841}
842
Yu Gaoc8c18552022-06-22 14:38:45843bool FrameTree::IsLoadingIncludingInnerFrameTrees() const {
Nate Chapin470dbc62023-04-25 16:34:38844 return GetLoadingState() != LoadingState::NONE;
845}
846
847LoadingState FrameTree::GetLoadingState() const {
848 // The overall loading state for the FrameTree matches the root node's loading
849 // state if the root is loading.
850 if (root_.GetLoadingState() != LoadingState::NONE) {
851 return root_.GetLoadingState();
dcheng57e39e22016-01-21 00:25:38852 }
Nate Chapin470dbc62023-04-25 16:34:38853
854 // Otherwise, check if a subframe is loading without an associated navigation
855 // in the root frame. If so, we are loading, but we don't want to show
856 // loading UI.
857 for (const FrameTreeNode* node_to_check :
858 const_cast<FrameTree*>(this)->CollectNodesForIsLoading()) {
859 if (node_to_check->IsLoading()) {
860 return LoadingState::LOADING_WITHOUT_UI;
861 }
862 }
863 return LoadingState::NONE;
fdegans1d16355162015-03-26 11:58:34864}
865
alexmos3fcd0ca2015-10-23 18:18:33866void FrameTree::ReplicatePageFocus(bool is_focused) {
Dave Tapuska53e6ce12021-08-06 16:08:24867 // Focus loss may occur while this FrameTree is being destroyed. Don't
868 // send the message in this case, as the main frame's RenderFrameHost and
869 // other state has already been cleared.
870 if (is_being_destroyed_)
871 return;
Sharon Yangefe52632022-03-08 23:06:06872 std::set<SiteInstanceGroup*> frame_tree_site_instance_groups =
873 CollectSiteInstanceGroups(this);
alexmos3fcd0ca2015-10-23 18:18:33874
Sharon Yangefe52632022-03-08 23:06:06875 // Send the focus update to main frame's proxies in all SiteInstanceGroups of
alexmos3fcd0ca2015-10-23 18:18:33876 // other frames in this FrameTree. Note that the main frame might also know
Sharon Yangefe52632022-03-08 23:06:06877 // about proxies in SiteInstanceGroups for frames in a different FrameTree
878 // (e.g., for window.open), so we can't just iterate over its proxy_hosts_ in
alexmos3fcd0ca2015-10-23 18:18:33879 // RenderFrameHostManager.
Sharon Yangefe52632022-03-08 23:06:06880 for (auto* group : frame_tree_site_instance_groups)
881 SetPageFocus(group, is_focused);
alexmos0d7e0b09b2015-10-29 22:11:48882}
alexmos3fcd0ca2015-10-23 18:18:33883
Sharon Yangefe52632022-03-08 23:06:06884void FrameTree::SetPageFocus(SiteInstanceGroup* group, bool is_focused) {
Paul Semel3e241042022-10-11 12:57:31885 RenderFrameHostManager* root_manager = root_.render_manager();
alexmos0d7e0b09b2015-10-29 22:11:48886
887 // This is only used to set page-level focus in cross-process subframes, and
Sharon Yangefe52632022-03-08 23:06:06888 // requests to set focus in main frame's SiteInstanceGroup are ignored.
889 if (group != root_manager->current_frame_host()->GetSiteInstance()->group()) {
890 RenderFrameProxyHost* proxy = root_manager->current_frame_host()
891 ->browsing_context_state()
892 ->GetRenderFrameProxyHost(group);
Dave Tapuska82b54012022-07-15 23:26:10893 if (proxy->is_render_frame_proxy_live())
894 proxy->GetAssociatedRemoteFrame()->SetPageFocus(is_focused);
alexmos3fcd0ca2015-10-23 18:18:33895 }
896}
897
W. James MacLeanc07dc41b2022-07-25 18:52:16898void FrameTree::RegisterExistingOriginAsHavingDefaultIsolation(
W. James MacLeanb70fab82020-05-01 18:51:14899 const url::Origin& previously_visited_origin,
900 NavigationRequest* navigation_request_to_exclude) {
W. James MacLeanc07dc41b2022-07-25 18:52:16901 controller().RegisterExistingOriginAsHavingDefaultIsolation(
W. James MacLeanc6dc86c2021-08-12 13:58:37902 previously_visited_origin);
903
Charlie Reis37be2682023-01-10 17:04:47904 std::unordered_set<SiteInstanceImpl*> matching_site_instances;
W. James MacLeanb70fab82020-05-01 18:51:14905
906 // Be sure to visit all RenderFrameHosts associated with this frame that might
907 // have an origin that could script other frames. We skip RenderFrameHosts
908 // that are in the bfcache, assuming there's no way for a frame to join the
909 // BrowsingInstance of a bfcache RFH while it's in the cache.
910 for (auto* frame_tree_node : SubtreeNodes(root())) {
911 auto* frame_host = frame_tree_node->current_frame_host();
W. James MacLeanb70fab82020-05-01 18:51:14912 if (previously_visited_origin == frame_host->GetLastCommittedOrigin())
913 matching_site_instances.insert(frame_host->GetSiteInstance());
914
915 if (frame_host->HasCommittingNavigationRequestForOrigin(
916 previously_visited_origin, navigation_request_to_exclude)) {
917 matching_site_instances.insert(frame_host->GetSiteInstance());
918 }
919
920 auto* spec_frame_host =
921 frame_tree_node->render_manager()->speculative_frame_host();
922 if (spec_frame_host &&
923 spec_frame_host->HasCommittingNavigationRequestForOrigin(
924 previously_visited_origin, navigation_request_to_exclude)) {
925 matching_site_instances.insert(spec_frame_host->GetSiteInstance());
926 }
927
928 auto* navigation_request = frame_tree_node->navigation_request();
929 if (navigation_request &&
930 navigation_request != navigation_request_to_exclude &&
931 navigation_request->HasCommittingOrigin(previously_visited_origin)) {
932 matching_site_instances.insert(frame_host->GetSiteInstance());
933 }
934 }
935
936 // Update any SiteInstances found to contain |origin|.
937 for (auto* site_instance : matching_site_instances) {
Charlie Reis37be2682023-01-10 17:04:47938 site_instance->RegisterAsDefaultOriginIsolation(previously_visited_origin);
W. James MacLeanb70fab82020-05-01 18:51:14939 }
940}
941
Charlie Reis37be2682023-01-10 17:04:47942void FrameTree::Init(SiteInstanceImpl* main_frame_site_instance,
Carlos Caballero40b0efd2021-01-26 11:55:00943 bool renderer_initiated_creation,
Rakina Zata Amniafd3c6582021-11-30 06:19:17944 const std::string& main_frame_name,
Rakina Zata Amni4eb716e2022-04-05 21:32:46945 RenderFrameHostImpl* opener_for_origin,
Danil Somsikov259aa65f2022-11-11 20:49:44946 const blink::FramePolicy& frame_policy,
947 const base::UnguessableToken& devtools_frame_token) {
Carlos Caballero40b0efd2021-01-26 11:55:00948 // blink::FrameTree::SetName always keeps |unique_name| empty in case of a
949 // main frame - let's do the same thing here.
950 std::string unique_name;
Paul Semel3e241042022-10-11 12:57:31951 root_.render_manager()->InitRoot(main_frame_site_instance,
952 renderer_initiated_creation, frame_policy,
Danil Somsikov259aa65f2022-11-11 20:49:44953 main_frame_name, devtools_frame_token);
Paul Semel3e241042022-10-11 12:57:31954 root_.SetFencedFramePropertiesIfNeeded();
Rakina Zata Amniafd3c6582021-11-30 06:19:17955
sbingler1f758842023-02-22 00:23:32956 // The initial empty document should inherit the origin (the origin may
957 // change after the first commit) and other state (such as the
958 // RuntimeFeatureStateReadContext) from its opener, except when they are in
Rakina Zata Amni4eb716e2022-04-05 21:32:46959 // different browsing context groups (`renderer_initiated_creation` will be
sbingler1f758842023-02-22 00:23:32960 // false), where it should use a new opaque origin and default values for the
961 // other state, respectively.
Rakina Zata Amniafd3c6582021-11-30 06:19:17962 // See also https://crbug.com/932067.
963 //
964 // Note that the origin of the new frame might depend on sandbox flags.
965 // Checking sandbox flags of the new frame should be safe at this point,
966 // because the flags should be already inherited when creating the root node.
Rakina Zata Amni4eb716e2022-04-05 21:32:46967 DCHECK(!renderer_initiated_creation || opener_for_origin);
Paul Semel3e241042022-10-11 12:57:31968 root_.current_frame_host()->SetOriginDependentStateOfNewFrame(
sbingler1f758842023-02-22 00:23:32969 renderer_initiated_creation ? opener_for_origin : nullptr);
Rakina Zata Amni2322f4f82022-01-24 13:24:24970
Rakina Zata Amni46087a12022-11-11 08:28:38971 controller().CreateInitialEntry();
Carlos Caballero40b0efd2021-01-26 11:55:00972}
973
Carlos Caballeroede6f8c2021-01-28 11:01:50974void FrameTree::DidAccessInitialMainDocument() {
975 OPTIONAL_TRACE_EVENT0("content", "FrameTree::DidAccessInitialDocument");
976 has_accessed_initial_main_document_ = true;
977 controller().DidAccessInitialMainDocument();
978}
979
Nate Chapin470dbc62023-04-25 16:34:38980void FrameTree::NodeLoadingStateChanged(
981 FrameTreeNode& node,
982 LoadingState previous_frame_tree_loading_state) {
983 LoadingState new_frame_tree_loading_state = GetLoadingState();
984 if (previous_frame_tree_loading_state == new_frame_tree_loading_state) {
Carlos Caballero03262522021-02-05 14:49:58985 return;
Nate Chapin470dbc62023-04-25 16:34:38986 }
Carlos Caballero03262522021-02-05 14:49:58987
Nate Chapin470dbc62023-04-25 16:34:38988 root()->render_manager()->SetIsLoading(new_frame_tree_loading_state !=
989 LoadingState::NONE);
990 delegate_->LoadingStateChanged(new_frame_tree_loading_state);
991 if (previous_frame_tree_loading_state == LoadingState::NONE) {
992 delegate_->DidStartLoading(&node);
993 } else if (new_frame_tree_loading_state == LoadingState::NONE) {
994 delegate_->DidStopLoading();
995 }
Carlos Caballero03262522021-02-05 14:49:58996}
997
Carlos Caballero03262522021-02-05 14:49:58998void FrameTree::DidCancelLoading() {
999 OPTIONAL_TRACE_EVENT0("content", "FrameTree::DidCancelLoading");
1000 navigator_.controller().DiscardNonCommittedEntries();
Carlos Caballero03262522021-02-05 14:49:581001}
1002
1003void FrameTree::StopLoading() {
1004 for (FrameTreeNode* node : Nodes())
1005 node->StopLoading();
1006}
1007
Carlos Caballero101ac26b2021-03-24 11:54:051008void FrameTree::Shutdown() {
Dave Tapuskae88286de2021-08-05 19:10:421009 is_being_destroyed_ = true;
Carlos Caballero101ac26b2021-03-24 11:54:051010#if DCHECK_IS_ON()
1011 DCHECK(!was_shut_down_);
1012 was_shut_down_ = true;
1013#endif
1014
Paul Semel3e241042022-10-11 12:57:311015 RenderFrameHostManager* root_manager = root_.render_manager();
Carlos Caballero101ac26b2021-03-24 11:54:051016
Carlos Caballerodb7a8f6e2021-04-09 18:17:471017 if (!root_manager->current_frame_host()) {
1018 // The page has been transferred out during an activation. There is little
1019 // left to do.
Alison Gale770f3fc2024-04-27 00:39:581020 // TODO(crbug.com/40177949): If we decide that pending delete RFHs
Carlos Caballerodb7a8f6e2021-04-09 18:17:471021 // need to be moved along during activation replace this line with a DCHECK
1022 // that there are no pending delete instances.
1023 root_manager->ClearRFHsPendingShutdown();
Paul Semel3e241042022-10-11 12:57:311024 DCHECK(!root_.navigation_request());
Carlos Caballerodb7a8f6e2021-04-09 18:17:471025 DCHECK(!root_manager->speculative_frame_host());
Paul Semel3e241042022-10-11 12:57:311026 manager_delegate_->OnFrameTreeNodeDestroyed(&root_);
Carlos Caballero101ac26b2021-03-24 11:54:051027 return;
Carlos Caballerodb7a8f6e2021-04-09 18:17:471028 }
Carlos Caballero101ac26b2021-03-24 11:54:051029
1030 for (FrameTreeNode* node : Nodes()) {
1031 // Delete all RFHs pending shutdown, which will lead the corresponding RVHs
1032 // to be shutdown and be deleted as well.
1033 node->render_manager()->ClearRFHsPendingShutdown();
Alison Gale47d1537d2024-04-19 21:31:461034 // TODO(crbug.com/40177939): Ban WebUI instance in Prerender pages.
Carlos Caballero101ac26b2021-03-24 11:54:051035 node->render_manager()->ClearWebUIInstances();
1036 }
1037
1038 // Destroy all subframes now. This notifies observers.
1039 root_manager->current_frame_host()->ResetChildren();
Harkiran Bolaria0b3bdef02022-03-10 13:04:401040 root_manager->current_frame_host()
1041 ->browsing_context_state()
1042 ->ResetProxyHosts();
Carlos Caballero101ac26b2021-03-24 11:54:051043
Carlos Caballero101ac26b2021-03-24 11:54:051044 // Manually call the observer methods for the root FrameTreeNode. It is
1045 // necessary to manually delete all objects tracking navigations
1046 // (NavigationHandle, NavigationRequest) for observers to be properly
1047 // notified of these navigations stopping before the WebContents is
1048 // destroyed.
1049
1050 root_manager->current_frame_host()->RenderFrameDeleted();
Rakina Zata Amnif8f2bb62022-11-23 05:54:321051 root_manager->current_frame_host()->ResetOwnedNavigationRequests(
1052 NavigationDiscardReason::kWillRemoveFrame);
Carlos Caballero101ac26b2021-03-24 11:54:051053
1054 // Do not update state as the FrameTree::Delegate (possibly a WebContents) is
1055 // being destroyed.
Rakina Zata Amni58681c62024-06-25 06:32:131056 root_.ResetNavigationRequestButKeepState(
1057 NavigationDiscardReason::kWillRemoveFrame);
Carlos Caballero101ac26b2021-03-24 11:54:051058 if (root_manager->speculative_frame_host()) {
Daniel Chengc3d1e8d2021-06-23 02:11:451059 root_manager->DiscardSpeculativeRenderFrameHostForShutdown();
Carlos Caballero101ac26b2021-03-24 11:54:051060 }
1061
Alexander Timin8aeee642021-05-12 08:39:331062 // NavigationRequests restoring the page from bfcache have a reference to the
1063 // RFHs stored in the cache, so the cache should be cleared after the
1064 // navigation request is reset.
1065 controller().GetBackForwardCache().Shutdown();
1066
Paul Semel3e241042022-10-11 12:57:311067 manager_delegate_->OnFrameTreeNodeDestroyed(&root_);
Carlos Caballero101ac26b2021-03-24 11:54:051068 render_view_delegate_->RenderViewDeleted(
1069 root_manager->current_frame_host()->render_view_host());
1070}
1071
Dave Tapuskad8b0530f2021-10-19 15:12:311072base::SafeRef<FrameTree> FrameTree::GetSafeRef() {
1073 return weak_ptr_factory_.GetSafeRef();
1074}
1075
Dave Tapuska54c76a032021-10-27 22:10:421076void FrameTree::FocusOuterFrameTrees() {
1077 OPTIONAL_TRACE_EVENT0("content", "FrameTree::FocusOuterFrameTrees");
1078
1079 FrameTree* frame_tree_to_focus = this;
1080 while (true) {
1081 FrameTreeNode* outer_node = FrameTreeNode::GloballyFindByID(
1082 frame_tree_to_focus->delegate()->GetOuterDelegateFrameTreeNodeId());
1083 if (!outer_node || !outer_node->current_frame_host()->IsActive()) {
1084 // Don't set focus on an inactive FrameTreeNode.
1085 return;
1086 }
Arthur Sonzognif6785ec2022-12-05 10:11:501087 outer_node->frame_tree().SetFocusedFrame(outer_node, nullptr);
Dave Tapuska54c76a032021-10-27 22:10:421088
1089 // For a browser initiated focus change, let embedding renderer know of the
1090 // change. Otherwise, if the currently focused element is just across a
1091 // process boundary in focus order, it will not be possible to move across
1092 // that boundary. This is because the target element will already be focused
1093 // (that renderer was not notified) and drop the event.
1094 if (auto* proxy_to_outer_delegate = frame_tree_to_focus->root()
1095 ->render_manager()
1096 ->GetProxyToOuterDelegate()) {
1097 proxy_to_outer_delegate->SetFocusedFrame();
1098 }
Arthur Sonzognif6785ec2022-12-05 10:11:501099 frame_tree_to_focus = &outer_node->frame_tree();
Dave Tapuska54c76a032021-10-27 22:10:421100 }
1101}
1102
Thomas Lukaszewicze4cdf6e2025-07-31 23:32:271103void FrameTree::Discard(base::OnceClosure on_discarded_cb) {
1104 const auto attempt_discard = [this](base::OnceClosure on_discarded_cb) {
Thomas Lukaszewicz0ef0f45f2025-02-18 17:59:421105 // A speculative pending-commit rfh should not be cancelled or deleted. In
1106 // this case ignore the discard request and allow the navigation to complete
1107 // as normal.
1108 if (const auto* speculative_rfh =
1109 root()->render_manager()->speculative_frame_host();
1110 speculative_rfh && speculative_rfh->HasPendingCommitNavigation()) {
1111 return false;
1112 }
Thomas Lukaszewicz1b672fe2024-09-17 08:35:031113
Thomas Lukaszewicz0ef0f45f2025-02-18 17:59:421114 root()->set_was_discarded();
Thomas Lukaszewicze4cdf6e2025-07-31 23:32:271115 root()->current_frame_host()->DiscardFrame(std::move(on_discarded_cb));
Thomas Lukaszewicz0ef0f45f2025-02-18 17:59:421116 NavigationControllerImpl& navigation_controller = controller();
1117 navigation_controller.SetNeedsReload();
1118 navigation_controller.GetBackForwardCache().Flush();
1119 return true;
1120 };
Thomas Lukaszewicze4cdf6e2025-07-31 23:32:271121 base::UmaHistogramBoolean("Discarding.DiscardFrameTree",
1122 attempt_discard(std::move(on_discarded_cb)));
Thomas Lukaszewicz8ada31b2024-09-01 19:18:161123}
1124
[email protected]9b159a52013-10-03 17:24:551125} // namespace content