blob: f3f58473bca7f886f304ffaa262302c93e4fa67d [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_node.h"
[email protected]9b159a52013-10-03 17:24:556
Daniel Cheng6ca7f1c92017-08-09 21:45:417#include <math.h>
Kevin McNee2585e732024-10-28 22:11:198
[email protected]9b159a52013-10-03 17:24:559#include <queue>
dcheng36b6aec92015-12-26 06:16:3610#include <utility>
[email protected]9b159a52013-10-03 17:24:5511
Mingyu Lei4c13aad82023-08-27 07:55:1412#include "base/debug/crash_logging.h"
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1413#include "base/feature_list.h"
scottmg6ece5ae2017-02-01 18:25:1914#include "base/lazy_instance.h"
Keishi Hattori0e45c022021-11-27 09:25:5215#include "base/memory/raw_ptr.h"
Liviu Tintad9391fb92020-09-28 23:50:0716#include "base/metrics/histogram_functions.h"
dcheng23ca947d2016-05-04 20:04:1517#include "base/metrics/histogram_macros.h"
Kevin McNee2585e732024-10-28 22:11:1918#include "base/notreached.h"
David Sandersd4bf5eb2022-03-17 07:12:0519#include "base/observer_list.h"
Clark DuVallc97bcf72021-12-08 22:58:2420#include "base/strings/strcat.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4121#include "base/strings/string_util.h"
Clark DuVallc97bcf72021-12-08 22:58:2422#include "base/timer/elapsed_timer.h"
Andrey Kosyakovf2d4ff72018-10-29 20:09:5923#include "content/browser/devtools/devtools_instrumentation.h"
Dominic Farolino8a2187b2021-12-24 20:44:2124#include "content/browser/fenced_frame/fenced_frame.h"
Miyoung Shinff13ed22022-11-30 09:21:4725#include "content/browser/network/cross_origin_embedder_policy_reporter.h"
Paul Semel3e241042022-10-11 12:57:3126#include "content/browser/renderer_host/frame_tree.h"
danakjc492bf82020-09-09 20:02:4427#include "content/browser/renderer_host/navigation_controller_impl.h"
28#include "content/browser/renderer_host/navigation_request.h"
29#include "content/browser/renderer_host/navigator.h"
30#include "content/browser/renderer_host/navigator_delegate.h"
31#include "content/browser/renderer_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4132#include "content/browser/renderer_host/render_view_host_impl.h"
Lucas Furukawa Gadanief8290a2019-07-29 20:27:5133#include "content/common/navigation_params_utils.h"
dmazzonie950ea232015-03-13 21:39:4534#include "content/public/browser/browser_thread.h"
Nan Linaaf84f72021-12-02 22:31:5635#include "content/public/browser/site_isolation_policy.h"
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1436#include "content/public/common/content_features.h"
arthursonzognib93a4472020-04-10 07:38:0037#include "services/network/public/cpp/web_sandbox_flags.h"
38#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
Daniel Cheng0d143e52025-04-03 19:43:1639#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
Harkiran Bolaria59290d62021-03-17 01:53:0140#include "third_party/blink/public/common/features.h"
Liam Bradyb0f1f0e2022-08-19 21:42:1141#include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1542#include "third_party/blink/public/common/loader/loader_constants.h"
Antonio Gomes4b2c5132020-01-16 11:49:4843#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:3744#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
[email protected]9b159a52013-10-03 17:24:5545
46namespace content {
47
dmazzonie950ea232015-03-13 21:39:4548namespace {
49
50// This is a global map between frame_tree_node_ids and pointers to
51// FrameTreeNodes.
Daniel Cheng0d143e52025-04-03 19:43:1652using FrameTreeNodeIdMap = absl::flat_hash_map<FrameTreeNodeId, FrameTreeNode*>;
dmazzonie950ea232015-03-13 21:39:4553
scottmg5e65e3a2017-03-08 08:48:4654base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
55 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4556
Nan Line376738a2022-03-25 22:05:4157FencedFrame* FindFencedFrame(const FrameTreeNode* frame_tree_node) {
Alison Gale770f3fc2024-04-27 00:39:5858 // TODO(crbug.com/40053214): Consider having a pointer to `FencedFrame` in
Nan Line376738a2022-03-25 22:05:4159 // `FrameTreeNode` or having a map between them.
60
61 // Try and find the `FencedFrame` that `frame_tree_node` represents.
62 DCHECK(frame_tree_node->parent());
63 std::vector<FencedFrame*> fenced_frames =
64 frame_tree_node->parent()->GetFencedFrames();
65 for (FencedFrame* fenced_frame : fenced_frames) {
66 if (frame_tree_node->frame_tree_node_id() ==
67 fenced_frame->GetOuterDelegateFrameTreeNodeId()) {
68 return fenced_frame;
69 }
70 }
71 return nullptr;
72}
73
fdegansa696e5112015-04-17 01:57:5974} // namespace
fdegans1d16355162015-03-26 11:58:3475
alexmose201c7cd2015-06-10 17:14:2176// This observer watches the opener of its owner FrameTreeNode and clears the
Arthur Hemerye4659282022-03-28 08:36:1577// owner's opener if the opener is destroyed or swaps BrowsingInstance.
alexmose201c7cd2015-06-10 17:14:2178class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
79 public:
jochen6004a362017-02-04 00:11:4080 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
81 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2182
Peter Boström9b036532021-10-28 23:37:2883 OpenerDestroyedObserver(const OpenerDestroyedObserver&) = delete;
84 OpenerDestroyedObserver& operator=(const OpenerDestroyedObserver&) = delete;
85
alexmose201c7cd2015-06-10 17:14:2186 // FrameTreeNode::Observer
87 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
Arthur Hemerye4659282022-03-28 08:36:1588 NullifyOpener(node);
89 }
90
91 // FrameTreeNode::Observer
92 void OnFrameTreeNodeDisownedOpenee(FrameTreeNode* node) override {
93 NullifyOpener(node);
94 }
95
96 void NullifyOpener(FrameTreeNode* node) {
jochen6004a362017-02-04 00:11:4097 if (observing_original_opener_) {
Rakina Zata Amni3a48ae42022-05-05 03:39:5698 // The "original opener" is special. It's used for attribution, and
99 // clients walk down the original opener chain. Therefore, if a link in
100 // the chain is being destroyed, reconnect the observation to the parent
101 // of the link being destroyed.
102 CHECK_EQ(owner_->first_live_main_frame_in_original_opener_chain(), node);
103 owner_->SetOriginalOpener(
104 node->first_live_main_frame_in_original_opener_chain());
Avi Drissman36465f332017-09-11 20:49:39105 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:40106 } else {
107 CHECK_EQ(owner_->opener(), node);
108 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:39109 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:40110 }
alexmose201c7cd2015-06-10 17:14:21111 }
112
113 private:
Keishi Hattori0e45c022021-11-27 09:25:52114 raw_ptr<FrameTreeNode> owner_;
jochen6004a362017-02-04 00:11:40115 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:21116};
117
Avi Drissmanbd153642024-09-03 18:58:05118// static
119FrameTreeNodeId::Generator FrameTreeNode::frame_tree_node_id_generator_;
[email protected]9b159a52013-10-03 17:24:55120
dmazzonie950ea232015-03-13 21:39:45121// static
Avi Drissmanbd153642024-09-03 18:58:05122FrameTreeNode* FrameTreeNode::GloballyFindByID(
123 FrameTreeNodeId frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:19124 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:15125 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:46126 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:45127 return it == nodes->end() ? nullptr : it->second;
128}
129
Alexander Timin381e7e182020-04-28 19:04:03130// static
131FrameTreeNode* FrameTreeNode::From(RenderFrameHost* rfh) {
132 if (!rfh)
133 return nullptr;
134 return static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
135}
136
Abhijeet Kandalkarb43affa72022-09-27 16:48:01137FrameTreeNode::FencedFrameStatus ComputeFencedFrameStatus(
Arthur Sonzognif6785ec2022-12-05 10:11:50138 const FrameTree& frame_tree,
Harkiran Bolaria16f2c48d2022-04-22 12:39:57139 RenderFrameHostImpl* parent,
140 const blink::FramePolicy& frame_policy) {
Abhijeet Kandalkarb43affa72022-09-27 16:48:01141 using FencedFrameStatus = FrameTreeNode::FencedFrameStatus;
Dominic Farolino0b067632022-11-11 02:57:49142 if (blink::features::IsFencedFramesEnabled() &&
Takashi Toyoshima7c041d82023-09-26 16:09:21143 frame_tree.is_fenced_frame()) {
144 if (!parent) {
Dominic Farolino0b067632022-11-11 02:57:49145 return FencedFrameStatus::kFencedFrameRoot;
Takashi Toyoshima7c041d82023-09-26 16:09:21146 }
Dominic Farolino0b067632022-11-11 02:57:49147 return FencedFrameStatus::kIframeNestedWithinFencedFrame;
Harkiran Bolaria16f2c48d2022-04-22 12:39:57148 }
149
Abhijeet Kandalkar3f29bc42022-09-23 12:39:58150 return FencedFrameStatus::kNotNestedInFencedFrame;
Harkiran Bolaria16f2c48d2022-04-22 12:39:57151}
152
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54153FrameTreeNode::FrameTreeNode(
Arthur Sonzognif6785ec2022-12-05 10:11:50154 FrameTree& frame_tree,
Alexander Timin381e7e182020-04-28 19:04:03155 RenderFrameHostImpl* parent,
Daniel Cheng6ac128172021-05-25 18:49:01156 blink::mojom::TreeScopeType tree_scope_type,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54157 bool is_created_by_script,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54158 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Kevin McNee43fe8292021-10-04 22:59:41159 blink::FrameOwnerElementType owner_type,
Dominic Farolino08662c82021-06-11 07:36:34160 const blink::FramePolicy& frame_policy)
[email protected]bffc8302014-01-23 20:52:16161 : frame_tree_(frame_tree),
Avi Drissmanbd153642024-09-03 18:58:05162 frame_tree_node_id_(frame_tree_node_id_generator_.GenerateNextId()),
xiaochengh98488162016-05-19 15:17:59163 parent_(parent),
Daniel Cheng9bd90f92021-04-23 20:49:45164 frame_owner_element_type_(owner_type),
Daniel Cheng6ac128172021-05-25 18:49:01165 tree_scope_type_(tree_scope_type),
Dominic Farolino08662c82021-06-11 07:36:34166 pending_frame_policy_(frame_policy),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45167 is_created_by_script_(is_created_by_script),
lazyboy70605c32015-11-03 01:27:31168 frame_owner_properties_(frame_owner_properties),
Yuzu Saijo03dbf9b2022-07-22 04:29:45169 attributes_(blink::mojom::IframeAttributes::New()),
Harkiran Bolaria16f2c48d2022-04-22 12:39:57170 fenced_frame_status_(
Arthur Sonzognif6785ec2022-12-05 10:11:50171 ComputeFencedFrameStatus(frame_tree, parent_, frame_policy)),
172 render_manager_(this, frame_tree.manager_delegate()) {
Patrick Monette3250ac42025-05-09 21:55:01173 TRACE_EVENT_BEGIN("navigation.debug", "FrameTreeNode",
Harkiran Bolariaa8347782022-04-06 09:25:11174 perfetto::Track::FromPointer(this),
175 "frame_tree_node_when_created", this);
rob97250742015-12-10 17:45:15176 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45177 g_frame_tree_node_id_map.Get().insert(
178 std::make_pair(frame_tree_node_id_, this));
179 CHECK(result.second);
alexmos998581d2015-01-22 01:01:59180}
[email protected]9b159a52013-10-03 17:24:55181
Dominic Farolino8a2187b2021-12-24 20:44:21182void FrameTreeNode::DestroyInnerFrameTreeIfExists() {
Kevin McNee2585e732024-10-28 22:11:19183 if (!current_frame_host() ||
184 !current_frame_host()->inner_tree_main_frame_tree_node_id()) {
185 return;
186 }
187
188 FrameTreeNode* inner_tree_main_frame_tree_node =
189 FrameTreeNode::GloballyFindByID(
190 current_frame_host()->inner_tree_main_frame_tree_node_id());
191 if (!inner_tree_main_frame_tree_node) {
192 return;
193 }
194
Dominic Farolino8a2187b2021-12-24 20:44:21195 // If `this` is an dummy outer delegate node, then we really are representing
196 // an inner FrameTree for one of the following consumers:
Dominic Farolino8a2187b2021-12-24 20:44:21197 // - `FencedFrame`
198 // - `GuestView`
Kevin McNee2585e732024-10-28 22:11:19199 switch (inner_tree_main_frame_tree_node->GetFrameType()) {
200 case FrameType::kSubframe:
201 case FrameType::kPrerenderMainFrame:
202 NOTREACHED();
203 case FrameType::kPrimaryMainFrame:
204 // This is possible for inner WebContents based GuestViews. The lifetimes
205 // of inner WebContents are dealt with separately.
206 // TODO(crbug.com/40202416): Once inner WebContents are removed, this can
207 // be NOTREACHED.
208 break;
209 case FrameType::kFencedFrameRoot:
210 // If we are representing a `FencedFrame` object, we need to destroy it
211 // alongside ourself.
212 if (FencedFrame* doomed_fenced_frame = FindFencedFrame(this)) {
213 parent()->DestroyFencedFrame(*doomed_fenced_frame);
214 }
215 break;
216 case FrameType::kGuestMainFrame:
217 parent()->DestroyGuestPage(this);
218 break;
Dominic Farolino8a2187b2021-12-24 20:44:21219 }
220}
221
[email protected]9b159a52013-10-03 17:24:55222FrameTreeNode::~FrameTreeNode() {
Harkiran Bolariaa8347782022-04-06 09:25:11223 TRACE_EVENT("navigation", "FrameTreeNode::~FrameTreeNode");
Daniel Chengc3d1e8d2021-06-23 02:11:45224 // There should always be a current RenderFrameHost except during prerender
225 // activation. Prerender activation moves the current RenderFrameHost from
226 // the old FrameTree's FrameTreeNode to the new FrameTree's FrameTreeNode and
227 // then destroys the old FrameTree. See
228 // `RenderFrameHostManager::TakePrerenderedPage()`.
Harkiran Bolaria59290d62021-03-17 01:53:01229 if (current_frame_host()) {
230 // Remove the children.
231 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45232
Harkiran Bolaria59290d62021-03-17 01:53:01233 current_frame_host()->ResetLoadingState();
234 } else {
Harkiran Bolaria59290d62021-03-17 01:53:01235 DCHECK(!parent()); // Only main documents can be activated.
236 DCHECK(!opener()); // Prerendered frame trees can't have openers.
237
238 // Activation is not allowed during ongoing navigations.
Kevin McNeeb63b1ce2023-03-27 14:57:20239 CHECK(!navigation_request_);
Harkiran Bolaria59290d62021-03-17 01:53:01240
Alison Gale770f3fc2024-04-27 00:39:58241 // TODO(crbug.com/40177949): Need to determine how to handle pending
Harkiran Bolaria59290d62021-03-17 01:53:01242 // deletions, as observers will be notified.
Kevin McNeeb63b1ce2023-03-27 14:57:20243 CHECK(!render_manager()->speculative_frame_host());
Harkiran Bolaria59290d62021-03-17 01:53:01244 }
Nate Chapin22ea6592019-03-05 22:29:02245
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45246 // If the removed frame was created by a script, then its history entry will
247 // never be reused - we can save some memory by removing the history entry.
248 // See also https://crbug.com/784356.
249 if (is_created_by_script_ && parent_) {
Carlos Caballero04aab362021-02-15 17:38:16250 NavigationEntryImpl* nav_entry =
251 navigator().controller().GetLastCommittedEntry();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45252 if (nav_entry) {
253 nav_entry->RemoveEntryForFrame(this,
254 /* only_if_different_position = */ false);
255 }
256 }
257
dmazzonie950ea232015-03-13 21:39:45258 frame_tree_->FrameRemoved(this);
Carlos Caballero6ff6ace2021-02-05 16:53:00259
Dominic Farolino8a2187b2021-12-24 20:44:21260 DestroyInnerFrameTreeIfExists();
261
Alex Rudenkobfc5c192022-11-03 07:27:37262 devtools_instrumentation::OnFrameTreeNodeDestroyed(*this);
Carlos Caballero6ff6ace2021-02-05 16:53:00263 // Do not dispatch notification for the root frame as ~WebContentsImpl already
264 // dispatches it for now.
Alison Gale770f3fc2024-04-27 00:39:58265 // TODO(crbug.com/40165695): This is only needed because the FrameTree
Carlos Caballero6ff6ace2021-02-05 16:53:00266 // is a member of WebContentsImpl and we would call back into it during
267 // destruction. We should clean up the FrameTree destruction code and call the
268 // delegate unconditionally.
269 if (parent())
270 render_manager_.delegate()->OnFrameTreeNodeDestroyed(this);
271
ericwilligers254597b2016-10-17 10:32:31272 for (auto& observer : observers_)
273 observer.OnFrameTreeNodeDestroyed(this);
Lukasz Anforowicz147141962020-12-16 18:03:24274 observers_.Clear();
alexmose201c7cd2015-06-10 17:14:21275
276 if (opener_)
277 opener_->RemoveObserver(opener_observer_.get());
Rakina Zata Amni3a48ae42022-05-05 03:39:56278 if (first_live_main_frame_in_original_opener_chain_)
279 first_live_main_frame_in_original_opener_chain_->RemoveObserver(
280 original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45281
282 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18283
Daniel Chengc3d1e8d2021-06-23 02:11:45284 // If a frame with a pending navigation is detached, make sure the
285 // WebContents (and its observers) update their loading state.
286 // TODO(dcheng): This should just check `IsLoading()`, but `IsLoading()`
287 // assumes that `current_frame_host_` is not null. This is incompatible with
288 // prerender activation when destroying the old frame tree (see above).
danakjf9400602019-06-07 15:44:58289 bool did_stop_loading = false;
290
jam39258caf2016-11-02 14:48:18291 if (navigation_request_) {
Rakina Zata Amni58681c62024-06-25 06:32:13292 navigation_request_->set_navigation_discard_reason(
293 NavigationDiscardReason::kWillRemoveFrame);
danakjf9400602019-06-07 15:44:58294 navigation_request_.reset();
danakjf9400602019-06-07 15:44:58295 did_stop_loading = true;
jam39258caf2016-11-02 14:48:18296 }
Nate Chapin22ea6592019-03-05 22:29:02297
danakjf9400602019-06-07 15:44:58298 // ~SiteProcessCountTracker DCHECKs in some tests if the speculative
299 // RenderFrameHostImpl is not destroyed last. Ideally this would be closer to
300 // (possible before) the ResetLoadingState() call above.
danakjf9400602019-06-07 15:44:58301 if (render_manager_.speculative_frame_host()) {
Daniel Chengc3d1e8d2021-06-23 02:11:45302 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative
303 // RenderFrameHost always be considered loading?
danakjf9400602019-06-07 15:44:58304 did_stop_loading |= render_manager_.speculative_frame_host()->is_loading();
Daniel Chengc3d1e8d2021-06-23 02:11:45305 // `FrameTree::Shutdown()` has special handling for the main frame's
306 // speculative RenderFrameHost, and the speculative RenderFrameHost should
307 // already be reset for main frames.
308 DCHECK(!IsMainFrame());
309
310 // This does not use `UnsetSpeculativeRenderFrameHost()`: if the speculative
311 // RenderFrameHost has already reached kPendingCommit, it would needlessly
312 // re-create a proxy for a frame that's going away.
313 render_manager_.DiscardSpeculativeRenderFrameHostForShutdown();
danakjf9400602019-06-07 15:44:58314 }
315
316 if (did_stop_loading)
317 DidStopLoading();
318
Harkiran Bolaria59290d62021-03-17 01:53:01319 // IsLoading() requires that current_frame_host() is non-null.
320 DCHECK(!current_frame_host() || !IsLoading());
Harkiran Bolariaa8347782022-04-06 09:25:11321
322 // Matches the TRACE_EVENT_BEGIN in the constructor.
Patrick Monette3250ac42025-05-09 21:55:01323 TRACE_EVENT_END("navigation.debug", perfetto::Track::FromPointer(this));
[email protected]9b159a52013-10-03 17:24:55324}
325
alexmose201c7cd2015-06-10 17:14:21326void FrameTreeNode::AddObserver(Observer* observer) {
327 observers_.AddObserver(observer);
328}
329
330void FrameTreeNode::RemoveObserver(Observer* observer) {
331 observers_.RemoveObserver(observer);
332}
333
[email protected]94d0cc12013-12-18 00:07:41334bool FrameTreeNode::IsMainFrame() const {
335 return frame_tree_->root() == this;
336}
337
Paul Semel3e241042022-10-11 12:57:31338Navigator& FrameTreeNode::navigator() {
Arthur Sonzognif6785ec2022-12-05 10:11:50339 return frame_tree().navigator();
Paul Semel3e241042022-10-11 12:57:31340}
341
Arthur Hemerya06697f2023-03-14 09:20:57342bool FrameTreeNode::IsOutermostMainFrame() const {
Ian Vollick25a9d032022-04-12 23:20:17343 return !GetParentOrOuterDocument();
344}
345
Arthur Hemerya06697f2023-03-14 09:20:57346RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocument() const {
Kevin McNee86e64ee2023-02-17 16:35:50347 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/false,
348 /*include_prospective=*/true);
Dave Tapuskac8de3b02021-12-03 21:51:01349}
350
351RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentOrEmbedder() {
Kevin McNee86e64ee2023-02-17 16:35:50352 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/true,
353 /*include_prospective=*/true);
Dave Tapuskac8de3b02021-12-03 21:51:01354}
355
356RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentHelper(
Kevin McNee86e64ee2023-02-17 16:35:50357 bool escape_guest_view,
Arthur Hemerya06697f2023-03-14 09:20:57358 bool include_prospective) const {
Dave Tapuskac8de3b02021-12-03 21:51:01359 // Find the parent in the FrameTree (iframe).
Kevin McNee86e64ee2023-02-17 16:35:50360 if (parent_) {
Dave Tapuskac8de3b02021-12-03 21:51:01361 return parent_;
Kevin McNee86e64ee2023-02-17 16:35:50362 }
Dave Tapuskac8de3b02021-12-03 21:51:01363
364 if (!escape_guest_view) {
Jeremy Romanc0c69be2023-11-21 19:14:52365 // If we are not a fenced frame root then return early.
Dave Tapuskac8de3b02021-12-03 21:51:01366 // This code does not escape GuestViews.
Jeremy Romanc0c69be2023-11-21 19:14:52367 if (!IsFencedFrameRoot()) {
Dave Tapuskac8de3b02021-12-03 21:51:01368 return nullptr;
Kevin McNee86e64ee2023-02-17 16:35:50369 }
Dave Tapuskac8de3b02021-12-03 21:51:01370 }
371
Jeremy Romanc0c69be2023-11-21 19:14:52372 // Find the parent in the outer embedder (GuestView or Fenced Frame).
Dave Tapuskac8de3b02021-12-03 21:51:01373 FrameTreeNode* frame_in_embedder = render_manager()->GetOuterDelegateNode();
Kevin McNee86e64ee2023-02-17 16:35:50374 if (frame_in_embedder) {
Dave Tapuskac8de3b02021-12-03 21:51:01375 return frame_in_embedder->current_frame_host()->GetParent();
Kevin McNee86e64ee2023-02-17 16:35:50376 }
377
378 // Consider embedders which own our frame tree, but have not yet attached it
379 // to the outer frame tree.
380 if (include_prospective) {
381 RenderFrameHostImpl* prospective_outer_document =
382 frame_tree_->delegate()->GetProspectiveOuterDocument();
383 if (prospective_outer_document) {
384 return prospective_outer_document;
385 }
386 }
Dave Tapuskac8de3b02021-12-03 21:51:01387
388 // No parent found.
389 return nullptr;
390}
391
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55392FrameType FrameTreeNode::GetFrameType() const {
393 if (!IsMainFrame())
394 return FrameType::kSubframe;
395
Arthur Sonzognif6785ec2022-12-05 10:11:50396 switch (frame_tree().type()) {
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55397 case FrameTree::Type::kPrimary:
398 return FrameType::kPrimaryMainFrame;
399 case FrameTree::Type::kPrerender:
400 return FrameType::kPrerenderMainFrame;
401 case FrameTree::Type::kFencedFrame:
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55402 return FrameType::kFencedFrameRoot;
Kevin McNee2585e732024-10-28 22:11:19403 case FrameTree::Type::kGuest:
404 return FrameType::kGuestMainFrame;
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55405 }
406}
407
alexmose201c7cd2015-06-10 17:14:21408void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
Harkiran Bolariaa8347782022-04-06 09:25:11409 TRACE_EVENT("navigation", "FrameTreeNode::SetOpener",
410 ChromeTrackEvent::kFrameTreeNodeInfo, opener);
alexmose201c7cd2015-06-10 17:14:21411 if (opener_) {
412 opener_->RemoveObserver(opener_observer_.get());
413 opener_observer_.reset();
414 }
415
416 opener_ = opener;
417
418 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55419 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21420 opener_->AddObserver(opener_observer_.get());
421 }
422}
423
Wolfgang Beyerd8809db2020-09-30 15:29:39424void FrameTreeNode::SetOpenerDevtoolsFrameToken(
425 base::UnguessableToken opener_devtools_frame_token) {
426 DCHECK(!opener_devtools_frame_token_ ||
427 opener_devtools_frame_token_->is_empty());
428 opener_devtools_frame_token_ = std::move(opener_devtools_frame_token);
429}
430
jochen6004a362017-02-04 00:11:40431void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39432 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37433 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40434
Rakina Zata Amni3a48ae42022-05-05 03:39:56435 if (first_live_main_frame_in_original_opener_chain_) {
436 first_live_main_frame_in_original_opener_chain_->RemoveObserver(
437 original_opener_observer_.get());
Avi Drissman36465f332017-09-11 20:49:39438 original_opener_observer_.reset();
439 }
440
Rakina Zata Amni3a48ae42022-05-05 03:39:56441 first_live_main_frame_in_original_opener_chain_ = opener;
jochen6004a362017-02-04 00:11:40442
Rakina Zata Amni3a48ae42022-05-05 03:39:56443 if (first_live_main_frame_in_original_opener_chain_) {
444 original_opener_observer_ = std::make_unique<OpenerDestroyedObserver>(
445 this, true /* observing_original_opener */);
446 first_live_main_frame_in_original_opener_chain_->AddObserver(
447 original_opener_observer_.get());
jochen6004a362017-02-04 00:11:40448 }
449}
450
engedy6e2e0992017-05-25 18:58:42451void FrameTreeNode::SetCollapsed(bool collapsed) {
Dave Tapuska65e50aa2022-03-09 23:44:13452 DCHECK(!IsMainFrame() || IsFencedFrameRoot());
engedy6e2e0992017-05-25 18:58:42453 if (is_collapsed_ == collapsed)
454 return;
455
456 is_collapsed_ = collapsed;
457 render_manager_.OnDidChangeCollapsedState(collapsed);
458}
459
Harkiran Bolaria59290d62021-03-17 01:53:01460void FrameTreeNode::SetFrameTree(FrameTree& frame_tree) {
Arthur Sonzognif6785ec2022-12-05 10:11:50461 frame_tree_ = frame_tree;
Kevin McNeeb110d0c2021-10-26 15:53:00462 DCHECK(current_frame_host());
463 current_frame_host()->SetFrameTree(frame_tree);
464 RenderFrameHostImpl* speculative_frame_host =
465 render_manager_.speculative_frame_host();
466 if (speculative_frame_host)
467 speculative_frame_host->SetFrameTree(frame_tree);
Harkiran Bolaria59290d62021-03-17 01:53:01468}
469
Luna Luc3fdacdf2017-11-08 04:48:53470void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Liam Bradyb0f1f0e2022-08-19 21:42:11471 // Inside of a fenced frame, the sandbox flags should not be able to change
472 // from its initial value. If the flags change, we have to assume the change
473 // came from a compromised renderer and terminate it.
474 // We will only do the check if the sandbox flags are already set to
475 // kFencedFrameForcedSandboxFlags. This is to allow the sandbox flags to
476 // be set initially (go from kNone -> kFencedFrameForcedSandboxFlags). Once
477 // it has been set, it cannot change to another value.
Dominic Farolino0b067632022-11-11 02:57:49478 // If the flags do change via a compromised fenced frame, then
479 // `RenderFrameHostImpl::DidChangeFramePolicy()` will detect that the change
480 // wasn't initiated by the parent, and will terminate the renderer before we
481 // reach this point, so we can CHECK() here.
482 bool fenced_frame_sandbox_flags_changed =
483 (IsFencedFrameRoot() &&
484 pending_frame_policy_.sandbox_flags ==
485 blink::kFencedFrameForcedSandboxFlags &&
486 frame_policy.sandbox_flags != blink::kFencedFrameForcedSandboxFlags);
487 CHECK(!fenced_frame_sandbox_flags_changed);
Liam Bradyb0f1f0e2022-08-19 21:42:11488
Ian Clellandcdc4f312017-10-13 22:24:12489 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25490
Ian Clellandcdc4f312017-10-13 22:24:12491 if (parent()) {
492 // Subframes should always inherit their parent's sandbox flags.
Alexander Timin381e7e182020-04-28 19:04:03493 pending_frame_policy_.sandbox_flags |=
Harkiran Bolaria4eacb3a2021-12-13 20:03:47494 parent()->browsing_context_state()->active_sandbox_flags();
Charlie Hue1b77ac2019-12-13 21:30:17495 // This is only applied on subframes; container policy and required document
496 // policy are not mutable on main frame.
Ian Clellandcdc4f312017-10-13 22:24:12497 pending_frame_policy_.container_policy = frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17498 pending_frame_policy_.required_document_policy =
499 frame_policy.required_document_policy;
Ian Clellandcdc4f312017-10-13 22:24:12500 }
Liam Brady25a14162022-12-02 15:25:57501
Ming-Ying Chung0430c592025-01-21 00:33:10502 pending_frame_policy_.deferred_fetch_policy =
503 frame_policy.deferred_fetch_policy;
504
Liam Brady25a14162022-12-02 15:25:57505 // Fenced frame roots do not have a parent, so add an extra check here to
506 // still allow a fenced frame to properly set its container policy. The
507 // required document policy and sandbox flags should stay unmodified.
508 if (IsFencedFrameRoot()) {
509 DCHECK(pending_frame_policy_.required_document_policy.empty());
510 DCHECK_EQ(pending_frame_policy_.sandbox_flags, frame_policy.sandbox_flags);
511 pending_frame_policy_.container_policy = frame_policy.container_policy;
512 }
iclelland92f8c0b2017-04-19 12:43:05513}
514
Yuzu Saijo03dbf9b2022-07-22 04:29:45515void FrameTreeNode::SetAttributes(
516 blink::mojom::IframeAttributesPtr attributes) {
Miyoung Shinc9ff4812023-01-05 08:58:05517 if (!Credentialless() && attributes->credentialless) {
Arthur Sonzogni64457592022-11-22 11:08:59518 // Log this only when credentialless is changed to true.
Arthur Sonzogni2e9c6111392022-05-02 08:37:13519 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
520 parent_, blink::mojom::WebFeature::kAnonymousIframe);
521 }
Yuzu Saijo03dbf9b2022-07-22 04:29:45522 attributes_ = std::move(attributes);
Arthur Sonzogni2e9c6111392022-05-02 08:37:13523}
524
fdegans4a49ce932015-03-12 17:11:37525bool FrameTreeNode::IsLoading() const {
Nate Chapin470dbc62023-04-25 16:34:38526 return GetLoadingState() != LoadingState::NONE;
527}
528
529LoadingState FrameTreeNode::GetLoadingState() const {
fdegans4a49ce932015-03-12 17:11:37530 RenderFrameHostImpl* current_frame_host =
531 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37532 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39533
Nate Chapin470dbc62023-04-25 16:34:38534 if (navigation_request_) {
535 // If navigation_request_ is non-null, the navigation has not been moved to
536 // the RenderFrameHostImpl or sent to the renderer to be committed. This
537 // loading UI policy is provisional, as the navigation API might "intercept"
538 // a same-document commit and change it from LOADING_WITHOUT_UI to
539 // LOADING_UI_REQUESTED.
540 return navigation_request_->IsSameDocument()
541 ? LoadingState::LOADING_WITHOUT_UI
542 : LoadingState::LOADING_UI_REQUESTED;
543 }
clamy11e11512015-07-07 16:42:17544
clamy610c63b32017-12-22 15:05:18545 RenderFrameHostImpl* speculative_frame_host =
546 render_manager_.speculative_frame_host();
Daniel Chengc3d1e8d2021-06-23 02:11:45547 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative RenderFrameHost
548 // always be considered loading?
Nate Chapin470dbc62023-04-25 16:34:38549 if (speculative_frame_host && speculative_frame_host->is_loading()) {
550 return LoadingState::LOADING_UI_REQUESTED;
551 }
552 return current_frame_host->loading_state();
fdegans4a49ce932015-03-12 17:11:37553}
554
Alex Moshchuk9b0fd822020-10-26 23:08:15555bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
556 // Having a |navigation_request_| on FrameTreeNode implies that there's an
557 // ongoing navigation that hasn't reached the ReadyToCommit state. If the
558 // navigation is between ReadyToCommit and DidCommitNavigation, the
559 // NavigationRequest will be held by RenderFrameHost, which is checked below.
560 if (navigation_request_ && !navigation_request_->IsSameDocument())
561 return true;
562
563 // Having a speculative RenderFrameHost should imply a cross-document
564 // navigation.
565 if (render_manager_.speculative_frame_host())
566 return true;
567
568 return render_manager_.current_frame_host()
569 ->HasPendingCommitForCrossDocumentNavigation();
570}
571
Arthur Hemeryc3380172018-01-22 14:00:17572void FrameTreeNode::TransferNavigationRequestOwnership(
573 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59574 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17575 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
576}
577
Charlie Reis09952ee2022-12-08 16:35:07578void FrameTreeNode::TakeNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57579 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37580 // This is never called when navigating to a Javascript URL. For the loading
581 // state, this matches what Blink is doing: Blink doesn't send throbber
582 // notifications for Javascript URLS.
583 DCHECK(!navigation_request->common_params().url.SchemeIs(
584 url::kJavaScriptScheme));
585
Nate Chapin470dbc62023-04-25 16:34:38586 LoadingState previous_frame_tree_loading_state =
587 frame_tree().LoadingTree()->GetLoadingState();
clamy44e84ce2016-02-22 15:38:25588
Rakina Zata Amnif8f2bb62022-11-23 05:54:32589 // Reset the previous NavigationRequest owned by `this`. However, there's no
590 // need to reset the state: there's still an ongoing load, and the
clamy82a2f4d2016-02-02 14:20:41591 // RenderFrameHostManager will take care of updates to the speculative
592 // RenderFrameHost in DidCreateNavigationRequest below.
Nate Chapin470dbc62023-04-25 16:34:38593 if (previous_frame_tree_loading_state != LoadingState::NONE) {
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31594 if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
jamcd0b7b22017-03-24 22:13:05595 // Mark the old request as aborted.
Mohamed Abdelhalimb4db22a2019-06-18 10:46:52596 navigation_request_->set_net_error(net::ERR_ABORTED);
jamcd0b7b22017-03-24 22:13:05597 }
Rakina Zata Amnib5dbc9f2024-07-16 07:47:33598 ResetNavigationRequestButKeepState(
599 navigation_request->GetTypeForNavigationDiscardReason());
Rakina Zata Amni63a7ab02024-09-15 07:40:03600 } else if (navigation_request_ &&
601 !navigation_request_->GetNavigationDiscardReason().has_value()) {
Rakina Zata Amni58681c62024-06-25 06:32:13602 navigation_request_->set_navigation_discard_reason(
Rakina Zata Amnib5dbc9f2024-07-16 07:47:33603 navigation_request->GetTypeForNavigationDiscardReason());
jamcd0b7b22017-03-24 22:13:05604 }
clamy44e84ce2016-02-22 15:38:25605
Mingyu Lei7956b8b2023-07-24 08:24:08606 // Cancel any task that will restart BackForwardCache navigation that was
607 // initiated previously.
608 CancelRestartingBackForwardCacheNavigation();
609
Mingyu Lei99b11712023-10-09 06:35:49610 // If `navigation_request` is a BFCache navigation, the RFH for BFCache
611 // restore should not be evicted before.
612 // This CHECK is added with the fix of https://crbug.com/1468984. See
613 // `BackForwardCacheBrowserTest.TwoBackNavigationsToTheSameEntry` for how
614 // BFCache entry could be evicted before the BFCache `NavigationRequest`
615 // is moved to the FrameTreeNode without the fix.
616 if (navigation_request->IsServedFromBackForwardCache()) {
617 CHECK(!navigation_request->GetRenderFrameHostRestoredFromBackForwardCache()
618 ->is_evicted_from_back_forward_cache());
619 }
620
clamy44e84ce2016-02-22 15:38:25621 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06622 if (was_discarded_) {
623 navigation_request_->set_was_discarded();
624 was_discarded_ = false;
625 }
clamy8e2e299202016-04-05 11:44:59626 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
Maksim Sadym2ed58602025-01-30 00:01:59627
628 devtools_instrumentation::DidStartNavigating(
629 *this, navigation_request_->common_params().url,
630 navigation_request_->devtools_navigation_token(),
631 navigation_request_->common_params().navigation_type);
632
Nate Chapin470dbc62023-04-25 16:34:38633 DidStartLoading(previous_frame_tree_loading_state);
clamydcb434c12015-04-16 19:29:16634}
635
Daniel Cheng390e2a72022-09-28 06:07:53636void FrameTreeNode::ResetNavigationRequest(NavigationDiscardReason reason) {
637 if (!navigation_request_)
638 return;
639
Rakina Zata Amni58681c62024-06-25 06:32:13640 ResetNavigationRequestButKeepState(reason);
Daniel Cheng390e2a72022-09-28 06:07:53641
642 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
643 // it created for the navigation. Also register that the load stopped.
644 DidStopLoading();
Rakina Zata Amnif8f2bb62022-11-23 05:54:32645 render_manager_.DiscardSpeculativeRFHIfUnused(reason);
Xiaochen Zhou8294af82024-05-30 20:48:02646
647 // An ancestor's network revocation status could've changed as a result of
648 // the NavigationRequest getting reset. When fenced frames revoke network
649 // access by calling `window.fence.disableUntrustedNetwork`, the returned
650 // promise cannot be resolved until ongoing navigations in descendant frames
651 // complete.
652 current_frame_host()
653 ->GetOutermostMainFrame()
654 ->CalculateUntrustedNetworkStatus();
Daniel Cheng390e2a72022-09-28 06:07:53655}
656
Rakina Zata Amni58681c62024-06-25 06:32:13657void FrameTreeNode::ResetNavigationRequestButKeepState(
658 NavigationDiscardReason reason) {
fdegans39ff0382015-04-29 19:04:39659 if (!navigation_request_)
660 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23661
Mingyu Lei7956b8b2023-07-24 08:24:08662 // When resetting the NavigationRequest, any BFCache navigation restarting
663 // task should be cancelled. This is to ensure that the FrameTreeNode won't
664 // accidentally complete a navigation that should be reset.
665 CancelRestartingBackForwardCacheNavigation();
Andrey Kosyakovf2d4ff72018-10-29 20:09:59666 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Rakina Zata Amni63a7ab02024-09-15 07:40:03667 if (!navigation_request_->GetNavigationDiscardReason().has_value()) {
668 navigation_request_->set_navigation_discard_reason(reason);
669 }
clamydcb434c12015-04-16 19:29:16670 navigation_request_.reset();
671}
672
Nate Chapin470dbc62023-04-25 16:34:38673void FrameTreeNode::DidStartLoading(
674 LoadingState previous_frame_tree_loading_state) {
Camille Lamyefd54b02018-10-04 16:54:14675 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
Nate Chapin470dbc62023-04-25 16:34:38676 "frame_tree_node", frame_tree_node_id(), "loading_state",
677 GetLoadingState());
Clark DuVallc97bcf72021-12-08 22:58:24678 base::ElapsedTimer timer;
fdegansa696e5112015-04-17 01:57:59679
Nate Chapin470dbc62023-04-25 16:34:38680 frame_tree().LoadingTree()->NodeLoadingStateChanged(
681 *this, previous_frame_tree_loading_state);
fdegansa696e5112015-04-17 01:57:59682
683 // Set initial load progress and update overall progress. This will notify
684 // the WebContents of the load progress change.
Sreeja Kamishetty15f9944a22022-03-10 10:16:08685 //
686 // Only notify when the load is triggered from primary/prerender main frame as
687 // we only update load progress for these nodes which happens when the frame
688 // tree matches the loading tree.
Arthur Sonzognif6785ec2022-12-05 10:11:50689 if (&frame_tree() == frame_tree().LoadingTree())
Sreeja Kamishetty15f9944a22022-03-10 10:16:08690 DidChangeLoadProgress(blink::kInitialLoadProgress);
fdegansa696e5112015-04-17 01:57:59691
Harkiran Bolaria3f83fba72022-03-10 17:48:40692 // Notify the proxies of the event.
693 current_frame_host()->browsing_context_state()->OnDidStartLoading();
Andrey Kosyakov4401fdf2023-08-28 20:03:59694 devtools_instrumentation::DidChangeFrameLoadingState(*this);
Clark DuVallc97bcf72021-12-08 22:58:24695 base::UmaHistogramTimes(
696 base::StrCat({"Navigation.DidStartLoading.",
Ian Vollick5f45867c2022-08-05 08:29:56697 IsOutermostMainFrame() ? "MainFrame" : "Subframe"}),
Clark DuVallc97bcf72021-12-08 22:58:24698 timer.Elapsed());
fdegansa696e5112015-04-17 01:57:59699}
700
701void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14702 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
703 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59704 // Set final load progress and update overall progress. This will notify
705 // the WebContents of the load progress change.
Sreeja Kamishetty15f9944a22022-03-10 10:16:08706 //
707 // Only notify when the load is triggered from primary/prerender main frame as
708 // we only update load progress for these nodes which happens when the frame
709 // tree matches the loading tree.
Arthur Sonzognif6785ec2022-12-05 10:11:50710 if (&frame_tree() == frame_tree().LoadingTree())
Sreeja Kamishetty15f9944a22022-03-10 10:16:08711 DidChangeLoadProgress(blink::kFinalLoadProgress);
fdegansa696e5112015-04-17 01:57:59712
Harkiran Bolaria3f83fba72022-03-10 17:48:40713 // Notify the proxies of the event.
714 current_frame_host()->browsing_context_state()->OnDidStopLoading();
Lucas Furukawa Gadani6faef602019-05-06 21:16:03715
Arthur Sonzognif6785ec2022-12-05 10:11:50716 FrameTree* loading_tree = frame_tree().LoadingTree();
Nate Chapin470dbc62023-04-25 16:34:38717 // When loading tree is null, ignore invoking NodeLoadingStateChanged as the
718 // frame tree is already deleted. This can happen when prerendering gets
719 // cancelled and DidStopLoading is called during FrameTree destruction.
720 if (loading_tree && !loading_tree->IsLoadingIncludingInnerFrameTrees()) {
721 // If `loading_tree->IsLoadingIncludingInnerFrameTrees()` is now false, this
722 // was the last FrameTreeNode to be loading, and the FrameTree as a whole
723 // has now stopped loading. Notify the FrameTree.
724 // It doesn't matter whether we pass LOADING_UI_REQUESTED or
725 // LOADING_WITHOUT_UI as the previous_frame_tree_loading_state param,
726 // because the previous value is only used to detect when the FrameTree's
727 // overall loading state hasn't changed, and we know that the new state will
728 // be LoadingState::NONE.
729 loading_tree->NodeLoadingStateChanged(*this,
730 LoadingState::LOADING_UI_REQUESTED);
731 }
Andrey Kosyakov4401fdf2023-08-28 20:03:59732 devtools_instrumentation::DidChangeFrameLoadingState(*this);
fdegansa696e5112015-04-17 01:57:59733}
734
735void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15736 DCHECK_GE(load_progress, blink::kInitialLoadProgress);
737 DCHECK_LE(load_progress, blink::kFinalLoadProgress);
738 current_frame_host()->DidChangeLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59739}
740
clamyf73862c42015-07-08 12:31:33741bool FrameTreeNode::StopLoading() {
arthursonzogni66f711c2019-10-08 14:40:36742 if (navigation_request_ && navigation_request_->IsNavigationStarted())
743 navigation_request_->set_net_error(net::ERR_ABORTED);
Rakina Zata Amni58681c62024-06-25 06:32:13744 ResetNavigationRequest(NavigationDiscardReason::kExplicitCancellation);
clamyf73862c42015-07-08 12:31:33745
clamyf73862c42015-07-08 12:31:33746 if (!IsMainFrame())
747 return true;
748
749 render_manager_.Stop();
750 return true;
751}
752
alexmos21acae52015-11-07 01:04:43753void FrameTreeNode::DidFocus() {
754 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31755 for (auto& observer : observers_)
756 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43757}
758
clamy44e84ce2016-02-22 15:38:25759void FrameTreeNode::BeforeUnloadCanceled() {
Julie Jeongeun Kim8cf7ae32022-05-02 03:47:29760 // TODO(clamy): Support BeforeUnload in subframes. Fenced Frames don't run
761 // BeforeUnload. Maybe need to check whether other MPArch inner pages cases
Jeremy Romanc0c69be2023-11-21 19:14:52762 // need beforeunload(e.g., GuestView if it gets ported to MPArch).
Ian Vollick1c6dd3e2022-04-13 02:06:26763 if (!IsOutermostMainFrame())
clamy44e84ce2016-02-22 15:38:25764 return;
765
766 RenderFrameHostImpl* current_frame_host =
767 render_manager_.current_frame_host();
768 DCHECK(current_frame_host);
769 current_frame_host->ResetLoadingState();
770
clamy610c63b32017-12-22 15:05:18771 RenderFrameHostImpl* speculative_frame_host =
772 render_manager_.speculative_frame_host();
773 if (speculative_frame_host)
774 speculative_frame_host->ResetLoadingState();
Alexander Timin23c110b2021-01-14 02:39:04775 // Note: there is no need to set an error code on the NavigationHandle as
776 // the observers have not been notified about its creation.
777 // We also reset navigation request only when this navigation request was
778 // responsible for this dialog, as a new navigation request might cancel
779 // existing unrelated dialog.
Daniel Cheng390e2a72022-09-28 06:07:53780 if (navigation_request_ && navigation_request_->IsWaitingForBeforeUnload()) {
Rakina Zata Amni58681c62024-06-25 06:32:13781 ResetNavigationRequest(NavigationDiscardReason::kExplicitCancellation);
Daniel Cheng390e2a72022-09-28 06:07:53782 }
clamy44e84ce2016-02-22 15:38:25783}
784
Liam Brady38b84562024-03-07 22:11:26785bool FrameTreeNode::NotifyUserActivationStickyOnly() {
786 return NotifyUserActivation(
787 blink::mojom::UserActivationNotificationType::kNone,
788 /*sticky_only=*/true);
789}
790
Mustaq Ahmedecb5c38e2020-07-29 00:34:30791bool FrameTreeNode::NotifyUserActivation(
Liam Brady38b84562024-03-07 22:11:26792 blink::mojom::UserActivationNotificationType notification_type,
793 bool sticky_only) {
Alex Moshchuk03904192021-04-02 07:29:08794 // User Activation V2 requires activating all ancestor frames in addition to
795 // the current frame. See
796 // https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation.
Alexander Timina1dfadaa2020-04-28 13:30:06797 for (RenderFrameHostImpl* rfh = current_frame_host(); rfh;
798 rfh = rfh->GetParent()) {
John Delaneyb625dca92021-04-14 17:00:34799 rfh->DidReceiveUserActivation();
Liam Brady38b84562024-03-07 22:11:26800 rfh->ActivateUserActivation(notification_type, sticky_only);
John Delaneyedd8d6c2019-01-25 00:23:57801 }
Alex Moshchuk03904192021-04-02 07:29:08802
Tommy Steimel71f154462024-05-22 19:05:07803 // If we're in a picture-in-picture frame tree, then also activate the opener
804 // frame of the picture-in-picture root.
805 FrameTree* pip_opener =
806 frame_tree().delegate()->GetPictureInPictureOpenerFrameTree();
807 if (base::FeatureList::IsEnabled(
808 blink::features::kDocumentPictureInPictureUserActivation) &&
809 pip_opener) {
810 RenderFrameHostImpl* opener_frame_host =
811 pip_opener->root()->current_frame_host();
812
813 opener_frame_host->DidReceiveUserActivation();
814 opener_frame_host->ActivateUserActivation(notification_type, sticky_only);
815 }
816
Harkiran Bolaria0b3bdef02022-03-10 13:04:40817 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
818 true);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14819
Mustaq Ahmed0180320f2019-03-21 16:07:01820 // See the "Same-origin Visibility" section in |UserActivationState| class
821 // doc.
Nathan Memmott0717db642024-12-13 21:47:25822 const url::Origin& current_origin =
823 this->current_frame_host()->GetLastCommittedOrigin();
824 for (FrameTreeNode* node : frame_tree().Nodes()) {
825 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
826 current_origin)) {
827 node->current_frame_host()->ActivateUserActivation(notification_type,
828 sticky_only);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14829 }
Nathan Memmott0717db642024-12-13 21:47:25830 }
Tommy Steimel71f154462024-05-22 19:05:07831
Nathan Memmott0717db642024-12-13 21:47:25832 if (base::FeatureList::IsEnabled(
833 blink::features::kDocumentPictureInPictureUserActivation)) {
834 // If we own a picture-in-picture window, then also activate same-origin
835 // frames within the picture-in-picture window.
836 FrameTree* picture_in_picture_frame_tree =
837 frame_tree().delegate()->GetOwnedPictureInPictureFrameTree();
838 if (picture_in_picture_frame_tree) {
839 for (FrameTreeNode* node : picture_in_picture_frame_tree->Nodes()) {
840 if (node->current_frame_host()
841 ->GetLastCommittedOrigin()
842 .IsSameOriginWith(current_origin)) {
843 node->current_frame_host()->ActivateUserActivation(notification_type,
844 sticky_only);
Tommy Steimel71f154462024-05-22 19:05:07845 }
846 }
847 }
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14848 }
849
Carlos Caballero40b0efd2021-01-26 11:55:00850 navigator().controller().NotifyUserActivation();
Alex Moshchuk03904192021-04-02 07:29:08851 current_frame_host()->MaybeIsolateForUserActivation();
Shivani Sharma194877032019-03-07 17:52:47852
Mustaq Ahmedc4cb7162018-06-05 16:28:36853 return true;
854}
855
Anguluri Aravind Kumara8aa5952025-02-23 02:53:07856bool FrameTreeNode::AreAncestorsSecure() {
857 RenderFrameHostImpl* frame = parent();
858 while (frame) {
859 if (!network::IsOriginPotentiallyTrustworthy(
860 frame->GetLastCommittedOrigin())) {
861 return false;
862 }
863 frame = frame->GetParent();
864 }
865 return true;
866}
867
Mustaq Ahmedc4cb7162018-06-05 16:28:36868bool FrameTreeNode::ConsumeTransientUserActivation() {
Miyoung Shin8a66ec022022-11-28 23:50:09869 bool was_active = current_frame_host()->IsActiveUserActivation();
Arthur Sonzognif6785ec2022-12-05 10:11:50870 for (FrameTreeNode* node : frame_tree().Nodes()) {
Miyoung Shin8a66ec022022-11-28 23:50:09871 node->current_frame_host()->ConsumeTransientUserActivation();
Garrett Tanzer753cc532022-03-02 21:30:59872 }
Tommy Steimel71f154462024-05-22 19:05:07873
874 if (base::FeatureList::IsEnabled(
875 blink::features::kDocumentPictureInPictureUserActivation)) {
876 // If we're consuming user activation in a picture-in-picture window, ensure
877 // that its opener's frames also consume activation.
878 FrameTree* pip_opener =
879 frame_tree().delegate()->GetPictureInPictureOpenerFrameTree();
880 if (pip_opener) {
881 for (FrameTreeNode* node : pip_opener->Nodes()) {
882 node->current_frame_host()->ConsumeTransientUserActivation();
883 }
884 }
885
886 // If we own a picture-in-picture window, ensure that its frames also
887 // consume activation.
888 FrameTree* picture_in_picture_frame_tree =
889 frame_tree().delegate()->GetOwnedPictureInPictureFrameTree();
890 if (picture_in_picture_frame_tree) {
891 for (FrameTreeNode* node : picture_in_picture_frame_tree->Nodes()) {
892 node->current_frame_host()->ConsumeTransientUserActivation();
893 }
894 }
895 }
896
Harkiran Bolaria0b3bdef02022-03-10 13:04:40897 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
898 false);
Mustaq Ahmedc4cb7162018-06-05 16:28:36899 return was_active;
900}
901
Shivani Sharmac4f561582018-11-15 15:58:39902bool FrameTreeNode::ClearUserActivation() {
Tommy Steimel71f154462024-05-22 19:05:07903 // Note that we don't need to clear user activation for the picture-in-picture
904 // subtree here since this is only called for a navigation, which closes the
905 // picture-in-picture window.
Arthur Sonzognif6785ec2022-12-05 10:11:50906 for (FrameTreeNode* node : frame_tree().SubtreeNodes(this))
Miyoung Shin8a66ec022022-11-28 23:50:09907 node->current_frame_host()->ClearUserActivation();
Harkiran Bolaria0b3bdef02022-03-10 13:04:40908 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
909 false);
Shivani Sharmac4f561582018-11-15 15:58:39910 return true;
911}
912
Mustaq Ahmedc4cb7162018-06-05 16:28:36913bool FrameTreeNode::UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11914 blink::mojom::UserActivationUpdateType update_type,
915 blink::mojom::UserActivationNotificationType notification_type) {
Ella Ge9caed612019-08-09 16:17:25916 bool update_result = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36917 switch (update_type) {
Antonio Gomes4b2c5132020-01-16 11:49:48918 case blink::mojom::UserActivationUpdateType::kConsumeTransientActivation:
Ella Ge9caed612019-08-09 16:17:25919 update_result = ConsumeTransientUserActivation();
920 break;
Antonio Gomes4b2c5132020-01-16 11:49:48921 case blink::mojom::UserActivationUpdateType::kNotifyActivation:
Mustaq Ahmeddc195e5b2020-08-04 18:45:11922 update_result = NotifyUserActivation(notification_type);
Ella Ge9caed612019-08-09 16:17:25923 break;
Liam Brady38b84562024-03-07 22:11:26924 case blink::mojom::UserActivationUpdateType::kNotifyActivationStickyOnly:
925 update_result = NotifyUserActivationStickyOnly();
926 break;
Antonio Gomes4b2c5132020-01-16 11:49:48927 case blink::mojom::UserActivationUpdateType::kClearActivation:
Ella Ge9caed612019-08-09 16:17:25928 update_result = ClearUserActivation();
929 break;
Mustaq Ahmedc4cb7162018-06-05 16:28:36930 }
Mustaq Ahmeddc195e5b2020-08-04 18:45:11931 render_manager_.UpdateUserActivationState(update_type, notification_type);
Ella Ge9caed612019-08-09 16:17:25932 return update_result;
japhet61835ae12017-01-20 01:25:39933}
934
Nate Chapin47276a62023-02-16 16:53:44935void FrameTreeNode::DidConsumeHistoryUserActivation() {
936 for (FrameTreeNode* node : frame_tree().Nodes()) {
937 node->current_frame_host()->ConsumeHistoryUserActivation();
938 }
939}
940
Charlie Reis734db662024-01-11 18:20:03941void FrameTreeNode::DidOpenDocumentInputStream() {
942 // document.open causes the document to lose its "initial empty document"
943 // status.
944 set_not_on_initial_empty_document();
945}
946
Arthur Sonzognif8840b92018-11-07 14:10:35947void FrameTreeNode::PruneChildFrameNavigationEntries(
948 NavigationEntryImpl* entry) {
949 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
950 FrameTreeNode* child = current_frame_host()->child_at(i);
951 if (child->is_created_by_script_) {
952 entry->RemoveEntryForFrame(child,
953 /* only_if_different_position = */ false);
954 } else {
955 child->PruneChildFrameNavigationEntries(entry);
956 }
957 }
958}
959
arthursonzogni034bb9c2020-10-01 08:29:56960void FrameTreeNode::SetInitialPopupURL(const GURL& initial_popup_url) {
961 DCHECK(initial_popup_url_.is_empty());
Abhijeet Kandalkarb86993b2022-11-22 05:17:40962 DCHECK(is_on_initial_empty_document());
arthursonzogni034bb9c2020-10-01 08:29:56963 initial_popup_url_ = initial_popup_url;
964}
965
966void FrameTreeNode::SetPopupCreatorOrigin(
967 const url::Origin& popup_creator_origin) {
Abhijeet Kandalkarb86993b2022-11-22 05:17:40968 DCHECK(is_on_initial_empty_document());
arthursonzogni034bb9c2020-10-01 08:29:56969 popup_creator_origin_ = popup_creator_origin;
970}
971
Rakina Zata Amni4b1968d2021-09-09 03:29:47972void FrameTreeNode::WriteIntoTrace(
Alexander Timin074cd182022-03-23 18:11:22973 perfetto::TracedProto<TraceProto> proto) const {
Avi Drissmanbd153642024-09-03 18:58:05974 proto->set_frame_tree_node_id(frame_tree_node_id().value());
Alexander Timin074cd182022-03-23 18:11:22975 proto->set_is_main_frame(IsMainFrame());
976 proto.Set(TraceProto::kCurrentFrameHost, current_frame_host());
977 proto.Set(TraceProto::kSpeculativeFrameHost,
978 render_manager()->speculative_frame_host());
Rakina Zata Amni4b1968d2021-09-09 03:29:47979}
980
Carlos Caballero76711352021-03-24 17:38:21981bool FrameTreeNode::HasNavigation() {
982 if (navigation_request())
983 return true;
984
985 // Same-RenderFrameHost navigation is committing:
986 if (current_frame_host()->HasPendingCommitNavigation())
987 return true;
988
989 // Cross-RenderFrameHost navigation is committing:
990 if (render_manager()->speculative_frame_host())
991 return true;
992
993 return false;
994}
995
murakinonoka97a8f042024-01-10 09:17:07996bool FrameTreeNode::HasPendingCommitNavigation() {
997 // Same-RenderFrameHost navigation is committing:
998 if (current_frame_host()->HasPendingCommitNavigation()) {
999 return true;
1000 }
1001
1002 // Cross-RenderFrameHost navigation is committing:
1003 RenderFrameHostImpl* speculative_frame_host =
1004 render_manager()->speculative_frame_host();
1005 if (speculative_frame_host &&
1006 speculative_frame_host->HasPendingCommitNavigation()) {
1007 return true;
1008 }
1009
1010 return false;
1011}
1012
Dominic Farolino4bc10ee2021-08-31 00:37:361013bool FrameTreeNode::IsFencedFrameRoot() const {
Abhijeet Kandalkar3f29bc42022-09-23 12:39:581014 return fenced_frame_status_ == FencedFrameStatus::kFencedFrameRoot;
shivanigithubf3ddff52021-07-03 22:06:301015}
1016
1017bool FrameTreeNode::IsInFencedFrameTree() const {
Abhijeet Kandalkar3f29bc42022-09-23 12:39:581018 return fenced_frame_status_ != FencedFrameStatus::kNotNestedInFencedFrame;
shivanigithubf3ddff52021-07-03 22:06:301019}
1020
Liam Brady27da6a22024-06-05 16:35:341021FrameTreeNode* FrameTreeNode::GetClosestAncestorWithFencedFrameProperties() {
1022 FrameTreeNode* node = this;
1023 while (node) {
1024 if (node->fenced_frame_properties_.has_value()) {
1025 return node;
1026 }
1027 node = node->parent() ? node->parent()->frame_tree_node() : nullptr;
1028 }
1029
1030 return nullptr;
1031}
1032
Arthur Sonzognic686e8f2024-01-11 08:36:371033std::optional<FencedFrameProperties>& FrameTreeNode::GetFencedFrameProperties(
Xiaochen Zhou86f2e712023-09-13 19:55:041034 FencedFramePropertiesNodeSource node_source) {
1035 if (node_source == FencedFramePropertiesNodeSource::kFrameTreeRoot) {
Liam Brady6da2cc9e2023-01-30 17:09:431036 return frame_tree().root()->fenced_frame_properties_;
Garrett Tanzer34cb92fe2022-09-28 17:50:541037 }
1038
Xiaochen Zhou86f2e712023-09-13 19:55:041039 // The only other option is `kClosestAncestor`. In this case the fenced frame
1040 // properties are obtained by a bottom-up traversal.
1041 CHECK_EQ(node_source, FencedFramePropertiesNodeSource::kClosestAncestor);
1042
Liam Brady27da6a22024-06-05 16:35:341043 FrameTreeNode* node = GetClosestAncestorWithFencedFrameProperties();
Liam Brady6da2cc9e2023-01-30 17:09:431044
Liam Brady27da6a22024-06-05 16:35:341045 return node ? node->fenced_frame_properties_ : fenced_frame_properties_;
Liam Brady6da2cc9e2023-01-30 17:09:431046}
1047
Yao Xiaof9ae90a2023-03-01 20:52:441048size_t FrameTreeNode::GetFencedFrameDepth(
1049 size_t& shared_storage_fenced_frame_root_count) {
1050 DCHECK_EQ(shared_storage_fenced_frame_root_count, 0u);
1051
Yao Xiaoa2337ad2022-10-12 20:59:291052 size_t depth = 0;
1053 FrameTreeNode* node = this;
1054
1055 while (node->fenced_frame_status() !=
1056 FencedFrameStatus::kNotNestedInFencedFrame) {
1057 if (node->fenced_frame_status() == FencedFrameStatus::kFencedFrameRoot) {
1058 depth += 1;
Yao Xiaof9ae90a2023-03-01 20:52:441059
1060 // This implies the fenced frame is from shared storage.
1061 if (node->fenced_frame_properties_ &&
Garrett Tanzer06980702023-12-12 19:48:201062 node->fenced_frame_properties_->shared_storage_budget_metadata()) {
Yao Xiaof9ae90a2023-03-01 20:52:441063 shared_storage_fenced_frame_root_count += 1;
1064 }
Yao Xiaoa2337ad2022-10-12 20:59:291065 } else {
1066 DCHECK_EQ(node->fenced_frame_status(),
1067 FencedFrameStatus::kIframeNestedWithinFencedFrame);
1068 }
1069
1070 DCHECK(node->GetParentOrOuterDocument());
1071 node = node->GetParentOrOuterDocument()->frame_tree_node();
1072 }
1073
1074 return depth;
1075}
1076
Arthur Sonzognic686e8f2024-01-11 08:36:371077std::optional<base::UnguessableToken> FrameTreeNode::GetFencedFrameNonce() {
Xiaochen Zhou86f2e712023-09-13 19:55:041078 // For partition nonce, all nested frame inside a fenced frame tree should
1079 // operate on the partition nonce of the frame tree root.
1080 auto& root_fenced_frame_properties = GetFencedFrameProperties(
1081 /*node_source=*/FencedFramePropertiesNodeSource::kFrameTreeRoot);
Garrett Tanzer34cb92fe2022-09-28 17:50:541082 if (!root_fenced_frame_properties.has_value()) {
Arthur Sonzognic686e8f2024-01-11 08:36:371083 return std::nullopt;
Garrett Tanzer34cb92fe2022-09-28 17:50:541084 }
Garrett Tanzer06980702023-12-12 19:48:201085 if (root_fenced_frame_properties->partition_nonce().has_value()) {
1086 return root_fenced_frame_properties->partition_nonce()
Garrett Tanzer29de7112022-12-06 21:26:321087 ->GetValueIgnoringVisibility();
1088 }
1089 // It is only possible for there to be `FencedFrameProperties` but no
1090 // partition nonce in urn iframes (when not nested inside a fenced frame).
1091 CHECK(blink::features::IsAllowURNsInIframeEnabled());
1092 CHECK(!IsInFencedFrameTree());
Arthur Sonzognic686e8f2024-01-11 08:36:371093 return std::nullopt;
Garrett Tanzer34cb92fe2022-09-28 17:50:541094}
1095
1096void FrameTreeNode::SetFencedFramePropertiesIfNeeded() {
1097 if (!IsFencedFrameRoot()) {
shivanigithub4cd016a2021-09-20 21:10:301098 return;
1099 }
1100
Garrett Tanzer34cb92fe2022-09-28 17:50:541101 // The fenced frame properties are set only on the fenced frame root.
1102 // In the future, they will be set on the FrameTree instead.
Garrett Tanzer29de7112022-12-06 21:26:321103 fenced_frame_properties_ = FencedFrameProperties();
shivanigithub4cd016a2021-09-20 21:10:301104}
1105
Garrett Tanzer291a2d52023-03-20 22:41:571106blink::FencedFrame::DeprecatedFencedFrameMode
1107FrameTreeNode::GetDeprecatedFencedFrameMode() {
Garrett Tanzera42fdef2022-06-13 16:09:141108 if (!IsInFencedFrameTree()) {
Garrett Tanzer291a2d52023-03-20 22:41:571109 return blink::FencedFrame::DeprecatedFencedFrameMode::kDefault;
Garrett Tanzera42fdef2022-06-13 16:09:141110 }
Nan Lin171fe9a2022-02-17 16:42:161111
Xiaochen Zhou86f2e712023-09-13 19:55:041112 // See test "NestedUrnIframeUnderFencedFrameUnfencedTopNavigation" in
1113 // "FencedFrameParameterizedBrowserTest" for why tree traversal is
1114 // needed here to obtain the correct fenced frame properties.
Alison Gale81f4f2c72024-04-22 19:33:311115 // TODO(crbug.com/40279729): Now the fenced frame properties here are obtained
Xiaochen Zhou86f2e712023-09-13 19:55:041116 // via tree traversal, we should make sure it does not break things at
1117 // renderers, for example, `_unfencedTop` navigation. Note these issues are
1118 // pre-existing.
Alison Gale770f3fc2024-04-27 00:39:581119 // TODO(crbug.com/40060657): Once navigation support for urn::uuid in iframes
Xiaochen Zhou86f2e712023-09-13 19:55:041120 // is deprecated, the issue above will no longer be relevant.
Garrett Tanzer291a2d52023-03-20 22:41:571121 auto& root_fenced_frame_properties = GetFencedFrameProperties();
1122 if (!root_fenced_frame_properties.has_value()) {
1123 return blink::FencedFrame::DeprecatedFencedFrameMode::kDefault;
1124 }
Nan Lin171fe9a2022-02-17 16:42:161125
Garrett Tanzer06980702023-12-12 19:48:201126 return root_fenced_frame_properties->mode();
Nan Lin171fe9a2022-02-17 16:42:161127}
1128
Nan Linaaf84f72021-12-02 22:31:561129bool FrameTreeNode::IsErrorPageIsolationEnabled() const {
Nan Lind9de87d2022-03-18 16:53:031130 // Error page isolation is enabled for main frames only (crbug.com/1092524).
Nan Lind9de87d2022-03-18 16:53:031131 return SiteIsolationPolicy::IsErrorPageIsolationEnabled(IsMainFrame());
Nan Linaaf84f72021-12-02 22:31:561132}
1133
W. James MacLean81b8d01f2022-01-25 20:50:591134void FrameTreeNode::SetSrcdocValue(const std::string& srcdoc_value) {
1135 srcdoc_value_ = srcdoc_value;
1136}
1137
Garrett Tanzer29de7112022-12-06 21:26:321138std::vector<const SharedStorageBudgetMetadata*>
Yao Xiao1ac702d2022-06-08 17:20:491139FrameTreeNode::FindSharedStorageBudgetMetadata() {
Garrett Tanzer29de7112022-12-06 21:26:321140 std::vector<const SharedStorageBudgetMetadata*> result;
Yao Xiao1ac702d2022-06-08 17:20:491141 FrameTreeNode* node = this;
1142
1143 while (true) {
Garrett Tanzer2975eeac2022-08-22 16:34:011144 if (node->fenced_frame_properties_ &&
Garrett Tanzer06980702023-12-12 19:48:201145 node->fenced_frame_properties_->shared_storage_budget_metadata()) {
Garrett Tanzer29de7112022-12-06 21:26:321146 result.emplace_back(
Garrett Tanzer06980702023-12-12 19:48:201147 node->fenced_frame_properties_->shared_storage_budget_metadata()
Garrett Tanzer29de7112022-12-06 21:26:321148 ->GetValueIgnoringVisibility());
Yao Xiao1ac702d2022-06-08 17:20:491149 }
1150
Garrett Tanzer29de7112022-12-06 21:26:321151 if (!node->GetParentOrOuterDocument()) {
Yao Xiao1ac702d2022-06-08 17:20:491152 break;
1153 }
Garrett Tanzer29de7112022-12-06 21:26:321154
1155 node = node->GetParentOrOuterDocument()->frame_tree_node();
Yao Xiao1ac702d2022-06-08 17:20:491156 }
1157
Yao Xiaoa2337ad2022-10-12 20:59:291158 return result;
Yao Xiao1ac702d2022-06-08 17:20:491159}
1160
Arthur Sonzognic686e8f2024-01-11 08:36:371161std::optional<std::u16string>
Camillia Smith Barnes7218518c2023-03-06 19:02:171162FrameTreeNode::GetEmbedderSharedStorageContextIfAllowed() {
Arthur Sonzognic686e8f2024-01-11 08:36:371163 std::optional<FencedFrameProperties>& properties = GetFencedFrameProperties();
Camillia Smith Barnes7218518c2023-03-06 19:02:171164 // We only return embedder context for frames that are same origin with the
1165 // fenced frame root or ancestor URN iframe.
Garrett Tanzer06980702023-12-12 19:48:201166 if (!properties || !properties->mapped_url().has_value() ||
Camillia Smith Barnes7218518c2023-03-06 19:02:171167 !current_origin().IsSameOriginWith(url::Origin::Create(
Garrett Tanzer06980702023-12-12 19:48:201168 properties->mapped_url()->GetValueIgnoringVisibility()))) {
Arthur Sonzognic686e8f2024-01-11 08:36:371169 return std::nullopt;
Camillia Smith Barnes7218518c2023-03-06 19:02:171170 }
Garrett Tanzer06980702023-12-12 19:48:201171 return properties->embedder_shared_storage_context();
Camillia Smith Barnes7218518c2023-03-06 19:02:171172}
1173
Harkiran Bolariaebbe7702022-02-22 19:19:031174const scoped_refptr<BrowsingContextState>&
1175FrameTreeNode::GetBrowsingContextStateForSubframe() const {
1176 DCHECK(!IsMainFrame());
1177 return current_frame_host()->browsing_context_state();
1178}
1179
Arthur Hemerye4659282022-03-28 08:36:151180void FrameTreeNode::ClearOpenerReferences() {
1181 // Simulate the FrameTreeNode being dead to opener observers. They will
1182 // nullify their opener.
1183 // Note: observers remove themselves from observers_, no need to take care of
1184 // that manually.
1185 for (auto& observer : observers_)
1186 observer.OnFrameTreeNodeDisownedOpenee(this);
1187}
1188
Liam Bradyd2a41e152022-07-19 13:58:481189bool FrameTreeNode::AncestorOrSelfHasCSPEE() const {
1190 // Check if CSPEE is set in this frame or any ancestor frames.
Yuzu Saijo03dbf9b2022-07-22 04:29:451191 return csp_attribute() || (parent() && parent()->required_csp());
Liam Bradyd2a41e152022-07-19 13:58:481192}
1193
Arthur Sonzogni8e8eb1f2023-01-10 14:51:011194void FrameTreeNode::ResetAllNavigationsForFrameDetach() {
1195 NavigationDiscardReason reason = NavigationDiscardReason::kWillRemoveFrame;
1196 for (FrameTreeNode* frame : frame_tree().SubtreeNodes(this)) {
1197 frame->ResetNavigationRequest(reason);
1198 frame->current_frame_host()->ResetOwnedNavigationRequests(reason);
1199 frame->GetRenderFrameHostManager().DiscardSpeculativeRFH(reason);
1200 }
1201}
1202
Miyoung Shin7cf88b42022-11-07 13:22:301203void FrameTreeNode::RestartNavigationAsCrossDocument(
1204 std::unique_ptr<NavigationRequest> navigation_request) {
1205 navigator().RestartNavigationAsCrossDocument(std::move(navigation_request));
1206}
1207
Miyoung Shin1504eb712022-12-07 10:32:181208bool FrameTreeNode::Reload() {
1209 return navigator().controller().ReloadFrame(this);
1210}
1211
Julie Jeongeun Kimc1b07c32022-11-11 10:26:321212Navigator& FrameTreeNode::GetCurrentNavigator() {
1213 return navigator();
1214}
1215
Miyoung Shine16cd2262022-11-30 05:52:161216RenderFrameHostManager& FrameTreeNode::GetRenderFrameHostManager() {
1217 return render_manager_;
1218}
1219
Miyoung Shin64fd1bea2023-01-04 04:22:081220FrameTreeNode* FrameTreeNode::GetOpener() const {
1221 return opener_;
1222}
1223
Julie Jeongeun Kim2132b37f82022-11-23 08:30:461224void FrameTreeNode::SetFocusedFrame(SiteInstanceGroup* source) {
1225 frame_tree_->delegate()->SetFocusedFrame(this, source);
1226}
1227
Julie Jeongeun Kim0e242242022-11-30 10:45:091228void FrameTreeNode::DidChangeReferrerPolicy(
1229 network::mojom::ReferrerPolicy referrer_policy) {
1230 navigator().controller().DidChangeReferrerPolicy(this, referrer_policy);
1231}
1232
Miyoung Shinff13ed22022-11-30 09:21:471233std::unique_ptr<NavigationRequest>
1234FrameTreeNode::CreateNavigationRequestForSynchronousRendererCommit(
1235 RenderFrameHostImpl* render_frame_host,
1236 bool is_same_document,
1237 const GURL& url,
1238 const url::Origin& origin,
Arthur Sonzognic686e8f2024-01-11 08:36:371239 const std::optional<GURL>& initiator_base_url,
Miyoung Shinff13ed22022-11-30 09:21:471240 const net::IsolationInfo& isolation_info_for_subresources,
1241 blink::mojom::ReferrerPtr referrer,
1242 const ui::PageTransition& transition,
1243 bool should_replace_current_entry,
1244 const std::string& method,
1245 bool has_transient_activation,
1246 bool is_overriding_user_agent,
1247 const std::vector<GURL>& redirects,
1248 const GURL& original_url,
1249 std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter,
Camille Lamy36afacd2025-01-16 14:25:181250 std::unique_ptr<DocumentIsolationPolicyReporter> dip_reporter,
Charlie Reise1d9b8182025-04-02 04:32:121251 int http_response_code,
1252 base::TimeTicks actual_navigation_start) {
Miyoung Shinff13ed22022-11-30 09:21:471253 return NavigationRequest::CreateForSynchronousRendererCommit(
1254 this, render_frame_host, is_same_document, url, origin,
W. James MacLean23e90a12022-12-21 04:38:211255 initiator_base_url, isolation_info_for_subresources, std::move(referrer),
1256 transition, should_replace_current_entry, method,
1257 has_transient_activation, is_overriding_user_agent, redirects,
Camille Lamy36afacd2025-01-16 14:25:181258 original_url, std::move(coep_reporter), std::move(dip_reporter),
Charlie Reise1d9b8182025-04-02 04:32:121259 http_response_code, actual_navigation_start);
Miyoung Shinff13ed22022-11-30 09:21:471260}
1261
Rakina Zata Amni58681c62024-06-25 06:32:131262void FrameTreeNode::CancelNavigation(NavigationDiscardReason reason) {
Miyoung Shinb5561802022-12-01 08:21:351263 if (navigation_request() && navigation_request()->IsNavigationStarted()) {
1264 navigation_request()->set_net_error(net::ERR_ABORTED);
1265 }
Rakina Zata Amni58681c62024-06-25 06:32:131266 ResetNavigationRequest(reason);
Miyoung Shinb5561802022-12-01 08:21:351267}
1268
Thomas Lukaszewicz1b672fe2024-09-17 08:35:031269void FrameTreeNode::ResetNavigationsForDiscard() {
1270 for (FrameTreeNode* frame : frame_tree().SubtreeNodes(this)) {
1271 // TODO(crbug.com/365481515): Consider adding a separate discard reason for
1272 // frame tree discarding.
1273 frame->ResetNavigationRequest(NavigationDiscardReason::kWillRemoveFrame);
1274 frame->current_frame_host()->ResetOwnedNavigationRequests(
1275 NavigationDiscardReason::kWillRemoveFrame);
1276 }
1277}
1278
Miyoung Shinc9ff4812023-01-05 08:58:051279bool FrameTreeNode::Credentialless() const {
1280 return attributes_->credentialless;
1281}
1282
Kevin McNeef1b0f0b2024-09-17 21:49:411283FrameType FrameTreeNode::GetCurrentFrameType() const {
1284 return GetFrameType();
1285}
1286
Mingyu Lei7956b8b2023-07-24 08:24:081287void FrameTreeNode::RestartBackForwardCachedNavigationAsync(int nav_entry_id) {
1288 TRACE_EVENT0("navigation",
1289 "FrameTreeNode::RestartBackForwardCachedNavigationAsync");
1290 // The `navigation_request_` must be the BFCache navigation to the same entry
1291 // as the restarted navigation.
1292 CHECK(navigation_request_->IsServedFromBackForwardCache());
1293 CHECK_EQ(navigation_request_->nav_entry_id(), nav_entry_id);
1294 // Reset the `NavigationRequest` since the BFCache navigation will be
1295 // restarted.
Rakina Zata Amnib5dbc9f2024-07-16 07:47:331296 ResetNavigationRequest(NavigationDiscardReason::kInternalCancellation);
Mingyu Lei7956b8b2023-07-24 08:24:081297
1298 // Post a task to restart the navigation asynchronously.
1299 restart_back_forward_cached_navigation_tracker_.PostTask(
1300 GetUIThreadTaskRunner({}).get(), FROM_HERE,
1301 base::BindOnce(&FrameTreeNode::RestartBackForwardCachedNavigationImpl,
1302 weak_factory_.GetWeakPtr(), nav_entry_id));
1303}
1304
1305void FrameTreeNode::RestartBackForwardCachedNavigationImpl(int nav_entry_id) {
1306 TRACE_EVENT0("navigation",
1307 "FrameTreeNode::RestartBackForwardCachedNavigationImpl");
1308 NavigationControllerImpl& controller = frame_tree_->controller();
1309 int nav_index = controller.GetEntryIndexWithUniqueID(nav_entry_id);
1310 // If the NavigationEntry was deleted, do not do anything.
1311 if (nav_index != -1) {
1312 controller.GoToIndex(nav_index);
1313 }
1314}
1315
1316void FrameTreeNode::CancelRestartingBackForwardCacheNavigation() {
1317 TRACE_EVENT0("navigation",
1318 "FrameTreeNode::CancelRestartingBackForwardCacheNavigation");
1319 restart_back_forward_cached_navigation_tracker_.TryCancelAll();
1320}
1321
[email protected]9b159a52013-10-03 17:24:551322} // namespace content