blob: 6b109fe2a15c7cebe3fed5e4b6ce0899bde61582 [file] [log] [blame]
[email protected]9b159a52013-10-03 17:24:551// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_host/frame_tree_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
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1412#include "base/feature_list.h"
scottmg6ece5ae2017-02-01 18:25:1913#include "base/lazy_instance.h"
Keishi Hattori0e45c022021-11-27 09:25:5214#include "base/memory/raw_ptr.h"
Liviu Tintad9391fb92020-09-28 23:50:0715#include "base/metrics/histogram_functions.h"
dcheng23ca947d2016-05-04 20:04:1516#include "base/metrics/histogram_macros.h"
David Sandersd4bf5eb2022-03-17 07:12:0517#include "base/observer_list.h"
Clark DuVallc97bcf72021-12-08 22:58:2418#include "base/strings/strcat.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4119#include "base/strings/string_util.h"
Clark DuVallc97bcf72021-12-08 22:58:2420#include "base/timer/elapsed_timer.h"
Andrey Kosyakovf2d4ff72018-10-29 20:09:5921#include "content/browser/devtools/devtools_instrumentation.h"
Dominic Farolino8a2187b2021-12-24 20:44:2122#include "content/browser/fenced_frame/fenced_frame.h"
danakjc492bf82020-09-09 20:02:4423#include "content/browser/renderer_host/navigation_controller_impl.h"
24#include "content/browser/renderer_host/navigation_request.h"
25#include "content/browser/renderer_host/navigator.h"
26#include "content/browser/renderer_host/navigator_delegate.h"
27#include "content/browser/renderer_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4128#include "content/browser/renderer_host/render_view_host_impl.h"
Lucas Furukawa Gadanief8290a2019-07-29 20:27:5129#include "content/common/navigation_params_utils.h"
dmazzonie950ea232015-03-13 21:39:4530#include "content/public/browser/browser_thread.h"
Nan Linaaf84f72021-12-02 22:31:5631#include "content/public/browser/site_isolation_policy.h"
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1432#include "content/public/common/content_features.h"
arthursonzognib93a4472020-04-10 07:38:0033#include "services/network/public/cpp/web_sandbox_flags.h"
34#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
Harkiran Bolaria59290d62021-03-17 01:53:0135#include "third_party/blink/public/common/features.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1536#include "third_party/blink/public/common/loader/loader_constants.h"
Antonio Gomes4b2c5132020-01-16 11:49:4837#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:3738#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
[email protected]9b159a52013-10-03 17:24:5539
40namespace content {
41
dmazzonie950ea232015-03-13 21:39:4542namespace {
43
44// This is a global map between frame_tree_node_ids and pointers to
45// FrameTreeNodes.
Takuto Ikutaadf31eb2019-01-05 00:32:4846typedef std::unordered_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4547
scottmg5e65e3a2017-03-08 08:48:4648base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
49 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4550
fdegansa696e5112015-04-17 01:57:5951} // namespace
fdegans1d16355162015-03-26 11:58:3452
alexmose201c7cd2015-06-10 17:14:2153// This observer watches the opener of its owner FrameTreeNode and clears the
54// owner's opener if the opener is destroyed.
55class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
56 public:
jochen6004a362017-02-04 00:11:4057 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
58 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2159
Peter Boström9b036532021-10-28 23:37:2860 OpenerDestroyedObserver(const OpenerDestroyedObserver&) = delete;
61 OpenerDestroyedObserver& operator=(const OpenerDestroyedObserver&) = delete;
62
alexmose201c7cd2015-06-10 17:14:2163 // FrameTreeNode::Observer
64 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4065 if (observing_original_opener_) {
Avi Drissman36465f332017-09-11 20:49:3966 // The "original owner" is special. It's used for attribution, and clients
67 // walk down the original owner chain. Therefore, if a link in the chain
68 // is being destroyed, reconnect the observation to the parent of the link
69 // being destroyed.
jochen6004a362017-02-04 00:11:4070 CHECK_EQ(owner_->original_opener(), node);
Avi Drissman36465f332017-09-11 20:49:3971 owner_->SetOriginalOpener(node->original_opener());
72 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4073 } else {
74 CHECK_EQ(owner_->opener(), node);
75 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:3976 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4077 }
alexmose201c7cd2015-06-10 17:14:2178 }
79
80 private:
Keishi Hattori0e45c022021-11-27 09:25:5281 raw_ptr<FrameTreeNode> owner_;
jochen6004a362017-02-04 00:11:4082 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2183};
84
Kevin McNee88e61552020-10-22 20:41:1185const int FrameTreeNode::kFrameTreeNodeInvalidId = -1;
86
87static_assert(FrameTreeNode::kFrameTreeNodeInvalidId ==
88 RenderFrameHost::kNoFrameTreeNodeId,
89 "Have consistent sentinel values for an invalid FTN id.");
90
vishal.b782eb5d2015-04-29 12:22:5791int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5592
dmazzonie950ea232015-03-13 21:39:4593// static
vishal.b782eb5d2015-04-29 12:22:5794FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1995 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1596 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:4697 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4598 return it == nodes->end() ? nullptr : it->second;
99}
100
Alexander Timin381e7e182020-04-28 19:04:03101// static
102FrameTreeNode* FrameTreeNode::From(RenderFrameHost* rfh) {
103 if (!rfh)
104 return nullptr;
105 return static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
106}
107
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54108FrameTreeNode::FrameTreeNode(
109 FrameTree* frame_tree,
Alexander Timin381e7e182020-04-28 19:04:03110 RenderFrameHostImpl* parent,
Daniel Cheng6ac128172021-05-25 18:49:01111 blink::mojom::TreeScopeType tree_scope_type,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54112 bool is_created_by_script,
113 const base::UnguessableToken& devtools_frame_token,
114 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Kevin McNee43fe8292021-10-04 22:59:41115 blink::FrameOwnerElementType owner_type,
Dominic Farolino08662c82021-06-11 07:36:34116 const blink::FramePolicy& frame_policy)
[email protected]bffc8302014-01-23 20:52:16117 : frame_tree_(frame_tree),
[email protected]bffc8302014-01-23 20:52:16118 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59119 parent_(parent),
Daniel Cheng9bd90f92021-04-23 20:49:45120 frame_owner_element_type_(owner_type),
Daniel Cheng6ac128172021-05-25 18:49:01121 tree_scope_type_(tree_scope_type),
Dominic Farolino08662c82021-06-11 07:36:34122 pending_frame_policy_(frame_policy),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45123 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06124 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31125 frame_owner_properties_(frame_owner_properties),
Lukasz Anforowicz147141962020-12-16 18:03:24126 blame_context_(frame_tree_node_id_, FrameTreeNode::From(parent)),
Harkiran Bolaria0b3bdef02022-03-10 13:04:40127 render_manager_(this, frame_tree->manager_delegate()) {
rob97250742015-12-10 17:45:15128 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45129 g_frame_tree_node_id_map.Get().insert(
130 std::make_pair(frame_tree_node_id_, this));
131 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33132
xiaochenghb9554bb2016-05-21 14:20:48133 // Note: this should always be done last in the constructor.
134 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59135}
[email protected]9b159a52013-10-03 17:24:55136
Dominic Farolino8a2187b2021-12-24 20:44:21137void FrameTreeNode::DestroyInnerFrameTreeIfExists() {
138 // If `this` is an dummy outer delegate node, then we really are representing
139 // an inner FrameTree for one of the following consumers:
140 // - `Portal`
141 // - `FencedFrame`
142 // - `GuestView`
143 // If we are representing a `FencedFrame` object, we need to destroy it
144 // alongside ourself. `Portals` and `GuestView` however, *currently* have a
145 // more complex lifetime and are dealt with separately.
146 bool is_outer_dummy_node = false;
147 if (current_frame_host() &&
148 current_frame_host()->inner_tree_main_frame_tree_node_id() !=
149 FrameTreeNode::kFrameTreeNodeInvalidId) {
150 is_outer_dummy_node = true;
151 }
152
153 if (is_outer_dummy_node) {
154 DCHECK(parent());
155 // Try and find the `FencedFrame` that `this` represents.
156 std::vector<FencedFrame*> fenced_frames = parent()->GetFencedFrames();
157 FencedFrame* doomed_fenced_frame = nullptr;
158 for (FencedFrame* fenced_frame : fenced_frames) {
159 if (frame_tree_node_id() ==
160 fenced_frame->GetOuterDelegateFrameTreeNodeId()) {
161 doomed_fenced_frame = fenced_frame;
162 break;
163 }
164 }
165
166 // `doomed_fenced_frame` might not actually exist, because some outer dummy
167 // `FrameTreeNode`s might correspond to `Portal`s, which do not have their
168 // lifetime managed in the same way as `FencedFrames`.
169 if (doomed_fenced_frame) {
170 parent()->DestroyFencedFrame(*doomed_fenced_frame);
171 }
172 }
173}
174
[email protected]9b159a52013-10-03 17:24:55175FrameTreeNode::~FrameTreeNode() {
Daniel Chengc3d1e8d2021-06-23 02:11:45176 // There should always be a current RenderFrameHost except during prerender
177 // activation. Prerender activation moves the current RenderFrameHost from
178 // the old FrameTree's FrameTreeNode to the new FrameTree's FrameTreeNode and
179 // then destroys the old FrameTree. See
180 // `RenderFrameHostManager::TakePrerenderedPage()`.
Harkiran Bolaria59290d62021-03-17 01:53:01181 if (current_frame_host()) {
182 // Remove the children.
183 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45184
Harkiran Bolaria59290d62021-03-17 01:53:01185 current_frame_host()->ResetLoadingState();
186 } else {
Hiroki Nakagawa0a90bd42021-04-21 01:53:05187 DCHECK(blink::features::IsPrerender2Enabled());
Harkiran Bolaria59290d62021-03-17 01:53:01188 DCHECK(!parent()); // Only main documents can be activated.
189 DCHECK(!opener()); // Prerendered frame trees can't have openers.
190
191 // Activation is not allowed during ongoing navigations.
192 DCHECK(!navigation_request_);
193
Carlos Caballerod1c80432021-04-20 08:16:32194 // TODO(https://crbug.com/1199693): Need to determine how to handle pending
Harkiran Bolaria59290d62021-03-17 01:53:01195 // deletions, as observers will be notified.
196 DCHECK(!render_manager()->speculative_frame_host());
197 }
Nate Chapin22ea6592019-03-05 22:29:02198
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45199 // If the removed frame was created by a script, then its history entry will
200 // never be reused - we can save some memory by removing the history entry.
201 // See also https://crbug.com/784356.
202 if (is_created_by_script_ && parent_) {
Carlos Caballero04aab362021-02-15 17:38:16203 NavigationEntryImpl* nav_entry =
204 navigator().controller().GetLastCommittedEntry();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45205 if (nav_entry) {
206 nav_entry->RemoveEntryForFrame(this,
207 /* only_if_different_position = */ false);
208 }
209 }
210
dmazzonie950ea232015-03-13 21:39:45211 frame_tree_->FrameRemoved(this);
Carlos Caballero6ff6ace2021-02-05 16:53:00212
Dominic Farolino8a2187b2021-12-24 20:44:21213 DestroyInnerFrameTreeIfExists();
214
Carlos Caballero6ff6ace2021-02-05 16:53:00215 // Do not dispatch notification for the root frame as ~WebContentsImpl already
216 // dispatches it for now.
217 // TODO(https://crbug.com/1170277): This is only needed because the FrameTree
218 // is a member of WebContentsImpl and we would call back into it during
219 // destruction. We should clean up the FrameTree destruction code and call the
220 // delegate unconditionally.
221 if (parent())
222 render_manager_.delegate()->OnFrameTreeNodeDestroyed(this);
223
ericwilligers254597b2016-10-17 10:32:31224 for (auto& observer : observers_)
225 observer.OnFrameTreeNodeDestroyed(this);
Lukasz Anforowicz147141962020-12-16 18:03:24226 observers_.Clear();
alexmose201c7cd2015-06-10 17:14:21227
228 if (opener_)
229 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40230 if (original_opener_)
231 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45232
233 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18234
Daniel Chengc3d1e8d2021-06-23 02:11:45235 // If a frame with a pending navigation is detached, make sure the
236 // WebContents (and its observers) update their loading state.
237 // TODO(dcheng): This should just check `IsLoading()`, but `IsLoading()`
238 // assumes that `current_frame_host_` is not null. This is incompatible with
239 // prerender activation when destroying the old frame tree (see above).
danakjf9400602019-06-07 15:44:58240 bool did_stop_loading = false;
241
jam39258caf2016-11-02 14:48:18242 if (navigation_request_) {
danakjf9400602019-06-07 15:44:58243 navigation_request_.reset();
danakjf9400602019-06-07 15:44:58244 did_stop_loading = true;
jam39258caf2016-11-02 14:48:18245 }
Nate Chapin22ea6592019-03-05 22:29:02246
danakjf9400602019-06-07 15:44:58247 // ~SiteProcessCountTracker DCHECKs in some tests if the speculative
248 // RenderFrameHostImpl is not destroyed last. Ideally this would be closer to
249 // (possible before) the ResetLoadingState() call above.
danakjf9400602019-06-07 15:44:58250 if (render_manager_.speculative_frame_host()) {
Daniel Chengc3d1e8d2021-06-23 02:11:45251 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative
252 // RenderFrameHost always be considered loading?
danakjf9400602019-06-07 15:44:58253 did_stop_loading |= render_manager_.speculative_frame_host()->is_loading();
Daniel Chengc3d1e8d2021-06-23 02:11:45254 // `FrameTree::Shutdown()` has special handling for the main frame's
255 // speculative RenderFrameHost, and the speculative RenderFrameHost should
256 // already be reset for main frames.
257 DCHECK(!IsMainFrame());
258
259 // This does not use `UnsetSpeculativeRenderFrameHost()`: if the speculative
260 // RenderFrameHost has already reached kPendingCommit, it would needlessly
261 // re-create a proxy for a frame that's going away.
262 render_manager_.DiscardSpeculativeRenderFrameHostForShutdown();
danakjf9400602019-06-07 15:44:58263 }
264
265 if (did_stop_loading)
266 DidStopLoading();
267
Harkiran Bolaria59290d62021-03-17 01:53:01268 // IsLoading() requires that current_frame_host() is non-null.
269 DCHECK(!current_frame_host() || !IsLoading());
[email protected]9b159a52013-10-03 17:24:55270}
271
alexmose201c7cd2015-06-10 17:14:21272void FrameTreeNode::AddObserver(Observer* observer) {
273 observers_.AddObserver(observer);
274}
275
276void FrameTreeNode::RemoveObserver(Observer* observer) {
277 observers_.RemoveObserver(observer);
278}
279
[email protected]94d0cc12013-12-18 00:07:41280bool FrameTreeNode::IsMainFrame() const {
281 return frame_tree_->root() == this;
282}
283
Hiroki Nakagawaab309622021-05-19 16:38:13284void FrameTreeNode::ResetForNavigation() {
arthursonzogni76098e52020-11-25 14:18:45285 // This frame has had its user activation bits cleared in the renderer before
286 // arriving here. We just need to clear them here and in the other renderer
287 // processes that may have a reference to this frame.
Alexander Timin45b716c2020-11-06 01:40:31288 //
289 // We do not take user activation into account when calculating
290 // |ResetForNavigationResult|, as we are using it to determine bfcache
291 // eligibility and the page can get another user gesture after restore.
Antonio Gomes4b2c5132020-01-16 11:49:48292 UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11293 blink::mojom::UserActivationUpdateType::kClearActivation,
294 blink::mojom::UserActivationNotificationType::kNone);
Ian Clelland5cbaaf82017-11-27 22:00:03295}
296
Dave Tapuskac8de3b02021-12-03 21:51:01297RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocument() {
298 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/false);
299}
300
301RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentOrEmbedder() {
302 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/true);
303}
304
305RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentHelper(
306 bool escape_guest_view) {
307 // Find the parent in the FrameTree (iframe).
308 if (parent_)
309 return parent_;
310
311 if (!escape_guest_view) {
312 // If we are not a fenced frame root nor inside a portal then return early.
313 // This code does not escape GuestViews.
314 if (!IsFencedFrameRoot() && !frame_tree_->delegate()->IsPortal())
315 return nullptr;
316 }
317
318 // Find the parent in the outer embedder (GuestView, Portal, or Fenced Frame).
319 FrameTreeNode* frame_in_embedder = render_manager()->GetOuterDelegateNode();
320 if (frame_in_embedder)
321 return frame_in_embedder->current_frame_host()->GetParent();
322
323 // No parent found.
324 return nullptr;
325}
326
Julie Jeongeun Kimf38c1eca2021-12-14 07:46:55327FrameType FrameTreeNode::GetFrameType() const {
328 if (!IsMainFrame())
329 return FrameType::kSubframe;
330
331 switch (frame_tree()->type()) {
332 case FrameTree::Type::kPrimary:
333 return FrameType::kPrimaryMainFrame;
334 case FrameTree::Type::kPrerender:
335 return FrameType::kPrerenderMainFrame;
336 case FrameTree::Type::kFencedFrame:
337 // We also have FencedFramesImplementationType::kShadowDOM for a
338 // fenced frame implementation based on <iframe> + shadowDOM,
339 // which will return kSubframe as it's a modified <iframe> rather
340 // than a dedicated FrameTree. This returns kSubframe for the
341 // shadow dom implementation in order to keep consistency (i.e.
342 // NavigationHandle::GetParentFrame returning non-null value for
343 // shadow-dom based FFs).
344 return FrameType::kFencedFrameRoot;
345 }
346}
347
alexmose201c7cd2015-06-10 17:14:21348void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
349 if (opener_) {
350 opener_->RemoveObserver(opener_observer_.get());
351 opener_observer_.reset();
352 }
353
354 opener_ = opener;
355
356 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55357 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21358 opener_->AddObserver(opener_observer_.get());
359 }
360}
361
Wolfgang Beyerd8809db2020-09-30 15:29:39362void FrameTreeNode::SetOpenerDevtoolsFrameToken(
363 base::UnguessableToken opener_devtools_frame_token) {
364 DCHECK(!opener_devtools_frame_token_ ||
365 opener_devtools_frame_token_->is_empty());
366 opener_devtools_frame_token_ = std::move(opener_devtools_frame_token);
367}
368
jochen6004a362017-02-04 00:11:40369void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39370 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37371 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40372
Avi Drissman36465f332017-09-11 20:49:39373 if (original_opener_) {
374 original_opener_->RemoveObserver(original_opener_observer_.get());
375 original_opener_observer_.reset();
376 }
377
jochen6004a362017-02-04 00:11:40378 original_opener_ = opener;
379
380 if (original_opener_) {
jochen6004a362017-02-04 00:11:40381 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55382 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40383 original_opener_->AddObserver(original_opener_observer_.get());
384 }
385}
386
creisf0f069a2015-07-23 23:51:53387void FrameTreeNode::SetCurrentURL(const GURL& url) {
Erik Chen173bf3042017-07-31 06:06:21388 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48389 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53390}
391
engedy6e2e0992017-05-25 18:58:42392void FrameTreeNode::SetCollapsed(bool collapsed) {
Dave Tapuska65e50aa2022-03-09 23:44:13393 DCHECK(!IsMainFrame() || IsFencedFrameRoot());
engedy6e2e0992017-05-25 18:58:42394 if (is_collapsed_ == collapsed)
395 return;
396
397 is_collapsed_ = collapsed;
398 render_manager_.OnDidChangeCollapsedState(collapsed);
399}
400
Harkiran Bolaria59290d62021-03-17 01:53:01401void FrameTreeNode::SetFrameTree(FrameTree& frame_tree) {
Hiroki Nakagawa0a90bd42021-04-21 01:53:05402 DCHECK(blink::features::IsPrerender2Enabled());
Harkiran Bolaria59290d62021-03-17 01:53:01403 frame_tree_ = &frame_tree;
Kevin McNeeb110d0c2021-10-26 15:53:00404 DCHECK(current_frame_host());
405 current_frame_host()->SetFrameTree(frame_tree);
406 RenderFrameHostImpl* speculative_frame_host =
407 render_manager_.speculative_frame_host();
408 if (speculative_frame_host)
409 speculative_frame_host->SetFrameTree(frame_tree);
Harkiran Bolaria59290d62021-03-17 01:53:01410}
411
Luna Luc3fdacdf2017-11-08 04:48:53412void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Dominic Farolino08662c82021-06-11 07:36:34413 // The |is_fenced| bit should never be able to transition from what its
414 // initial value was. Since we never expect to be in a position where it can
415 // even be updated to new value, if we catch this happening we have to kill
416 // the renderer and refuse to accept any other frame policy changes here.
417 if (pending_frame_policy_.is_fenced != frame_policy.is_fenced) {
418 mojo::ReportBadMessage(
419 "The `is_fenced` FramePolicy bit is const and should never be changed");
420 return;
421 }
422
Ian Clellandcdc4f312017-10-13 22:24:12423 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25424
Ian Clellandcdc4f312017-10-13 22:24:12425 if (parent()) {
426 // Subframes should always inherit their parent's sandbox flags.
Alexander Timin381e7e182020-04-28 19:04:03427 pending_frame_policy_.sandbox_flags |=
Harkiran Bolaria4eacb3a2021-12-13 20:03:47428 parent()->browsing_context_state()->active_sandbox_flags();
Charlie Hue1b77ac2019-12-13 21:30:17429 // This is only applied on subframes; container policy and required document
430 // policy are not mutable on main frame.
Ian Clellandcdc4f312017-10-13 22:24:12431 pending_frame_policy_.container_policy = frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17432 pending_frame_policy_.required_document_policy =
433 frame_policy.required_document_policy;
Ian Clellandcdc4f312017-10-13 22:24:12434 }
iclelland92f8c0b2017-04-19 12:43:05435}
436
fdegans4a49ce932015-03-12 17:11:37437bool FrameTreeNode::IsLoading() const {
438 RenderFrameHostImpl* current_frame_host =
439 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37440
441 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39442
clamy610c63b32017-12-22 15:05:18443 if (navigation_request_)
444 return true;
clamy11e11512015-07-07 16:42:17445
clamy610c63b32017-12-22 15:05:18446 RenderFrameHostImpl* speculative_frame_host =
447 render_manager_.speculative_frame_host();
Daniel Chengc3d1e8d2021-06-23 02:11:45448 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative RenderFrameHost
449 // always be considered loading?
clamy610c63b32017-12-22 15:05:18450 if (speculative_frame_host && speculative_frame_host->is_loading())
451 return true;
fdegans4a49ce932015-03-12 17:11:37452 return current_frame_host->is_loading();
453}
454
Alex Moshchuk9b0fd822020-10-26 23:08:15455bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
456 // Having a |navigation_request_| on FrameTreeNode implies that there's an
457 // ongoing navigation that hasn't reached the ReadyToCommit state. If the
458 // navigation is between ReadyToCommit and DidCommitNavigation, the
459 // NavigationRequest will be held by RenderFrameHost, which is checked below.
460 if (navigation_request_ && !navigation_request_->IsSameDocument())
461 return true;
462
463 // Having a speculative RenderFrameHost should imply a cross-document
464 // navigation.
465 if (render_manager_.speculative_frame_host())
466 return true;
467
468 return render_manager_.current_frame_host()
469 ->HasPendingCommitForCrossDocumentNavigation();
470}
471
Arthur Hemeryc3380172018-01-22 14:00:17472void FrameTreeNode::TransferNavigationRequestOwnership(
473 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59474 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17475 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
476}
477
carloskc49005eb2015-06-16 11:25:07478void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57479 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37480 // This is never called when navigating to a Javascript URL. For the loading
481 // state, this matches what Blink is doing: Blink doesn't send throbber
482 // notifications for Javascript URLS.
483 DCHECK(!navigation_request->common_params().url.SchemeIs(
484 url::kJavaScriptScheme));
485
Sreeja Kamishetty15f9944a22022-03-10 10:16:08486 bool was_previously_loading = frame_tree()->LoadingTree()->IsLoading();
clamy44e84ce2016-02-22 15:38:25487
clamy82a2f4d2016-02-02 14:20:41488 // There's no need to reset the state: there's still an ongoing load, and the
489 // RenderFrameHostManager will take care of updates to the speculative
490 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05491 if (was_previously_loading) {
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31492 if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
jamcd0b7b22017-03-24 22:13:05493 // Mark the old request as aborted.
Mohamed Abdelhalimb4db22a2019-06-18 10:46:52494 navigation_request_->set_net_error(net::ERR_ABORTED);
jamcd0b7b22017-03-24 22:13:05495 }
Arthur Hemery241b9392019-10-24 11:08:41496 ResetNavigationRequest(true);
jamcd0b7b22017-03-24 22:13:05497 }
clamy44e84ce2016-02-22 15:38:25498
499 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06500 if (was_discarded_) {
501 navigation_request_->set_was_discarded();
502 was_discarded_ = false;
503 }
clamy8e2e299202016-04-05 11:44:59504 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39505
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51506 bool to_different_document = !NavigationTypeUtils::IsSameDocument(
arthursonzogni92f18682017-02-08 23:00:04507 navigation_request_->common_params().navigation_type);
508
509 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16510}
511
Arthur Hemery241b9392019-10-24 11:08:41512void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
fdegans39ff0382015-04-29 19:04:39513 if (!navigation_request_)
514 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23515
Andrey Kosyakovf2d4ff72018-10-29 20:09:59516 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
clamydcb434c12015-04-16 19:29:16517 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39518
clamy82a2f4d2016-02-02 14:20:41519 if (keep_state)
fdegans39ff0382015-04-29 19:04:39520 return;
521
clamy82a2f4d2016-02-02 14:20:41522 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
523 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39524 DidStopLoading();
525 render_manager_.CleanUpNavigation();
clamydcb434c12015-04-16 19:29:16526}
527
Nate Chapin9aabf5f2021-11-12 00:31:19528void FrameTreeNode::DidStartLoading(bool should_show_loading_ui,
clamy44e84ce2016-02-22 15:38:25529 bool was_previously_loading) {
Camille Lamyefd54b02018-10-04 16:54:14530 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
Nate Chapin9aabf5f2021-11-12 00:31:19531 "frame_tree_node", frame_tree_node_id(),
532 "should_show_loading_ui ", should_show_loading_ui);
Clark DuVallc97bcf72021-12-08 22:58:24533 base::ElapsedTimer timer;
fdegansa696e5112015-04-17 01:57:59534
Sreeja Kamishetty15f9944a22022-03-10 10:16:08535 frame_tree()->LoadingTree()->DidStartLoadingNode(
536 *this, should_show_loading_ui, was_previously_loading);
fdegansa696e5112015-04-17 01:57:59537
538 // Set initial load progress and update overall progress. This will notify
539 // the WebContents of the load progress change.
Sreeja Kamishetty15f9944a22022-03-10 10:16:08540 //
541 // Only notify when the load is triggered from primary/prerender main frame as
542 // we only update load progress for these nodes which happens when the frame
543 // tree matches the loading tree.
544 if (frame_tree() == frame_tree()->LoadingTree())
545 DidChangeLoadProgress(blink::kInitialLoadProgress);
fdegansa696e5112015-04-17 01:57:59546
Harkiran Bolaria3f83fba72022-03-10 17:48:40547 // Notify the proxies of the event.
548 current_frame_host()->browsing_context_state()->OnDidStartLoading();
Clark DuVallc97bcf72021-12-08 22:58:24549 base::UmaHistogramTimes(
550 base::StrCat({"Navigation.DidStartLoading.",
551 IsMainFrame() ? "MainFrame" : "Subframe"}),
552 timer.Elapsed());
fdegansa696e5112015-04-17 01:57:59553}
554
555void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14556 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
557 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59558 // Set final load progress and update overall progress. This will notify
559 // the WebContents of the load progress change.
Sreeja Kamishetty15f9944a22022-03-10 10:16:08560 //
561 // Only notify when the load is triggered from primary/prerender main frame as
562 // we only update load progress for these nodes which happens when the frame
563 // tree matches the loading tree.
564 if (frame_tree() == frame_tree()->LoadingTree())
565 DidChangeLoadProgress(blink::kFinalLoadProgress);
fdegansa696e5112015-04-17 01:57:59566
Harkiran Bolaria3f83fba72022-03-10 17:48:40567 // Notify the proxies of the event.
568 current_frame_host()->browsing_context_state()->OnDidStopLoading();
Lucas Furukawa Gadani6faef602019-05-06 21:16:03569
Sreeja Kamishetty15f9944a22022-03-10 10:16:08570 FrameTree* loading_tree = frame_tree()->LoadingTree();
571 // When loading tree is null, ignore invoking DidStopLoadingNode as the frame
572 // tree is already deleted. This can happen when prerendering gets cancelled
573 // and DidStopLoading is called during FrameTree destruction.
574 if (loading_tree)
575 loading_tree->DidStopLoadingNode(*this);
fdegansa696e5112015-04-17 01:57:59576}
577
578void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15579 DCHECK_GE(load_progress, blink::kInitialLoadProgress);
580 DCHECK_LE(load_progress, blink::kFinalLoadProgress);
581 current_frame_host()->DidChangeLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59582}
583
clamyf73862c42015-07-08 12:31:33584bool FrameTreeNode::StopLoading() {
arthursonzogni66f711c2019-10-08 14:40:36585 if (navigation_request_ && navigation_request_->IsNavigationStarted())
586 navigation_request_->set_net_error(net::ERR_ABORTED);
Arthur Hemery241b9392019-10-24 11:08:41587 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33588
clamyf73862c42015-07-08 12:31:33589 if (!IsMainFrame())
590 return true;
591
592 render_manager_.Stop();
593 return true;
594}
595
alexmos21acae52015-11-07 01:04:43596void FrameTreeNode::DidFocus() {
597 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31598 for (auto& observer : observers_)
599 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43600}
601
clamy44e84ce2016-02-22 15:38:25602void FrameTreeNode::BeforeUnloadCanceled() {
603 // TODO(clamy): Support BeforeUnload in subframes.
604 if (!IsMainFrame())
605 return;
606
607 RenderFrameHostImpl* current_frame_host =
608 render_manager_.current_frame_host();
609 DCHECK(current_frame_host);
610 current_frame_host->ResetLoadingState();
611
clamy610c63b32017-12-22 15:05:18612 RenderFrameHostImpl* speculative_frame_host =
613 render_manager_.speculative_frame_host();
614 if (speculative_frame_host)
615 speculative_frame_host->ResetLoadingState();
Alexander Timin23c110b2021-01-14 02:39:04616 // Note: there is no need to set an error code on the NavigationHandle as
617 // the observers have not been notified about its creation.
618 // We also reset navigation request only when this navigation request was
619 // responsible for this dialog, as a new navigation request might cancel
620 // existing unrelated dialog.
621 if (navigation_request_ && navigation_request_->IsWaitingForBeforeUnload())
Arthur Hemery241b9392019-10-24 11:08:41622 ResetNavigationRequest(false);
clamy44e84ce2016-02-22 15:38:25623}
624
Mustaq Ahmedecb5c38e2020-07-29 00:34:30625bool FrameTreeNode::NotifyUserActivation(
626 blink::mojom::UserActivationNotificationType notification_type) {
Garrett Tanzer753cc532022-03-02 21:30:59627 // User activation notifications shouldn't propagate into/out of fenced
628 // frames.
629 // For ShadowDOM, fenced frames are in the same frame tree as their embedder,
630 // so we need to perform additional checks to enforce the boundary.
631 // For MPArch, fenced frames have a separate frame tree, so this boundary is
632 // enforced by default.
633 // https://docs.google.com/document/d/1WnIhXOFycoje_sEoZR3Mo0YNSR2Ki7LABIC_HEWFaog
634 bool shadow_dom_fenced_frame_enabled =
635 blink::features::IsFencedFramesEnabled() &&
636 blink::features::IsFencedFramesShadowDOMBased();
637
Alex Moshchuk03904192021-04-02 07:29:08638 // User Activation V2 requires activating all ancestor frames in addition to
639 // the current frame. See
640 // https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation.
Alexander Timina1dfadaa2020-04-28 13:30:06641 for (RenderFrameHostImpl* rfh = current_frame_host(); rfh;
642 rfh = rfh->GetParent()) {
John Delaneyb625dca92021-04-14 17:00:34643 rfh->DidReceiveUserActivation();
Mustaq Ahmedecb5c38e2020-07-29 00:34:30644 rfh->frame_tree_node()->user_activation_state_.Activate(notification_type);
Garrett Tanzer753cc532022-03-02 21:30:59645
646 if (shadow_dom_fenced_frame_enabled &&
647 rfh->frame_tree_node()->IsFencedFrameRoot()) {
648 break;
649 }
John Delaneyedd8d6c2019-01-25 00:23:57650 }
Alex Moshchuk03904192021-04-02 07:29:08651
Harkiran Bolaria0b3bdef02022-03-10 13:04:40652 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
653 true);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14654
Garrett Tanzer753cc532022-03-02 21:30:59655 absl::optional<base::UnguessableToken> originator_nonce =
656 fenced_frame_nonce();
657
Mustaq Ahmed0180320f2019-03-21 16:07:01658 // See the "Same-origin Visibility" section in |UserActivationState| class
659 // doc.
Mustaq Ahmede5f12562019-10-30 18:02:03660 if (base::FeatureList::IsEnabled(
Garrett Tanzer753cc532022-03-02 21:30:59661 features::kUserActivationSameOriginVisibility)) {
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14662 const url::Origin& current_origin =
663 this->current_frame_host()->GetLastCommittedOrigin();
664 for (FrameTreeNode* node : frame_tree()->Nodes()) {
Garrett Tanzer753cc532022-03-02 21:30:59665 if (shadow_dom_fenced_frame_enabled &&
666 node->fenced_frame_nonce() != originator_nonce) {
667 continue;
668 }
669
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14670 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
671 current_origin)) {
Mustaq Ahmedecb5c38e2020-07-29 00:34:30672 node->user_activation_state_.Activate(notification_type);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14673 }
674 }
675 }
676
Carlos Caballero40b0efd2021-01-26 11:55:00677 navigator().controller().NotifyUserActivation();
Alex Moshchuk03904192021-04-02 07:29:08678 current_frame_host()->MaybeIsolateForUserActivation();
Shivani Sharma194877032019-03-07 17:52:47679
Mustaq Ahmedc4cb7162018-06-05 16:28:36680 return true;
681}
682
683bool FrameTreeNode::ConsumeTransientUserActivation() {
Garrett Tanzer753cc532022-03-02 21:30:59684 // User activation consumptions shouldn't propagate into/out of fenced
685 // frames.
686 // For ShadowDOM, fenced frames are in the same frame tree as their embedder,
687 // so we need to perform additional checks to enforce the boundary.
688 // For MPArch, fenced frames have a separate frame tree, so this boundary is
689 // enforced by default.
690 // https://docs.google.com/document/d/1WnIhXOFycoje_sEoZR3Mo0YNSR2Ki7LABIC_HEWFaog
691 bool shadow_dom_fenced_frame_enabled =
692 blink::features::IsFencedFramesEnabled() &&
693 blink::features::IsFencedFramesShadowDOMBased();
694 absl::optional<base::UnguessableToken> originator_nonce =
695 fenced_frame_nonce();
696
Mustaq Ahmedc4cb7162018-06-05 16:28:36697 bool was_active = user_activation_state_.IsActive();
Garrett Tanzer753cc532022-03-02 21:30:59698 for (FrameTreeNode* node : frame_tree()->Nodes()) {
699 if (shadow_dom_fenced_frame_enabled &&
700 node->fenced_frame_nonce() != originator_nonce) {
701 continue;
702 }
703
Mustaq Ahmedc4cb7162018-06-05 16:28:36704 node->user_activation_state_.ConsumeIfActive();
Garrett Tanzer753cc532022-03-02 21:30:59705 }
Harkiran Bolaria0b3bdef02022-03-10 13:04:40706 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
707 false);
Mustaq Ahmedc4cb7162018-06-05 16:28:36708 return was_active;
709}
710
Shivani Sharmac4f561582018-11-15 15:58:39711bool FrameTreeNode::ClearUserActivation() {
Shivani Sharmac4f561582018-11-15 15:58:39712 for (FrameTreeNode* node : frame_tree()->SubtreeNodes(this))
713 node->user_activation_state_.Clear();
Harkiran Bolaria0b3bdef02022-03-10 13:04:40714 current_frame_host()->browsing_context_state()->set_has_active_user_gesture(
715 false);
Shivani Sharmac4f561582018-11-15 15:58:39716 return true;
717}
718
Ella Ge9caed612019-08-09 16:17:25719bool FrameTreeNode::VerifyUserActivation() {
Ella Gea78f6772019-12-11 10:35:25720 DCHECK(base::FeatureList::IsEnabled(
721 features::kBrowserVerifiedUserActivationMouse) ||
722 base::FeatureList::IsEnabled(
723 features::kBrowserVerifiedUserActivationKeyboard));
724
Ella Ge9caed612019-08-09 16:17:25725 return render_manager_.current_frame_host()
726 ->GetRenderWidgetHost()
Mustaq Ahmed83bb1722019-10-22 20:00:10727 ->RemovePendingUserActivationIfAvailable();
Ella Ge9caed612019-08-09 16:17:25728}
729
Mustaq Ahmedc4cb7162018-06-05 16:28:36730bool FrameTreeNode::UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11731 blink::mojom::UserActivationUpdateType update_type,
732 blink::mojom::UserActivationNotificationType notification_type) {
Ella Ge9caed612019-08-09 16:17:25733 bool update_result = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36734 switch (update_type) {
Antonio Gomes4b2c5132020-01-16 11:49:48735 case blink::mojom::UserActivationUpdateType::kConsumeTransientActivation:
Ella Ge9caed612019-08-09 16:17:25736 update_result = ConsumeTransientUserActivation();
737 break;
Antonio Gomes4b2c5132020-01-16 11:49:48738 case blink::mojom::UserActivationUpdateType::kNotifyActivation:
Mustaq Ahmeddc195e5b2020-08-04 18:45:11739 update_result = NotifyUserActivation(notification_type);
Ella Ge9caed612019-08-09 16:17:25740 break;
Antonio Gomes4b2c5132020-01-16 11:49:48741 case blink::mojom::UserActivationUpdateType::
Liviu Tintad9391fb92020-09-28 23:50:07742 kNotifyActivationPendingBrowserVerification: {
743 const bool user_activation_verified = VerifyUserActivation();
744 // Add UMA metric for when browser user activation verification succeeds
745 base::UmaHistogramBoolean("Event.BrowserVerifiedUserActivation",
746 user_activation_verified);
747 if (user_activation_verified) {
Mustaq Ahmedecb5c38e2020-07-29 00:34:30748 update_result = NotifyUserActivation(
Mustaq Ahmed2cfb0402020-09-29 19:24:35749 blink::mojom::UserActivationNotificationType::kInteraction);
Antonio Gomes4b2c5132020-01-16 11:49:48750 update_type = blink::mojom::UserActivationUpdateType::kNotifyActivation;
Ella Ge9caed612019-08-09 16:17:25751 } else {
arthursonzogni9816b9192021-03-29 16:09:19752 // TODO(https://crbug.com/848778): We need to decide what to do when
753 // user activation verification failed. NOTREACHED here will make all
Ella Ge9caed612019-08-09 16:17:25754 // unrelated tests that inject event to renderer fail.
755 return false;
756 }
Liviu Tintad9391fb92020-09-28 23:50:07757 } break;
Antonio Gomes4b2c5132020-01-16 11:49:48758 case blink::mojom::UserActivationUpdateType::kClearActivation:
Ella Ge9caed612019-08-09 16:17:25759 update_result = ClearUserActivation();
760 break;
Mustaq Ahmedc4cb7162018-06-05 16:28:36761 }
Mustaq Ahmeddc195e5b2020-08-04 18:45:11762 render_manager_.UpdateUserActivationState(update_type, notification_type);
Ella Ge9caed612019-08-09 16:17:25763 return update_result;
japhet61835ae12017-01-20 01:25:39764}
765
Arthur Sonzognif8840b92018-11-07 14:10:35766void FrameTreeNode::PruneChildFrameNavigationEntries(
767 NavigationEntryImpl* entry) {
768 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
769 FrameTreeNode* child = current_frame_host()->child_at(i);
770 if (child->is_created_by_script_) {
771 entry->RemoveEntryForFrame(child,
772 /* only_if_different_position = */ false);
773 } else {
774 child->PruneChildFrameNavigationEntries(entry);
775 }
776 }
777}
778
arthursonzogni034bb9c2020-10-01 08:29:56779void FrameTreeNode::SetInitialPopupURL(const GURL& initial_popup_url) {
780 DCHECK(initial_popup_url_.is_empty());
Rakina Zata Amni4182b032021-11-01 04:22:01781 DCHECK(is_on_initial_empty_document_);
arthursonzogni034bb9c2020-10-01 08:29:56782 initial_popup_url_ = initial_popup_url;
783}
784
785void FrameTreeNode::SetPopupCreatorOrigin(
786 const url::Origin& popup_creator_origin) {
Rakina Zata Amni4182b032021-11-01 04:22:01787 DCHECK(is_on_initial_empty_document_);
arthursonzogni034bb9c2020-10-01 08:29:56788 popup_creator_origin_ = popup_creator_origin;
789}
790
Alexander Timinbebb2002021-04-20 15:42:24791void FrameTreeNode::WriteIntoTrace(perfetto::TracedValue context) const {
Alexander Timinf785f342021-03-18 00:00:56792 auto dict = std::move(context).WriteDictionary();
793 dict.Add("id", frame_tree_node_id());
794 dict.Add("is_main_frame", IsMainFrame());
Harkiran Bolaria3bf5457f2022-03-10 20:04:37795 dict.Add("current_frame_host", current_frame_host());
Alexander Timinf785f342021-03-18 00:00:56796}
797
Rakina Zata Amni4b1968d2021-09-09 03:29:47798void FrameTreeNode::WriteIntoTrace(
Alexander Timin33e2e2c12022-03-03 04:21:33799 perfetto::TracedProto<perfetto::protos::pbzero::FrameTreeNodeInfo> proto)
800 const {
Rakina Zata Amni4b1968d2021-09-09 03:29:47801 proto->set_is_main_frame(IsMainFrame());
802 proto->set_frame_tree_node_id(frame_tree_node_id());
803 proto->set_has_speculative_render_frame_host(
804 !!render_manager()->speculative_frame_host());
Harkiran Bolaria3bf5457f2022-03-10 20:04:37805 if (current_frame_host()) {
806 current_frame_host()->WriteIntoTrace(proto.WriteNestedMessage(
807 perfetto::protos::pbzero::FrameTreeNodeInfo::kCurrentFrameHost));
808 }
Rakina Zata Amni4b1968d2021-09-09 03:29:47809}
810
Carlos Caballero76711352021-03-24 17:38:21811bool FrameTreeNode::HasNavigation() {
812 if (navigation_request())
813 return true;
814
815 // Same-RenderFrameHost navigation is committing:
816 if (current_frame_host()->HasPendingCommitNavigation())
817 return true;
818
819 // Cross-RenderFrameHost navigation is committing:
820 if (render_manager()->speculative_frame_host())
821 return true;
822
823 return false;
824}
825
Dominic Farolino4bc10ee2021-08-31 00:37:36826bool FrameTreeNode::IsFencedFrameRoot() const {
Harkiran Bolaria0b3bdef02022-03-10 13:04:40827 return current_frame_host()->IsFencedFrameRootNoStatus();
shivanigithubf3ddff52021-07-03 22:06:30828}
829
830bool FrameTreeNode::IsInFencedFrameTree() const {
Harkiran Bolaria0b3bdef02022-03-10 13:04:40831 return current_frame_host()->IsInFencedFrameTree();
shivanigithubf3ddff52021-07-03 22:06:30832}
833
shivanigithub4cd016a2021-09-20 21:10:30834void FrameTreeNode::SetFencedFrameNonceIfNeeded() {
835 if (!IsInFencedFrameTree()) {
836 return;
837 }
838
839 if (IsFencedFrameRoot()) {
840 fenced_frame_nonce_ = base::UnguessableToken::Create();
841 return;
842 }
843
844 // For nested iframes in a fenced frame tree, propagate the same nonce as was
845 // set in the fenced frame root.
846 DCHECK(parent_);
847 absl::optional<base::UnguessableToken> nonce =
848 parent_->frame_tree_node()->fenced_frame_nonce();
849 DCHECK(nonce.has_value());
850 fenced_frame_nonce_ = nonce;
851}
852
Nan Lin171fe9a2022-02-17 16:42:16853void FrameTreeNode::SetFencedFrameModeIfNeeded(
854 FencedFrameMode fenced_frame_mode) {
855 if (!IsFencedFrameRoot())
856 return;
857
858 // TODO(crbug.com/1123606): The 'mode' attribute cannot be changed once
859 // applied to a fenced frame. This will be enforced before this point so add
860 // a DCHECK here.
861
862 fenced_frame_mode_ = fenced_frame_mode;
863}
864
Nan Linaaf84f72021-12-02 22:31:56865bool FrameTreeNode::IsErrorPageIsolationEnabled() const {
Nan Lind9de87d2022-03-18 16:53:03866 // Error page isolation is enabled for main frames only (crbug.com/1092524).
867 // Note that this will also enable error page isolation for fenced frames in
868 // MPArch mode, but not ShadowDOM mode.
869 // See the issue in crbug.com/1264224#c7 for why it can't be enabled for
870 // ShadowDOM mode.
871 return SiteIsolationPolicy::IsErrorPageIsolationEnabled(IsMainFrame());
Nan Linaaf84f72021-12-02 22:31:56872}
873
W. James MacLean81b8d01f2022-01-25 20:50:59874void FrameTreeNode::SetSrcdocValue(const std::string& srcdoc_value) {
875 srcdoc_value_ = srcdoc_value;
876}
877
Harkiran Bolariaebbe7702022-02-22 19:19:03878const scoped_refptr<BrowsingContextState>&
879FrameTreeNode::GetBrowsingContextStateForSubframe() const {
880 DCHECK(!IsMainFrame());
881 return current_frame_host()->browsing_context_state();
882}
883
[email protected]9b159a52013-10-03 17:24:55884} // namespace content