blob: a12085b307249ec099c4803ca73381b19db8236a [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"
Clark DuVallc97bcf72021-12-08 22:58:2417#include "base/strings/strcat.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4118#include "base/strings/string_util.h"
Clark DuVallc97bcf72021-12-08 22:58:2419#include "base/timer/elapsed_timer.h"
Andrey Kosyakovf2d4ff72018-10-29 20:09:5920#include "content/browser/devtools/devtools_instrumentation.h"
danakjc492bf82020-09-09 20:02:4421#include "content/browser/renderer_host/navigation_controller_impl.h"
22#include "content/browser/renderer_host/navigation_request.h"
23#include "content/browser/renderer_host/navigator.h"
24#include "content/browser/renderer_host/navigator_delegate.h"
25#include "content/browser/renderer_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4126#include "content/browser/renderer_host/render_view_host_impl.h"
Lucas Furukawa Gadanief8290a2019-07-29 20:27:5127#include "content/common/navigation_params_utils.h"
dmazzonie950ea232015-03-13 21:39:4528#include "content/public/browser/browser_thread.h"
Nan Linaaf84f72021-12-02 22:31:5629#include "content/public/browser/site_isolation_policy.h"
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1430#include "content/public/common/content_features.h"
arthursonzognib93a4472020-04-10 07:38:0031#include "services/network/public/cpp/web_sandbox_flags.h"
32#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
Harkiran Bolaria59290d62021-03-17 01:53:0133#include "third_party/blink/public/common/features.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1534#include "third_party/blink/public/common/loader/loader_constants.h"
Antonio Gomes4b2c5132020-01-16 11:49:4835#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:3736#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
[email protected]9b159a52013-10-03 17:24:5537
38namespace content {
39
dmazzonie950ea232015-03-13 21:39:4540namespace {
41
42// This is a global map between frame_tree_node_ids and pointers to
43// FrameTreeNodes.
Takuto Ikutaadf31eb2019-01-05 00:32:4844typedef std::unordered_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4545
scottmg5e65e3a2017-03-08 08:48:4646base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
47 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4548
fdegansa696e5112015-04-17 01:57:5949} // namespace
fdegans1d16355162015-03-26 11:58:3450
alexmose201c7cd2015-06-10 17:14:2151// This observer watches the opener of its owner FrameTreeNode and clears the
52// owner's opener if the opener is destroyed.
53class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
54 public:
jochen6004a362017-02-04 00:11:4055 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
56 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2157
Peter Boström9b036532021-10-28 23:37:2858 OpenerDestroyedObserver(const OpenerDestroyedObserver&) = delete;
59 OpenerDestroyedObserver& operator=(const OpenerDestroyedObserver&) = delete;
60
alexmose201c7cd2015-06-10 17:14:2161 // FrameTreeNode::Observer
62 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4063 if (observing_original_opener_) {
Avi Drissman36465f332017-09-11 20:49:3964 // The "original owner" is special. It's used for attribution, and clients
65 // walk down the original owner chain. Therefore, if a link in the chain
66 // is being destroyed, reconnect the observation to the parent of the link
67 // being destroyed.
jochen6004a362017-02-04 00:11:4068 CHECK_EQ(owner_->original_opener(), node);
Avi Drissman36465f332017-09-11 20:49:3969 owner_->SetOriginalOpener(node->original_opener());
70 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4071 } else {
72 CHECK_EQ(owner_->opener(), node);
73 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:3974 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4075 }
alexmose201c7cd2015-06-10 17:14:2176 }
77
78 private:
Keishi Hattori0e45c022021-11-27 09:25:5279 raw_ptr<FrameTreeNode> owner_;
jochen6004a362017-02-04 00:11:4080 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2181};
82
Kevin McNee88e61552020-10-22 20:41:1183const int FrameTreeNode::kFrameTreeNodeInvalidId = -1;
84
85static_assert(FrameTreeNode::kFrameTreeNodeInvalidId ==
86 RenderFrameHost::kNoFrameTreeNodeId,
87 "Have consistent sentinel values for an invalid FTN id.");
88
vishal.b782eb5d2015-04-29 12:22:5789int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5590
dmazzonie950ea232015-03-13 21:39:4591// static
vishal.b782eb5d2015-04-29 12:22:5792FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1993 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1594 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:4695 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4596 return it == nodes->end() ? nullptr : it->second;
97}
98
Alexander Timin381e7e182020-04-28 19:04:0399// static
100FrameTreeNode* FrameTreeNode::From(RenderFrameHost* rfh) {
101 if (!rfh)
102 return nullptr;
103 return static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
104}
105
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54106FrameTreeNode::FrameTreeNode(
107 FrameTree* frame_tree,
Alexander Timin381e7e182020-04-28 19:04:03108 RenderFrameHostImpl* parent,
Daniel Cheng6ac128172021-05-25 18:49:01109 blink::mojom::TreeScopeType tree_scope_type,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54110 const std::string& name,
111 const std::string& unique_name,
112 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),
Gyuyoung Kimc16e52e92021-03-19 02:45:37122 replication_state_(blink::mojom::FrameReplicationState::New(
Antonio Sartori90f41212021-01-22 10:08:34123 url::Origin(),
estarka886b8d2015-12-18 21:53:08124 name,
lukasza464d8692016-02-22 19:26:32125 unique_name,
Charlie Hue24f04832021-03-04 21:07:06126 blink::ParsedPermissionsPolicy(),
Antonio Sartori90f41212021-01-22 10:08:34127 network::mojom::WebSandboxFlags::kNone,
Dominic Farolino08662c82021-06-11 07:36:34128 frame_policy,
Daniel Cheng9bd90f92021-04-23 20:49:45129 // should enforce strict mixed content checking
130 blink::mojom::InsecureRequestPolicy::kLeaveInsecureRequestsAlone,
131 // hashes of hosts for insecure request upgrades
132 std::vector<uint32_t>(),
japhet61835ae12017-01-20 01:25:39133 false /* is a potentially trustworthy unique origin */,
danakj359a4342020-05-29 20:38:39134 false /* has an active user gesture */,
Ehsan Karamad192a8da2018-10-21 03:48:08135 false /* has received a user gesture before nav */,
Alex Turner10d557a42021-06-01 19:06:49136 false /* is_ad_subframe */)),
Dominic Farolino08662c82021-06-11 07:36:34137 pending_frame_policy_(frame_policy),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45138 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06139 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31140 frame_owner_properties_(frame_owner_properties),
Lukasz Anforowicz147141962020-12-16 18:03:24141 blame_context_(frame_tree_node_id_, FrameTreeNode::From(parent)),
142 render_manager_(this, frame_tree->manager_delegate()) {
rob97250742015-12-10 17:45:15143 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45144 g_frame_tree_node_id_map.Get().insert(
145 std::make_pair(frame_tree_node_id_, this));
146 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33147
xiaochenghb9554bb2016-05-21 14:20:48148 // Note: this should always be done last in the constructor.
149 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59150}
[email protected]9b159a52013-10-03 17:24:55151
152FrameTreeNode::~FrameTreeNode() {
Daniel Chengc3d1e8d2021-06-23 02:11:45153 // There should always be a current RenderFrameHost except during prerender
154 // activation. Prerender activation moves the current RenderFrameHost from
155 // the old FrameTree's FrameTreeNode to the new FrameTree's FrameTreeNode and
156 // then destroys the old FrameTree. See
157 // `RenderFrameHostManager::TakePrerenderedPage()`.
Harkiran Bolaria59290d62021-03-17 01:53:01158 if (current_frame_host()) {
159 // Remove the children.
160 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45161
Harkiran Bolaria59290d62021-03-17 01:53:01162 current_frame_host()->ResetLoadingState();
163 } else {
Hiroki Nakagawa0a90bd42021-04-21 01:53:05164 DCHECK(blink::features::IsPrerender2Enabled());
Harkiran Bolaria59290d62021-03-17 01:53:01165 DCHECK(!parent()); // Only main documents can be activated.
166 DCHECK(!opener()); // Prerendered frame trees can't have openers.
167
168 // Activation is not allowed during ongoing navigations.
169 DCHECK(!navigation_request_);
170
Carlos Caballerod1c80432021-04-20 08:16:32171 // TODO(https://crbug.com/1199693): Need to determine how to handle pending
Harkiran Bolaria59290d62021-03-17 01:53:01172 // deletions, as observers will be notified.
173 DCHECK(!render_manager()->speculative_frame_host());
174 }
Nate Chapin22ea6592019-03-05 22:29:02175
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45176 // If the removed frame was created by a script, then its history entry will
177 // never be reused - we can save some memory by removing the history entry.
178 // See also https://crbug.com/784356.
179 if (is_created_by_script_ && parent_) {
Carlos Caballero04aab362021-02-15 17:38:16180 NavigationEntryImpl* nav_entry =
181 navigator().controller().GetLastCommittedEntry();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45182 if (nav_entry) {
183 nav_entry->RemoveEntryForFrame(this,
184 /* only_if_different_position = */ false);
185 }
186 }
187
dmazzonie950ea232015-03-13 21:39:45188 frame_tree_->FrameRemoved(this);
Carlos Caballero6ff6ace2021-02-05 16:53:00189
190 // Do not dispatch notification for the root frame as ~WebContentsImpl already
191 // dispatches it for now.
192 // TODO(https://crbug.com/1170277): This is only needed because the FrameTree
193 // is a member of WebContentsImpl and we would call back into it during
194 // destruction. We should clean up the FrameTree destruction code and call the
195 // delegate unconditionally.
196 if (parent())
197 render_manager_.delegate()->OnFrameTreeNodeDestroyed(this);
198
ericwilligers254597b2016-10-17 10:32:31199 for (auto& observer : observers_)
200 observer.OnFrameTreeNodeDestroyed(this);
Lukasz Anforowicz147141962020-12-16 18:03:24201 observers_.Clear();
alexmose201c7cd2015-06-10 17:14:21202
203 if (opener_)
204 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40205 if (original_opener_)
206 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45207
208 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18209
Daniel Chengc3d1e8d2021-06-23 02:11:45210 // If a frame with a pending navigation is detached, make sure the
211 // WebContents (and its observers) update their loading state.
212 // TODO(dcheng): This should just check `IsLoading()`, but `IsLoading()`
213 // assumes that `current_frame_host_` is not null. This is incompatible with
214 // prerender activation when destroying the old frame tree (see above).
danakjf9400602019-06-07 15:44:58215 bool did_stop_loading = false;
216
jam39258caf2016-11-02 14:48:18217 if (navigation_request_) {
danakjf9400602019-06-07 15:44:58218 navigation_request_.reset();
danakjf9400602019-06-07 15:44:58219 did_stop_loading = true;
jam39258caf2016-11-02 14:48:18220 }
Nate Chapin22ea6592019-03-05 22:29:02221
danakjf9400602019-06-07 15:44:58222 // ~SiteProcessCountTracker DCHECKs in some tests if the speculative
223 // RenderFrameHostImpl is not destroyed last. Ideally this would be closer to
224 // (possible before) the ResetLoadingState() call above.
danakjf9400602019-06-07 15:44:58225 if (render_manager_.speculative_frame_host()) {
Daniel Chengc3d1e8d2021-06-23 02:11:45226 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative
227 // RenderFrameHost always be considered loading?
danakjf9400602019-06-07 15:44:58228 did_stop_loading |= render_manager_.speculative_frame_host()->is_loading();
Daniel Chengc3d1e8d2021-06-23 02:11:45229 // `FrameTree::Shutdown()` has special handling for the main frame's
230 // speculative RenderFrameHost, and the speculative RenderFrameHost should
231 // already be reset for main frames.
232 DCHECK(!IsMainFrame());
233
234 // This does not use `UnsetSpeculativeRenderFrameHost()`: if the speculative
235 // RenderFrameHost has already reached kPendingCommit, it would needlessly
236 // re-create a proxy for a frame that's going away.
237 render_manager_.DiscardSpeculativeRenderFrameHostForShutdown();
danakjf9400602019-06-07 15:44:58238 }
239
240 if (did_stop_loading)
241 DidStopLoading();
242
Harkiran Bolaria59290d62021-03-17 01:53:01243 // IsLoading() requires that current_frame_host() is non-null.
244 DCHECK(!current_frame_host() || !IsLoading());
[email protected]9b159a52013-10-03 17:24:55245}
246
alexmose201c7cd2015-06-10 17:14:21247void FrameTreeNode::AddObserver(Observer* observer) {
248 observers_.AddObserver(observer);
249}
250
251void FrameTreeNode::RemoveObserver(Observer* observer) {
252 observers_.RemoveObserver(observer);
253}
254
[email protected]94d0cc12013-12-18 00:07:41255bool FrameTreeNode::IsMainFrame() const {
256 return frame_tree_->root() == this;
257}
258
Hiroki Nakagawaab309622021-05-19 16:38:13259void FrameTreeNode::ResetForNavigation() {
arthursonzogni76098e52020-11-25 14:18:45260 // This frame has had its user activation bits cleared in the renderer before
261 // arriving here. We just need to clear them here and in the other renderer
262 // processes that may have a reference to this frame.
Alexander Timin45b716c2020-11-06 01:40:31263 //
264 // We do not take user activation into account when calculating
265 // |ResetForNavigationResult|, as we are using it to determine bfcache
266 // eligibility and the page can get another user gesture after restore.
Antonio Gomes4b2c5132020-01-16 11:49:48267 UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11268 blink::mojom::UserActivationUpdateType::kClearActivation,
269 blink::mojom::UserActivationNotificationType::kNone);
Ian Clelland5cbaaf82017-11-27 22:00:03270}
271
Dave Tapuskac8de3b02021-12-03 21:51:01272RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocument() {
273 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/false);
274}
275
276RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentOrEmbedder() {
277 return GetParentOrOuterDocumentHelper(/*escape_guest_view=*/true);
278}
279
280RenderFrameHostImpl* FrameTreeNode::GetParentOrOuterDocumentHelper(
281 bool escape_guest_view) {
282 // Find the parent in the FrameTree (iframe).
283 if (parent_)
284 return parent_;
285
286 if (!escape_guest_view) {
287 // If we are not a fenced frame root nor inside a portal then return early.
288 // This code does not escape GuestViews.
289 if (!IsFencedFrameRoot() && !frame_tree_->delegate()->IsPortal())
290 return nullptr;
291 }
292
293 // Find the parent in the outer embedder (GuestView, Portal, or Fenced Frame).
294 FrameTreeNode* frame_in_embedder = render_manager()->GetOuterDelegateNode();
295 if (frame_in_embedder)
296 return frame_in_embedder->current_frame_host()->GetParent();
297
298 // No parent found.
299 return nullptr;
300}
301
yilkal34a3d752019-08-30 18:20:30302size_t FrameTreeNode::GetFrameTreeSize() const {
303 if (is_collapsed())
304 return 0;
305
306 size_t size = 0;
307 for (size_t i = 0; i < child_count(); i++) {
308 size += child_at(i)->GetFrameTreeSize();
309 }
310
311 // Account for this node.
312 size++;
313 return size;
314}
315
alexmose201c7cd2015-06-10 17:14:21316void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
317 if (opener_) {
318 opener_->RemoveObserver(opener_observer_.get());
319 opener_observer_.reset();
320 }
321
322 opener_ = opener;
323
324 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55325 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21326 opener_->AddObserver(opener_observer_.get());
327 }
328}
329
Wolfgang Beyerd8809db2020-09-30 15:29:39330void FrameTreeNode::SetOpenerDevtoolsFrameToken(
331 base::UnguessableToken opener_devtools_frame_token) {
332 DCHECK(!opener_devtools_frame_token_ ||
333 opener_devtools_frame_token_->is_empty());
334 opener_devtools_frame_token_ = std::move(opener_devtools_frame_token);
335}
336
jochen6004a362017-02-04 00:11:40337void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39338 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37339 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40340
Avi Drissman36465f332017-09-11 20:49:39341 if (original_opener_) {
342 original_opener_->RemoveObserver(original_opener_observer_.get());
343 original_opener_observer_.reset();
344 }
345
jochen6004a362017-02-04 00:11:40346 original_opener_ = opener;
347
348 if (original_opener_) {
jochen6004a362017-02-04 00:11:40349 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55350 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40351 original_opener_->AddObserver(original_opener_observer_.get());
352 }
353}
354
creisf0f069a2015-07-23 23:51:53355void FrameTreeNode::SetCurrentURL(const GURL& url) {
Erik Chen173bf3042017-07-31 06:06:21356 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48357 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53358}
359
Rakina Zata Amni86c88fa2021-11-01 01:27:30360void FrameTreeNode::DidCommitNonInitialEmptyDocument() {
Rakina Zata Amni86c88fa2021-11-01 01:27:30361 is_on_initial_empty_document_ = false;
362}
363
estarkbd8e26f2016-03-16 23:30:37364void FrameTreeNode::SetCurrentOrigin(
365 const url::Origin& origin,
366 bool is_potentially_trustworthy_unique_origin) {
Antonio Sartori90f41212021-01-22 10:08:34367 if (!origin.IsSameOriginWith(replication_state_->origin) ||
368 replication_state_->has_potentially_trustworthy_unique_origin !=
estarkbd8e26f2016-03-16 23:30:37369 is_potentially_trustworthy_unique_origin) {
370 render_manager_.OnDidUpdateOrigin(origin,
371 is_potentially_trustworthy_unique_origin);
372 }
Antonio Sartori90f41212021-01-22 10:08:34373 replication_state_->origin = origin;
374 replication_state_->has_potentially_trustworthy_unique_origin =
estarkbd8e26f2016-03-16 23:30:37375 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56376}
alexmosbe2f4c32015-03-10 02:30:23377
engedy6e2e0992017-05-25 18:58:42378void FrameTreeNode::SetCollapsed(bool collapsed) {
379 DCHECK(!IsMainFrame());
380 if (is_collapsed_ == collapsed)
381 return;
382
383 is_collapsed_ = collapsed;
384 render_manager_.OnDidChangeCollapsedState(collapsed);
385}
386
Harkiran Bolaria59290d62021-03-17 01:53:01387void FrameTreeNode::SetFrameTree(FrameTree& frame_tree) {
Hiroki Nakagawa0a90bd42021-04-21 01:53:05388 DCHECK(blink::features::IsPrerender2Enabled());
Harkiran Bolaria59290d62021-03-17 01:53:01389 frame_tree_ = &frame_tree;
Kevin McNeeb110d0c2021-10-26 15:53:00390 DCHECK(current_frame_host());
391 current_frame_host()->SetFrameTree(frame_tree);
392 RenderFrameHostImpl* speculative_frame_host =
393 render_manager_.speculative_frame_host();
394 if (speculative_frame_host)
395 speculative_frame_host->SetFrameTree(frame_tree);
Harkiran Bolaria59290d62021-03-17 01:53:01396}
397
lukasza464d8692016-02-22 19:26:32398void FrameTreeNode::SetFrameName(const std::string& name,
399 const std::string& unique_name) {
Antonio Sartori90f41212021-01-22 10:08:34400 if (name == replication_state_->name) {
lukasza464d8692016-02-22 19:26:32401 // |unique_name| shouldn't change unless |name| changes.
Antonio Sartori90f41212021-01-22 10:08:34402 DCHECK_EQ(unique_name, replication_state_->unique_name);
lukasza464d8692016-02-22 19:26:32403 return;
404 }
lukasza5140a412016-09-15 21:12:30405
406 if (parent()) {
407 // Non-main frames should have a non-empty unique name.
408 DCHECK(!unique_name.empty());
409 } else {
410 // Unique name of main frames should always stay empty.
411 DCHECK(unique_name.empty());
412 }
413
Daniel Cheng6ca7f1c92017-08-09 21:45:41414 // Note the unique name should only be able to change before the first real
415 // load is committed, but that's not strongly enforced here.
lukasza464d8692016-02-22 19:26:32416 render_manager_.OnDidUpdateName(name, unique_name);
Antonio Sartori90f41212021-01-22 10:08:34417 replication_state_->name = name;
418 replication_state_->unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23419}
420
mkwstf672e7ef2016-06-09 20:51:07421void FrameTreeNode::SetInsecureRequestPolicy(
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:37422 blink::mojom::InsecureRequestPolicy policy) {
Antonio Sartori90f41212021-01-22 10:08:34423 if (policy == replication_state_->insecure_request_policy)
estarka886b8d2015-12-18 21:53:08424 return;
mkwstf672e7ef2016-06-09 20:51:07425 render_manager_.OnEnforceInsecureRequestPolicy(policy);
Antonio Sartori90f41212021-01-22 10:08:34426 replication_state_->insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08427}
428
arthursonzogni4b62a5cb2018-01-17 14:14:26429void FrameTreeNode::SetInsecureNavigationsSet(
430 const std::vector<uint32_t>& insecure_navigations_set) {
431 DCHECK(std::is_sorted(insecure_navigations_set.begin(),
432 insecure_navigations_set.end()));
Antonio Sartori90f41212021-01-22 10:08:34433 if (insecure_navigations_set == replication_state_->insecure_navigations_set)
arthursonzogni4b62a5cb2018-01-17 14:14:26434 return;
435 render_manager_.OnEnforceInsecureNavigationsSet(insecure_navigations_set);
Antonio Sartori90f41212021-01-22 10:08:34436 replication_state_->insecure_navigations_set = insecure_navigations_set;
arthursonzogni4b62a5cb2018-01-17 14:14:26437}
438
Luna Luc3fdacdf2017-11-08 04:48:53439void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Dominic Farolino08662c82021-06-11 07:36:34440 // The |is_fenced| bit should never be able to transition from what its
441 // initial value was. Since we never expect to be in a position where it can
442 // even be updated to new value, if we catch this happening we have to kill
443 // the renderer and refuse to accept any other frame policy changes here.
444 if (pending_frame_policy_.is_fenced != frame_policy.is_fenced) {
445 mojo::ReportBadMessage(
446 "The `is_fenced` FramePolicy bit is const and should never be changed");
447 return;
448 }
449
Ian Clellandcdc4f312017-10-13 22:24:12450 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25451
Ian Clellandcdc4f312017-10-13 22:24:12452 if (parent()) {
453 // Subframes should always inherit their parent's sandbox flags.
Alexander Timin381e7e182020-04-28 19:04:03454 pending_frame_policy_.sandbox_flags |=
455 parent()->frame_tree_node()->active_sandbox_flags();
Charlie Hue1b77ac2019-12-13 21:30:17456 // This is only applied on subframes; container policy and required document
457 // policy are not mutable on main frame.
Ian Clellandcdc4f312017-10-13 22:24:12458 pending_frame_policy_.container_policy = frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17459 pending_frame_policy_.required_document_policy =
460 frame_policy.required_document_policy;
Ian Clellandcdc4f312017-10-13 22:24:12461 }
iclelland92f8c0b2017-04-19 12:43:05462}
463
fdegans4a49ce932015-03-12 17:11:37464bool FrameTreeNode::IsLoading() const {
465 RenderFrameHostImpl* current_frame_host =
466 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37467
468 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39469
clamy610c63b32017-12-22 15:05:18470 if (navigation_request_)
471 return true;
clamy11e11512015-07-07 16:42:17472
clamy610c63b32017-12-22 15:05:18473 RenderFrameHostImpl* speculative_frame_host =
474 render_manager_.speculative_frame_host();
Daniel Chengc3d1e8d2021-06-23 02:11:45475 // TODO(dcheng): Shouldn't a FrameTreeNode with a speculative RenderFrameHost
476 // always be considered loading?
clamy610c63b32017-12-22 15:05:18477 if (speculative_frame_host && speculative_frame_host->is_loading())
478 return true;
fdegans4a49ce932015-03-12 17:11:37479 return current_frame_host->is_loading();
480}
481
Alex Moshchuk9b0fd822020-10-26 23:08:15482bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
483 // Having a |navigation_request_| on FrameTreeNode implies that there's an
484 // ongoing navigation that hasn't reached the ReadyToCommit state. If the
485 // navigation is between ReadyToCommit and DidCommitNavigation, the
486 // NavigationRequest will be held by RenderFrameHost, which is checked below.
487 if (navigation_request_ && !navigation_request_->IsSameDocument())
488 return true;
489
490 // Having a speculative RenderFrameHost should imply a cross-document
491 // navigation.
492 if (render_manager_.speculative_frame_host())
493 return true;
494
495 return render_manager_.current_frame_host()
496 ->HasPendingCommitForCrossDocumentNavigation();
497}
498
Charlie Hu5ffc0152019-12-06 15:59:53499bool FrameTreeNode::CommitFramePolicy(
500 const blink::FramePolicy& new_frame_policy) {
Arthur Sonzogni62f4f822021-10-21 11:44:35501 // Documents create iframes, iframes host new documents. Both are associated
502 // with sandbox flags. They are required to be stricter or equal to their
503 // owner when they change, as we go down.
504 // TODO(https://crbug.com/1262061). Enforce the invariant mentioned above,
505 // once the interactions with FencedIframe has been tested and clarified.
506
Charlie Hu5ffc0152019-12-06 15:59:53507 bool did_change_flags = new_frame_policy.sandbox_flags !=
Antonio Sartori90f41212021-01-22 10:08:34508 replication_state_->frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05509 bool did_change_container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53510 new_frame_policy.container_policy !=
Antonio Sartori90f41212021-01-22 10:08:34511 replication_state_->frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17512 bool did_change_required_document_policy =
513 pending_frame_policy_.required_document_policy !=
Antonio Sartori90f41212021-01-22 10:08:34514 replication_state_->frame_policy.required_document_policy;
Dominic Farolino08662c82021-06-11 07:36:34515 DCHECK_EQ(new_frame_policy.is_fenced,
516 replication_state_->frame_policy.is_fenced);
Antonio Sartori90f41212021-01-22 10:08:34517 if (did_change_flags) {
518 replication_state_->frame_policy.sandbox_flags =
Charlie Hu5ffc0152019-12-06 15:59:53519 new_frame_policy.sandbox_flags;
Antonio Sartori90f41212021-01-22 10:08:34520 }
521 if (did_change_container_policy) {
522 replication_state_->frame_policy.container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53523 new_frame_policy.container_policy;
Antonio Sartori90f41212021-01-22 10:08:34524 }
525 if (did_change_required_document_policy) {
526 replication_state_->frame_policy.required_document_policy =
Charlie Hue1b77ac2019-12-13 21:30:17527 new_frame_policy.required_document_policy;
Antonio Sartori90f41212021-01-22 10:08:34528 }
Charlie Hue1b77ac2019-12-13 21:30:17529
Charlie Hu5ffc0152019-12-06 15:59:53530 UpdateFramePolicyHeaders(new_frame_policy.sandbox_flags,
Charlie Hue20fe2f2021-03-07 03:39:59531 replication_state_->permissions_policy_header);
Charlie Hue1b77ac2019-12-13 21:30:17532 return did_change_flags || did_change_container_policy ||
Dave Tapuska7fdfc2f2021-06-08 17:38:40533 did_change_required_document_policy;
alexmos6b294562015-03-05 19:24:10534}
535
Arthur Hemeryc3380172018-01-22 14:00:17536void FrameTreeNode::TransferNavigationRequestOwnership(
537 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59538 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17539 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
540}
541
carloskc49005eb2015-06-16 11:25:07542void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57543 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37544 // This is never called when navigating to a Javascript URL. For the loading
545 // state, this matches what Blink is doing: Blink doesn't send throbber
546 // notifications for Javascript URLS.
547 DCHECK(!navigation_request->common_params().url.SchemeIs(
548 url::kJavaScriptScheme));
549
clamy44e84ce2016-02-22 15:38:25550 bool was_previously_loading = frame_tree()->IsLoading();
551
clamy82a2f4d2016-02-02 14:20:41552 // There's no need to reset the state: there's still an ongoing load, and the
553 // RenderFrameHostManager will take care of updates to the speculative
554 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05555 if (was_previously_loading) {
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31556 if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
jamcd0b7b22017-03-24 22:13:05557 // Mark the old request as aborted.
Mohamed Abdelhalimb4db22a2019-06-18 10:46:52558 navigation_request_->set_net_error(net::ERR_ABORTED);
jamcd0b7b22017-03-24 22:13:05559 }
Arthur Hemery241b9392019-10-24 11:08:41560 ResetNavigationRequest(true);
jamcd0b7b22017-03-24 22:13:05561 }
clamy44e84ce2016-02-22 15:38:25562
563 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06564 if (was_discarded_) {
565 navigation_request_->set_was_discarded();
566 was_discarded_ = false;
567 }
clamy8e2e299202016-04-05 11:44:59568 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39569
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51570 bool to_different_document = !NavigationTypeUtils::IsSameDocument(
arthursonzogni92f18682017-02-08 23:00:04571 navigation_request_->common_params().navigation_type);
572
573 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16574}
575
Arthur Hemery241b9392019-10-24 11:08:41576void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
fdegans39ff0382015-04-29 19:04:39577 if (!navigation_request_)
578 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23579
Andrey Kosyakovf2d4ff72018-10-29 20:09:59580 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
clamydcb434c12015-04-16 19:29:16581 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39582
clamy82a2f4d2016-02-02 14:20:41583 if (keep_state)
fdegans39ff0382015-04-29 19:04:39584 return;
585
clamy82a2f4d2016-02-02 14:20:41586 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
587 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39588 DidStopLoading();
589 render_manager_.CleanUpNavigation();
clamydcb434c12015-04-16 19:29:16590}
591
Nate Chapin9aabf5f2021-11-12 00:31:19592void FrameTreeNode::DidStartLoading(bool should_show_loading_ui,
clamy44e84ce2016-02-22 15:38:25593 bool was_previously_loading) {
Camille Lamyefd54b02018-10-04 16:54:14594 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
Nate Chapin9aabf5f2021-11-12 00:31:19595 "frame_tree_node", frame_tree_node_id(),
596 "should_show_loading_ui ", should_show_loading_ui);
Clark DuVallc97bcf72021-12-08 22:58:24597 base::ElapsedTimer timer;
fdegansa696e5112015-04-17 01:57:59598
Nate Chapin9aabf5f2021-11-12 00:31:19599 frame_tree_->DidStartLoadingNode(*this, should_show_loading_ui,
Carlos Caballero03262522021-02-05 14:49:58600 was_previously_loading);
fdegansa696e5112015-04-17 01:57:59601
602 // Set initial load progress and update overall progress. This will notify
603 // the WebContents of the load progress change.
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15604 DidChangeLoadProgress(blink::kInitialLoadProgress);
fdegansa696e5112015-04-17 01:57:59605
606 // Notify the RenderFrameHostManager of the event.
607 render_manager()->OnDidStartLoading();
Clark DuVallc97bcf72021-12-08 22:58:24608 base::UmaHistogramTimes(
609 base::StrCat({"Navigation.DidStartLoading.",
610 IsMainFrame() ? "MainFrame" : "Subframe"}),
611 timer.Elapsed());
fdegansa696e5112015-04-17 01:57:59612}
613
614void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14615 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
616 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59617 // Set final load progress and update overall progress. This will notify
618 // the WebContents of the load progress change.
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15619 DidChangeLoadProgress(blink::kFinalLoadProgress);
fdegansa696e5112015-04-17 01:57:59620
Lucas Furukawa Gadani6faef602019-05-06 21:16:03621 // Notify the RenderFrameHostManager of the event.
622 render_manager()->OnDidStopLoading();
623
Carlos Caballero03262522021-02-05 14:49:58624 frame_tree_->DidStopLoadingNode(*this);
fdegansa696e5112015-04-17 01:57:59625}
626
627void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15628 DCHECK_GE(load_progress, blink::kInitialLoadProgress);
629 DCHECK_LE(load_progress, blink::kFinalLoadProgress);
630 current_frame_host()->DidChangeLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59631}
632
clamyf73862c42015-07-08 12:31:33633bool FrameTreeNode::StopLoading() {
arthursonzogni66f711c2019-10-08 14:40:36634 if (navigation_request_ && navigation_request_->IsNavigationStarted())
635 navigation_request_->set_net_error(net::ERR_ABORTED);
Arthur Hemery241b9392019-10-24 11:08:41636 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33637
clamyf73862c42015-07-08 12:31:33638 if (!IsMainFrame())
639 return true;
640
641 render_manager_.Stop();
642 return true;
643}
644
alexmos21acae52015-11-07 01:04:43645void FrameTreeNode::DidFocus() {
646 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31647 for (auto& observer : observers_)
648 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43649}
650
clamy44e84ce2016-02-22 15:38:25651void FrameTreeNode::BeforeUnloadCanceled() {
652 // TODO(clamy): Support BeforeUnload in subframes.
653 if (!IsMainFrame())
654 return;
655
656 RenderFrameHostImpl* current_frame_host =
657 render_manager_.current_frame_host();
658 DCHECK(current_frame_host);
659 current_frame_host->ResetLoadingState();
660
clamy610c63b32017-12-22 15:05:18661 RenderFrameHostImpl* speculative_frame_host =
662 render_manager_.speculative_frame_host();
663 if (speculative_frame_host)
664 speculative_frame_host->ResetLoadingState();
Alexander Timin23c110b2021-01-14 02:39:04665 // Note: there is no need to set an error code on the NavigationHandle as
666 // the observers have not been notified about its creation.
667 // We also reset navigation request only when this navigation request was
668 // responsible for this dialog, as a new navigation request might cancel
669 // existing unrelated dialog.
670 if (navigation_request_ && navigation_request_->IsWaitingForBeforeUnload())
Arthur Hemery241b9392019-10-24 11:08:41671 ResetNavigationRequest(false);
clamy44e84ce2016-02-22 15:38:25672}
673
Mustaq Ahmedecb5c38e2020-07-29 00:34:30674bool FrameTreeNode::NotifyUserActivation(
675 blink::mojom::UserActivationNotificationType notification_type) {
Alex Moshchuk03904192021-04-02 07:29:08676 // User Activation V2 requires activating all ancestor frames in addition to
677 // the current frame. See
678 // https://html.spec.whatwg.org/multipage/interaction.html#tracking-user-activation.
Alexander Timina1dfadaa2020-04-28 13:30:06679 for (RenderFrameHostImpl* rfh = current_frame_host(); rfh;
680 rfh = rfh->GetParent()) {
John Delaneyb625dca92021-04-14 17:00:34681 rfh->DidReceiveUserActivation();
Mustaq Ahmedecb5c38e2020-07-29 00:34:30682 rfh->frame_tree_node()->user_activation_state_.Activate(notification_type);
John Delaneyedd8d6c2019-01-25 00:23:57683 }
Alex Moshchuk03904192021-04-02 07:29:08684
Antonio Sartori90f41212021-01-22 10:08:34685 replication_state_->has_active_user_gesture = true;
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14686
Mustaq Ahmed0180320f2019-03-21 16:07:01687 // See the "Same-origin Visibility" section in |UserActivationState| class
688 // doc.
Mustaq Ahmede5f12562019-10-30 18:02:03689 if (base::FeatureList::IsEnabled(
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14690 features::kUserActivationSameOriginVisibility)) {
691 const url::Origin& current_origin =
692 this->current_frame_host()->GetLastCommittedOrigin();
693 for (FrameTreeNode* node : frame_tree()->Nodes()) {
694 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
695 current_origin)) {
Mustaq Ahmedecb5c38e2020-07-29 00:34:30696 node->user_activation_state_.Activate(notification_type);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14697 }
698 }
699 }
700
Carlos Caballero40b0efd2021-01-26 11:55:00701 navigator().controller().NotifyUserActivation();
Alex Moshchuk03904192021-04-02 07:29:08702 current_frame_host()->MaybeIsolateForUserActivation();
Shivani Sharma194877032019-03-07 17:52:47703
Mustaq Ahmedc4cb7162018-06-05 16:28:36704 return true;
705}
706
707bool FrameTreeNode::ConsumeTransientUserActivation() {
708 bool was_active = user_activation_state_.IsActive();
709 for (FrameTreeNode* node : frame_tree()->Nodes())
710 node->user_activation_state_.ConsumeIfActive();
Antonio Sartori90f41212021-01-22 10:08:34711 replication_state_->has_active_user_gesture = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36712 return was_active;
713}
714
Shivani Sharmac4f561582018-11-15 15:58:39715bool FrameTreeNode::ClearUserActivation() {
Shivani Sharmac4f561582018-11-15 15:58:39716 for (FrameTreeNode* node : frame_tree()->SubtreeNodes(this))
717 node->user_activation_state_.Clear();
Antonio Sartori90f41212021-01-22 10:08:34718 replication_state_->has_active_user_gesture = false;
Shivani Sharmac4f561582018-11-15 15:58:39719 return true;
720}
721
Ella Ge9caed612019-08-09 16:17:25722bool FrameTreeNode::VerifyUserActivation() {
Ella Gea78f6772019-12-11 10:35:25723 DCHECK(base::FeatureList::IsEnabled(
724 features::kBrowserVerifiedUserActivationMouse) ||
725 base::FeatureList::IsEnabled(
726 features::kBrowserVerifiedUserActivationKeyboard));
727
Ella Ge9caed612019-08-09 16:17:25728 return render_manager_.current_frame_host()
729 ->GetRenderWidgetHost()
Mustaq Ahmed83bb1722019-10-22 20:00:10730 ->RemovePendingUserActivationIfAvailable();
Ella Ge9caed612019-08-09 16:17:25731}
732
Mustaq Ahmedc4cb7162018-06-05 16:28:36733bool FrameTreeNode::UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11734 blink::mojom::UserActivationUpdateType update_type,
735 blink::mojom::UserActivationNotificationType notification_type) {
Ella Ge9caed612019-08-09 16:17:25736 bool update_result = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36737 switch (update_type) {
Antonio Gomes4b2c5132020-01-16 11:49:48738 case blink::mojom::UserActivationUpdateType::kConsumeTransientActivation:
Ella Ge9caed612019-08-09 16:17:25739 update_result = ConsumeTransientUserActivation();
740 break;
Antonio Gomes4b2c5132020-01-16 11:49:48741 case blink::mojom::UserActivationUpdateType::kNotifyActivation:
Mustaq Ahmeddc195e5b2020-08-04 18:45:11742 update_result = NotifyUserActivation(notification_type);
Ella Ge9caed612019-08-09 16:17:25743 break;
Antonio Gomes4b2c5132020-01-16 11:49:48744 case blink::mojom::UserActivationUpdateType::
Liviu Tintad9391fb92020-09-28 23:50:07745 kNotifyActivationPendingBrowserVerification: {
746 const bool user_activation_verified = VerifyUserActivation();
747 // Add UMA metric for when browser user activation verification succeeds
748 base::UmaHistogramBoolean("Event.BrowserVerifiedUserActivation",
749 user_activation_verified);
750 if (user_activation_verified) {
Mustaq Ahmedecb5c38e2020-07-29 00:34:30751 update_result = NotifyUserActivation(
Mustaq Ahmed2cfb0402020-09-29 19:24:35752 blink::mojom::UserActivationNotificationType::kInteraction);
Antonio Gomes4b2c5132020-01-16 11:49:48753 update_type = blink::mojom::UserActivationUpdateType::kNotifyActivation;
Ella Ge9caed612019-08-09 16:17:25754 } else {
arthursonzogni9816b9192021-03-29 16:09:19755 // TODO(https://crbug.com/848778): We need to decide what to do when
756 // user activation verification failed. NOTREACHED here will make all
Ella Ge9caed612019-08-09 16:17:25757 // unrelated tests that inject event to renderer fail.
758 return false;
759 }
Liviu Tintad9391fb92020-09-28 23:50:07760 } break;
Antonio Gomes4b2c5132020-01-16 11:49:48761 case blink::mojom::UserActivationUpdateType::kClearActivation:
Ella Ge9caed612019-08-09 16:17:25762 update_result = ClearUserActivation();
763 break;
Mustaq Ahmedc4cb7162018-06-05 16:28:36764 }
Mustaq Ahmeddc195e5b2020-08-04 18:45:11765 render_manager_.UpdateUserActivationState(update_type, notification_type);
Ella Ge9caed612019-08-09 16:17:25766 return update_result;
japhet61835ae12017-01-20 01:25:39767}
768
Mustaq Ahmed01261742019-12-16 15:49:06769void FrameTreeNode::OnSetHadStickyUserActivationBeforeNavigation(bool value) {
770 render_manager_.OnSetHadStickyUserActivationBeforeNavigation(value);
Antonio Sartori90f41212021-01-22 10:08:34771 replication_state_->has_received_user_gesture_before_nav = value;
Becca Hughes60af7d42017-12-12 10:53:15772}
773
Alexander Timin45b716c2020-11-06 01:40:31774bool FrameTreeNode::UpdateFramePolicyHeaders(
arthursonzognib93a4472020-04-10 07:38:00775 network::mojom::WebSandboxFlags sandbox_flags,
Charlie Hue24f04832021-03-04 21:07:06776 const blink::ParsedPermissionsPolicy& parsed_header) {
Ian Clellandedb8c5dd2018-03-01 17:01:37777 bool changed = false;
Charlie Hue20fe2f2021-03-07 03:39:59778 if (replication_state_->permissions_policy_header != parsed_header) {
779 replication_state_->permissions_policy_header = parsed_header;
Ian Clellandedb8c5dd2018-03-01 17:01:37780 changed = true;
781 }
Ian Clelland5cbaaf82017-11-27 22:00:03782 // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the
783 // currently effective sandbox flags from the frame. https://crbug.com/740556
arthursonzognib93a4472020-04-10 07:38:00784 network::mojom::WebSandboxFlags updated_flags =
Ian Clelland5cbaaf82017-11-27 22:00:03785 sandbox_flags | effective_frame_policy().sandbox_flags;
Antonio Sartori90f41212021-01-22 10:08:34786 if (replication_state_->active_sandbox_flags != updated_flags) {
787 replication_state_->active_sandbox_flags = updated_flags;
Ian Clellandedb8c5dd2018-03-01 17:01:37788 changed = true;
789 }
790 // Notify any proxies if the policies have been changed.
791 if (changed)
792 render_manager()->OnDidSetFramePolicyHeaders();
Alexander Timin45b716c2020-11-06 01:40:31793 return changed;
Ian Clelland5cbaaf82017-11-27 22:00:03794}
795
Arthur Sonzognif8840b92018-11-07 14:10:35796void FrameTreeNode::PruneChildFrameNavigationEntries(
797 NavigationEntryImpl* entry) {
798 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
799 FrameTreeNode* child = current_frame_host()->child_at(i);
800 if (child->is_created_by_script_) {
801 entry->RemoveEntryForFrame(child,
802 /* only_if_different_position = */ false);
803 } else {
804 child->PruneChildFrameNavigationEntries(entry);
805 }
806 }
807}
808
Alex Turner10d557a42021-06-01 19:06:49809void FrameTreeNode::SetIsAdSubframe(bool is_ad_subframe) {
810 if (is_ad_subframe == replication_state_->is_ad_subframe)
Alex Turner5a09c462021-03-17 17:07:35811 return;
812
Alex Turner10d557a42021-06-01 19:06:49813 replication_state_->is_ad_subframe = is_ad_subframe;
814 render_manager()->OnDidSetIsAdSubframe(is_ad_subframe);
Yao Xiao24ec9aa2020-01-28 16:36:00815}
816
arthursonzogni034bb9c2020-10-01 08:29:56817void FrameTreeNode::SetInitialPopupURL(const GURL& initial_popup_url) {
818 DCHECK(initial_popup_url_.is_empty());
Rakina Zata Amni4182b032021-11-01 04:22:01819 DCHECK(is_on_initial_empty_document_);
arthursonzogni034bb9c2020-10-01 08:29:56820 initial_popup_url_ = initial_popup_url;
821}
822
823void FrameTreeNode::SetPopupCreatorOrigin(
824 const url::Origin& popup_creator_origin) {
Rakina Zata Amni4182b032021-11-01 04:22:01825 DCHECK(is_on_initial_empty_document_);
arthursonzogni034bb9c2020-10-01 08:29:56826 popup_creator_origin_ = popup_creator_origin;
827}
828
Alexander Timinbebb2002021-04-20 15:42:24829void FrameTreeNode::WriteIntoTrace(perfetto::TracedValue context) const {
Alexander Timinf785f342021-03-18 00:00:56830 auto dict = std::move(context).WriteDictionary();
831 dict.Add("id", frame_tree_node_id());
832 dict.Add("is_main_frame", IsMainFrame());
833}
834
Rakina Zata Amni4b1968d2021-09-09 03:29:47835void FrameTreeNode::WriteIntoTrace(
836 perfetto::TracedProto<perfetto::protos::pbzero::FrameTreeNodeInfo> proto) {
837 proto->set_is_main_frame(IsMainFrame());
838 proto->set_frame_tree_node_id(frame_tree_node_id());
839 proto->set_has_speculative_render_frame_host(
840 !!render_manager()->speculative_frame_host());
841}
842
Carlos Caballero76711352021-03-24 17:38:21843bool FrameTreeNode::HasNavigation() {
844 if (navigation_request())
845 return true;
846
847 // Same-RenderFrameHost navigation is committing:
848 if (current_frame_host()->HasPendingCommitNavigation())
849 return true;
850
851 // Cross-RenderFrameHost navigation is committing:
852 if (render_manager()->speculative_frame_host())
853 return true;
854
855 return false;
856}
857
Dominic Farolino4bc10ee2021-08-31 00:37:36858bool FrameTreeNode::IsFencedFrameRoot() const {
shivanigithubf3ddff52021-07-03 22:06:30859 if (!blink::features::IsFencedFramesEnabled())
860 return false;
861
862 switch (blink::features::kFencedFramesImplementationTypeParam.Get()) {
863 case blink::features::FencedFramesImplementationType::kMPArch: {
Dominic Farolino4bc10ee2021-08-31 00:37:36864 return IsMainFrame() &&
865 frame_tree()->type() == FrameTree::Type::kFencedFrame;
shivanigithubf3ddff52021-07-03 22:06:30866 }
867 case blink::features::FencedFramesImplementationType::kShadowDOM: {
868 return effective_frame_policy().is_fenced;
869 }
870 default:
871 return false;
872 }
873}
874
875bool FrameTreeNode::IsInFencedFrameTree() const {
876 if (!blink::features::IsFencedFramesEnabled())
877 return false;
878
879 switch (blink::features::kFencedFramesImplementationTypeParam.Get()) {
880 case blink::features::FencedFramesImplementationType::kMPArch:
Dominic Farolino4bc10ee2021-08-31 00:37:36881 return frame_tree()->type() == FrameTree::Type::kFencedFrame;
shivanigithubf3ddff52021-07-03 22:06:30882 case blink::features::FencedFramesImplementationType::kShadowDOM: {
883 auto* node = this;
884 while (node) {
885 if (node->effective_frame_policy().is_fenced) {
886 return true;
887 }
888 node = node->parent() ? node->parent()->frame_tree_node() : nullptr;
889 }
890 return false;
891 }
892 default:
893 return false;
894 }
895}
896
shivanigithub4cd016a2021-09-20 21:10:30897void FrameTreeNode::SetFencedFrameNonceIfNeeded() {
898 if (!IsInFencedFrameTree()) {
899 return;
900 }
901
902 if (IsFencedFrameRoot()) {
903 fenced_frame_nonce_ = base::UnguessableToken::Create();
904 return;
905 }
906
907 // For nested iframes in a fenced frame tree, propagate the same nonce as was
908 // set in the fenced frame root.
909 DCHECK(parent_);
910 absl::optional<base::UnguessableToken> nonce =
911 parent_->frame_tree_node()->fenced_frame_nonce();
912 DCHECK(nonce.has_value());
913 fenced_frame_nonce_ = nonce;
914}
915
Nan Linaaf84f72021-12-02 22:31:56916bool FrameTreeNode::IsErrorPageIsolationEnabled() const {
917 // Enable error page isolation for fenced frames in both MPArch and ShadowDOM
918 // modes to address the issue with invalid urn:uuid (crbug.com/1264224).
919 //
920 // Note that `IsMainFrame()` only covers MPArch, therefore we add explicit
921 // `IsFencedFrameRoot()` check for ShadowDOM, at least until error page
922 // isolation is supported for subframes in crbug.com/1092524.
923 return SiteIsolationPolicy::IsErrorPageIsolationEnabled(IsMainFrame() ||
924 IsFencedFrameRoot());
925}
926
[email protected]9b159a52013-10-03 17:24:55927} // namespace content