blob: 32300291e89ee9ac9c193c27d851ba5581ea29b7 [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>
dcheng36b6aec92015-12-26 06:16:3610#include <utility>
[email protected]9b159a52013-10-03 17:24:5511
scottmg6ece5ae2017-02-01 18:25:1912#include "base/lazy_instance.h"
avib7348942015-12-25 20:57:1013#include "base/macros.h"
dcheng23ca947d2016-05-04 20:04:1514#include "base/metrics/histogram_macros.h"
[email protected]9b159a52013-10-03 17:24:5515#include "base/stl_util.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4116#include "base/strings/string_util.h"
Pavel Feldmand8352ac2017-11-10 00:37:4117#include "content/browser/devtools/render_frame_devtools_agent_host.h"
[email protected]94d0cc12013-12-18 00:07:4118#include "content/browser/frame_host/frame_tree.h"
clamydcb434c12015-04-16 19:29:1619#include "content/browser/frame_host/navigation_request.h"
[email protected]190b8c52013-11-09 01:35:4420#include "content/browser/frame_host/navigator.h"
[email protected]d4a8ca482013-10-30 21:06:4021#include "content/browser/frame_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4122#include "content/browser/renderer_host/render_view_host_impl.h"
clamyf73862c42015-07-08 12:31:3323#include "content/common/frame_messages.h"
dmazzonie950ea232015-03-13 21:39:4524#include "content/public/browser/browser_thread.h"
carloskd80262f52015-12-16 14:40:3525#include "content/public/common/browser_side_navigation_policy.h"
Blink Reformata30d4232018-04-07 15:31:0626#include "third_party/blink/public/common/frame/sandbox_flags.h"
Mustaq Ahmedc4cb7162018-06-05 16:28:3627#include "third_party/blink/public/common/frame/user_activation_update_type.h"
[email protected]9b159a52013-10-03 17:24:5528
29namespace content {
30
dmazzonie950ea232015-03-13 21:39:4531namespace {
32
33// This is a global map between frame_tree_node_ids and pointers to
34// FrameTreeNodes.
rob97250742015-12-10 17:45:1535typedef base::hash_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4536
scottmg5e65e3a2017-03-08 08:48:4637base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
38 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4539
fdegansa696e5112015-04-17 01:57:5940// These values indicate the loading progress status. The minimum progress
41// value matches what Blink's ProgressTracker has traditionally used for a
42// minimum progress value.
fdegansa696e5112015-04-17 01:57:5943const double kLoadingProgressMinimum = 0.1;
44const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4545
fdegansa696e5112015-04-17 01:57:5946} // namespace
fdegans1d16355162015-03-26 11:58:3447
alexmose201c7cd2015-06-10 17:14:2148// This observer watches the opener of its owner FrameTreeNode and clears the
49// owner's opener if the opener is destroyed.
50class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
51 public:
jochen6004a362017-02-04 00:11:4052 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
53 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2154
55 // FrameTreeNode::Observer
56 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4057 if (observing_original_opener_) {
Avi Drissman36465f332017-09-11 20:49:3958 // The "original owner" is special. It's used for attribution, and clients
59 // walk down the original owner chain. Therefore, if a link in the chain
60 // is being destroyed, reconnect the observation to the parent of the link
61 // being destroyed.
jochen6004a362017-02-04 00:11:4062 CHECK_EQ(owner_->original_opener(), node);
Avi Drissman36465f332017-09-11 20:49:3963 owner_->SetOriginalOpener(node->original_opener());
64 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4065 } else {
66 CHECK_EQ(owner_->opener(), node);
67 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:3968 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4069 }
alexmose201c7cd2015-06-10 17:14:2170 }
71
72 private:
73 FrameTreeNode* owner_;
jochen6004a362017-02-04 00:11:4074 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2175
76 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
77};
78
vishal.b782eb5d2015-04-29 12:22:5779int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5580
dmazzonie950ea232015-03-13 21:39:4581// static
vishal.b782eb5d2015-04-29 12:22:5782FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1983 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1584 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:4685 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4586 return it == nodes->end() ? nullptr : it->second;
87}
88
raymes31457802016-07-20 06:08:0989FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
90 Navigator* navigator,
raymes31457802016-07-20 06:08:0991 FrameTreeNode* parent,
92 blink::WebTreeScopeType scope,
93 const std::string& name,
94 const std::string& unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:4595 bool is_created_by_script,
Pavel Feldman25234722017-10-11 02:49:0696 const base::UnguessableToken& devtools_frame_token,
Ehsan Karamad192a8da2018-10-21 03:48:0897 const FrameOwnerProperties& frame_owner_properties,
98 blink::FrameOwnerElementType owner_type)
[email protected]bffc8302014-01-23 20:52:1699 : frame_tree_(frame_tree),
100 navigator_(navigator),
Lucas Furukawa Gadani72cc21c2018-09-04 18:50:46101 render_manager_(this, frame_tree->manager_delegate()),
[email protected]bffc8302014-01-23 20:52:16102 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59103 parent_(parent),
Bo Liua13e7c02018-03-28 22:24:02104 depth_(parent ? parent->depth_ + 1 : 0u),
alexmose201c7cd2015-06-10 17:14:21105 opener_(nullptr),
jochen6004a362017-02-04 00:11:40106 original_opener_(nullptr),
creisf0f069a2015-07-23 23:51:53107 has_committed_real_load_(false),
engedy6e2e0992017-05-25 18:58:42108 is_collapsed_(false),
estarka886b8d2015-12-18 21:53:08109 replication_state_(
110 scope,
111 name,
lukasza464d8692016-02-22 19:26:32112 unique_name,
estarkbd8e26f2016-03-16 23:30:37113 false /* should enforce strict mixed content checking */,
arthursonzogni4b62a5cb2018-01-17 14:14:26114 std::vector<uint32_t>()
115 /* hashes of hosts for insecure request upgrades */,
japhet61835ae12017-01-20 01:25:39116 false /* is a potentially trustworthy unique origin */,
Becca Hughes60af7d42017-12-12 10:53:15117 false /* has received a user gesture */,
Ehsan Karamad192a8da2018-10-21 03:48:08118 false /* has received a user gesture before nav */,
119 owner_type),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45120 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06121 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31122 frame_owner_properties_(frame_owner_properties),
Shubhie Panickerddf2a4e2018-03-06 00:09:06123 was_discarded_(false),
xiaochenghb9554bb2016-05-21 14:20:48124 blame_context_(frame_tree_node_id_, parent) {
rob97250742015-12-10 17:45:15125 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45126 g_frame_tree_node_id_map.Get().insert(
127 std::make_pair(frame_tree_node_id_, this));
128 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33129
xiaochenghb9554bb2016-05-21 14:20:48130 // Note: this should always be done last in the constructor.
131 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59132}
[email protected]9b159a52013-10-03 17:24:55133
134FrameTreeNode::~FrameTreeNode() {
Nasko Oskov252ae042018-10-04 21:44:12135 // Remove the children.
136 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45137
138 // If the removed frame was created by a script, then its history entry will
139 // never be reused - we can save some memory by removing the history entry.
140 // See also https://crbug.com/784356.
141 if (is_created_by_script_ && parent_) {
142 NavigationEntryImpl* nav_entry = static_cast<NavigationEntryImpl*>(
143 navigator()->GetController()->GetLastCommittedEntry());
144 if (nav_entry) {
145 nav_entry->RemoveEntryForFrame(this,
146 /* only_if_different_position = */ false);
147 }
148 }
149
dmazzonie950ea232015-03-13 21:39:45150 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31151 for (auto& observer : observers_)
152 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21153
154 if (opener_)
155 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40156 if (original_opener_)
157 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45158
159 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18160
161 if (navigation_request_) {
162 // PlzNavigate: if a frame with a pending navigation is detached, make sure
163 // the WebContents (and its observers) update their loading state.
164 navigation_request_.reset();
165 DidStopLoading();
166 }
[email protected]9b159a52013-10-03 17:24:55167}
168
alexmose201c7cd2015-06-10 17:14:21169void FrameTreeNode::AddObserver(Observer* observer) {
170 observers_.AddObserver(observer);
171}
172
173void FrameTreeNode::RemoveObserver(Observer* observer) {
174 observers_.RemoveObserver(observer);
175}
176
[email protected]94d0cc12013-12-18 00:07:41177bool FrameTreeNode::IsMainFrame() const {
178 return frame_tree_->root() == this;
179}
180
Ian Clelland5cbaaf82017-11-27 22:00:03181void FrameTreeNode::ResetForNavigation() {
182 // Discard any CSP headers from the previous document.
183 replication_state_.accumulated_csp_headers.clear();
184 render_manager_.OnDidResetContentSecurityPolicy();
185
Ian Clellandedb8c5dd2018-03-01 17:01:37186 // Clear any CSP-set sandbox flags, and the declared feature policy for the
187 // frame.
188 UpdateFramePolicyHeaders(blink::WebSandboxFlags::kNone, {});
Ian Clelland5cbaaf82017-11-27 22:00:03189}
190
alexmose201c7cd2015-06-10 17:14:21191void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
192 if (opener_) {
193 opener_->RemoveObserver(opener_observer_.get());
194 opener_observer_.reset();
195 }
196
197 opener_ = opener;
198
199 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55200 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21201 opener_->AddObserver(opener_observer_.get());
202 }
203}
204
jochen6004a362017-02-04 00:11:40205void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39206 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37207 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40208
Avi Drissman36465f332017-09-11 20:49:39209 if (original_opener_) {
210 original_opener_->RemoveObserver(original_opener_observer_.get());
211 original_opener_observer_.reset();
212 }
213
jochen6004a362017-02-04 00:11:40214 original_opener_ = opener;
215
216 if (original_opener_) {
jochen6004a362017-02-04 00:11:40217 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55218 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40219 original_opener_->AddObserver(original_opener_observer_.get());
220 }
221}
222
creisf0f069a2015-07-23 23:51:53223void FrameTreeNode::SetCurrentURL(const GURL& url) {
Balazs Engedyc8a7cccf2018-03-12 23:00:49224 if (!has_committed_real_load_ && !url.IsAboutBlank())
creisf0f069a2015-07-23 23:51:53225 has_committed_real_load_ = true;
Erik Chen173bf3042017-07-31 06:06:21226 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48227 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53228}
229
estarkbd8e26f2016-03-16 23:30:37230void FrameTreeNode::SetCurrentOrigin(
231 const url::Origin& origin,
232 bool is_potentially_trustworthy_unique_origin) {
233 if (!origin.IsSameOriginWith(replication_state_.origin) ||
234 replication_state_.has_potentially_trustworthy_unique_origin !=
235 is_potentially_trustworthy_unique_origin) {
236 render_manager_.OnDidUpdateOrigin(origin,
237 is_potentially_trustworthy_unique_origin);
238 }
alexmosa7a4ff822015-04-27 17:59:56239 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37240 replication_state_.has_potentially_trustworthy_unique_origin =
241 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56242}
alexmosbe2f4c32015-03-10 02:30:23243
engedy6e2e0992017-05-25 18:58:42244void FrameTreeNode::SetCollapsed(bool collapsed) {
245 DCHECK(!IsMainFrame());
246 if (is_collapsed_ == collapsed)
247 return;
248
249 is_collapsed_ = collapsed;
250 render_manager_.OnDidChangeCollapsedState(collapsed);
251}
252
lukasza464d8692016-02-22 19:26:32253void FrameTreeNode::SetFrameName(const std::string& name,
254 const std::string& unique_name) {
255 if (name == replication_state_.name) {
256 // |unique_name| shouldn't change unless |name| changes.
257 DCHECK_EQ(unique_name, replication_state_.unique_name);
258 return;
259 }
lukasza5140a412016-09-15 21:12:30260
261 if (parent()) {
262 // Non-main frames should have a non-empty unique name.
263 DCHECK(!unique_name.empty());
264 } else {
265 // Unique name of main frames should always stay empty.
266 DCHECK(unique_name.empty());
267 }
268
Daniel Cheng6ca7f1c92017-08-09 21:45:41269 // Note the unique name should only be able to change before the first real
270 // load is committed, but that's not strongly enforced here.
lukasza464d8692016-02-22 19:26:32271 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56272 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32273 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23274}
275
arthursonzogni662aa652017-03-28 11:09:50276void FrameTreeNode::AddContentSecurityPolicies(
277 const std::vector<ContentSecurityPolicyHeader>& headers) {
278 replication_state_.accumulated_csp_headers.insert(
279 replication_state_.accumulated_csp_headers.end(), headers.begin(),
280 headers.end());
281 render_manager_.OnDidAddContentSecurityPolicies(headers);
lukasza8e1c02e42016-05-17 20:05:10282}
283
mkwstf672e7ef2016-06-09 20:51:07284void FrameTreeNode::SetInsecureRequestPolicy(
285 blink::WebInsecureRequestPolicy policy) {
286 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08287 return;
mkwstf672e7ef2016-06-09 20:51:07288 render_manager_.OnEnforceInsecureRequestPolicy(policy);
289 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08290}
291
arthursonzogni4b62a5cb2018-01-17 14:14:26292void FrameTreeNode::SetInsecureNavigationsSet(
293 const std::vector<uint32_t>& insecure_navigations_set) {
294 DCHECK(std::is_sorted(insecure_navigations_set.begin(),
295 insecure_navigations_set.end()));
296 if (insecure_navigations_set == replication_state_.insecure_navigations_set)
297 return;
298 render_manager_.OnEnforceInsecureNavigationsSet(insecure_navigations_set);
299 replication_state_.insecure_navigations_set = insecure_navigations_set;
300}
301
Luna Luc3fdacdf2017-11-08 04:48:53302void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Ian Clellandcdc4f312017-10-13 22:24:12303 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25304
Ian Clellandcdc4f312017-10-13 22:24:12305 if (parent()) {
306 // Subframes should always inherit their parent's sandbox flags.
Ian Clelland5cbaaf82017-11-27 22:00:03307 pending_frame_policy_.sandbox_flags |= parent()->active_sandbox_flags();
Ian Clellandcdc4f312017-10-13 22:24:12308 // This is only applied on subframes; container policy is not mutable on
309 // main frame.
310 pending_frame_policy_.container_policy = frame_policy.container_policy;
311 }
iclelland92f8c0b2017-04-19 12:43:05312}
313
alexmos9f8705a2015-05-06 19:58:59314FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39315 return GetSibling(-1);
316}
alexmos9f8705a2015-05-06 19:58:59317
paulmeyer322777fb2016-05-16 23:15:39318FrameTreeNode* FrameTreeNode::NextSibling() const {
319 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59320}
321
fdegans4a49ce932015-03-12 17:11:37322bool FrameTreeNode::IsLoading() const {
323 RenderFrameHostImpl* current_frame_host =
324 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37325
326 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39327
clamy610c63b32017-12-22 15:05:18328 if (navigation_request_)
329 return true;
clamy11e11512015-07-07 16:42:17330
clamy610c63b32017-12-22 15:05:18331 RenderFrameHostImpl* speculative_frame_host =
332 render_manager_.speculative_frame_host();
333 if (speculative_frame_host && speculative_frame_host->is_loading())
334 return true;
fdegans4a49ce932015-03-12 17:11:37335 return current_frame_host->is_loading();
336}
337
iclelland92f8c0b2017-04-19 12:43:05338bool FrameTreeNode::CommitPendingFramePolicy() {
Ian Clellandcdc4f312017-10-13 22:24:12339 bool did_change_flags = pending_frame_policy_.sandbox_flags !=
340 replication_state_.frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05341 bool did_change_container_policy =
Ian Clellandcdc4f312017-10-13 22:24:12342 pending_frame_policy_.container_policy !=
343 replication_state_.frame_policy.container_policy;
iclelland92f8c0b2017-04-19 12:43:05344 if (did_change_flags)
Ian Clellandcdc4f312017-10-13 22:24:12345 replication_state_.frame_policy.sandbox_flags =
346 pending_frame_policy_.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05347 if (did_change_container_policy)
Ian Clellandcdc4f312017-10-13 22:24:12348 replication_state_.frame_policy.container_policy =
349 pending_frame_policy_.container_policy;
Ian Clellandedb8c5dd2018-03-01 17:01:37350 UpdateFramePolicyHeaders(pending_frame_policy_.sandbox_flags,
351 replication_state_.feature_policy_header);
iclelland92f8c0b2017-04-19 12:43:05352 return did_change_flags || did_change_container_policy;
alexmos6b294562015-03-05 19:24:10353}
354
Arthur Hemeryc3380172018-01-22 14:00:17355void FrameTreeNode::TransferNavigationRequestOwnership(
356 RenderFrameHostImpl* render_frame_host) {
357 RenderFrameDevToolsAgentHost::OnResetNavigationRequest(
358 navigation_request_.get());
359 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
360}
361
carloskc49005eb2015-06-16 11:25:07362void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57363 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37364 // This is never called when navigating to a Javascript URL. For the loading
365 // state, this matches what Blink is doing: Blink doesn't send throbber
366 // notifications for Javascript URLS.
367 DCHECK(!navigation_request->common_params().url.SchemeIs(
368 url::kJavaScriptScheme));
369
clamy44e84ce2016-02-22 15:38:25370 bool was_previously_loading = frame_tree()->IsLoading();
371
clamy82a2f4d2016-02-02 14:20:41372 // There's no need to reset the state: there's still an ongoing load, and the
373 // RenderFrameHostManager will take care of updates to the speculative
374 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05375 if (was_previously_loading) {
clamy080e7962017-05-25 00:44:18376 if (navigation_request_ && navigation_request_->navigation_handle()) {
jamcd0b7b22017-03-24 22:13:05377 // Mark the old request as aborted.
378 navigation_request_->navigation_handle()->set_net_error_code(
379 net::ERR_ABORTED);
380 }
clamya86695b2017-03-23 14:45:48381 ResetNavigationRequest(true, true);
jamcd0b7b22017-03-24 22:13:05382 }
clamy44e84ce2016-02-22 15:38:25383
384 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06385 if (was_discarded_) {
386 navigation_request_->set_was_discarded();
387 was_discarded_ = false;
388 }
clamy8e2e299202016-04-05 11:44:59389 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39390
arthursonzogni92f18682017-02-08 23:00:04391 bool to_different_document = !FrameMsg_Navigate_Type::IsSameDocument(
392 navigation_request_->common_params().navigation_type);
393
394 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16395}
396
clamya86695b2017-03-23 14:45:48397void FrameTreeNode::ResetNavigationRequest(bool keep_state,
398 bool inform_renderer) {
fdegans39ff0382015-04-29 19:04:39399 if (!navigation_request_)
400 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23401
Pavel Feldmand8352ac2017-11-10 00:37:41402 RenderFrameDevToolsAgentHost::OnResetNavigationRequest(
403 navigation_request_.get());
404
John Abd-El-Malekdcc7bf42017-09-12 22:30:23405 // The renderer should be informed if the caller allows to do so and the
406 // navigation came from a BeginNavigation IPC.
Arthur Hemeryd3011f62018-05-30 10:38:44407 bool need_to_inform_renderer =
408 !IsPerNavigationMojoInterfaceEnabled() & inform_renderer &&
409 navigation_request_->from_begin_navigation();
John Abd-El-Malekdcc7bf42017-09-12 22:30:23410
clamy8e2e299202016-04-05 11:44:59411 NavigationRequest::AssociatedSiteInstanceType site_instance_type =
412 navigation_request_->associated_site_instance_type();
clamydcb434c12015-04-16 19:29:16413 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39414
clamy82a2f4d2016-02-02 14:20:41415 if (keep_state)
fdegans39ff0382015-04-29 19:04:39416 return;
417
clamy82a2f4d2016-02-02 14:20:41418 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
419 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39420 DidStopLoading();
421 render_manager_.CleanUpNavigation();
clamy2567242a2016-02-22 18:27:38422
clamy8e2e299202016-04-05 11:44:59423 // When reusing the same SiteInstance, a pending WebUI may have been created
424 // on behalf of the navigation in the current RenderFrameHost. Clear it.
425 if (site_instance_type ==
426 NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
427 current_frame_host()->ClearPendingWebUI();
428 }
429
clamy2567242a2016-02-22 18:27:38430 // If the navigation is renderer-initiated, the renderer should also be
clamya86695b2017-03-23 14:45:48431 // informed that the navigation stopped if needed. In the case the renderer
432 // process asked for the navigation to be aborted, e.g. following a
433 // document.open, do not send an IPC to the renderer process as it already
434 // expects the navigation to stop.
John Abd-El-Malekdcc7bf42017-09-12 22:30:23435 if (need_to_inform_renderer) {
clamy2567242a2016-02-22 18:27:38436 current_frame_host()->Send(
John Abd-El-Malekdcc7bf42017-09-12 22:30:23437 new FrameMsg_DroppedNavigation(current_frame_host()->GetRoutingID()));
clamy2567242a2016-02-22 18:27:38438 }
clamydcb434c12015-04-16 19:29:16439}
440
clamy44e84ce2016-02-22 15:38:25441void FrameTreeNode::DidStartLoading(bool to_different_document,
442 bool was_previously_loading) {
Camille Lamyefd54b02018-10-04 16:54:14443 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
444 "frame_tree_node", frame_tree_node_id(), "to different document",
445 to_different_document);
fdegansa696e5112015-04-17 01:57:59446 // Any main frame load to a new document should reset the load progress since
447 // it will replace the current page and any frames. The WebContents will
448 // be notified when DidChangeLoadProgress is called.
449 if (to_different_document && IsMainFrame())
450 frame_tree_->ResetLoadProgress();
451
452 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25453 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59454 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
455
456 // Set initial load progress and update overall progress. This will notify
457 // the WebContents of the load progress change.
458 DidChangeLoadProgress(kLoadingProgressMinimum);
459
460 // Notify the RenderFrameHostManager of the event.
461 render_manager()->OnDidStartLoading();
462}
463
464void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14465 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
466 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59467 // Set final load progress and update overall progress. This will notify
468 // the WebContents of the load progress change.
469 DidChangeLoadProgress(kLoadingProgressDone);
470
fdegansa696e5112015-04-17 01:57:59471 // Notify the WebContents.
472 if (!frame_tree_->IsLoading())
473 navigator()->GetDelegate()->DidStopLoading();
474
fdegansa696e5112015-04-17 01:57:59475 // Notify the RenderFrameHostManager of the event.
476 render_manager()->OnDidStopLoading();
Dominic Mazzoni3c7007a2017-12-12 07:34:05477
478 // Notify accessibility that the user is no longer trying to load or
479 // reload a page.
480 BrowserAccessibilityManager* manager =
481 current_frame_host()->browser_accessibility_manager();
482 if (manager)
483 manager->DidStopLoading();
fdegansa696e5112015-04-17 01:57:59484}
485
486void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Nate Chapin93536702018-02-07 00:12:21487 DCHECK_GE(load_progress, kLoadingProgressMinimum);
488 DCHECK_LE(load_progress, kLoadingProgressDone);
489 if (IsMainFrame())
490 frame_tree_->UpdateLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59491}
492
clamyf73862c42015-07-08 12:31:33493bool FrameTreeNode::StopLoading() {
Nasko Oskova9511352018-09-15 00:11:10494 if (navigation_request_) {
495 int expected_pending_nav_entry_id = navigation_request_->nav_entry_id();
496 if (navigation_request_->navigation_handle()) {
497 navigation_request_->navigation_handle()->set_net_error_code(
498 net::ERR_ABORTED);
499 expected_pending_nav_entry_id =
500 navigation_request_->navigation_handle()->pending_nav_entry_id();
jam0299edae2017-03-10 00:49:22501 }
Nasko Oskova9511352018-09-15 00:11:10502 navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
jam0299edae2017-03-10 00:49:22503 }
Nasko Oskova9511352018-09-15 00:11:10504 ResetNavigationRequest(false, true);
clamyf73862c42015-07-08 12:31:33505
506 // TODO(nasko): see if child frames should send IPCs in site-per-process
507 // mode.
508 if (!IsMainFrame())
509 return true;
510
511 render_manager_.Stop();
512 return true;
513}
514
alexmos21acae52015-11-07 01:04:43515void FrameTreeNode::DidFocus() {
516 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31517 for (auto& observer : observers_)
518 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43519}
520
clamy44e84ce2016-02-22 15:38:25521void FrameTreeNode::BeforeUnloadCanceled() {
522 // TODO(clamy): Support BeforeUnload in subframes.
523 if (!IsMainFrame())
524 return;
525
526 RenderFrameHostImpl* current_frame_host =
527 render_manager_.current_frame_host();
528 DCHECK(current_frame_host);
529 current_frame_host->ResetLoadingState();
530
clamy610c63b32017-12-22 15:05:18531 RenderFrameHostImpl* speculative_frame_host =
532 render_manager_.speculative_frame_host();
533 if (speculative_frame_host)
534 speculative_frame_host->ResetLoadingState();
535 // Note: there is no need to set an error code on the NavigationHandle here
536 // as it has not been created yet. It is only created when the
537 // BeforeUnloadACK is received.
538 if (navigation_request_)
539 ResetNavigationRequest(false, true);
clamy44e84ce2016-02-22 15:38:25540}
541
Mustaq Ahmedc4cb7162018-06-05 16:28:36542bool FrameTreeNode::NotifyUserActivation() {
543 for (FrameTreeNode* node = this; node; node = node->parent())
544 node->user_activation_state_.Activate();
japhet61835ae12017-01-20 01:25:39545 replication_state_.has_received_user_gesture = true;
Mustaq Ahmedc4cb7162018-06-05 16:28:36546 return true;
547}
548
549bool FrameTreeNode::ConsumeTransientUserActivation() {
550 bool was_active = user_activation_state_.IsActive();
551 for (FrameTreeNode* node : frame_tree()->Nodes())
552 node->user_activation_state_.ConsumeIfActive();
553 return was_active;
554}
555
556bool FrameTreeNode::UpdateUserActivationState(
557 blink::UserActivationUpdateType update_type) {
558 render_manager_.UpdateUserActivationState(update_type);
559 switch (update_type) {
560 case blink::UserActivationUpdateType::kConsumeTransientActivation:
561 return ConsumeTransientUserActivation();
562
563 case blink::UserActivationUpdateType::kNotifyActivation:
564 return NotifyUserActivation();
565 }
566 NOTREACHED() << "Invalid update_type.";
japhet61835ae12017-01-20 01:25:39567}
568
Becca Hughes60af7d42017-12-12 10:53:15569void FrameTreeNode::OnSetHasReceivedUserGestureBeforeNavigation(bool value) {
570 render_manager_.OnSetHasReceivedUserGestureBeforeNavigation(value);
571 replication_state_.has_received_user_gesture_before_nav = value;
572}
573
paulmeyer322777fb2016-05-16 23:15:39574FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19575 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39576 return nullptr;
577
578 for (size_t i = 0; i < parent_->child_count(); ++i) {
579 if (parent_->child_at(i) == this) {
580 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
581 i + relative_offset >= parent_->child_count()) {
582 return nullptr;
583 }
584 return parent_->child_at(i + relative_offset);
585 }
586 }
587
588 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
589 return nullptr;
590}
591
Ian Clellandedb8c5dd2018-03-01 17:01:37592void FrameTreeNode::UpdateFramePolicyHeaders(
593 blink::WebSandboxFlags sandbox_flags,
594 const blink::ParsedFeaturePolicy& parsed_header) {
595 bool changed = false;
596 if (replication_state_.feature_policy_header != parsed_header) {
597 replication_state_.feature_policy_header = parsed_header;
598 changed = true;
599 }
Ian Clelland5cbaaf82017-11-27 22:00:03600 // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the
601 // currently effective sandbox flags from the frame. https://crbug.com/740556
Ian Clellandedb8c5dd2018-03-01 17:01:37602 blink::WebSandboxFlags updated_flags =
Ian Clelland5cbaaf82017-11-27 22:00:03603 sandbox_flags | effective_frame_policy().sandbox_flags;
Ian Clellandedb8c5dd2018-03-01 17:01:37604 if (replication_state_.active_sandbox_flags != updated_flags) {
605 replication_state_.active_sandbox_flags = updated_flags;
606 changed = true;
607 }
608 // Notify any proxies if the policies have been changed.
609 if (changed)
610 render_manager()->OnDidSetFramePolicyHeaders();
Ian Clelland5cbaaf82017-11-27 22:00:03611}
612
[email protected]9b159a52013-10-03 17:24:55613} // namespace content