blob: bda0a796a20a3b5ffc5f223b396b0c3cae0ad09d [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>
[email protected]9b159a52013-10-03 17:24:558#include <queue>
Takuto Ikutaadf31eb2019-01-05 00:32:489#include <unordered_map>
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"
David Sandersd4bf5eb2022-03-17 07:12:0518#include "base/observer_list.h"
Clark DuVallc97bcf72021-12-08 22:58:2419#include "base/strings/strcat.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4120#include "base/strings/string_util.h"
Clark DuVallc97bcf72021-12-08 22:58:2421#include "base/timer/elapsed_timer.h"
Andrey Kosyakovf2d4ff72018-10-29 20:09:5922#include "content/browser/devtools/devtools_instrumentation.h"
Dominic Farolino8a2187b2021-12-24 20:44:2123#include "content/browser/fenced_frame/fenced_frame.h"
Miyoung Shinff13ed22022-11-30 09:21:4724#include "content/browser/network/cross_origin_embedder_policy_reporter.h"
Paul Semel3e241042022-10-11 12:57:3125#include "content/browser/renderer_host/frame_tree.h"
danakjc492bf82020-09-09 20:02:4426#include "content/browser/renderer_host/navigation_controller_impl.h"
27#include "content/browser/renderer_host/navigation_request.h"
28#include "content/browser/renderer_host/navigator.h"
29#include "content/browser/renderer_host/navigator_delegate.h"
30#include "content/browser/renderer_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4131#include "content/browser/renderer_host/render_view_host_impl.h"
Adam Langley1e03fb02023-03-16 23:02:0332#include "content/browser/webauth/authenticator_environment.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"
Harkiran Bolaria59290d62021-03-17 01:53:0139#include "third_party/blink/public/common/features.h"
Liam Bradyb0f1f0e2022-08-19 21:42:1140#include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1541#include "third_party/blink/public/common/loader/loader_constants.h"
Antonio Gomes4b2c5132020-01-16 11:49:4842#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:3743#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
[email protected]9b159a52013-10-03 17:24:5544
45namespace content {
46
dmazzonie950ea232015-03-13 21:39:4547namespace {
48
49// This is a global map between frame_tree_node_ids and pointers to
50// FrameTreeNodes.
Takuto Ikutaadf31eb2019-01-05 00:32:4851typedef std::unordered_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4552
scottmg5e65e3a2017-03-08 08:48:4653base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
54 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4555
Nan Line376738a2022-03-25 22:05:4156FencedFrame* FindFencedFrame(const FrameTreeNode* frame_tree_node) {
57 // TODO(crbug.com/1123606): Consider having a pointer to `FencedFrame` in
58 // `FrameTreeNode` or having a map between them.
59
60 // Try and find the `FencedFrame` that `frame_tree_node` represents.
61 DCHECK(frame_tree_node->parent());
62 std::vector<FencedFrame*> fenced_frames =
63 frame_tree_node->parent()->GetFencedFrames();
64 for (FencedFrame* fenced_frame : fenced_frames) {
65 if (frame_tree_node->frame_tree_node_id() ==
66 fenced_frame->GetOuterDelegateFrameTreeNodeId()) {
67 return fenced_frame;
68 }
69 }
70 return nullptr;
71}
72
fdegansa696e5112015-04-17 01:57:5973} // namespace
fdegans1d16355162015-03-26 11:58:3474
alexmose201c7cd2015-06-10 17:14:2175// This observer watches the opener of its owner FrameTreeNode and clears the
Arthur Hemerye4659282022-03-28 08:36:1576// owner's opener if the opener is destroyed or swaps BrowsingInstance.
alexmose201c7cd2015-06-10 17:14:2177class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
78 public:
jochen6004a362017-02-04 00:11:4079 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
80 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2181
Peter Boström9b036532021-10-28 23:37:2882 OpenerDestroyedObserver(const OpenerDestroyedObserver&) = delete;
83 OpenerDestroyedObserver& operator=(const OpenerDestroyedObserver&) = delete;
84
alexmose201c7cd2015-06-10 17:14:2185 // FrameTreeNode::Observer
86 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
Arthur Hemerye4659282022-03-28 08:36:1587 NullifyOpener(node);
88 }
89
90 // FrameTreeNode::Observer
91 void OnFrameTreeNodeDisownedOpenee(FrameTreeNode* node) override {
92 NullifyOpener(node);
93 }
94
95 void NullifyOpener(FrameTreeNode* node) {
jochen6004a362017-02-04 00:11:4096 if (observing_original_opener_) {
Rakina Zata Amni3a48ae42022-05-05 03:39:5697 // The "original opener" is special. It's used for attribution, and
98 // clients walk down the original opener chain. Therefore, if a link in
99 // the chain is being destroyed, reconnect the observation to the parent
100 // of the link being destroyed.
101 CHECK_EQ(owner_->first_live_main_frame_in_original_opener_chain(), node);
102 owner_->SetOriginalOpener(
103 node->first_live_main_frame_in_original_opener_chain());
Avi Drissman36465f332017-09-11 20:49:39104 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:40105 } else {
106 CHECK_EQ(owner_->opener(), node);
107 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:39108 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:40109 }
alexmose201c7cd2015-06-10 17:14:21110 }
111
112 private:
Keishi Hattori0e45c022021-11-27 09:25:52113 raw_ptr<FrameTreeNode> owner_;
jochen6004a362017-02-04 00:11:40114 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:21115};
116
Kevin McNee88e61552020-10-22 20:41:11117const int FrameTreeNode::kFrameTreeNodeInvalidId = -1;
118
119static_assert(FrameTreeNode::kFrameTreeNodeInvalidId ==
120 RenderFrameHost::kNoFrameTreeNodeId,
121 "Have consistent sentinel values for an invalid FTN id.");
122
vishal.b782eb5d2015-04-29 12:22:57123int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:55124
dmazzonie950ea232015-03-13 21:39:45125// static
vishal.b782eb5d2015-04-29 12:22:57126FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:19127 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:15128 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:46129 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:45130 return it == nodes->end() ? nullptr : it->second;
131}
132
Alexander Timin381e7e182020-04-28 19:04:03133// static
134FrameTreeNode* FrameTreeNode::From(RenderFrameHost* rfh) {
135 if (!rfh)
136 return nullptr;
137 return static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
138}
139
Abhijeet Kandalkarb43affa72022-09-27 16:48:01140FrameTreeNode::FencedFrameStatus ComputeFencedFrameStatus(
Arthur Sonzognif6785ec2022-12-05 10:11:50141 const FrameTree& frame_tree,
Harkiran Bolaria16f2c48d2022-04-22 12:39:57142 RenderFrameHostImpl* parent,
143 const blink::FramePolicy& frame_policy) {
Abhijeet Kandalkarb43affa72022-09-27 16:48:01144 using FencedFrameStatus = FrameTreeNode::FencedFrameStatus;
Dominic Farolino0b067632022-11-11 02:57:49145 if (blink::features::IsFencedFramesEnabled() &&
Takashi Toyoshima7c041d82023-09-26 16:09:21146 frame_tree.is_fenced_frame()) {
147 if (!parent) {
Dominic Farolino0b067632022-11-11 02:57:49148 return FencedFrameStatus::kFencedFrameRoot;
Takashi Toyoshima7c041d82023-09-26 16:09:21149 }
Dominic Farolino0b067632022-11-11 02:57:49150 return FencedFrameStatus::kIframeNestedWithinFencedFrame;
Harkiran Bolaria16f2c48d2022-04-22 12:39:57151 }
152
Abhijeet Kandalkar3f29bc42022-09-23 12:39:58153 return FencedFrameStatus::kNotNestedInFencedFrame;
Harkiran Bolaria16f2c48d2022-04-22 12:39:57154}
155
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54156FrameTreeNode::FrameTreeNode(
Arthur Sonzognif6785ec2022-12-05 10:11:50157 FrameTree& frame_tree,
Alexander Timin381e7e182020-04-28 19:04:03158 RenderFrameHostImpl* parent,
Daniel Cheng6ac128172021-05-25 18:49:01159 blink::mojom::TreeScopeType tree_scope_type,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54160 bool is_created_by_script,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54161 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Kevin McNee43fe8292021-10-04 22:59:41162 blink::FrameOwnerElementType owner_type,
Dominic Farolino08662c82021-06-11 07:36:34163 const blink::FramePolicy& frame_policy)
[email protected]bffc8302014-01-23 20:52:16164 : frame_tree_(frame_tree),
[email protected]bffc8302014-01-23 20:52:16165 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59166 parent_(parent),
Daniel Cheng9bd90f92021-04-23 20:49:45167 frame_owner_element_type_(owner_type),
Daniel Cheng6ac128172021-05-25 18:49:01168 tree_scope_type_(tree_scope_type),
Dominic Farolino08662c82021-06-11 07:36:34169 pending_frame_policy_(frame_policy),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45170 is_created_by_script_(is_created_by_script),
lazyboy70605c32015-11-03 01:27:31171 frame_owner_properties_(frame_owner_properties),
Yuzu Saijo03dbf9b2022-07-22 04:29:45172 attributes_(blink::mojom::IframeAttributes::New()),
Harkiran Bolaria16f2c48d2022-04-22 12:39:57173 fenced_frame_status_(
Arthur Sonzognif6785ec2022-12-05 10:11:50174 ComputeFencedFrameStatus(frame_tree, parent_, frame_policy)),
175 render_manager_(this, frame_tree.manager_delegate()) {
Harkiran Bolariaa8347782022-04-06 09:25:11176 TRACE_EVENT_BEGIN("navigation", "FrameTreeNode",
177 perfetto::Track::FromPointer(this),
178 "frame_tree_node_when_created", this);
rob97250742015-12-10 17:45:15179 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45180 g_frame_tree_node_id_map.Get().insert(
181 std::make_pair(frame_tree_node_id_, this));
182 CHECK(result.second);
alexmos998581d2015-01-22 01:01:59183}
[email protected]9b159a52013-10-03 17:24:55184
Dominic Farolino8a2187b2021-12-24 20:44:21185void FrameTreeNode::DestroyInnerFrameTreeIfExists() {
186 // If `this` is an dummy outer delegate node, then we really are representing
187 // an inner FrameTree for one of the following consumers:
Dominic Farolino8a2187b2021-12-24 20:44:21188 // - `FencedFrame`
189 // - `GuestView`
190 // If we are representing a `FencedFrame` object, we need to destroy it
Jeremy Romanc0c69be2023-11-21 19:14:52191 // alongside ourself. `GuestView` however, *currently* has a more complex
192 // lifetime and is dealt with separately.
Dominic Farolino8a2187b2021-12-24 20:44:21193 bool is_outer_dummy_node = false;
194 if (current_frame_host() &&
195 current_frame_host()->inner_tree_main_frame_tree_node_id() !=
196 FrameTreeNode::kFrameTreeNodeInvalidId) {
197 is_outer_dummy_node = true;
198 }
199
200 if (is_outer_dummy_node) {
Jeremy Romanc0c69be2023-11-21 19:14:52201 if (FencedFrame* doomed_fenced_frame = FindFencedFrame(this)) {
Dominic Farolino8a2187b2021-12-24 20:44:21202 parent()->DestroyFencedFrame(*doomed_fenced_frame);
203 }
204 }
205}
206
[email protected]9b159a52013-10-03 17:24:55207FrameTreeNode::~FrameTreeNode() {
Harkiran Bolariaa8347782022-04-06 09:25:11208 TRACE_EVENT("navigation", "FrameTreeNode::~FrameTreeNode");
Daniel Chengc3d1e8d2021-06-23 02:11:45209 // There should always be a current RenderFrameHost except during prerender
210 // activation. Prerender activation moves the current RenderFrameHost from
211 // the old FrameTree's FrameTreeNode to the new FrameTree's FrameTreeNode and
212 // then destroys the old FrameTree. See
213 // `RenderFrameHostManager::TakePrerenderedPage()`.
Harkiran Bolaria59290d62021-03-17 01:53:01214 if (current_frame_host()) {
215 // Remove the children.
216 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45217
Harkiran Bolaria59290d62021-03-17 01:53:01218 current_frame_host()->ResetLoadingState();
219 } else {
Harkiran Bolaria59290d62021-03-17 01:53:01220 DCHECK(!parent()); // Only main documents can be activated.
221 DCHECK(!opener()); // Prerendered frame trees can't have openers.
222
223 // Activation is not allowed during ongoing navigations.
Kevin McNeeb63b1ce2023-03-27 14:57:20224 CHECK(!navigation_request_);
Harkiran Bolaria59290d62021-03-17 01:53:01225
Carlos Caballerod1c80432021-04-20 08:16:32226 // TODO(https://crbug.com/1199693): Need to determine how to handle pending
Harkiran Bolaria59290d62021-03-17 01:53:01227 // deletions, as observers will be notified.
Kevin McNeeb63b1ce2023-03-27 14:57:20228 CHECK(!render_manager()->speculative_frame_host());
Harkiran Bolaria59290d62021-03-17 01:53:01229 }
Nate Chapin22ea6592019-03-05 22:29:02230
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45231 // If the removed frame was created by a script, then its history entry will
232 // never be reused - we can save some memory by removing the history entry.
233 // See also https://crbug.com/784356.
234 if (is_created_by_script_ && parent_) {
Carlos Caballero04aab362021-02-15 17:38:16235 NavigationEntryImpl* nav_entry =
236 navigator().controller().GetLastCommittedEntry();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45237 if (nav_entry) {
238 nav_entry->RemoveEntryForFrame(this,
239 /* only_if_different_position = */ false);
240 }
241 }
242
dmazzonie950ea232015-03-13 21:39:45243 frame_tree_->FrameRemoved(this);
Carlos Caballero6ff6ace2021-02-05 16:53:00244
Dominic Farolino8a2187b2021-12-24 20:44:21245 DestroyInnerFrameTreeIfExists();
246
Alex Rudenkobfc5c192022-11-03 07:27:37247 devtools_instrumentation::OnFrameTreeNodeDestroyed(*this);
Carlos Caballero6ff6ace2021-02-05 16:53:00248 // Do not dispatch notification for the root frame as ~WebContentsImpl already
249 // dispatches it for now.
250 // TODO(https://crbug.com/1170277): This is only needed because the FrameTree
251 // is a member of WebContentsImpl and we would call back into it during
252 // destruction. We should clean up the FrameTree destruction code and call the
253 // delegate unconditionally.
254 if (parent())
255 render_manager_.delegate()->OnFrameTreeNodeDestroyed(this);
256
ericwilligers254597b2016-10-17 10:32:31257 for (auto& observer : observers_)
258 observer.OnFrameTreeNodeDestroyed(this);
Lukasz Anforowicz147141962020-12-16 18:03:24259 observers_.Clear();
alexmose201c7cd2015-06-10 17:14:21260
261 if (opener_)
262 opener_->RemoveObserver(opener_observer_.get());
Rakina Zata Amni3a48ae42022-05-05 03:39:56263 if (first_live_main_frame_in_original_opener_chain_)
264 first_live_main_frame_in_original_opener_chain_->RemoveObserver(
265 original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45266
267 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18268
Daniel Chengc3d1e8d2021-06-23 02:11:45269 // If a frame with a pending navigation is detached, make sure the
270 // WebContents (and its observers) update their loading state.
271 // TODO(dcheng): This should just check `IsLoading()`, but `IsLoading()`
272 // assumes that `current_frame_host_` is not null. This is incompatible with
273 // prerender activation when destroying the old frame tree (see above).
danakjf9400602019-06-07 15:44:58274 bool did_stop_loading = false;
275
jam39258caf2016-11-02 14:48:18276 if (navigation_request_) {
danakjf9400602019-06-07 15:44:58277 navigation_request_.reset();
danakjf9400602019-06-07 15:44:58278 did_stop_loading = true;
jam39258caf2016-11-02 14:48:18279 }
Nate Chapin22ea6592019-03-05 22:29:02280
danakjf9400602019-06-07 15:44:58281 // ~SiteProcessCountTracker DCHECKs in some tests if the speculative
282 // RenderFrameHostImpl is not destroyed last. Ideally this would be closer to
283 // (possible before) the ResetLoadingState() call above.
danakjf9400602019-06-07 15:44:58284 if (render_manager_.speculative_frame_host()) {
Daniel Chengc3d1e8d2021-06-23 02:11:45285 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative
286 // RenderFrameHost always be considered loading?
danakjf9400602019-06-07 15:44:58287 did_stop_loading |= render_manager_.speculative_frame_host()->is_loading();
Daniel Chengc3d1e8d2021-06-23 02:11:45288 // `FrameTree::Shutdown()` has special handling for the main frame's
289 // speculative RenderFrameHost, and the speculative RenderFrameHost should
290 // already be reset for main frames.
291 DCHECK(!IsMainFrame());
292
293 // This does not use `UnsetSpeculativeRenderFrameHost()`: if the speculative
294 // RenderFrameHost has already reached kPendingCommit, it would needlessly
295 // re-create a proxy for a frame that's going away.
296 render_manager_.DiscardSpeculativeRenderFrameHostForShutdown();
danakjf9400602019-06-07 15:44:58297 }
298
299 if (did_stop_loading)
300 DidStopLoading();
301
Harkiran Bolaria59290d62021-03-17 01:53:01302 // IsLoading() requires that current_frame_host() is non-null.
303 DCHECK(!current_frame_host() || !IsLoading());
Harkiran Bolariaa8347782022-04-06 09:25:11304
305 // Matches the TRACE_EVENT_BEGIN in the constructor.
306 TRACE_EVENT_END("navigation", perfetto::Track::FromPointer(this));
[email protected]9b159a52013-10-03 17:24:55307}
308
alexmose201c7cd2015-06-10 17:14:21309void FrameTreeNode::AddObserver(Observer* observer) {
310 observers_.AddObserver(observer);
311}
312
313void FrameTreeNode::RemoveObserver(Observer* observer) {
314 observers_.RemoveObserver(observer);
315}
316
[email protected]94d0cc12013-12-18 00:07:41317bool FrameTreeNode::IsMainFrame() const {
318 return frame_tree_->root() == this;
319}
320
Paul Semel3e241042022-10-11 12:57:31321Navigator& FrameTreeNode::navigator() {
Arthur Sonzognif6785ec2022-12-05 10:11:50322 return frame_tree().navigator();
Paul Semel3e241042022-10-11 12:57:31323}
324
Arthur Hemerya06697f2023-03-14 09:20:57325bool FrameTreeNode::IsOutermostMainFrame() const {
Ian Vollick25a9d032022-04-12 23:20:17326 return !GetParentOrOuterDocument();
327}
328
Hiroki Nakagawaab309622021-05-19 16:38:13329void FrameTreeNode::ResetForNavigation() {
arthursonzogni76098e52020-11-25 14:18:45330 // This frame has had its user activation bits cleared in the renderer before
331 // arriving here. We just need to clear them here and in the other renderer
332 // processes that may have a reference to this frame.
Alexander Timin45b716c2020-11-06 01:40:31333 //
334 // We do not take user activation into account when calculating
335 // |ResetForNavigationResult|, as we are using it to determine bfcache
336 // eligibility and the page can get another user gesture after restore.
Antonio Gomes4b2c5132020-01-16 11:49:48337 UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11338 blink::mojom::UserActivationUpdateType::kClearActivation,
339 blink::mojom::UserActivationNotificationType::kNone);
Ian Clelland5cbaaf82017-11-27 22:00:03340}
341
Arthur Hemerya06697f2023-03-14 09:20:57342RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocument() const {
Kevin McNee86e64ee2023-02-17 16:35:50343 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/false,
344 /*include_prospective=*/true);
Dave Tapuskac8de3b02021-12-03 21:51:01345}
346
347RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentOrEmbedder() {
Kevin McNee86e64ee2023-02-17 16:35:50348 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/true,
349 /*include_prospective=*/true);
Dave Tapuskac8de3b02021-12-03 21:51:01350}
351
352RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentHelper(
Kevin McNee86e64ee2023-02-17 16:35:50353 bool escape_guest_view,
Arthur Hemerya06697f2023-03-14 09:20:57354 bool include_prospective) const {
Dave Tapuskac8de3b02021-12-03 21:51:01355 // Find the parent in the FrameTree (iframe).
Kevin McNee86e64ee2023-02-17 16:35:50356 if (parent_) {
Dave Tapuskac8de3b02021-12-03 21:51:01357 return parent_;
Kevin McNee86e64ee2023-02-17 16:35:50358 }
Dave Tapuskac8de3b02021-12-03 21:51:01359
360 if (!escape_guest_view) {
Jeremy Romanc0c69be2023-11-21 19:14:52361 // If we are not a fenced frame root then return early.
Dave Tapuskac8de3b02021-12-03 21:51:01362 // This code does not escape GuestViews.
Jeremy Romanc0c69be2023-11-21 19:14:52363 if (!IsFencedFrameRoot()) {
Dave Tapuskac8de3b02021-12-03 21:51:01364 return nullptr;
Kevin McNee86e64ee2023-02-17 16:35:50365 }
Dave Tapuskac8de3b02021-12-03 21:51:01366 }
367
Jeremy Romanc0c69be2023-11-21 19:14:52368 // Find the parent in the outer embedder (GuestView or Fenced Frame).
Dave Tapuskac8de3b02021-12-03 21:51:01369 FrameTreeNode* frame_in_embedder = render_manager()->GetOuterDelegateNode();
Kevin McNee86e64ee2023-02-17 16:35:50370 if (frame_in_embedder) {
Dave Tapuskac8de3b02021-12-03 21:51:01371 return frame_in_embedder->current_frame_host()->GetParent();
Kevin McNee86e64ee2023-02-17 16:35:50372 }
373
374 // Consider embedders which own our frame tree, but have not yet attached it
375 // to the outer frame tree.
376 if (include_prospective) {
377 RenderFrameHostImpl* prospective_outer_document =
378 frame_tree_->delegate()->GetProspectiveOuterDocument();
379 if (prospective_outer_document) {
380 return prospective_outer_document;
381 }
382 }
Dave Tapuskac8de3b02021-12-03 21:51:01383
384 // No parent found.
385 return nullptr;
386}
387
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55388FrameType FrameTreeNode::GetFrameType() const {
389 if (!IsMainFrame())
390 return FrameType::kSubframe;
391
Arthur Sonzognif6785ec2022-12-05 10:11:50392 switch (frame_tree().type()) {
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55393 case FrameTree::Type::kPrimary:
394 return FrameType::kPrimaryMainFrame;
395 case FrameTree::Type::kPrerender:
396 return FrameType::kPrerenderMainFrame;
397 case FrameTree::Type::kFencedFrame:
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55398 return FrameType::kFencedFrameRoot;
399 }
400}
401
alexmose201c7cd2015-06-10 17:14:21402void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
Harkiran Bolariaa8347782022-04-06 09:25:11403 TRACE_EVENT("navigation", "FrameTreeNode::SetOpener",
404 ChromeTrackEvent::kFrameTreeNodeInfo, opener);
alexmose201c7cd2015-06-10 17:14:21405 if (opener_) {
406 opener_->RemoveObserver(opener_observer_.get());
407 opener_observer_.reset();
408 }
409
410 opener_ = opener;
411
412 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55413 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21414 opener_->AddObserver(opener_observer_.get());
415 }
416}
417
Wolfgang Beyerd8809db2020-09-30 15:29:39418void FrameTreeNode::SetOpenerDevtoolsFrameToken(
419 base::UnguessableToken opener_devtools_frame_token) {
420 DCHECK(!opener_devtools_frame_token_ ||
421 opener_devtools_frame_token_->is_empty());
422 opener_devtools_frame_token_ = std::move(opener_devtools_frame_token);
423}
424
jochen6004a362017-02-04 00:11:40425void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39426 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37427 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40428
Rakina Zata Amni3a48ae42022-05-05 03:39:56429 if (first_live_main_frame_in_original_opener_chain_) {
430 first_live_main_frame_in_original_opener_chain_->RemoveObserver(
431 original_opener_observer_.get());
Avi Drissman36465f332017-09-11 20:49:39432 original_opener_observer_.reset();
433 }
434
Rakina Zata Amni3a48ae42022-05-05 03:39:56435 first_live_main_frame_in_original_opener_chain_ = opener;
jochen6004a362017-02-04 00:11:40436
Rakina Zata Amni3a48ae42022-05-05 03:39:56437 if (first_live_main_frame_in_original_opener_chain_) {
438 original_opener_observer_ = std::make_unique<OpenerDestroyedObserver>(
439 this, true /* observing_original_opener */);
440 first_live_main_frame_in_original_opener_chain_->AddObserver(
441 original_opener_observer_.get());
jochen6004a362017-02-04 00:11:40442 }
443}
444
engedy6e2e0992017-05-25 18:58:42445void FrameTreeNode::SetCollapsed(bool collapsed) {
Dave Tapuska65e50aa2022-03-09 23:44:13446 DCHECK(!IsMainFrame() || IsFencedFrameRoot());
engedy6e2e0992017-05-25 18:58:42447 if (is_collapsed_ == collapsed)
448 return;
449
450 is_collapsed_ = collapsed;
451 render_manager_.OnDidChangeCollapsedState(collapsed);
452}
453
Harkiran Bolaria59290d62021-03-17 01:53:01454void FrameTreeNode::SetFrameTree(FrameTree& frame_tree) {
Arthur Sonzognif6785ec2022-12-05 10:11:50455 frame_tree_ = frame_tree;
Kevin McNeeb110d0c2021-10-26 15:53:00456 DCHECK(current_frame_host());
457 current_frame_host()->SetFrameTree(frame_tree);
458 RenderFrameHostImpl* speculative_frame_host =
459 render_manager_.speculative_frame_host();
460 if (speculative_frame_host)
461 speculative_frame_host->SetFrameTree(frame_tree);
Harkiran Bolaria59290d62021-03-17 01:53:01462}
463
Luna Luc3fdacdf2017-11-08 04:48:53464void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Liam Bradyb0f1f0e2022-08-19 21:42:11465 // Inside of a fenced frame, the sandbox flags should not be able to change
466 // from its initial value. If the flags change, we have to assume the change
467 // came from a compromised renderer and terminate it.
468 // We will only do the check if the sandbox flags are already set to
469 // kFencedFrameForcedSandboxFlags. This is to allow the sandbox flags to
470 // be set initially (go from kNone -> kFencedFrameForcedSandboxFlags). Once
471 // it has been set, it cannot change to another value.
Dominic Farolino0b067632022-11-11 02:57:49472 // If the flags do change via a compromised fenced frame, then
473 // `RenderFrameHostImpl::DidChangeFramePolicy()` will detect that the change
474 // wasn't initiated by the parent, and will terminate the renderer before we
475 // reach this point, so we can CHECK() here.
476 bool fenced_frame_sandbox_flags_changed =
477 (IsFencedFrameRoot() &&
478 pending_frame_policy_.sandbox_flags ==
479 blink::kFencedFrameForcedSandboxFlags &&
480 frame_policy.sandbox_flags != blink::kFencedFrameForcedSandboxFlags);
481 CHECK(!fenced_frame_sandbox_flags_changed);
Liam Bradyb0f1f0e2022-08-19 21:42:11482
Ian Clellandcdc4f312017-10-13 22:24:12483 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25484
Ian Clellandcdc4f312017-10-13 22:24:12485 if (parent()) {
486 // Subframes should always inherit their parent's sandbox flags.
Alexander Timin381e7e182020-04-28 19:04:03487 pending_frame_policy_.sandbox_flags |=
Harkiran Bolaria4eacb3a2021-12-13 20:03:47488 parent()->browsing_context_state()->active_sandbox_flags();
Charlie Hue1b77ac2019-12-13 21:30:17489 // This is only applied on subframes; container policy and required document
490 // policy are not mutable on main frame.
Ian Clellandcdc4f312017-10-13 22:24:12491 pending_frame_policy_.container_policy = frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17492 pending_frame_policy_.required_document_policy =
493 frame_policy.required_document_policy;
Ian Clellandcdc4f312017-10-13 22:24:12494 }
Liam Brady25a14162022-12-02 15:25:57495
496 // Fenced frame roots do not have a parent, so add an extra check here to
497 // still allow a fenced frame to properly set its container policy. The
498 // required document policy and sandbox flags should stay unmodified.
499 if (IsFencedFrameRoot()) {
500 DCHECK(pending_frame_policy_.required_document_policy.empty());
501 DCHECK_EQ(pending_frame_policy_.sandbox_flags, frame_policy.sandbox_flags);
502 pending_frame_policy_.container_policy = frame_policy.container_policy;
503 }
iclelland92f8c0b2017-04-19 12:43:05504}
505
Yuzu Saijo03dbf9b2022-07-22 04:29:45506void FrameTreeNode::SetAttributes(
507 blink::mojom::IframeAttributesPtr attributes) {
Miyoung Shinc9ff4812023-01-05 08:58:05508 if (!Credentialless() && attributes->credentialless) {
Arthur Sonzogni64457592022-11-22 11:08:59509 // Log this only when credentialless is changed to true.
Arthur Sonzogni2e9c6111392022-05-02 08:37:13510 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
511 parent_, blink::mojom::WebFeature::kAnonymousIframe);
512 }
Yuzu Saijo03dbf9b2022-07-22 04:29:45513 attributes_ = std::move(attributes);
Arthur Sonzogni2e9c6111392022-05-02 08:37:13514}
515
fdegans4a49ce932015-03-12 17:11:37516bool FrameTreeNode::IsLoading() const {
Nate Chapin470dbc62023-04-25 16:34:38517 return GetLoadingState() != LoadingState::NONE;
518}
519
520LoadingState FrameTreeNode::GetLoadingState() const {
fdegans4a49ce932015-03-12 17:11:37521 RenderFrameHostImpl* current_frame_host =
522 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37523 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39524
Nate Chapin470dbc62023-04-25 16:34:38525 if (navigation_request_) {
526 // If navigation_request_ is non-null, the navigation has not been moved to
527 // the RenderFrameHostImpl or sent to the renderer to be committed. This
528 // loading UI policy is provisional, as the navigation API might "intercept"
529 // a same-document commit and change it from LOADING_WITHOUT_UI to
530 // LOADING_UI_REQUESTED.
531 return navigation_request_->IsSameDocument()
532 ? LoadingState::LOADING_WITHOUT_UI
533 : LoadingState::LOADING_UI_REQUESTED;
534 }
clamy11e11512015-07-07 16:42:17535
clamy610c63b32017-12-22 15:05:18536 RenderFrameHostImpl* speculative_frame_host =
537 render_manager_.speculative_frame_host();
Daniel Chengc3d1e8d2021-06-23 02:11:45538 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative RenderFrameHost
539 // always be considered loading?
Nate Chapin470dbc62023-04-25 16:34:38540 if (speculative_frame_host && speculative_frame_host->is_loading()) {
541 return LoadingState::LOADING_UI_REQUESTED;
542 }
543 return current_frame_host->loading_state();
fdegans4a49ce932015-03-12 17:11:37544}
545
Alex Moshchuk9b0fd822020-10-26 23:08:15546bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
547 // Having a |navigation_request_| on FrameTreeNode implies that there's an
548 // ongoing navigation that hasn't reached the ReadyToCommit state. If the
549 // navigation is between ReadyToCommit and DidCommitNavigation, the
550 // NavigationRequest will be held by RenderFrameHost, which is checked below.
551 if (navigation_request_ && !navigation_request_->IsSameDocument())
552 return true;
553
554 // Having a speculative RenderFrameHost should imply a cross-document
555 // navigation.
556 if (render_manager_.speculative_frame_host())
557 return true;
558
559 return render_manager_.current_frame_host()
560 ->HasPendingCommitForCrossDocumentNavigation();
561}
562
Arthur Hemeryc3380172018-01-22 14:00:17563void FrameTreeNode::TransferNavigationRequestOwnership(
564 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59565 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17566 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
567}
568
Charlie Reis09952ee2022-12-08 16:35:07569void FrameTreeNode::TakeNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57570 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37571 // This is never called when navigating to a Javascript URL. For the loading
572 // state, this matches what Blink is doing: Blink doesn't send throbber
573 // notifications for Javascript URLS.
574 DCHECK(!navigation_request->common_params().url.SchemeIs(
575 url::kJavaScriptScheme));
576
Nate Chapin470dbc62023-04-25 16:34:38577 LoadingState previous_frame_tree_loading_state =
578 frame_tree().LoadingTree()->GetLoadingState();
clamy44e84ce2016-02-22 15:38:25579
Rakina Zata Amnif8f2bb62022-11-23 05:54:32580 // Reset the previous NavigationRequest owned by `this`. However, there's no
581 // need to reset the state: there's still an ongoing load, and the
clamy82a2f4d2016-02-02 14:20:41582 // RenderFrameHostManager will take care of updates to the speculative
583 // RenderFrameHost in DidCreateNavigationRequest below.
Nate Chapin470dbc62023-04-25 16:34:38584 if (previous_frame_tree_loading_state != LoadingState::NONE) {
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31585 if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
jamcd0b7b22017-03-24 22:13:05586 // Mark the old request as aborted.
Mohamed Abdelhalimb4db22a2019-06-18 10:46:52587 navigation_request_->set_net_error(net::ERR_ABORTED);
jamcd0b7b22017-03-24 22:13:05588 }
Daniel Cheng390e2a72022-09-28 06:07:53589 ResetNavigationRequestButKeepState();
jamcd0b7b22017-03-24 22:13:05590 }
clamy44e84ce2016-02-22 15:38:25591
Mingyu Lei7956b8b2023-07-24 08:24:08592 // Cancel any task that will restart BackForwardCache navigation that was
593 // initiated previously.
594 CancelRestartingBackForwardCacheNavigation();
595
Mingyu Lei99b11712023-10-09 06:35:49596 // If `navigation_request` is a BFCache navigation, the RFH for BFCache
597 // restore should not be evicted before.
598 // This CHECK is added with the fix of https://crbug.com/1468984. See
599 // `BackForwardCacheBrowserTest.TwoBackNavigationsToTheSameEntry` for how
600 // BFCache entry could be evicted before the BFCache `NavigationRequest`
601 // is moved to the FrameTreeNode without the fix.
602 if (navigation_request->IsServedFromBackForwardCache()) {
603 CHECK(!navigation_request->GetRenderFrameHostRestoredFromBackForwardCache()
604 ->is_evicted_from_back_forward_cache());
605 }
606
clamy44e84ce2016-02-22 15:38:25607 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06608 if (was_discarded_) {
609 navigation_request_->set_was_discarded();
610 was_discarded_ = false;
611 }
clamy8e2e299202016-04-05 11:44:59612 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
Nate Chapin470dbc62023-04-25 16:34:38613 DidStartLoading(previous_frame_tree_loading_state);
clamydcb434c12015-04-16 19:29:16614}
615
Daniel Cheng390e2a72022-09-28 06:07:53616void FrameTreeNode::ResetNavigationRequest(NavigationDiscardReason reason) {
617 if (!navigation_request_)
618 return;
619
620 ResetNavigationRequestButKeepState();
621
622 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
623 // it created for the navigation. Also register that the load stopped.
624 DidStopLoading();
Rakina Zata Amnif8f2bb62022-11-23 05:54:32625 render_manager_.DiscardSpeculativeRFHIfUnused(reason);
Daniel Cheng390e2a72022-09-28 06:07:53626}
627
628void FrameTreeNode::ResetNavigationRequestButKeepState() {
fdegans39ff0382015-04-29 19:04:39629 if (!navigation_request_)
630 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23631
Mingyu Lei7956b8b2023-07-24 08:24:08632 // When resetting the NavigationRequest, any BFCache navigation restarting
633 // task should be cancelled. This is to ensure that the FrameTreeNode won't
634 // accidentally complete a navigation that should be reset.
635 CancelRestartingBackForwardCacheNavigation();
Andrey Kosyakovf2d4ff72018-10-29 20:09:59636 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
clamydcb434c12015-04-16 19:29:16637 navigation_request_.reset();
638}
639
Nate Chapin470dbc62023-04-25 16:34:38640void FrameTreeNode::DidStartLoading(
641 LoadingState previous_frame_tree_loading_state) {
Camille Lamyefd54b02018-10-04 16:54:14642 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
Nate Chapin470dbc62023-04-25 16:34:38643 "frame_tree_node", frame_tree_node_id(), "loading_state",
644 GetLoadingState());
Clark DuVallc97bcf72021-12-08 22:58:24645 base::ElapsedTimer timer;
fdegansa696e5112015-04-17 01:57:59646
Nate Chapin470dbc62023-04-25 16:34:38647 frame_tree().LoadingTree()->NodeLoadingStateChanged(
648 *this, previous_frame_tree_loading_state);
fdegansa696e5112015-04-17 01:57:59649
650 // Set initial load progress and update overall progress. This will notify
651 // the WebContents of the load progress change.
Sreeja Kamishetty15f9944a22022-03-10 10:16:08652 //
653 // Only notify when the load is triggered from primary/prerender main frame as
654 // we only update load progress for these nodes which happens when the frame
655 // tree matches the loading tree.
Arthur Sonzognif6785ec2022-12-05 10:11:50656 if (&frame_tree() == frame_tree().LoadingTree())
Sreeja Kamishetty15f9944a22022-03-10 10:16:08657 DidChangeLoadProgress(blink::kInitialLoadProgress);
fdegansa696e5112015-04-17 01:57:59658
Harkiran Bolaria3f83fba72022-03-10 17:48:40659 // Notify the proxies of the event.
660 current_frame_host()->browsing_context_state()->OnDidStartLoading();
Andrey Kosyakov4401fdf2023-08-28 20:03:59661 devtools_instrumentation::DidChangeFrameLoadingState(*this);
Clark DuVallc97bcf72021-12-08 22:58:24662 base::UmaHistogramTimes(
663 base::StrCat({"Navigation.DidStartLoading.",
Ian Vollick5f45867c2022-08-05 08:29:56664 IsOutermostMainFrame() ? "MainFrame" : "Subframe"}),
Clark DuVallc97bcf72021-12-08 22:58:24665 timer.Elapsed());
fdegansa696e5112015-04-17 01:57:59666}
667
668void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14669 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
670 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59671 // Set final load progress and update overall progress. This will notify
672 // the WebContents of the load progress change.
Sreeja Kamishetty15f9944a22022-03-10 10:16:08673 //
674 // Only notify when the load is triggered from primary/prerender main frame as
675 // we only update load progress for these nodes which happens when the frame
676 // tree matches the loading tree.
Arthur Sonzognif6785ec2022-12-05 10:11:50677 if (&frame_tree() == frame_tree().LoadingTree())
Sreeja Kamishetty15f9944a22022-03-10 10:16:08678 DidChangeLoadProgress(blink::kFinalLoadProgress);
fdegansa696e5112015-04-17 01:57:59679
Harkiran Bolaria3f83fba72022-03-10 17:48:40680 // Notify the proxies of the event.
681 current_frame_host()->browsing_context_state()->OnDidStopLoading();
Lucas Furukawa Gadani6faef602019-05-06 21:16:03682
Arthur Sonzognif6785ec2022-12-05 10:11:50683 FrameTree* loading_tree = frame_tree().LoadingTree();
Nate Chapin470dbc62023-04-25 16:34:38684 // When loading tree is null, ignore invoking NodeLoadingStateChanged as the
685 // frame tree is already deleted. This can happen when prerendering gets
686 // cancelled and DidStopLoading is called during FrameTree destruction.
687 if (loading_tree && !loading_tree->IsLoadingIncludingInnerFrameTrees()) {
688 // If `loading_tree->IsLoadingIncludingInnerFrameTrees()` is now false, this
689 // was the last FrameTreeNode to be loading, and the FrameTree as a whole
690 // has now stopped loading. Notify the FrameTree.
691 // It doesn't matter whether we pass LOADING_UI_REQUESTED or
692 // LOADING_WITHOUT_UI as the previous_frame_tree_loading_state param,
693 // because the previous value is only used to detect when the FrameTree's
694 // overall loading state hasn't changed, and we know that the new state will
695 // be LoadingState::NONE.
696 loading_tree->NodeLoadingStateChanged(*this,
697 LoadingState::LOADING_UI_REQUESTED);
698 }
Andrey Kosyakov4401fdf2023-08-28 20:03:59699 devtools_instrumentation::DidChangeFrameLoadingState(*this);
fdegansa696e5112015-04-17 01:57:59700}
701
702void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15703 DCHECK_GE(load_progress, blink::kInitialLoadProgress);
704 DCHECK_LE(load_progress, blink::kFinalLoadProgress);
705 current_frame_host()->DidChangeLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59706}
707
clamyf73862c42015-07-08 12:31:33708bool FrameTreeNode::StopLoading() {
arthursonzogni66f711c2019-10-08 14:40:36709 if (navigation_request_ && navigation_request_->IsNavigationStarted())
710 navigation_request_->set_net_error(net::ERR_ABORTED);
Daniel Cheng390e2a72022-09-28 06:07:53711 ResetNavigationRequest(NavigationDiscardReason::kCancelled);
clamyf73862c42015-07-08 12:31:33712
clamyf73862c42015-07-08 12:31:33713 if (!IsMainFrame())
714 return true;
715
716 render_manager_.Stop();
717 return true;
718}
719
alexmos21acae52015-11-07 01:04:43720void FrameTreeNode::DidFocus() {
721 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31722 for (auto& observer : observers_)
723 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43724}
725
clamy44e84ce2016-02-22 15:38:25726void FrameTreeNode::BeforeUnloadCanceled() {
Julie Jeongeun Kim8cf7ae32022-05-02 03:47:29727 // TODO(clamy): Support BeforeUnload in subframes. Fenced Frames don't run
728 // BeforeUnload. Maybe need to check whether other MPArch inner pages cases
Jeremy Romanc0c69be2023-11-21 19:14:52729 // need beforeunload(e.g., GuestView if it gets ported to MPArch).
Ian Vollick1c6dd3e2022-04-13 02:06:26730 if (!IsOutermostMainFrame())
clamy44e84ce2016-02-22 15:38:25731 return;
732
733 RenderFrameHostImpl* current_frame_host =
734 render_manager_.current_frame_host();
735 DCHECK(current_frame_host);
736 current_frame_host->ResetLoadingState();
737
clamy610c63b32017-12-22 15:05:18738 RenderFrameHostImpl* speculative_frame_host =
739 render_manager_.speculative_frame_host();
740 if (speculative_frame_host)
741 speculative_frame_host->ResetLoadingState();
Alexander Timin23c110b2021-01-14 02:39:04742 // Note: there is no need to set an error code on the NavigationHandle as
743 // the observers have not been notified about its creation.
744 // We also reset navigation request only when this navigation request was
745 // responsible for this dialog, as a new navigation request might cancel
746 // existing unrelated dialog.
Daniel Cheng390e2a72022-09-28 06:07:53747 if (navigation_request_ && navigation_request_->IsWaitingForBeforeUnload()) {
748 ResetNavigationRequest(NavigationDiscardReason::kCancelled);
749 }
clamy44e84ce2016-02-22 15:38:25750}
751
Mustaq Ahmedecb5c38e2020-07-29 00:34:30752bool FrameTreeNode::NotifyUserActivation(
753 blink::mojom::UserActivationNotificationType notification_type) {
Alex Moshchuk03904192021-04-02 07:29:08754 // User Activation V2 requires activating all ancestor frames in addition to
755 // the current frame. See
756 // https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation.
Alexander Timina1dfadaa2020-04-28 13:30:06757 for (RenderFrameHostImpl* rfh = current_frame_host(); rfh;
758 rfh = rfh->GetParent()) {
John Delaneyb625dca92021-04-14 17:00:34759 rfh->DidReceiveUserActivation();
Miyoung Shin8a66ec022022-11-28 23:50:09760 rfh->ActivateUserActivation(notification_type);
John Delaneyedd8d6c2019-01-25 00:23:57761 }
Alex Moshchuk03904192021-04-02 07:29:08762
Harkiran Bolaria0b3bdef02022-03-10 13:04:40763 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
764 true);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14765
Mustaq Ahmed0180320f2019-03-21 16:07:01766 // See the "Same-origin Visibility" section in |UserActivationState| class
767 // doc.
Mustaq Ahmede5f12562019-10-30 18:02:03768 if (base::FeatureList::IsEnabled(
Garrett Tanzer753cc532022-03-02 21:30:59769 features::kUserActivationSameOriginVisibility)) {
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14770 const url::Origin& current_origin =
771 this->current_frame_host()->GetLastCommittedOrigin();
Arthur Sonzognif6785ec2022-12-05 10:11:50772 for (FrameTreeNode* node : frame_tree().Nodes()) {
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14773 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
774 current_origin)) {
Miyoung Shin8a66ec022022-11-28 23:50:09775 node->current_frame_host()->ActivateUserActivation(notification_type);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14776 }
777 }
778 }
779
Carlos Caballero40b0efd2021-01-26 11:55:00780 navigator().controller().NotifyUserActivation();
Alex Moshchuk03904192021-04-02 07:29:08781 current_frame_host()->MaybeIsolateForUserActivation();
Shivani Sharma194877032019-03-07 17:52:47782
Mustaq Ahmedc4cb7162018-06-05 16:28:36783 return true;
784}
785
786bool FrameTreeNode::ConsumeTransientUserActivation() {
Miyoung Shin8a66ec022022-11-28 23:50:09787 bool was_active = current_frame_host()->IsActiveUserActivation();
Arthur Sonzognif6785ec2022-12-05 10:11:50788 for (FrameTreeNode* node : frame_tree().Nodes()) {
Miyoung Shin8a66ec022022-11-28 23:50:09789 node->current_frame_host()->ConsumeTransientUserActivation();
Garrett Tanzer753cc532022-03-02 21:30:59790 }
Harkiran Bolaria0b3bdef02022-03-10 13:04:40791 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
792 false);
Mustaq Ahmedc4cb7162018-06-05 16:28:36793 return was_active;
794}
795
Shivani Sharmac4f561582018-11-15 15:58:39796bool FrameTreeNode::ClearUserActivation() {
Arthur Sonzognif6785ec2022-12-05 10:11:50797 for (FrameTreeNode* node : frame_tree().SubtreeNodes(this))
Miyoung Shin8a66ec022022-11-28 23:50:09798 node->current_frame_host()->ClearUserActivation();
Harkiran Bolaria0b3bdef02022-03-10 13:04:40799 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
800 false);
Shivani Sharmac4f561582018-11-15 15:58:39801 return true;
802}
803
Ella Ge9caed612019-08-09 16:17:25804bool FrameTreeNode::VerifyUserActivation() {
Ella Gea78f6772019-12-11 10:35:25805 DCHECK(base::FeatureList::IsEnabled(
806 features::kBrowserVerifiedUserActivationMouse) ||
807 base::FeatureList::IsEnabled(
808 features::kBrowserVerifiedUserActivationKeyboard));
809
Ella Ge9caed612019-08-09 16:17:25810 return render_manager_.current_frame_host()
811 ->GetRenderWidgetHost()
Mustaq Ahmed83bb1722019-10-22 20:00:10812 ->RemovePendingUserActivationIfAvailable();
Ella Ge9caed612019-08-09 16:17:25813}
814
Mustaq Ahmedc4cb7162018-06-05 16:28:36815bool FrameTreeNode::UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11816 blink::mojom::UserActivationUpdateType update_type,
817 blink::mojom::UserActivationNotificationType notification_type) {
Ella Ge9caed612019-08-09 16:17:25818 bool update_result = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36819 switch (update_type) {
Antonio Gomes4b2c5132020-01-16 11:49:48820 case blink::mojom::UserActivationUpdateType::kConsumeTransientActivation:
Ella Ge9caed612019-08-09 16:17:25821 update_result = ConsumeTransientUserActivation();
822 break;
Antonio Gomes4b2c5132020-01-16 11:49:48823 case blink::mojom::UserActivationUpdateType::kNotifyActivation:
Mustaq Ahmeddc195e5b2020-08-04 18:45:11824 update_result = NotifyUserActivation(notification_type);
Ella Ge9caed612019-08-09 16:17:25825 break;
Antonio Gomes4b2c5132020-01-16 11:49:48826 case blink::mojom::UserActivationUpdateType::
Liviu Tintad9391fb92020-09-28 23:50:07827 kNotifyActivationPendingBrowserVerification: {
Alexandra Reimers99d352d2023-11-29 17:18:37828 if (VerifyUserActivation()) {
Mustaq Ahmedecb5c38e2020-07-29 00:34:30829 update_result = NotifyUserActivation(
Mustaq Ahmed2cfb0402020-09-29 19:24:35830 blink::mojom::UserActivationNotificationType::kInteraction);
Antonio Gomes4b2c5132020-01-16 11:49:48831 update_type = blink::mojom::UserActivationUpdateType::kNotifyActivation;
Ella Ge9caed612019-08-09 16:17:25832 } else {
arthursonzogni9816b9192021-03-29 16:09:19833 // TODO(https://crbug.com/848778): We need to decide what to do when
834 // user activation verification failed. NOTREACHED here will make all
Ella Ge9caed612019-08-09 16:17:25835 // unrelated tests that inject event to renderer fail.
836 return false;
837 }
Liviu Tintad9391fb92020-09-28 23:50:07838 } break;
Antonio Gomes4b2c5132020-01-16 11:49:48839 case blink::mojom::UserActivationUpdateType::kClearActivation:
Ella Ge9caed612019-08-09 16:17:25840 update_result = ClearUserActivation();
841 break;
Mustaq Ahmedc4cb7162018-06-05 16:28:36842 }
Mustaq Ahmeddc195e5b2020-08-04 18:45:11843 render_manager_.UpdateUserActivationState(update_type, notification_type);
Ella Ge9caed612019-08-09 16:17:25844 return update_result;
japhet61835ae12017-01-20 01:25:39845}
846
Nate Chapin47276a62023-02-16 16:53:44847void FrameTreeNode::DidConsumeHistoryUserActivation() {
848 for (FrameTreeNode* node : frame_tree().Nodes()) {
849 node->current_frame_host()->ConsumeHistoryUserActivation();
850 }
851}
852
Arthur Sonzognif8840b92018-11-07 14:10:35853void FrameTreeNode::PruneChildFrameNavigationEntries(
854 NavigationEntryImpl* entry) {
855 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
856 FrameTreeNode* child = current_frame_host()->child_at(i);
857 if (child->is_created_by_script_) {
858 entry->RemoveEntryForFrame(child,
859 /* only_if_different_position = */ false);
860 } else {
861 child->PruneChildFrameNavigationEntries(entry);
862 }
863 }
864}
865
arthursonzogni034bb9c2020-10-01 08:29:56866void FrameTreeNode::SetInitialPopupURL(const GURL& initial_popup_url) {
867 DCHECK(initial_popup_url_.is_empty());
Abhijeet Kandalkarb86993b2022-11-22 05:17:40868 DCHECK(is_on_initial_empty_document());
arthursonzogni034bb9c2020-10-01 08:29:56869 initial_popup_url_ = initial_popup_url;
870}
871
872void FrameTreeNode::SetPopupCreatorOrigin(
873 const url::Origin& popup_creator_origin) {
Abhijeet Kandalkarb86993b2022-11-22 05:17:40874 DCHECK(is_on_initial_empty_document());
arthursonzogni034bb9c2020-10-01 08:29:56875 popup_creator_origin_ = popup_creator_origin;
876}
877
Rakina Zata Amni4b1968d2021-09-09 03:29:47878void FrameTreeNode::WriteIntoTrace(
Alexander Timin074cd182022-03-23 18:11:22879 perfetto::TracedProto<TraceProto> proto) const {
Rakina Zata Amni4b1968d2021-09-09 03:29:47880 proto->set_frame_tree_node_id(frame_tree_node_id());
Alexander Timin074cd182022-03-23 18:11:22881 proto->set_is_main_frame(IsMainFrame());
882 proto.Set(TraceProto::kCurrentFrameHost, current_frame_host());
883 proto.Set(TraceProto::kSpeculativeFrameHost,
884 render_manager()->speculative_frame_host());
Rakina Zata Amni4b1968d2021-09-09 03:29:47885}
886
Carlos Caballero76711352021-03-24 17:38:21887bool FrameTreeNode::HasNavigation() {
888 if (navigation_request())
889 return true;
890
891 // Same-RenderFrameHost navigation is committing:
892 if (current_frame_host()->HasPendingCommitNavigation())
893 return true;
894
895 // Cross-RenderFrameHost navigation is committing:
896 if (render_manager()->speculative_frame_host())
897 return true;
898
899 return false;
900}
901
Dominic Farolino4bc10ee2021-08-31 00:37:36902bool FrameTreeNode::IsFencedFrameRoot() const {
Abhijeet Kandalkar3f29bc42022-09-23 12:39:58903 return fenced_frame_status_ == FencedFrameStatus::kFencedFrameRoot;
shivanigithubf3ddff52021-07-03 22:06:30904}
905
906bool FrameTreeNode::IsInFencedFrameTree() const {
Abhijeet Kandalkar3f29bc42022-09-23 12:39:58907 return fenced_frame_status_ != FencedFrameStatus::kNotNestedInFencedFrame;
shivanigithubf3ddff52021-07-03 22:06:30908}
909
Garrett Tanzer29de7112022-12-06 21:26:32910const absl::optional<FencedFrameProperties>&
Xiaochen Zhou86f2e712023-09-13 19:55:04911FrameTreeNode::GetFencedFrameProperties(
912 FencedFramePropertiesNodeSource node_source) {
913 return GetFencedFramePropertiesForEditing(node_source);
Liam Brady6da2cc9e2023-01-30 17:09:43914}
915
916absl::optional<FencedFrameProperties>&
Xiaochen Zhou86f2e712023-09-13 19:55:04917FrameTreeNode::GetFencedFramePropertiesForEditing(
918 FencedFramePropertiesNodeSource node_source) {
919 if (node_source == FencedFramePropertiesNodeSource::kFrameTreeRoot) {
Liam Brady6da2cc9e2023-01-30 17:09:43920 return frame_tree().root()->fenced_frame_properties_;
Garrett Tanzer34cb92fe2022-09-28 17:50:54921 }
922
Xiaochen Zhou86f2e712023-09-13 19:55:04923 // The only other option is `kClosestAncestor`. In this case the fenced frame
924 // properties are obtained by a bottom-up traversal.
925 CHECK_EQ(node_source, FencedFramePropertiesNodeSource::kClosestAncestor);
926
927 FrameTreeNode* node = this;
928 while (node) {
929 if (node->fenced_frame_properties_.has_value()) {
930 return node->fenced_frame_properties_;
Liam Brady6da2cc9e2023-01-30 17:09:43931 }
Xiaochen Zhou86f2e712023-09-13 19:55:04932 node = node->parent() ? node->parent()->frame_tree_node() : nullptr;
Liam Brady6da2cc9e2023-01-30 17:09:43933 }
934
935 return fenced_frame_properties_;
936}
937
Liam Brady95434ea62023-11-02 19:18:32938void FrameTreeNode::MaybeResetFencedFrameAutomaticBeaconReportEventData(
939 blink::mojom::AutomaticBeaconType event_type) {
Liam Bradybe6621d12023-07-20 19:43:40940 absl::optional<FencedFrameProperties>& properties =
Xiaochen Zhou86f2e712023-09-13 19:55:04941 GetFencedFramePropertiesForEditing();
Liam Bradybe6621d12023-07-20 19:43:40942 // `properties` will exist for both fenced frames as well as iframes loaded
943 // with a urn:uuid.
944 if (!properties) {
945 return;
946 }
Liam Brady95434ea62023-11-02 19:18:32947 properties->MaybeResetAutomaticBeaconData(event_type);
Liam Bradybe6621d12023-07-20 19:43:40948}
949
Liam Brady6da2cc9e2023-01-30 17:09:43950void FrameTreeNode::SetFencedFrameAutomaticBeaconReportEventData(
Liam Brady95434ea62023-11-02 19:18:32951 blink::mojom::AutomaticBeaconType event_type,
Liam Brady6da2cc9e2023-01-30 17:09:43952 const std::string& event_data,
Nan Lindbce6e32023-05-10 22:42:55953 const std::vector<blink::FencedFrame::ReportingDestination>& destinations,
Liam Brady86ca0482023-12-06 19:49:25954 bool once,
955 bool cross_origin_exposed) {
Liam Brady6da2cc9e2023-01-30 17:09:43956 absl::optional<FencedFrameProperties>& properties =
Xiaochen Zhou86f2e712023-09-13 19:55:04957 GetFencedFramePropertiesForEditing();
Liam Brady6da2cc9e2023-01-30 17:09:43958 // `properties` will exist for both fenced frames as well as iframes loaded
959 // with a urn:uuid. This allows URN iframes to call this function without
960 // getting bad-messaged.
Garrett Tanzer06980702023-12-12 19:48:20961 if (!properties || !properties->fenced_frame_reporter()) {
Liam Brady6da2cc9e2023-01-30 17:09:43962 mojo::ReportBadMessage(
963 "Automatic beacon data can only be set in fenced frames or iframes "
Garrett Tanzer06c02f02023-02-20 21:24:41964 "loaded from a config with a fenced frame reporter.");
965 return;
966 }
967 // This metadata should only be present in the renderer in frames that are
968 // same-origin to the mapped url.
Garrett Tanzer06980702023-12-12 19:48:20969 if (!properties->mapped_url().has_value() ||
Garrett Tanzer06c02f02023-02-20 21:24:41970 !current_origin().IsSameOriginWith(url::Origin::Create(
Garrett Tanzer06980702023-12-12 19:48:20971 properties->mapped_url()->GetValueIgnoringVisibility()))) {
Garrett Tanzer06c02f02023-02-20 21:24:41972 mojo::ReportBadMessage(
973 "Automatic beacon data can only be set from documents that are same-"
974 "origin to the mapped url from the fenced frame config.");
Liam Brady6da2cc9e2023-01-30 17:09:43975 return;
976 }
Liam Brady95434ea62023-11-02 19:18:32977 properties->UpdateAutomaticBeaconData(event_type, event_data, destinations,
Liam Brady86ca0482023-12-06 19:49:25978 once, cross_origin_exposed);
Garrett Tanzer34cb92fe2022-09-28 17:50:54979}
980
Yao Xiaof9ae90a2023-03-01 20:52:44981size_t FrameTreeNode::GetFencedFrameDepth(
982 size_t& shared_storage_fenced_frame_root_count) {
983 DCHECK_EQ(shared_storage_fenced_frame_root_count, 0u);
984
Yao Xiaoa2337ad2022-10-12 20:59:29985 size_t depth = 0;
986 FrameTreeNode* node = this;
987
988 while (node->fenced_frame_status() !=
989 FencedFrameStatus::kNotNestedInFencedFrame) {
990 if (node->fenced_frame_status() == FencedFrameStatus::kFencedFrameRoot) {
991 depth += 1;
Yao Xiaof9ae90a2023-03-01 20:52:44992
993 // This implies the fenced frame is from shared storage.
994 if (node->fenced_frame_properties_ &&
Garrett Tanzer06980702023-12-12 19:48:20995 node->fenced_frame_properties_->shared_storage_budget_metadata()) {
Yao Xiaof9ae90a2023-03-01 20:52:44996 shared_storage_fenced_frame_root_count += 1;
997 }
Yao Xiaoa2337ad2022-10-12 20:59:29998 } else {
999 DCHECK_EQ(node->fenced_frame_status(),
1000 FencedFrameStatus::kIframeNestedWithinFencedFrame);
1001 }
1002
1003 DCHECK(node->GetParentOrOuterDocument());
1004 node = node->GetParentOrOuterDocument()->frame_tree_node();
1005 }
1006
1007 return depth;
1008}
1009
Garrett Tanzer34cb92fe2022-09-28 17:50:541010absl::optional<base::UnguessableToken> FrameTreeNode::GetFencedFrameNonce() {
Xiaochen Zhou86f2e712023-09-13 19:55:041011 // For partition nonce, all nested frame inside a fenced frame tree should
1012 // operate on the partition nonce of the frame tree root.
1013 auto& root_fenced_frame_properties = GetFencedFrameProperties(
1014 /*node_source=*/FencedFramePropertiesNodeSource::kFrameTreeRoot);
Garrett Tanzer34cb92fe2022-09-28 17:50:541015 if (!root_fenced_frame_properties.has_value()) {
1016 return absl::nullopt;
1017 }
Garrett Tanzer06980702023-12-12 19:48:201018 if (root_fenced_frame_properties->partition_nonce().has_value()) {
1019 return root_fenced_frame_properties->partition_nonce()
Garrett Tanzer29de7112022-12-06 21:26:321020 ->GetValueIgnoringVisibility();
1021 }
1022 // It is only possible for there to be `FencedFrameProperties` but no
1023 // partition nonce in urn iframes (when not nested inside a fenced frame).
1024 CHECK(blink::features::IsAllowURNsInIframeEnabled());
1025 CHECK(!IsInFencedFrameTree());
1026 return absl::nullopt;
Garrett Tanzer34cb92fe2022-09-28 17:50:541027}
1028
1029void FrameTreeNode::SetFencedFramePropertiesIfNeeded() {
1030 if (!IsFencedFrameRoot()) {
shivanigithub4cd016a2021-09-20 21:10:301031 return;
1032 }
1033
Garrett Tanzer34cb92fe2022-09-28 17:50:541034 // The fenced frame properties are set only on the fenced frame root.
1035 // In the future, they will be set on the FrameTree instead.
Garrett Tanzer29de7112022-12-06 21:26:321036 fenced_frame_properties_ = FencedFrameProperties();
shivanigithub4cd016a2021-09-20 21:10:301037}
1038
Garrett Tanzer291a2d52023-03-20 22:41:571039blink::FencedFrame::DeprecatedFencedFrameMode
1040FrameTreeNode::GetDeprecatedFencedFrameMode() {
Garrett Tanzera42fdef2022-06-13 16:09:141041 if (!IsInFencedFrameTree()) {
Garrett Tanzer291a2d52023-03-20 22:41:571042 return blink::FencedFrame::DeprecatedFencedFrameMode::kDefault;
Garrett Tanzera42fdef2022-06-13 16:09:141043 }
Nan Lin171fe9a2022-02-17 16:42:161044
Xiaochen Zhou86f2e712023-09-13 19:55:041045 // See test "NestedUrnIframeUnderFencedFrameUnfencedTopNavigation" in
1046 // "FencedFrameParameterizedBrowserTest" for why tree traversal is
1047 // needed here to obtain the correct fenced frame properties.
1048 // TODO(crbug.com/1475682): Now the fenced frame properties here are obtained
1049 // via tree traversal, we should make sure it does not break things at
1050 // renderers, for example, `_unfencedTop` navigation. Note these issues are
1051 // pre-existing.
1052 // TODO(crbug.com/1355857): Once navigation support for urn::uuid in iframes
1053 // is deprecated, the issue above will no longer be relevant.
Garrett Tanzer291a2d52023-03-20 22:41:571054 auto& root_fenced_frame_properties = GetFencedFrameProperties();
1055 if (!root_fenced_frame_properties.has_value()) {
1056 return blink::FencedFrame::DeprecatedFencedFrameMode::kDefault;
1057 }
Nan Lin171fe9a2022-02-17 16:42:161058
Garrett Tanzer06980702023-12-12 19:48:201059 return root_fenced_frame_properties->mode();
Nan Lin171fe9a2022-02-17 16:42:161060}
1061
Nan Linaaf84f72021-12-02 22:31:561062bool FrameTreeNode::IsErrorPageIsolationEnabled() const {
Nan Lind9de87d2022-03-18 16:53:031063 // Error page isolation is enabled for main frames only (crbug.com/1092524).
Nan Lind9de87d2022-03-18 16:53:031064 return SiteIsolationPolicy::IsErrorPageIsolationEnabled(IsMainFrame());
Nan Linaaf84f72021-12-02 22:31:561065}
1066
W. James MacLean81b8d01f2022-01-25 20:50:591067void FrameTreeNode::SetSrcdocValue(const std::string& srcdoc_value) {
1068 srcdoc_value_ = srcdoc_value;
1069}
1070
Garrett Tanzer29de7112022-12-06 21:26:321071std::vector<const SharedStorageBudgetMetadata*>
Yao Xiao1ac702d2022-06-08 17:20:491072FrameTreeNode::FindSharedStorageBudgetMetadata() {
Garrett Tanzer29de7112022-12-06 21:26:321073 std::vector<const SharedStorageBudgetMetadata*> result;
Yao Xiao1ac702d2022-06-08 17:20:491074 FrameTreeNode* node = this;
1075
1076 while (true) {
Garrett Tanzer2975eeac2022-08-22 16:34:011077 if (node->fenced_frame_properties_ &&
Garrett Tanzer06980702023-12-12 19:48:201078 node->fenced_frame_properties_->shared_storage_budget_metadata()) {
Garrett Tanzer29de7112022-12-06 21:26:321079 result.emplace_back(
Garrett Tanzer06980702023-12-12 19:48:201080 node->fenced_frame_properties_->shared_storage_budget_metadata()
Garrett Tanzer29de7112022-12-06 21:26:321081 ->GetValueIgnoringVisibility());
Yao Xiao1ac702d2022-06-08 17:20:491082 }
1083
Garrett Tanzer29de7112022-12-06 21:26:321084 if (!node->GetParentOrOuterDocument()) {
Yao Xiao1ac702d2022-06-08 17:20:491085 break;
1086 }
Garrett Tanzer29de7112022-12-06 21:26:321087
1088 node = node->GetParentOrOuterDocument()->frame_tree_node();
Yao Xiao1ac702d2022-06-08 17:20:491089 }
1090
Yao Xiaoa2337ad2022-10-12 20:59:291091 return result;
Yao Xiao1ac702d2022-06-08 17:20:491092}
1093
Camillia Smith Barnes7218518c2023-03-06 19:02:171094absl::optional<std::u16string>
1095FrameTreeNode::GetEmbedderSharedStorageContextIfAllowed() {
1096 absl::optional<FencedFrameProperties>& properties =
1097 GetFencedFramePropertiesForEditing();
1098 // We only return embedder context for frames that are same origin with the
1099 // fenced frame root or ancestor URN iframe.
Garrett Tanzer06980702023-12-12 19:48:201100 if (!properties || !properties->mapped_url().has_value() ||
Camillia Smith Barnes7218518c2023-03-06 19:02:171101 !current_origin().IsSameOriginWith(url::Origin::Create(
Garrett Tanzer06980702023-12-12 19:48:201102 properties->mapped_url()->GetValueIgnoringVisibility()))) {
Camillia Smith Barnes7218518c2023-03-06 19:02:171103 return absl::nullopt;
1104 }
Garrett Tanzer06980702023-12-12 19:48:201105 return properties->embedder_shared_storage_context();
Camillia Smith Barnes7218518c2023-03-06 19:02:171106}
1107
Harkiran Bolariaebbe7702022-02-22 19:19:031108const scoped_refptr<BrowsingContextState>&
1109FrameTreeNode::GetBrowsingContextStateForSubframe() const {
1110 DCHECK(!IsMainFrame());
1111 return current_frame_host()->browsing_context_state();
1112}
1113
Arthur Hemerye4659282022-03-28 08:36:151114void FrameTreeNode::ClearOpenerReferences() {
1115 // Simulate the FrameTreeNode being dead to opener observers. They will
1116 // nullify their opener.
1117 // Note: observers remove themselves from observers_, no need to take care of
1118 // that manually.
1119 for (auto& observer : observers_)
1120 observer.OnFrameTreeNodeDisownedOpenee(this);
1121}
1122
Liam Bradyd2a41e152022-07-19 13:58:481123bool FrameTreeNode::AncestorOrSelfHasCSPEE() const {
1124 // Check if CSPEE is set in this frame or any ancestor frames.
Yuzu Saijo03dbf9b2022-07-22 04:29:451125 return csp_attribute() || (parent() && parent()->required_csp());
Liam Bradyd2a41e152022-07-19 13:58:481126}
1127
Arthur Sonzogni8e8eb1f2023-01-10 14:51:011128void FrameTreeNode::ResetAllNavigationsForFrameDetach() {
1129 NavigationDiscardReason reason = NavigationDiscardReason::kWillRemoveFrame;
1130 for (FrameTreeNode* frame : frame_tree().SubtreeNodes(this)) {
1131 frame->ResetNavigationRequest(reason);
1132 frame->current_frame_host()->ResetOwnedNavigationRequests(reason);
1133 frame->GetRenderFrameHostManager().DiscardSpeculativeRFH(reason);
1134 }
1135}
1136
Miyoung Shin7cf88b42022-11-07 13:22:301137void FrameTreeNode::RestartNavigationAsCrossDocument(
1138 std::unique_ptr<NavigationRequest> navigation_request) {
1139 navigator().RestartNavigationAsCrossDocument(std::move(navigation_request));
1140}
1141
Miyoung Shin1504eb712022-12-07 10:32:181142bool FrameTreeNode::Reload() {
1143 return navigator().controller().ReloadFrame(this);
1144}
1145
Julie Jeongeun Kimc1b07c32022-11-11 10:26:321146Navigator& FrameTreeNode::GetCurrentNavigator() {
1147 return navigator();
1148}
1149
Miyoung Shine16cd2262022-11-30 05:52:161150RenderFrameHostManager& FrameTreeNode::GetRenderFrameHostManager() {
1151 return render_manager_;
1152}
1153
Miyoung Shin64fd1bea2023-01-04 04:22:081154FrameTreeNode* FrameTreeNode::GetOpener() const {
1155 return opener_;
1156}
1157
Julie Jeongeun Kim2132b37f82022-11-23 08:30:461158void FrameTreeNode::SetFocusedFrame(SiteInstanceGroup* source) {
1159 frame_tree_->delegate()->SetFocusedFrame(this, source);
1160}
1161
Julie Jeongeun Kim0e242242022-11-30 10:45:091162void FrameTreeNode::DidChangeReferrerPolicy(
1163 network::mojom::ReferrerPolicy referrer_policy) {
1164 navigator().controller().DidChangeReferrerPolicy(this, referrer_policy);
1165}
1166
Miyoung Shinff13ed22022-11-30 09:21:471167std::unique_ptr<NavigationRequest>
1168FrameTreeNode::CreateNavigationRequestForSynchronousRendererCommit(
1169 RenderFrameHostImpl* render_frame_host,
1170 bool is_same_document,
1171 const GURL& url,
1172 const url::Origin& origin,
W. James MacLean23e90a12022-12-21 04:38:211173 const absl::optional<GURL>& initiator_base_url,
Miyoung Shinff13ed22022-11-30 09:21:471174 const net::IsolationInfo& isolation_info_for_subresources,
1175 blink::mojom::ReferrerPtr referrer,
1176 const ui::PageTransition& transition,
1177 bool should_replace_current_entry,
1178 const std::string& method,
1179 bool has_transient_activation,
1180 bool is_overriding_user_agent,
1181 const std::vector<GURL>& redirects,
1182 const GURL& original_url,
1183 std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter,
Miyoung Shinff13ed22022-11-30 09:21:471184 int http_response_code) {
1185 return NavigationRequest::CreateForSynchronousRendererCommit(
1186 this, render_frame_host, is_same_document, url, origin,
W. James MacLean23e90a12022-12-21 04:38:211187 initiator_base_url, isolation_info_for_subresources, std::move(referrer),
1188 transition, should_replace_current_entry, method,
1189 has_transient_activation, is_overriding_user_agent, redirects,
Kunihiko Sakamoto2ae79e62023-05-26 00:34:151190 original_url, std::move(coep_reporter), http_response_code);
Miyoung Shinff13ed22022-11-30 09:21:471191}
1192
Miyoung Shinb5561802022-12-01 08:21:351193void FrameTreeNode::CancelNavigation() {
1194 if (navigation_request() && navigation_request()->IsNavigationStarted()) {
1195 navigation_request()->set_net_error(net::ERR_ABORTED);
1196 }
1197 ResetNavigationRequest(NavigationDiscardReason::kCancelled);
1198}
1199
Miyoung Shinc9ff4812023-01-05 08:58:051200bool FrameTreeNode::Credentialless() const {
1201 return attributes_->credentialless;
1202}
1203
Miyoung Shinaf9a34362023-01-31 02:46:511204#if !BUILDFLAG(IS_ANDROID)
1205void FrameTreeNode::GetVirtualAuthenticatorManager(
1206 mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
1207 receiver) {
Adam Langley1e03fb02023-03-16 23:02:031208 auto* environment_singleton = AuthenticatorEnvironment::GetInstance();
Miyoung Shinaf9a34362023-01-31 02:46:511209 environment_singleton->EnableVirtualAuthenticatorFor(this,
1210 /*enable_ui=*/false);
1211 environment_singleton->AddVirtualAuthenticatorReceiver(this,
1212 std::move(receiver));
1213}
1214#endif // !BUILDFLAG(IS_ANDROID)
1215
Mingyu Lei7956b8b2023-07-24 08:24:081216void FrameTreeNode::RestartBackForwardCachedNavigationAsync(int nav_entry_id) {
1217 TRACE_EVENT0("navigation",
1218 "FrameTreeNode::RestartBackForwardCachedNavigationAsync");
1219 // The `navigation_request_` must be the BFCache navigation to the same entry
1220 // as the restarted navigation.
1221 CHECK(navigation_request_->IsServedFromBackForwardCache());
1222 CHECK_EQ(navigation_request_->nav_entry_id(), nav_entry_id);
1223 // Reset the `NavigationRequest` since the BFCache navigation will be
1224 // restarted.
1225 ResetNavigationRequest(NavigationDiscardReason::kNewNavigation);
1226
1227 // Post a task to restart the navigation asynchronously.
1228 restart_back_forward_cached_navigation_tracker_.PostTask(
1229 GetUIThreadTaskRunner({}).get(), FROM_HERE,
1230 base::BindOnce(&FrameTreeNode::RestartBackForwardCachedNavigationImpl,
1231 weak_factory_.GetWeakPtr(), nav_entry_id));
1232}
1233
1234void FrameTreeNode::RestartBackForwardCachedNavigationImpl(int nav_entry_id) {
1235 TRACE_EVENT0("navigation",
1236 "FrameTreeNode::RestartBackForwardCachedNavigationImpl");
1237 NavigationControllerImpl& controller = frame_tree_->controller();
1238 int nav_index = controller.GetEntryIndexWithUniqueID(nav_entry_id);
1239 // If the NavigationEntry was deleted, do not do anything.
1240 if (nav_index != -1) {
1241 controller.GoToIndex(nav_index);
1242 }
1243}
1244
1245void FrameTreeNode::CancelRestartingBackForwardCacheNavigation() {
1246 TRACE_EVENT0("navigation",
1247 "FrameTreeNode::CancelRestartingBackForwardCacheNavigation");
1248 restart_back_forward_cached_navigation_tracker_.TryCancelAll();
1249}
1250
[email protected]9b159a52013-10-03 17:24:551251} // namespace content