blob: 155302d91ddb694fcf638234f4a1ecdcc81a95d7 [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
[email protected]d4a8ca482013-10-30 21:06:405#include "content/browser/frame_host/frame_tree_node.h"
[email protected]9b159a52013-10-03 17:24:556
Daniel Cheng6ca7f1c92017-08-09 21:45:417#include <math.h>
8
[email protected]9b159a52013-10-03 17:24:559#include <queue>
Takuto Ikutaadf31eb2019-01-05 00:32:4810#include <unordered_map>
dcheng36b6aec92015-12-26 06:16:3611#include <utility>
[email protected]9b159a52013-10-03 17:24:5512
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1413#include "base/feature_list.h"
scottmg6ece5ae2017-02-01 18:25:1914#include "base/lazy_instance.h"
avib7348942015-12-25 20:57:1015#include "base/macros.h"
dcheng23ca947d2016-05-04 20:04:1516#include "base/metrics/histogram_macros.h"
[email protected]9b159a52013-10-03 17:24:5517#include "base/stl_util.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4118#include "base/strings/string_util.h"
Andrey Kosyakovf2d4ff72018-10-29 20:09:5919#include "content/browser/devtools/devtools_instrumentation.h"
[email protected]94d0cc12013-12-18 00:07:4120#include "content/browser/frame_host/frame_tree.h"
Shivani Sharma194877032019-03-07 17:52:4721#include "content/browser/frame_host/navigation_controller_impl.h"
clamydcb434c12015-04-16 19:29:1622#include "content/browser/frame_host/navigation_request.h"
[email protected]190b8c52013-11-09 01:35:4423#include "content/browser/frame_host/navigator.h"
[email protected]d4a8ca482013-10-30 21:06:4024#include "content/browser/frame_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4125#include "content/browser/renderer_host/render_view_host_impl.h"
clamyf73862c42015-07-08 12:31:3326#include "content/common/frame_messages.h"
Lucas Furukawa Gadanief8290a2019-07-29 20:27:5127#include "content/common/navigation_params.h"
28#include "content/common/navigation_params_utils.h"
dmazzonie950ea232015-03-13 21:39:4529#include "content/public/browser/browser_thread.h"
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1430#include "content/public/common/content_features.h"
Arthur Sonzognif21fb512018-11-06 09:31:5831#include "content/public/common/navigation_policy.h"
Blink Reformata30d4232018-04-07 15:31:0632#include "third_party/blink/public/common/frame/sandbox_flags.h"
Antonio Gomes4b2c5132020-01-16 11:49:4833#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
[email protected]9b159a52013-10-03 17:24:5534
35namespace content {
36
dmazzonie950ea232015-03-13 21:39:4537namespace {
38
39// This is a global map between frame_tree_node_ids and pointers to
40// FrameTreeNodes.
Takuto Ikutaadf31eb2019-01-05 00:32:4841typedef std::unordered_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4542
scottmg5e65e3a2017-03-08 08:48:4643base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
44 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4545
fdegansa696e5112015-04-17 01:57:5946// These values indicate the loading progress status. The minimum progress
47// value matches what Blink's ProgressTracker has traditionally used for a
48// minimum progress value.
fdegansa696e5112015-04-17 01:57:5949const double kLoadingProgressMinimum = 0.1;
50const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4551
fdegansa696e5112015-04-17 01:57:5952} // namespace
fdegans1d16355162015-03-26 11:58:3453
Tsuyoshi Horof36fc4ef2019-10-16 10:02:1254const int FrameTreeNode::kFrameTreeNodeInvalidId = -1;
55
alexmose201c7cd2015-06-10 17:14:2156// This observer watches the opener of its owner FrameTreeNode and clears the
57// owner's opener if the opener is destroyed.
58class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
59 public:
jochen6004a362017-02-04 00:11:4060 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
61 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2162
63 // 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:
81 FrameTreeNode* owner_;
jochen6004a362017-02-04 00:11:4082 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2183
84 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
85};
86
vishal.b782eb5d2015-04-29 12:22:5787int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5588
dmazzonie950ea232015-03-13 21:39:4589// static
vishal.b782eb5d2015-04-29 12:22:5790FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1991 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1592 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:4693 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4594 return it == nodes->end() ? nullptr : it->second;
95}
96
raymes31457802016-07-20 06:08:0997FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
98 Navigator* navigator,
raymes31457802016-07-20 06:08:0999 FrameTreeNode* parent,
100 blink::WebTreeScopeType scope,
101 const std::string& name,
102 const std::string& unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45103 bool is_created_by_script,
Pavel Feldman25234722017-10-11 02:49:06104 const base::UnguessableToken& devtools_frame_token,
Ehsan Karamad192a8da2018-10-21 03:48:08105 const FrameOwnerProperties& frame_owner_properties,
106 blink::FrameOwnerElementType owner_type)
[email protected]bffc8302014-01-23 20:52:16107 : frame_tree_(frame_tree),
108 navigator_(navigator),
Lucas Furukawa Gadani72cc21c2018-09-04 18:50:46109 render_manager_(this, frame_tree->manager_delegate()),
[email protected]bffc8302014-01-23 20:52:16110 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59111 parent_(parent),
Bo Liua13e7c02018-03-28 22:24:02112 depth_(parent ? parent->depth_ + 1 : 0u),
alexmose201c7cd2015-06-10 17:14:21113 opener_(nullptr),
jochen6004a362017-02-04 00:11:40114 original_opener_(nullptr),
creisf0f069a2015-07-23 23:51:53115 has_committed_real_load_(false),
engedy6e2e0992017-05-25 18:58:42116 is_collapsed_(false),
estarka886b8d2015-12-18 21:53:08117 replication_state_(
118 scope,
119 name,
lukasza464d8692016-02-22 19:26:32120 unique_name,
estarkbd8e26f2016-03-16 23:30:37121 false /* should enforce strict mixed content checking */,
arthursonzogni4b62a5cb2018-01-17 14:14:26122 std::vector<uint32_t>()
123 /* hashes of hosts for insecure request upgrades */,
japhet61835ae12017-01-20 01:25:39124 false /* is a potentially trustworthy unique origin */,
Becca Hughes60af7d42017-12-12 10:53:15125 false /* has received a user gesture */,
Ehsan Karamad192a8da2018-10-21 03:48:08126 false /* has received a user gesture before nav */,
127 owner_type),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45128 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06129 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31130 frame_owner_properties_(frame_owner_properties),
Shubhie Panickerddf2a4e2018-03-06 00:09:06131 was_discarded_(false),
xiaochenghb9554bb2016-05-21 14:20:48132 blame_context_(frame_tree_node_id_, parent) {
rob97250742015-12-10 17:45:15133 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45134 g_frame_tree_node_id_map.Get().insert(
135 std::make_pair(frame_tree_node_id_, this));
136 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33137
xiaochenghb9554bb2016-05-21 14:20:48138 // Note: this should always be done last in the constructor.
139 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59140}
[email protected]9b159a52013-10-03 17:24:55141
142FrameTreeNode::~FrameTreeNode() {
Nasko Oskov252ae042018-10-04 21:44:12143 // Remove the children.
144 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45145
Nate Chapin22ea6592019-03-05 22:29:02146 current_frame_host()->ResetLoadingState();
147
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45148 // If the removed frame was created by a script, then its history entry will
149 // never be reused - we can save some memory by removing the history entry.
150 // See also https://crbug.com/784356.
151 if (is_created_by_script_ && parent_) {
152 NavigationEntryImpl* nav_entry = static_cast<NavigationEntryImpl*>(
153 navigator()->GetController()->GetLastCommittedEntry());
154 if (nav_entry) {
155 nav_entry->RemoveEntryForFrame(this,
156 /* only_if_different_position = */ false);
157 }
158 }
159
dmazzonie950ea232015-03-13 21:39:45160 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31161 for (auto& observer : observers_)
162 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21163
164 if (opener_)
165 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40166 if (original_opener_)
167 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45168
169 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18170
danakjf9400602019-06-07 15:44:58171 bool did_stop_loading = false;
172
jam39258caf2016-11-02 14:48:18173 if (navigation_request_) {
danakjf9400602019-06-07 15:44:58174 navigation_request_.reset();
Arthur Hemery0dd65812019-08-01 14:18:45175 // If a frame with a pending navigation is detached, make sure the
176 // WebContents (and its observers) update their loading state.
danakjf9400602019-06-07 15:44:58177 did_stop_loading = true;
jam39258caf2016-11-02 14:48:18178 }
Nate Chapin22ea6592019-03-05 22:29:02179
danakjf9400602019-06-07 15:44:58180 // ~SiteProcessCountTracker DCHECKs in some tests if the speculative
181 // RenderFrameHostImpl is not destroyed last. Ideally this would be closer to
182 // (possible before) the ResetLoadingState() call above.
183 //
184 // There is an inherent race condition causing bugs 838348/915179/et al, where
185 // the renderer may have committed the speculative main frame and the browser
186 // has not heard about it yet. If this is a main frame, then in that case the
187 // speculative RenderFrame was unable to be deleted (it is owned by the
188 // renderer) and we should not be able to cancel the navigation at this point.
189 // CleanUpNavigation() would normally be called here but it will try to undo
190 // the navigation and expose the race condition. When it replaces the main
191 // frame with a RenderFrameProxy, that leaks the committed main frame, leaving
192 // the frame and its friend group with pointers that will become invalid
193 // shortly as we are shutting everything down and deleting the RenderView etc.
194 // We avoid this problematic situation by not calling CleanUpNavigation() or
195 // DiscardUnusedFrame() here. The speculative RenderFrameHost is simply
196 // returned and deleted immediately. This satisfies the requirement that the
197 // speculative RenderFrameHost is removed from the RenderFrameHostManager
198 // before it is destroyed.
199 if (render_manager_.speculative_frame_host()) {
200 did_stop_loading |= render_manager_.speculative_frame_host()->is_loading();
201 render_manager_.UnsetSpeculativeRenderFrameHost();
202 }
203
204 if (did_stop_loading)
205 DidStopLoading();
206
Nate Chapin22ea6592019-03-05 22:29:02207 DCHECK(!IsLoading());
[email protected]9b159a52013-10-03 17:24:55208}
209
alexmose201c7cd2015-06-10 17:14:21210void FrameTreeNode::AddObserver(Observer* observer) {
211 observers_.AddObserver(observer);
212}
213
214void FrameTreeNode::RemoveObserver(Observer* observer) {
215 observers_.RemoveObserver(observer);
216}
217
[email protected]94d0cc12013-12-18 00:07:41218bool FrameTreeNode::IsMainFrame() const {
219 return frame_tree_->root() == this;
220}
221
Ian Clelland5cbaaf82017-11-27 22:00:03222void FrameTreeNode::ResetForNavigation() {
223 // Discard any CSP headers from the previous document.
224 replication_state_.accumulated_csp_headers.clear();
225 render_manager_.OnDidResetContentSecurityPolicy();
226
Ian Clellandedb8c5dd2018-03-01 17:01:37227 // Clear any CSP-set sandbox flags, and the declared feature policy for the
228 // frame.
229 UpdateFramePolicyHeaders(blink::WebSandboxFlags::kNone, {});
Shivani Sharmac4f561582018-11-15 15:58:39230
Mustaq Ahmedc53e4c562019-01-29 19:05:09231 // This frame has had its user activation bits cleared in the renderer
232 // before arriving here. We just need to clear them here and in the other
233 // renderer processes that may have a reference to this frame.
Antonio Gomes4b2c5132020-01-16 11:49:48234 UpdateUserActivationState(
235 blink::mojom::UserActivationUpdateType::kClearActivation);
Ian Clelland5cbaaf82017-11-27 22:00:03236}
237
yilkal34a3d752019-08-30 18:20:30238size_t FrameTreeNode::GetFrameTreeSize() const {
239 if (is_collapsed())
240 return 0;
241
242 size_t size = 0;
243 for (size_t i = 0; i < child_count(); i++) {
244 size += child_at(i)->GetFrameTreeSize();
245 }
246
247 // Account for this node.
248 size++;
249 return size;
250}
251
alexmose201c7cd2015-06-10 17:14:21252void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
253 if (opener_) {
254 opener_->RemoveObserver(opener_observer_.get());
255 opener_observer_.reset();
256 }
257
258 opener_ = opener;
259
260 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55261 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21262 opener_->AddObserver(opener_observer_.get());
263 }
264}
265
jochen6004a362017-02-04 00:11:40266void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39267 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37268 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40269
Avi Drissman36465f332017-09-11 20:49:39270 if (original_opener_) {
271 original_opener_->RemoveObserver(original_opener_observer_.get());
272 original_opener_observer_.reset();
273 }
274
jochen6004a362017-02-04 00:11:40275 original_opener_ = opener;
276
277 if (original_opener_) {
jochen6004a362017-02-04 00:11:40278 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55279 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40280 original_opener_->AddObserver(original_opener_observer_.get());
281 }
282}
283
creisf0f069a2015-07-23 23:51:53284void FrameTreeNode::SetCurrentURL(const GURL& url) {
Balazs Engedyc8a7cccf2018-03-12 23:00:49285 if (!has_committed_real_load_ && !url.IsAboutBlank())
creisf0f069a2015-07-23 23:51:53286 has_committed_real_load_ = true;
Erik Chen173bf3042017-07-31 06:06:21287 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48288 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53289}
290
estarkbd8e26f2016-03-16 23:30:37291void FrameTreeNode::SetCurrentOrigin(
292 const url::Origin& origin,
293 bool is_potentially_trustworthy_unique_origin) {
294 if (!origin.IsSameOriginWith(replication_state_.origin) ||
295 replication_state_.has_potentially_trustworthy_unique_origin !=
296 is_potentially_trustworthy_unique_origin) {
297 render_manager_.OnDidUpdateOrigin(origin,
298 is_potentially_trustworthy_unique_origin);
299 }
alexmosa7a4ff822015-04-27 17:59:56300 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37301 replication_state_.has_potentially_trustworthy_unique_origin =
302 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56303}
alexmosbe2f4c32015-03-10 02:30:23304
engedy6e2e0992017-05-25 18:58:42305void FrameTreeNode::SetCollapsed(bool collapsed) {
306 DCHECK(!IsMainFrame());
307 if (is_collapsed_ == collapsed)
308 return;
309
310 is_collapsed_ = collapsed;
311 render_manager_.OnDidChangeCollapsedState(collapsed);
312}
313
lukasza464d8692016-02-22 19:26:32314void FrameTreeNode::SetFrameName(const std::string& name,
315 const std::string& unique_name) {
316 if (name == replication_state_.name) {
317 // |unique_name| shouldn't change unless |name| changes.
318 DCHECK_EQ(unique_name, replication_state_.unique_name);
319 return;
320 }
lukasza5140a412016-09-15 21:12:30321
322 if (parent()) {
323 // Non-main frames should have a non-empty unique name.
324 DCHECK(!unique_name.empty());
325 } else {
326 // Unique name of main frames should always stay empty.
327 DCHECK(unique_name.empty());
328 }
329
Daniel Cheng6ca7f1c92017-08-09 21:45:41330 // Note the unique name should only be able to change before the first real
331 // load is committed, but that's not strongly enforced here.
lukasza464d8692016-02-22 19:26:32332 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56333 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32334 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23335}
336
arthursonzogni662aa652017-03-28 11:09:50337void FrameTreeNode::AddContentSecurityPolicies(
arthursonzogni35a95c72020-01-15 17:49:43338 std::vector<network::mojom::ContentSecurityPolicyHeaderPtr> headers) {
339 for (auto& header : headers)
340 replication_state_.accumulated_csp_headers.push_back(*header);
341 render_manager_.OnDidAddContentSecurityPolicies(std::move(headers));
lukasza8e1c02e42016-05-17 20:05:10342}
343
mkwstf672e7ef2016-06-09 20:51:07344void FrameTreeNode::SetInsecureRequestPolicy(
345 blink::WebInsecureRequestPolicy policy) {
346 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08347 return;
mkwstf672e7ef2016-06-09 20:51:07348 render_manager_.OnEnforceInsecureRequestPolicy(policy);
349 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08350}
351
arthursonzogni4b62a5cb2018-01-17 14:14:26352void FrameTreeNode::SetInsecureNavigationsSet(
353 const std::vector<uint32_t>& insecure_navigations_set) {
354 DCHECK(std::is_sorted(insecure_navigations_set.begin(),
355 insecure_navigations_set.end()));
356 if (insecure_navigations_set == replication_state_.insecure_navigations_set)
357 return;
358 render_manager_.OnEnforceInsecureNavigationsSet(insecure_navigations_set);
359 replication_state_.insecure_navigations_set = insecure_navigations_set;
360}
361
Luna Luc3fdacdf2017-11-08 04:48:53362void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Ian Clellandcdc4f312017-10-13 22:24:12363 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25364
Ian Clellandcdc4f312017-10-13 22:24:12365 if (parent()) {
366 // Subframes should always inherit their parent's sandbox flags.
Ian Clelland5cbaaf82017-11-27 22:00:03367 pending_frame_policy_.sandbox_flags |= parent()->active_sandbox_flags();
Charlie Hue1b77ac2019-12-13 21:30:17368 // This is only applied on subframes; container policy and required document
369 // policy are not mutable on main frame.
Ian Clellandcdc4f312017-10-13 22:24:12370 pending_frame_policy_.container_policy = frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17371 pending_frame_policy_.required_document_policy =
372 frame_policy.required_document_policy;
Ian Clellandcdc4f312017-10-13 22:24:12373 }
iclelland92f8c0b2017-04-19 12:43:05374}
375
alexmos9f8705a2015-05-06 19:58:59376FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39377 return GetSibling(-1);
378}
alexmos9f8705a2015-05-06 19:58:59379
paulmeyer322777fb2016-05-16 23:15:39380FrameTreeNode* FrameTreeNode::NextSibling() const {
381 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59382}
383
fdegans4a49ce932015-03-12 17:11:37384bool FrameTreeNode::IsLoading() const {
385 RenderFrameHostImpl* current_frame_host =
386 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37387
388 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39389
clamy610c63b32017-12-22 15:05:18390 if (navigation_request_)
391 return true;
clamy11e11512015-07-07 16:42:17392
clamy610c63b32017-12-22 15:05:18393 RenderFrameHostImpl* speculative_frame_host =
394 render_manager_.speculative_frame_host();
395 if (speculative_frame_host && speculative_frame_host->is_loading())
396 return true;
fdegans4a49ce932015-03-12 17:11:37397 return current_frame_host->is_loading();
398}
399
Charlie Hu5ffc0152019-12-06 15:59:53400bool FrameTreeNode::CommitFramePolicy(
401 const blink::FramePolicy& new_frame_policy) {
402 bool did_change_flags = new_frame_policy.sandbox_flags !=
Ian Clellandcdc4f312017-10-13 22:24:12403 replication_state_.frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05404 bool did_change_container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53405 new_frame_policy.container_policy !=
Ian Clellandcdc4f312017-10-13 22:24:12406 replication_state_.frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17407 bool did_change_required_document_policy =
408 pending_frame_policy_.required_document_policy !=
409 replication_state_.frame_policy.required_document_policy;
iclelland92f8c0b2017-04-19 12:43:05410 if (did_change_flags)
Ian Clellandcdc4f312017-10-13 22:24:12411 replication_state_.frame_policy.sandbox_flags =
Charlie Hu5ffc0152019-12-06 15:59:53412 new_frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05413 if (did_change_container_policy)
Ian Clellandcdc4f312017-10-13 22:24:12414 replication_state_.frame_policy.container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53415 new_frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17416 if (did_change_required_document_policy)
417 replication_state_.frame_policy.required_document_policy =
418 new_frame_policy.required_document_policy;
419
Charlie Hu5ffc0152019-12-06 15:59:53420 UpdateFramePolicyHeaders(new_frame_policy.sandbox_flags,
Ian Clellandedb8c5dd2018-03-01 17:01:37421 replication_state_.feature_policy_header);
Charlie Hue1b77ac2019-12-13 21:30:17422 return did_change_flags || did_change_container_policy ||
423 did_change_required_document_policy;
alexmos6b294562015-03-05 19:24:10424}
425
Arthur Hemeryc3380172018-01-22 14:00:17426void FrameTreeNode::TransferNavigationRequestOwnership(
427 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59428 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17429 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
430}
431
carloskc49005eb2015-06-16 11:25:07432void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57433 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37434 // This is never called when navigating to a Javascript URL. For the loading
435 // state, this matches what Blink is doing: Blink doesn't send throbber
436 // notifications for Javascript URLS.
437 DCHECK(!navigation_request->common_params().url.SchemeIs(
438 url::kJavaScriptScheme));
439
clamy44e84ce2016-02-22 15:38:25440 bool was_previously_loading = frame_tree()->IsLoading();
441
clamy82a2f4d2016-02-02 14:20:41442 // There's no need to reset the state: there's still an ongoing load, and the
443 // RenderFrameHostManager will take care of updates to the speculative
444 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05445 if (was_previously_loading) {
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31446 if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
jamcd0b7b22017-03-24 22:13:05447 // Mark the old request as aborted.
Mohamed Abdelhalimb4db22a2019-06-18 10:46:52448 navigation_request_->set_net_error(net::ERR_ABORTED);
jamcd0b7b22017-03-24 22:13:05449 }
Arthur Hemery241b9392019-10-24 11:08:41450 ResetNavigationRequest(true);
jamcd0b7b22017-03-24 22:13:05451 }
clamy44e84ce2016-02-22 15:38:25452
453 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06454 if (was_discarded_) {
455 navigation_request_->set_was_discarded();
456 was_discarded_ = false;
457 }
clamy8e2e299202016-04-05 11:44:59458 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39459
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51460 bool to_different_document = !NavigationTypeUtils::IsSameDocument(
arthursonzogni92f18682017-02-08 23:00:04461 navigation_request_->common_params().navigation_type);
462
463 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16464}
465
Arthur Hemery241b9392019-10-24 11:08:41466void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
fdegans39ff0382015-04-29 19:04:39467 if (!navigation_request_)
468 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23469
Andrey Kosyakovf2d4ff72018-10-29 20:09:59470 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
clamydcb434c12015-04-16 19:29:16471 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39472
clamy82a2f4d2016-02-02 14:20:41473 if (keep_state)
fdegans39ff0382015-04-29 19:04:39474 return;
475
clamy82a2f4d2016-02-02 14:20:41476 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
477 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39478 DidStopLoading();
479 render_manager_.CleanUpNavigation();
clamydcb434c12015-04-16 19:29:16480}
481
clamy44e84ce2016-02-22 15:38:25482void FrameTreeNode::DidStartLoading(bool to_different_document,
483 bool was_previously_loading) {
Camille Lamyefd54b02018-10-04 16:54:14484 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
485 "frame_tree_node", frame_tree_node_id(), "to different document",
486 to_different_document);
fdegansa696e5112015-04-17 01:57:59487 // Any main frame load to a new document should reset the load progress since
488 // it will replace the current page and any frames. The WebContents will
489 // be notified when DidChangeLoadProgress is called.
490 if (to_different_document && IsMainFrame())
491 frame_tree_->ResetLoadProgress();
492
493 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25494 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59495 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
496
497 // Set initial load progress and update overall progress. This will notify
498 // the WebContents of the load progress change.
499 DidChangeLoadProgress(kLoadingProgressMinimum);
500
501 // Notify the RenderFrameHostManager of the event.
502 render_manager()->OnDidStartLoading();
503}
504
505void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14506 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
507 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59508 // Set final load progress and update overall progress. This will notify
509 // the WebContents of the load progress change.
510 DidChangeLoadProgress(kLoadingProgressDone);
511
Lucas Furukawa Gadani6faef602019-05-06 21:16:03512 // Notify the RenderFrameHostManager of the event.
513 render_manager()->OnDidStopLoading();
514
fdegansa696e5112015-04-17 01:57:59515 // Notify the WebContents.
516 if (!frame_tree_->IsLoading())
517 navigator()->GetDelegate()->DidStopLoading();
fdegansa696e5112015-04-17 01:57:59518}
519
520void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Nate Chapin93536702018-02-07 00:12:21521 DCHECK_GE(load_progress, kLoadingProgressMinimum);
522 DCHECK_LE(load_progress, kLoadingProgressDone);
523 if (IsMainFrame())
524 frame_tree_->UpdateLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59525}
526
clamyf73862c42015-07-08 12:31:33527bool FrameTreeNode::StopLoading() {
arthursonzogni66f711c2019-10-08 14:40:36528 if (navigation_request_ && navigation_request_->IsNavigationStarted())
529 navigation_request_->set_net_error(net::ERR_ABORTED);
Arthur Hemery241b9392019-10-24 11:08:41530 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33531
532 // TODO(nasko): see if child frames should send IPCs in site-per-process
533 // mode.
534 if (!IsMainFrame())
535 return true;
536
537 render_manager_.Stop();
538 return true;
539}
540
alexmos21acae52015-11-07 01:04:43541void FrameTreeNode::DidFocus() {
542 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31543 for (auto& observer : observers_)
544 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43545}
546
clamy44e84ce2016-02-22 15:38:25547void FrameTreeNode::BeforeUnloadCanceled() {
548 // TODO(clamy): Support BeforeUnload in subframes.
549 if (!IsMainFrame())
550 return;
551
552 RenderFrameHostImpl* current_frame_host =
553 render_manager_.current_frame_host();
554 DCHECK(current_frame_host);
555 current_frame_host->ResetLoadingState();
556
clamy610c63b32017-12-22 15:05:18557 RenderFrameHostImpl* speculative_frame_host =
558 render_manager_.speculative_frame_host();
559 if (speculative_frame_host)
560 speculative_frame_host->ResetLoadingState();
561 // Note: there is no need to set an error code on the NavigationHandle here
562 // as it has not been created yet. It is only created when the
563 // BeforeUnloadACK is received.
564 if (navigation_request_)
Arthur Hemery241b9392019-10-24 11:08:41565 ResetNavigationRequest(false);
clamy44e84ce2016-02-22 15:38:25566}
567
Mustaq Ahmedc4cb7162018-06-05 16:28:36568bool FrameTreeNode::NotifyUserActivation() {
John Delaneyedd8d6c2019-01-25 00:23:57569 for (FrameTreeNode* node = this; node; node = node->parent()) {
570 if (!node->user_activation_state_.HasBeenActive() &&
571 node->current_frame_host())
572 node->current_frame_host()->DidReceiveFirstUserActivation();
Mustaq Ahmedc4cb7162018-06-05 16:28:36573 node->user_activation_state_.Activate();
John Delaneyedd8d6c2019-01-25 00:23:57574 }
japhet61835ae12017-01-20 01:25:39575 replication_state_.has_received_user_gesture = true;
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14576
Mustaq Ahmed0180320f2019-03-21 16:07:01577 // See the "Same-origin Visibility" section in |UserActivationState| class
578 // doc.
Mustaq Ahmede5f12562019-10-30 18:02:03579 if (base::FeatureList::IsEnabled(
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14580 features::kUserActivationSameOriginVisibility)) {
581 const url::Origin& current_origin =
582 this->current_frame_host()->GetLastCommittedOrigin();
583 for (FrameTreeNode* node : frame_tree()->Nodes()) {
584 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
585 current_origin)) {
586 node->user_activation_state_.Activate();
587 }
588 }
589 }
590
Shivani Sharma20749e922019-03-11 17:00:26591 NavigationControllerImpl* controller =
592 static_cast<NavigationControllerImpl*>(navigator()->GetController());
593 if (controller)
594 controller->NotifyUserActivation();
Shivani Sharma194877032019-03-07 17:52:47595
Mustaq Ahmedc4cb7162018-06-05 16:28:36596 return true;
597}
598
599bool FrameTreeNode::ConsumeTransientUserActivation() {
600 bool was_active = user_activation_state_.IsActive();
601 for (FrameTreeNode* node : frame_tree()->Nodes())
602 node->user_activation_state_.ConsumeIfActive();
603 return was_active;
604}
605
Shivani Sharmac4f561582018-11-15 15:58:39606bool FrameTreeNode::ClearUserActivation() {
Shivani Sharmac4f561582018-11-15 15:58:39607 for (FrameTreeNode* node : frame_tree()->SubtreeNodes(this))
608 node->user_activation_state_.Clear();
609 return true;
610}
611
Ella Ge9caed612019-08-09 16:17:25612bool FrameTreeNode::VerifyUserActivation() {
Ella Gea78f6772019-12-11 10:35:25613 DCHECK(base::FeatureList::IsEnabled(
614 features::kBrowserVerifiedUserActivationMouse) ||
615 base::FeatureList::IsEnabled(
616 features::kBrowserVerifiedUserActivationKeyboard));
617
Ella Ge9caed612019-08-09 16:17:25618 return render_manager_.current_frame_host()
619 ->GetRenderWidgetHost()
Mustaq Ahmed83bb1722019-10-22 20:00:10620 ->RemovePendingUserActivationIfAvailable();
Ella Ge9caed612019-08-09 16:17:25621}
622
Mustaq Ahmedc4cb7162018-06-05 16:28:36623bool FrameTreeNode::UpdateUserActivationState(
Antonio Gomes4b2c5132020-01-16 11:49:48624 blink::mojom::UserActivationUpdateType update_type) {
Ella Ge9caed612019-08-09 16:17:25625 bool update_result = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36626 switch (update_type) {
Antonio Gomes4b2c5132020-01-16 11:49:48627 case blink::mojom::UserActivationUpdateType::kConsumeTransientActivation:
Ella Ge9caed612019-08-09 16:17:25628 update_result = ConsumeTransientUserActivation();
629 break;
Antonio Gomes4b2c5132020-01-16 11:49:48630 case blink::mojom::UserActivationUpdateType::kNotifyActivation:
Ella Ge9caed612019-08-09 16:17:25631 update_result = NotifyUserActivation();
632 break;
Antonio Gomes4b2c5132020-01-16 11:49:48633 case blink::mojom::UserActivationUpdateType::
Ella Ge9caed612019-08-09 16:17:25634 kNotifyActivationPendingBrowserVerification:
635 if (VerifyUserActivation()) {
636 update_result = NotifyUserActivation();
Antonio Gomes4b2c5132020-01-16 11:49:48637 update_type = blink::mojom::UserActivationUpdateType::kNotifyActivation;
Ella Ge9caed612019-08-09 16:17:25638 } else {
639 // TODO(crbug.com/848778): We need to decide what to do when user
640 // activation verification failed. NOTREACHED here will make all
641 // unrelated tests that inject event to renderer fail.
642 return false;
643 }
644 break;
Antonio Gomes4b2c5132020-01-16 11:49:48645 case blink::mojom::UserActivationUpdateType::kClearActivation:
Ella Ge9caed612019-08-09 16:17:25646 update_result = ClearUserActivation();
647 break;
Mustaq Ahmedc4cb7162018-06-05 16:28:36648 }
Ella Ge9caed612019-08-09 16:17:25649 render_manager_.UpdateUserActivationState(update_type);
650 return update_result;
japhet61835ae12017-01-20 01:25:39651}
652
Mustaq Ahmed01261742019-12-16 15:49:06653void FrameTreeNode::OnSetHadStickyUserActivationBeforeNavigation(bool value) {
654 render_manager_.OnSetHadStickyUserActivationBeforeNavigation(value);
Becca Hughes60af7d42017-12-12 10:53:15655 replication_state_.has_received_user_gesture_before_nav = value;
656}
657
paulmeyer322777fb2016-05-16 23:15:39658FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19659 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39660 return nullptr;
661
662 for (size_t i = 0; i < parent_->child_count(); ++i) {
663 if (parent_->child_at(i) == this) {
664 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
665 i + relative_offset >= parent_->child_count()) {
666 return nullptr;
667 }
668 return parent_->child_at(i + relative_offset);
669 }
670 }
671
672 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
673 return nullptr;
674}
675
Ian Clellandedb8c5dd2018-03-01 17:01:37676void FrameTreeNode::UpdateFramePolicyHeaders(
677 blink::WebSandboxFlags sandbox_flags,
678 const blink::ParsedFeaturePolicy& parsed_header) {
679 bool changed = false;
680 if (replication_state_.feature_policy_header != parsed_header) {
681 replication_state_.feature_policy_header = parsed_header;
682 changed = true;
683 }
Ian Clelland5cbaaf82017-11-27 22:00:03684 // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the
685 // currently effective sandbox flags from the frame. https://crbug.com/740556
Ian Clellandedb8c5dd2018-03-01 17:01:37686 blink::WebSandboxFlags updated_flags =
Ian Clelland5cbaaf82017-11-27 22:00:03687 sandbox_flags | effective_frame_policy().sandbox_flags;
Ian Clellandedb8c5dd2018-03-01 17:01:37688 if (replication_state_.active_sandbox_flags != updated_flags) {
689 replication_state_.active_sandbox_flags = updated_flags;
690 changed = true;
691 }
692 // Notify any proxies if the policies have been changed.
693 if (changed)
694 render_manager()->OnDidSetFramePolicyHeaders();
Ian Clelland5cbaaf82017-11-27 22:00:03695}
696
Lan Weif0cb8e6e2019-04-19 00:14:53697void FrameTreeNode::TransferUserActivationFrom(
698 RenderFrameHostImpl* source_rfh) {
699 user_activation_state_.TransferFrom(
700 source_rfh->frame_tree_node()->user_activation_state_);
701
702 // Notify proxies in non-source and non-target renderer processes to
703 // transfer the activation state from the source proxy to the target
704 // so the user activation state of those proxies matches the source
705 // renderer and the target renderer (which are separately updated).
706 render_manager_.TransferUserActivationFrom(source_rfh);
Lan Wei550671a22019-03-19 00:59:24707}
708
Arthur Sonzognif8840b92018-11-07 14:10:35709void FrameTreeNode::PruneChildFrameNavigationEntries(
710 NavigationEntryImpl* entry) {
711 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
712 FrameTreeNode* child = current_frame_host()->child_at(i);
713 if (child->is_created_by_script_) {
714 entry->RemoveEntryForFrame(child,
715 /* only_if_different_position = */ false);
716 } else {
717 child->PruneChildFrameNavigationEntries(entry);
718 }
719 }
720}
721
Ehsan Karamad39407082019-02-19 23:38:19722void FrameTreeNode::SetOpenerFeaturePolicyState(
723 const blink::FeaturePolicy::FeatureState& feature_state) {
724 DCHECK(IsMainFrame());
725 if (base::FeatureList::IsEnabled(features::kFeaturePolicyForSandbox)) {
726 replication_state_.opener_feature_state = feature_state;
727 }
728}
729
ckitagawac2e43402020-01-17 00:09:25730const base::Optional<base::UnguessableToken>& FrameTreeNode::GetEmbeddingToken()
731 const {
732 return embedding_token_;
733}
734
735void FrameTreeNode::SetEmbeddingToken(
736 const base::Optional<base::UnguessableToken>& embedding_token) {
737 embedding_token_ = embedding_token;
738 if (embedding_token_.has_value()) {
739 // Propagate a non-null embedding token to the parent. Parents will
740 // invalidate their own tokens if a previously remote frame becomes local to
741 // them.
742 render_manager_.SetEmbeddingToken(embedding_token.value());
743 }
744}
745
Yao Xiao24ec9aa2020-01-28 16:36:00746void FrameTreeNode::SetAdFrameType(blink::mojom::AdFrameType ad_frame_type) {
747 DCHECK_NE(ad_frame_type, blink::mojom::AdFrameType::kNonAd);
748 if (replication_state_.ad_frame_type == blink::mojom::AdFrameType::kNonAd) {
749 replication_state_.ad_frame_type = ad_frame_type;
750 render_manager()->OnDidSetAdFrameType(ad_frame_type);
751 } else {
752 DCHECK_EQ(ad_frame_type, replication_state_.ad_frame_type);
753 }
754}
755
[email protected]9b159a52013-10-03 17:24:55756} // namespace content