blob: 7ea14dfe610487b3fd6178f56e68d53f2bc672cf [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"
dmazzonie950ea232015-03-13 21:39:4527#include "content/public/browser/browser_thread.h"
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1428#include "content/public/common/content_features.h"
Arthur Sonzognif21fb512018-11-06 09:31:5829#include "content/public/common/navigation_policy.h"
Blink Reformata30d4232018-04-07 15:31:0630#include "third_party/blink/public/common/frame/sandbox_flags.h"
Mustaq Ahmedc4cb7162018-06-05 16:28:3631#include "third_party/blink/public/common/frame/user_activation_update_type.h"
[email protected]9b159a52013-10-03 17:24:5532
33namespace content {
34
dmazzonie950ea232015-03-13 21:39:4535namespace {
36
37// This is a global map between frame_tree_node_ids and pointers to
38// FrameTreeNodes.
Takuto Ikutaadf31eb2019-01-05 00:32:4839typedef std::unordered_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4540
scottmg5e65e3a2017-03-08 08:48:4641base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
42 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4543
fdegansa696e5112015-04-17 01:57:5944// These values indicate the loading progress status. The minimum progress
45// value matches what Blink's ProgressTracker has traditionally used for a
46// minimum progress value.
fdegansa696e5112015-04-17 01:57:5947const double kLoadingProgressMinimum = 0.1;
48const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4549
fdegansa696e5112015-04-17 01:57:5950} // namespace
fdegans1d16355162015-03-26 11:58:3451
alexmose201c7cd2015-06-10 17:14:2152// This observer watches the opener of its owner FrameTreeNode and clears the
53// owner's opener if the opener is destroyed.
54class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
55 public:
jochen6004a362017-02-04 00:11:4056 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
57 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2158
59 // FrameTreeNode::Observer
60 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4061 if (observing_original_opener_) {
Avi Drissman36465f332017-09-11 20:49:3962 // The "original owner" is special. It's used for attribution, and clients
63 // walk down the original owner chain. Therefore, if a link in the chain
64 // is being destroyed, reconnect the observation to the parent of the link
65 // being destroyed.
jochen6004a362017-02-04 00:11:4066 CHECK_EQ(owner_->original_opener(), node);
Avi Drissman36465f332017-09-11 20:49:3967 owner_->SetOriginalOpener(node->original_opener());
68 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4069 } else {
70 CHECK_EQ(owner_->opener(), node);
71 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:3972 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4073 }
alexmose201c7cd2015-06-10 17:14:2174 }
75
76 private:
77 FrameTreeNode* owner_;
jochen6004a362017-02-04 00:11:4078 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2179
80 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
81};
82
vishal.b782eb5d2015-04-29 12:22:5783int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5584
dmazzonie950ea232015-03-13 21:39:4585// static
vishal.b782eb5d2015-04-29 12:22:5786FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1987 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1588 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:4689 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4590 return it == nodes->end() ? nullptr : it->second;
91}
92
raymes31457802016-07-20 06:08:0993FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
94 Navigator* navigator,
raymes31457802016-07-20 06:08:0995 FrameTreeNode* parent,
96 blink::WebTreeScopeType scope,
97 const std::string& name,
98 const std::string& unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:4599 bool is_created_by_script,
Pavel Feldman25234722017-10-11 02:49:06100 const base::UnguessableToken& devtools_frame_token,
Ehsan Karamad192a8da2018-10-21 03:48:08101 const FrameOwnerProperties& frame_owner_properties,
102 blink::FrameOwnerElementType owner_type)
[email protected]bffc8302014-01-23 20:52:16103 : frame_tree_(frame_tree),
104 navigator_(navigator),
Lucas Furukawa Gadani72cc21c2018-09-04 18:50:46105 render_manager_(this, frame_tree->manager_delegate()),
[email protected]bffc8302014-01-23 20:52:16106 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59107 parent_(parent),
Bo Liua13e7c02018-03-28 22:24:02108 depth_(parent ? parent->depth_ + 1 : 0u),
alexmose201c7cd2015-06-10 17:14:21109 opener_(nullptr),
jochen6004a362017-02-04 00:11:40110 original_opener_(nullptr),
creisf0f069a2015-07-23 23:51:53111 has_committed_real_load_(false),
engedy6e2e0992017-05-25 18:58:42112 is_collapsed_(false),
estarka886b8d2015-12-18 21:53:08113 replication_state_(
114 scope,
115 name,
lukasza464d8692016-02-22 19:26:32116 unique_name,
estarkbd8e26f2016-03-16 23:30:37117 false /* should enforce strict mixed content checking */,
arthursonzogni4b62a5cb2018-01-17 14:14:26118 std::vector<uint32_t>()
119 /* hashes of hosts for insecure request upgrades */,
japhet61835ae12017-01-20 01:25:39120 false /* is a potentially trustworthy unique origin */,
Becca Hughes60af7d42017-12-12 10:53:15121 false /* has received a user gesture */,
Ehsan Karamad192a8da2018-10-21 03:48:08122 false /* has received a user gesture before nav */,
123 owner_type),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45124 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06125 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31126 frame_owner_properties_(frame_owner_properties),
Shubhie Panickerddf2a4e2018-03-06 00:09:06127 was_discarded_(false),
xiaochenghb9554bb2016-05-21 14:20:48128 blame_context_(frame_tree_node_id_, parent) {
rob97250742015-12-10 17:45:15129 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45130 g_frame_tree_node_id_map.Get().insert(
131 std::make_pair(frame_tree_node_id_, this));
132 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33133
xiaochenghb9554bb2016-05-21 14:20:48134 // Note: this should always be done last in the constructor.
135 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59136}
[email protected]9b159a52013-10-03 17:24:55137
138FrameTreeNode::~FrameTreeNode() {
Nasko Oskov252ae042018-10-04 21:44:12139 // Remove the children.
140 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45141
Nate Chapin22ea6592019-03-05 22:29:02142 current_frame_host()->ResetLoadingState();
143
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45144 // If the removed frame was created by a script, then its history entry will
145 // never be reused - we can save some memory by removing the history entry.
146 // See also https://crbug.com/784356.
147 if (is_created_by_script_ && parent_) {
148 NavigationEntryImpl* nav_entry = static_cast<NavigationEntryImpl*>(
149 navigator()->GetController()->GetLastCommittedEntry());
150 if (nav_entry) {
151 nav_entry->RemoveEntryForFrame(this,
152 /* only_if_different_position = */ false);
153 }
154 }
155
dmazzonie950ea232015-03-13 21:39:45156 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31157 for (auto& observer : observers_)
158 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21159
160 if (opener_)
161 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40162 if (original_opener_)
163 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45164
165 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18166
167 if (navigation_request_) {
168 // PlzNavigate: if a frame with a pending navigation is detached, make sure
169 // the WebContents (and its observers) update their loading state.
170 navigation_request_.reset();
171 DidStopLoading();
172 }
Nate Chapin22ea6592019-03-05 22:29:02173
174 // ~SiteProcessCountTracker DCHECKs in some tests if CleanUpNavigation is not
175 // called last. Ideally this would be closer to (possible before) the
176 // ResetLoadingState() call above.
177 render_manager_.CleanUpNavigation();
178 DCHECK(!IsLoading());
[email protected]9b159a52013-10-03 17:24:55179}
180
alexmose201c7cd2015-06-10 17:14:21181void FrameTreeNode::AddObserver(Observer* observer) {
182 observers_.AddObserver(observer);
183}
184
185void FrameTreeNode::RemoveObserver(Observer* observer) {
186 observers_.RemoveObserver(observer);
187}
188
[email protected]94d0cc12013-12-18 00:07:41189bool FrameTreeNode::IsMainFrame() const {
190 return frame_tree_->root() == this;
191}
192
Ian Clelland5cbaaf82017-11-27 22:00:03193void FrameTreeNode::ResetForNavigation() {
194 // Discard any CSP headers from the previous document.
195 replication_state_.accumulated_csp_headers.clear();
196 render_manager_.OnDidResetContentSecurityPolicy();
197
Ian Clellandedb8c5dd2018-03-01 17:01:37198 // Clear any CSP-set sandbox flags, and the declared feature policy for the
199 // frame.
200 UpdateFramePolicyHeaders(blink::WebSandboxFlags::kNone, {});
Shivani Sharmac4f561582018-11-15 15:58:39201
Mustaq Ahmedc53e4c562019-01-29 19:05:09202 // This frame has had its user activation bits cleared in the renderer
203 // before arriving here. We just need to clear them here and in the other
204 // renderer processes that may have a reference to this frame.
205 UpdateUserActivationState(blink::UserActivationUpdateType::kClearActivation);
Ian Clelland5cbaaf82017-11-27 22:00:03206}
207
alexmose201c7cd2015-06-10 17:14:21208void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
209 if (opener_) {
210 opener_->RemoveObserver(opener_observer_.get());
211 opener_observer_.reset();
212 }
213
214 opener_ = opener;
215
216 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55217 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21218 opener_->AddObserver(opener_observer_.get());
219 }
220}
221
jochen6004a362017-02-04 00:11:40222void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39223 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37224 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40225
Avi Drissman36465f332017-09-11 20:49:39226 if (original_opener_) {
227 original_opener_->RemoveObserver(original_opener_observer_.get());
228 original_opener_observer_.reset();
229 }
230
jochen6004a362017-02-04 00:11:40231 original_opener_ = opener;
232
233 if (original_opener_) {
jochen6004a362017-02-04 00:11:40234 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55235 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40236 original_opener_->AddObserver(original_opener_observer_.get());
237 }
238}
239
creisf0f069a2015-07-23 23:51:53240void FrameTreeNode::SetCurrentURL(const GURL& url) {
Balazs Engedyc8a7cccf2018-03-12 23:00:49241 if (!has_committed_real_load_ && !url.IsAboutBlank())
creisf0f069a2015-07-23 23:51:53242 has_committed_real_load_ = true;
Erik Chen173bf3042017-07-31 06:06:21243 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48244 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53245}
246
estarkbd8e26f2016-03-16 23:30:37247void FrameTreeNode::SetCurrentOrigin(
248 const url::Origin& origin,
249 bool is_potentially_trustworthy_unique_origin) {
250 if (!origin.IsSameOriginWith(replication_state_.origin) ||
251 replication_state_.has_potentially_trustworthy_unique_origin !=
252 is_potentially_trustworthy_unique_origin) {
253 render_manager_.OnDidUpdateOrigin(origin,
254 is_potentially_trustworthy_unique_origin);
255 }
alexmosa7a4ff822015-04-27 17:59:56256 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37257 replication_state_.has_potentially_trustworthy_unique_origin =
258 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56259}
alexmosbe2f4c32015-03-10 02:30:23260
engedy6e2e0992017-05-25 18:58:42261void FrameTreeNode::SetCollapsed(bool collapsed) {
262 DCHECK(!IsMainFrame());
263 if (is_collapsed_ == collapsed)
264 return;
265
266 is_collapsed_ = collapsed;
267 render_manager_.OnDidChangeCollapsedState(collapsed);
268}
269
lukasza464d8692016-02-22 19:26:32270void FrameTreeNode::SetFrameName(const std::string& name,
271 const std::string& unique_name) {
272 if (name == replication_state_.name) {
273 // |unique_name| shouldn't change unless |name| changes.
274 DCHECK_EQ(unique_name, replication_state_.unique_name);
275 return;
276 }
lukasza5140a412016-09-15 21:12:30277
278 if (parent()) {
279 // Non-main frames should have a non-empty unique name.
280 DCHECK(!unique_name.empty());
281 } else {
282 // Unique name of main frames should always stay empty.
283 DCHECK(unique_name.empty());
284 }
285
Daniel Cheng6ca7f1c92017-08-09 21:45:41286 // Note the unique name should only be able to change before the first real
287 // load is committed, but that's not strongly enforced here.
lukasza464d8692016-02-22 19:26:32288 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56289 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32290 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23291}
292
arthursonzogni662aa652017-03-28 11:09:50293void FrameTreeNode::AddContentSecurityPolicies(
294 const std::vector<ContentSecurityPolicyHeader>& headers) {
295 replication_state_.accumulated_csp_headers.insert(
296 replication_state_.accumulated_csp_headers.end(), headers.begin(),
297 headers.end());
298 render_manager_.OnDidAddContentSecurityPolicies(headers);
lukasza8e1c02e42016-05-17 20:05:10299}
300
mkwstf672e7ef2016-06-09 20:51:07301void FrameTreeNode::SetInsecureRequestPolicy(
302 blink::WebInsecureRequestPolicy policy) {
303 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08304 return;
mkwstf672e7ef2016-06-09 20:51:07305 render_manager_.OnEnforceInsecureRequestPolicy(policy);
306 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08307}
308
arthursonzogni4b62a5cb2018-01-17 14:14:26309void FrameTreeNode::SetInsecureNavigationsSet(
310 const std::vector<uint32_t>& insecure_navigations_set) {
311 DCHECK(std::is_sorted(insecure_navigations_set.begin(),
312 insecure_navigations_set.end()));
313 if (insecure_navigations_set == replication_state_.insecure_navigations_set)
314 return;
315 render_manager_.OnEnforceInsecureNavigationsSet(insecure_navigations_set);
316 replication_state_.insecure_navigations_set = insecure_navigations_set;
317}
318
Luna Luc3fdacdf2017-11-08 04:48:53319void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Ian Clellandcdc4f312017-10-13 22:24:12320 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25321
Ian Clellandcdc4f312017-10-13 22:24:12322 if (parent()) {
323 // Subframes should always inherit their parent's sandbox flags.
Ian Clelland5cbaaf82017-11-27 22:00:03324 pending_frame_policy_.sandbox_flags |= parent()->active_sandbox_flags();
Ian Clellandcdc4f312017-10-13 22:24:12325 // This is only applied on subframes; container policy is not mutable on
326 // main frame.
327 pending_frame_policy_.container_policy = frame_policy.container_policy;
328 }
iclelland92f8c0b2017-04-19 12:43:05329}
330
alexmos9f8705a2015-05-06 19:58:59331FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39332 return GetSibling(-1);
333}
alexmos9f8705a2015-05-06 19:58:59334
paulmeyer322777fb2016-05-16 23:15:39335FrameTreeNode* FrameTreeNode::NextSibling() const {
336 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59337}
338
fdegans4a49ce932015-03-12 17:11:37339bool FrameTreeNode::IsLoading() const {
340 RenderFrameHostImpl* current_frame_host =
341 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37342
343 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39344
clamy610c63b32017-12-22 15:05:18345 if (navigation_request_)
346 return true;
clamy11e11512015-07-07 16:42:17347
clamy610c63b32017-12-22 15:05:18348 RenderFrameHostImpl* speculative_frame_host =
349 render_manager_.speculative_frame_host();
350 if (speculative_frame_host && speculative_frame_host->is_loading())
351 return true;
fdegans4a49ce932015-03-12 17:11:37352 return current_frame_host->is_loading();
353}
354
iclelland92f8c0b2017-04-19 12:43:05355bool FrameTreeNode::CommitPendingFramePolicy() {
Ian Clellandcdc4f312017-10-13 22:24:12356 bool did_change_flags = pending_frame_policy_.sandbox_flags !=
357 replication_state_.frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05358 bool did_change_container_policy =
Ian Clellandcdc4f312017-10-13 22:24:12359 pending_frame_policy_.container_policy !=
360 replication_state_.frame_policy.container_policy;
iclelland92f8c0b2017-04-19 12:43:05361 if (did_change_flags)
Ian Clellandcdc4f312017-10-13 22:24:12362 replication_state_.frame_policy.sandbox_flags =
363 pending_frame_policy_.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05364 if (did_change_container_policy)
Ian Clellandcdc4f312017-10-13 22:24:12365 replication_state_.frame_policy.container_policy =
366 pending_frame_policy_.container_policy;
Ian Clellandedb8c5dd2018-03-01 17:01:37367 UpdateFramePolicyHeaders(pending_frame_policy_.sandbox_flags,
368 replication_state_.feature_policy_header);
iclelland92f8c0b2017-04-19 12:43:05369 return did_change_flags || did_change_container_policy;
alexmos6b294562015-03-05 19:24:10370}
371
Arthur Hemeryc3380172018-01-22 14:00:17372void FrameTreeNode::TransferNavigationRequestOwnership(
373 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59374 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17375 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
376}
377
carloskc49005eb2015-06-16 11:25:07378void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57379 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37380 // This is never called when navigating to a Javascript URL. For the loading
381 // state, this matches what Blink is doing: Blink doesn't send throbber
382 // notifications for Javascript URLS.
383 DCHECK(!navigation_request->common_params().url.SchemeIs(
384 url::kJavaScriptScheme));
385
clamy44e84ce2016-02-22 15:38:25386 bool was_previously_loading = frame_tree()->IsLoading();
387
clamy82a2f4d2016-02-02 14:20:41388 // There's no need to reset the state: there's still an ongoing load, and the
389 // RenderFrameHostManager will take care of updates to the speculative
390 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05391 if (was_previously_loading) {
clamy080e7962017-05-25 00:44:18392 if (navigation_request_ && navigation_request_->navigation_handle()) {
jamcd0b7b22017-03-24 22:13:05393 // Mark the old request as aborted.
394 navigation_request_->navigation_handle()->set_net_error_code(
395 net::ERR_ABORTED);
396 }
clamya86695b2017-03-23 14:45:48397 ResetNavigationRequest(true, true);
jamcd0b7b22017-03-24 22:13:05398 }
clamy44e84ce2016-02-22 15:38:25399
400 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06401 if (was_discarded_) {
402 navigation_request_->set_was_discarded();
403 was_discarded_ = false;
404 }
clamy8e2e299202016-04-05 11:44:59405 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39406
arthursonzogni92f18682017-02-08 23:00:04407 bool to_different_document = !FrameMsg_Navigate_Type::IsSameDocument(
408 navigation_request_->common_params().navigation_type);
409
410 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16411}
412
clamya86695b2017-03-23 14:45:48413void FrameTreeNode::ResetNavigationRequest(bool keep_state,
414 bool inform_renderer) {
fdegans39ff0382015-04-29 19:04:39415 if (!navigation_request_)
416 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23417
Andrey Kosyakovf2d4ff72018-10-29 20:09:59418 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Pavel Feldmand8352ac2017-11-10 00:37:41419
John Abd-El-Malekdcc7bf42017-09-12 22:30:23420 // The renderer should be informed if the caller allows to do so and the
421 // navigation came from a BeginNavigation IPC.
Arthur Hemeryd3011f62018-05-30 10:38:44422 bool need_to_inform_renderer =
423 !IsPerNavigationMojoInterfaceEnabled() & inform_renderer &&
424 navigation_request_->from_begin_navigation();
John Abd-El-Malekdcc7bf42017-09-12 22:30:23425
clamy8e2e299202016-04-05 11:44:59426 NavigationRequest::AssociatedSiteInstanceType site_instance_type =
427 navigation_request_->associated_site_instance_type();
clamydcb434c12015-04-16 19:29:16428 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39429
clamy82a2f4d2016-02-02 14:20:41430 if (keep_state)
fdegans39ff0382015-04-29 19:04:39431 return;
432
clamy82a2f4d2016-02-02 14:20:41433 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
434 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39435 DidStopLoading();
436 render_manager_.CleanUpNavigation();
clamy2567242a2016-02-22 18:27:38437
clamy8e2e299202016-04-05 11:44:59438 // When reusing the same SiteInstance, a pending WebUI may have been created
439 // on behalf of the navigation in the current RenderFrameHost. Clear it.
440 if (site_instance_type ==
441 NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
442 current_frame_host()->ClearPendingWebUI();
443 }
444
clamy2567242a2016-02-22 18:27:38445 // If the navigation is renderer-initiated, the renderer should also be
clamya86695b2017-03-23 14:45:48446 // informed that the navigation stopped if needed. In the case the renderer
447 // process asked for the navigation to be aborted, e.g. following a
448 // document.open, do not send an IPC to the renderer process as it already
449 // expects the navigation to stop.
John Abd-El-Malekdcc7bf42017-09-12 22:30:23450 if (need_to_inform_renderer) {
clamy2567242a2016-02-22 18:27:38451 current_frame_host()->Send(
John Abd-El-Malekdcc7bf42017-09-12 22:30:23452 new FrameMsg_DroppedNavigation(current_frame_host()->GetRoutingID()));
clamy2567242a2016-02-22 18:27:38453 }
clamydcb434c12015-04-16 19:29:16454}
455
clamy44e84ce2016-02-22 15:38:25456void FrameTreeNode::DidStartLoading(bool to_different_document,
457 bool was_previously_loading) {
Camille Lamyefd54b02018-10-04 16:54:14458 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
459 "frame_tree_node", frame_tree_node_id(), "to different document",
460 to_different_document);
fdegansa696e5112015-04-17 01:57:59461 // Any main frame load to a new document should reset the load progress since
462 // it will replace the current page and any frames. The WebContents will
463 // be notified when DidChangeLoadProgress is called.
464 if (to_different_document && IsMainFrame())
465 frame_tree_->ResetLoadProgress();
466
467 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25468 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59469 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
470
471 // Set initial load progress and update overall progress. This will notify
472 // the WebContents of the load progress change.
473 DidChangeLoadProgress(kLoadingProgressMinimum);
474
475 // Notify the RenderFrameHostManager of the event.
476 render_manager()->OnDidStartLoading();
477}
478
479void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14480 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
481 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59482 // Set final load progress and update overall progress. This will notify
483 // the WebContents of the load progress change.
484 DidChangeLoadProgress(kLoadingProgressDone);
485
Lucas Furukawa Gadani6faef602019-05-06 21:16:03486 // Notify the RenderFrameHostManager of the event.
487 render_manager()->OnDidStopLoading();
488
fdegansa696e5112015-04-17 01:57:59489 // Notify the WebContents.
490 if (!frame_tree_->IsLoading())
491 navigator()->GetDelegate()->DidStopLoading();
492
Dominic Mazzoni3c7007a2017-12-12 07:34:05493 // Notify accessibility that the user is no longer trying to load or
494 // reload a page.
495 BrowserAccessibilityManager* manager =
496 current_frame_host()->browser_accessibility_manager();
497 if (manager)
498 manager->DidStopLoading();
fdegansa696e5112015-04-17 01:57:59499}
500
501void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Nate Chapin93536702018-02-07 00:12:21502 DCHECK_GE(load_progress, kLoadingProgressMinimum);
503 DCHECK_LE(load_progress, kLoadingProgressDone);
504 if (IsMainFrame())
505 frame_tree_->UpdateLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59506}
507
clamyf73862c42015-07-08 12:31:33508bool FrameTreeNode::StopLoading() {
Nasko Oskova9511352018-09-15 00:11:10509 if (navigation_request_) {
510 int expected_pending_nav_entry_id = navigation_request_->nav_entry_id();
511 if (navigation_request_->navigation_handle()) {
512 navigation_request_->navigation_handle()->set_net_error_code(
513 net::ERR_ABORTED);
514 expected_pending_nav_entry_id =
515 navigation_request_->navigation_handle()->pending_nav_entry_id();
jam0299edae2017-03-10 00:49:22516 }
Nasko Oskova9511352018-09-15 00:11:10517 navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
jam0299edae2017-03-10 00:49:22518 }
Nasko Oskova9511352018-09-15 00:11:10519 ResetNavigationRequest(false, true);
clamyf73862c42015-07-08 12:31:33520
521 // TODO(nasko): see if child frames should send IPCs in site-per-process
522 // mode.
523 if (!IsMainFrame())
524 return true;
525
526 render_manager_.Stop();
527 return true;
528}
529
alexmos21acae52015-11-07 01:04:43530void FrameTreeNode::DidFocus() {
531 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31532 for (auto& observer : observers_)
533 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43534}
535
clamy44e84ce2016-02-22 15:38:25536void FrameTreeNode::BeforeUnloadCanceled() {
537 // TODO(clamy): Support BeforeUnload in subframes.
538 if (!IsMainFrame())
539 return;
540
541 RenderFrameHostImpl* current_frame_host =
542 render_manager_.current_frame_host();
543 DCHECK(current_frame_host);
544 current_frame_host->ResetLoadingState();
545
clamy610c63b32017-12-22 15:05:18546 RenderFrameHostImpl* speculative_frame_host =
547 render_manager_.speculative_frame_host();
548 if (speculative_frame_host)
549 speculative_frame_host->ResetLoadingState();
550 // Note: there is no need to set an error code on the NavigationHandle here
551 // as it has not been created yet. It is only created when the
552 // BeforeUnloadACK is received.
553 if (navigation_request_)
554 ResetNavigationRequest(false, true);
clamy44e84ce2016-02-22 15:38:25555}
556
Mustaq Ahmedc4cb7162018-06-05 16:28:36557bool FrameTreeNode::NotifyUserActivation() {
John Delaneyedd8d6c2019-01-25 00:23:57558 for (FrameTreeNode* node = this; node; node = node->parent()) {
559 if (!node->user_activation_state_.HasBeenActive() &&
560 node->current_frame_host())
561 node->current_frame_host()->DidReceiveFirstUserActivation();
Mustaq Ahmedc4cb7162018-06-05 16:28:36562 node->user_activation_state_.Activate();
John Delaneyedd8d6c2019-01-25 00:23:57563 }
japhet61835ae12017-01-20 01:25:39564 replication_state_.has_received_user_gesture = true;
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14565
Mustaq Ahmed0180320f2019-03-21 16:07:01566 // See the "Same-origin Visibility" section in |UserActivationState| class
567 // doc.
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14568 if (base::FeatureList::IsEnabled(features::kUserActivationV2) &&
569 base::FeatureList::IsEnabled(
570 features::kUserActivationSameOriginVisibility)) {
571 const url::Origin& current_origin =
572 this->current_frame_host()->GetLastCommittedOrigin();
573 for (FrameTreeNode* node : frame_tree()->Nodes()) {
574 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
575 current_origin)) {
576 node->user_activation_state_.Activate();
577 }
578 }
579 }
580
Shivani Sharma20749e922019-03-11 17:00:26581 NavigationControllerImpl* controller =
582 static_cast<NavigationControllerImpl*>(navigator()->GetController());
583 if (controller)
584 controller->NotifyUserActivation();
Shivani Sharma194877032019-03-07 17:52:47585
Mustaq Ahmedc4cb7162018-06-05 16:28:36586 return true;
587}
588
589bool FrameTreeNode::ConsumeTransientUserActivation() {
590 bool was_active = user_activation_state_.IsActive();
591 for (FrameTreeNode* node : frame_tree()->Nodes())
592 node->user_activation_state_.ConsumeIfActive();
593 return was_active;
594}
595
Shivani Sharmac4f561582018-11-15 15:58:39596bool FrameTreeNode::ClearUserActivation() {
Shivani Sharmac4f561582018-11-15 15:58:39597 for (FrameTreeNode* node : frame_tree()->SubtreeNodes(this))
598 node->user_activation_state_.Clear();
599 return true;
600}
601
Mustaq Ahmedc4cb7162018-06-05 16:28:36602bool FrameTreeNode::UpdateUserActivationState(
603 blink::UserActivationUpdateType update_type) {
604 render_manager_.UpdateUserActivationState(update_type);
605 switch (update_type) {
606 case blink::UserActivationUpdateType::kConsumeTransientActivation:
607 return ConsumeTransientUserActivation();
608
609 case blink::UserActivationUpdateType::kNotifyActivation:
610 return NotifyUserActivation();
Shivani Sharmac4f561582018-11-15 15:58:39611
612 case blink::UserActivationUpdateType::kClearActivation:
613 return ClearUserActivation();
Mustaq Ahmedc4cb7162018-06-05 16:28:36614 }
615 NOTREACHED() << "Invalid update_type.";
japhet61835ae12017-01-20 01:25:39616}
617
Becca Hughes60af7d42017-12-12 10:53:15618void FrameTreeNode::OnSetHasReceivedUserGestureBeforeNavigation(bool value) {
619 render_manager_.OnSetHasReceivedUserGestureBeforeNavigation(value);
620 replication_state_.has_received_user_gesture_before_nav = value;
621}
622
paulmeyer322777fb2016-05-16 23:15:39623FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19624 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39625 return nullptr;
626
627 for (size_t i = 0; i < parent_->child_count(); ++i) {
628 if (parent_->child_at(i) == this) {
629 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
630 i + relative_offset >= parent_->child_count()) {
631 return nullptr;
632 }
633 return parent_->child_at(i + relative_offset);
634 }
635 }
636
637 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
638 return nullptr;
639}
640
Ian Clellandedb8c5dd2018-03-01 17:01:37641void FrameTreeNode::UpdateFramePolicyHeaders(
642 blink::WebSandboxFlags sandbox_flags,
643 const blink::ParsedFeaturePolicy& parsed_header) {
644 bool changed = false;
645 if (replication_state_.feature_policy_header != parsed_header) {
646 replication_state_.feature_policy_header = parsed_header;
647 changed = true;
648 }
Ian Clelland5cbaaf82017-11-27 22:00:03649 // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the
650 // currently effective sandbox flags from the frame. https://crbug.com/740556
Ian Clellandedb8c5dd2018-03-01 17:01:37651 blink::WebSandboxFlags updated_flags =
Ian Clelland5cbaaf82017-11-27 22:00:03652 sandbox_flags | effective_frame_policy().sandbox_flags;
Ian Clellandedb8c5dd2018-03-01 17:01:37653 if (replication_state_.active_sandbox_flags != updated_flags) {
654 replication_state_.active_sandbox_flags = updated_flags;
655 changed = true;
656 }
657 // Notify any proxies if the policies have been changed.
658 if (changed)
659 render_manager()->OnDidSetFramePolicyHeaders();
Ian Clelland5cbaaf82017-11-27 22:00:03660}
661
Lan Weif0cb8e6e2019-04-19 00:14:53662void FrameTreeNode::TransferUserActivationFrom(
663 RenderFrameHostImpl* source_rfh) {
664 user_activation_state_.TransferFrom(
665 source_rfh->frame_tree_node()->user_activation_state_);
666
667 // Notify proxies in non-source and non-target renderer processes to
668 // transfer the activation state from the source proxy to the target
669 // so the user activation state of those proxies matches the source
670 // renderer and the target renderer (which are separately updated).
671 render_manager_.TransferUserActivationFrom(source_rfh);
Lan Wei550671a22019-03-19 00:59:24672}
673
Arthur Sonzognif8840b92018-11-07 14:10:35674void FrameTreeNode::PruneChildFrameNavigationEntries(
675 NavigationEntryImpl* entry) {
676 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
677 FrameTreeNode* child = current_frame_host()->child_at(i);
678 if (child->is_created_by_script_) {
679 entry->RemoveEntryForFrame(child,
680 /* only_if_different_position = */ false);
681 } else {
682 child->PruneChildFrameNavigationEntries(entry);
683 }
684 }
685}
686
Ehsan Karamad39407082019-02-19 23:38:19687void FrameTreeNode::SetOpenerFeaturePolicyState(
688 const blink::FeaturePolicy::FeatureState& feature_state) {
689 DCHECK(IsMainFrame());
690 if (base::FeatureList::IsEnabled(features::kFeaturePolicyForSandbox)) {
691 replication_state_.opener_feature_state = feature_state;
692 }
693}
694
[email protected]9b159a52013-10-03 17:24:55695} // namespace content