blob: 49d8dac269260b5951aa4331280659813f42751d [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"
arthursonzognib93a4472020-04-10 07:38:0032#include "services/network/public/cpp/web_sandbox_flags.h"
33#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
Antonio Gomes4b2c5132020-01-16 11:49:4834#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:3735#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
[email protected]9b159a52013-10-03 17:24:5536
37namespace content {
38
dmazzonie950ea232015-03-13 21:39:4539namespace {
40
41// This is a global map between frame_tree_node_ids and pointers to
42// FrameTreeNodes.
Takuto Ikutaadf31eb2019-01-05 00:32:4843typedef std::unordered_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4544
scottmg5e65e3a2017-03-08 08:48:4645base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
46 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4547
fdegansa696e5112015-04-17 01:57:5948// These values indicate the loading progress status. The minimum progress
49// value matches what Blink's ProgressTracker has traditionally used for a
50// minimum progress value.
fdegansa696e5112015-04-17 01:57:5951const double kLoadingProgressMinimum = 0.1;
52const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4553
fdegansa696e5112015-04-17 01:57:5954} // namespace
fdegans1d16355162015-03-26 11:58:3455
Tsuyoshi Horof36fc4ef2019-10-16 10:02:1256const int FrameTreeNode::kFrameTreeNodeInvalidId = -1;
57
alexmose201c7cd2015-06-10 17:14:2158// This observer watches the opener of its owner FrameTreeNode and clears the
59// owner's opener if the opener is destroyed.
60class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
61 public:
jochen6004a362017-02-04 00:11:4062 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
63 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2164
65 // FrameTreeNode::Observer
66 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4067 if (observing_original_opener_) {
Avi Drissman36465f332017-09-11 20:49:3968 // The "original owner" is special. It's used for attribution, and clients
69 // walk down the original owner chain. Therefore, if a link in the chain
70 // is being destroyed, reconnect the observation to the parent of the link
71 // being destroyed.
jochen6004a362017-02-04 00:11:4072 CHECK_EQ(owner_->original_opener(), node);
Avi Drissman36465f332017-09-11 20:49:3973 owner_->SetOriginalOpener(node->original_opener());
74 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4075 } else {
76 CHECK_EQ(owner_->opener(), node);
77 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:3978 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4079 }
alexmose201c7cd2015-06-10 17:14:2180 }
81
82 private:
83 FrameTreeNode* owner_;
jochen6004a362017-02-04 00:11:4084 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2185
86 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
87};
88
vishal.b782eb5d2015-04-29 12:22:5789int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5590
dmazzonie950ea232015-03-13 21:39:4591// static
vishal.b782eb5d2015-04-29 12:22:5792FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1993 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1594 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:4695 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4596 return it == nodes->end() ? nullptr : it->second;
97}
98
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:5499FrameTreeNode::FrameTreeNode(
100 FrameTree* frame_tree,
101 Navigator* navigator,
102 FrameTreeNode* parent,
103 blink::WebTreeScopeType scope,
104 const std::string& name,
105 const std::string& unique_name,
106 bool is_created_by_script,
107 const base::UnguessableToken& devtools_frame_token,
108 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
109 blink::FrameOwnerElementType owner_type)
[email protected]bffc8302014-01-23 20:52:16110 : frame_tree_(frame_tree),
111 navigator_(navigator),
Lucas Furukawa Gadani72cc21c2018-09-04 18:50:46112 render_manager_(this, frame_tree->manager_delegate()),
[email protected]bffc8302014-01-23 20:52:16113 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59114 parent_(parent),
Bo Liua13e7c02018-03-28 22:24:02115 depth_(parent ? parent->depth_ + 1 : 0u),
alexmose201c7cd2015-06-10 17:14:21116 opener_(nullptr),
jochen6004a362017-02-04 00:11:40117 original_opener_(nullptr),
creisf0f069a2015-07-23 23:51:53118 has_committed_real_load_(false),
engedy6e2e0992017-05-25 18:58:42119 is_collapsed_(false),
estarka886b8d2015-12-18 21:53:08120 replication_state_(
121 scope,
122 name,
lukasza464d8692016-02-22 19:26:32123 unique_name,
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:37124 blink::mojom::InsecureRequestPolicy::
125 kLeaveInsecureRequestsAlone /* should enforce strict mixed content
126 checking */
127 ,
arthursonzogni4b62a5cb2018-01-17 14:14:26128 std::vector<uint32_t>()
129 /* hashes of hosts for insecure request upgrades */,
japhet61835ae12017-01-20 01:25:39130 false /* is a potentially trustworthy unique origin */,
Becca Hughes60af7d42017-12-12 10:53:15131 false /* has received a user gesture */,
Ehsan Karamad192a8da2018-10-21 03:48:08132 false /* has received a user gesture before nav */,
133 owner_type),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45134 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06135 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31136 frame_owner_properties_(frame_owner_properties),
Shubhie Panickerddf2a4e2018-03-06 00:09:06137 was_discarded_(false),
xiaochenghb9554bb2016-05-21 14:20:48138 blame_context_(frame_tree_node_id_, parent) {
rob97250742015-12-10 17:45:15139 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45140 g_frame_tree_node_id_map.Get().insert(
141 std::make_pair(frame_tree_node_id_, this));
142 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33143
xiaochenghb9554bb2016-05-21 14:20:48144 // Note: this should always be done last in the constructor.
145 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59146}
[email protected]9b159a52013-10-03 17:24:55147
148FrameTreeNode::~FrameTreeNode() {
Nasko Oskov252ae042018-10-04 21:44:12149 // Remove the children.
150 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45151
Nate Chapin22ea6592019-03-05 22:29:02152 current_frame_host()->ResetLoadingState();
153
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45154 // If the removed frame was created by a script, then its history entry will
155 // never be reused - we can save some memory by removing the history entry.
156 // See also https://crbug.com/784356.
157 if (is_created_by_script_ && parent_) {
158 NavigationEntryImpl* nav_entry = static_cast<NavigationEntryImpl*>(
159 navigator()->GetController()->GetLastCommittedEntry());
160 if (nav_entry) {
161 nav_entry->RemoveEntryForFrame(this,
162 /* only_if_different_position = */ false);
163 }
164 }
165
dmazzonie950ea232015-03-13 21:39:45166 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31167 for (auto& observer : observers_)
168 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21169
170 if (opener_)
171 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40172 if (original_opener_)
173 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45174
175 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18176
danakjf9400602019-06-07 15:44:58177 bool did_stop_loading = false;
178
jam39258caf2016-11-02 14:48:18179 if (navigation_request_) {
danakjf9400602019-06-07 15:44:58180 navigation_request_.reset();
Arthur Hemery0dd65812019-08-01 14:18:45181 // If a frame with a pending navigation is detached, make sure the
182 // WebContents (and its observers) update their loading state.
danakjf9400602019-06-07 15:44:58183 did_stop_loading = true;
jam39258caf2016-11-02 14:48:18184 }
Nate Chapin22ea6592019-03-05 22:29:02185
danakjf9400602019-06-07 15:44:58186 // ~SiteProcessCountTracker DCHECKs in some tests if the speculative
187 // RenderFrameHostImpl is not destroyed last. Ideally this would be closer to
188 // (possible before) the ResetLoadingState() call above.
189 //
190 // There is an inherent race condition causing bugs 838348/915179/et al, where
191 // the renderer may have committed the speculative main frame and the browser
192 // has not heard about it yet. If this is a main frame, then in that case the
193 // speculative RenderFrame was unable to be deleted (it is owned by the
194 // renderer) and we should not be able to cancel the navigation at this point.
195 // CleanUpNavigation() would normally be called here but it will try to undo
196 // the navigation and expose the race condition. When it replaces the main
197 // frame with a RenderFrameProxy, that leaks the committed main frame, leaving
198 // the frame and its friend group with pointers that will become invalid
199 // shortly as we are shutting everything down and deleting the RenderView etc.
200 // We avoid this problematic situation by not calling CleanUpNavigation() or
201 // DiscardUnusedFrame() here. The speculative RenderFrameHost is simply
202 // returned and deleted immediately. This satisfies the requirement that the
203 // speculative RenderFrameHost is removed from the RenderFrameHostManager
204 // before it is destroyed.
205 if (render_manager_.speculative_frame_host()) {
206 did_stop_loading |= render_manager_.speculative_frame_host()->is_loading();
207 render_manager_.UnsetSpeculativeRenderFrameHost();
208 }
209
210 if (did_stop_loading)
211 DidStopLoading();
212
Nate Chapin22ea6592019-03-05 22:29:02213 DCHECK(!IsLoading());
[email protected]9b159a52013-10-03 17:24:55214}
215
alexmose201c7cd2015-06-10 17:14:21216void FrameTreeNode::AddObserver(Observer* observer) {
217 observers_.AddObserver(observer);
218}
219
220void FrameTreeNode::RemoveObserver(Observer* observer) {
221 observers_.RemoveObserver(observer);
222}
223
[email protected]94d0cc12013-12-18 00:07:41224bool FrameTreeNode::IsMainFrame() const {
225 return frame_tree_->root() == this;
226}
227
Ian Clelland5cbaaf82017-11-27 22:00:03228void FrameTreeNode::ResetForNavigation() {
229 // Discard any CSP headers from the previous document.
230 replication_state_.accumulated_csp_headers.clear();
231 render_manager_.OnDidResetContentSecurityPolicy();
232
Ian Clellandedb8c5dd2018-03-01 17:01:37233 // Clear any CSP-set sandbox flags, and the declared feature policy for the
234 // frame.
arthursonzognib93a4472020-04-10 07:38:00235 UpdateFramePolicyHeaders(network::mojom::WebSandboxFlags::kNone, {});
Shivani Sharmac4f561582018-11-15 15:58:39236
Mustaq Ahmedc53e4c562019-01-29 19:05:09237 // This frame has had its user activation bits cleared in the renderer
238 // before arriving here. We just need to clear them here and in the other
239 // renderer processes that may have a reference to this frame.
Antonio Gomes4b2c5132020-01-16 11:49:48240 UpdateUserActivationState(
241 blink::mojom::UserActivationUpdateType::kClearActivation);
Ian Clelland5cbaaf82017-11-27 22:00:03242}
243
yilkal34a3d752019-08-30 18:20:30244size_t FrameTreeNode::GetFrameTreeSize() const {
245 if (is_collapsed())
246 return 0;
247
248 size_t size = 0;
249 for (size_t i = 0; i < child_count(); i++) {
250 size += child_at(i)->GetFrameTreeSize();
251 }
252
253 // Account for this node.
254 size++;
255 return size;
256}
257
alexmose201c7cd2015-06-10 17:14:21258void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
259 if (opener_) {
260 opener_->RemoveObserver(opener_observer_.get());
261 opener_observer_.reset();
262 }
263
264 opener_ = opener;
265
266 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55267 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21268 opener_->AddObserver(opener_observer_.get());
269 }
270}
271
jochen6004a362017-02-04 00:11:40272void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39273 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37274 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40275
Avi Drissman36465f332017-09-11 20:49:39276 if (original_opener_) {
277 original_opener_->RemoveObserver(original_opener_observer_.get());
278 original_opener_observer_.reset();
279 }
280
jochen6004a362017-02-04 00:11:40281 original_opener_ = opener;
282
283 if (original_opener_) {
jochen6004a362017-02-04 00:11:40284 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55285 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40286 original_opener_->AddObserver(original_opener_observer_.get());
287 }
288}
289
creisf0f069a2015-07-23 23:51:53290void FrameTreeNode::SetCurrentURL(const GURL& url) {
Balazs Engedyc8a7cccf2018-03-12 23:00:49291 if (!has_committed_real_load_ && !url.IsAboutBlank())
creisf0f069a2015-07-23 23:51:53292 has_committed_real_load_ = true;
Erik Chen173bf3042017-07-31 06:06:21293 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48294 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53295}
296
estarkbd8e26f2016-03-16 23:30:37297void FrameTreeNode::SetCurrentOrigin(
298 const url::Origin& origin,
299 bool is_potentially_trustworthy_unique_origin) {
300 if (!origin.IsSameOriginWith(replication_state_.origin) ||
301 replication_state_.has_potentially_trustworthy_unique_origin !=
302 is_potentially_trustworthy_unique_origin) {
303 render_manager_.OnDidUpdateOrigin(origin,
304 is_potentially_trustworthy_unique_origin);
305 }
alexmosa7a4ff822015-04-27 17:59:56306 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37307 replication_state_.has_potentially_trustworthy_unique_origin =
308 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56309}
alexmosbe2f4c32015-03-10 02:30:23310
engedy6e2e0992017-05-25 18:58:42311void FrameTreeNode::SetCollapsed(bool collapsed) {
312 DCHECK(!IsMainFrame());
313 if (is_collapsed_ == collapsed)
314 return;
315
316 is_collapsed_ = collapsed;
317 render_manager_.OnDidChangeCollapsedState(collapsed);
318}
319
lukasza464d8692016-02-22 19:26:32320void FrameTreeNode::SetFrameName(const std::string& name,
321 const std::string& unique_name) {
322 if (name == replication_state_.name) {
323 // |unique_name| shouldn't change unless |name| changes.
324 DCHECK_EQ(unique_name, replication_state_.unique_name);
325 return;
326 }
lukasza5140a412016-09-15 21:12:30327
328 if (parent()) {
329 // Non-main frames should have a non-empty unique name.
330 DCHECK(!unique_name.empty());
331 } else {
332 // Unique name of main frames should always stay empty.
333 DCHECK(unique_name.empty());
334 }
335
Daniel Cheng6ca7f1c92017-08-09 21:45:41336 // Note the unique name should only be able to change before the first real
337 // load is committed, but that's not strongly enforced here.
lukasza464d8692016-02-22 19:26:32338 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56339 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32340 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23341}
342
arthursonzogni662aa652017-03-28 11:09:50343void FrameTreeNode::AddContentSecurityPolicies(
arthursonzogni35a95c72020-01-15 17:49:43344 std::vector<network::mojom::ContentSecurityPolicyHeaderPtr> headers) {
345 for (auto& header : headers)
346 replication_state_.accumulated_csp_headers.push_back(*header);
347 render_manager_.OnDidAddContentSecurityPolicies(std::move(headers));
lukasza8e1c02e42016-05-17 20:05:10348}
349
mkwstf672e7ef2016-06-09 20:51:07350void FrameTreeNode::SetInsecureRequestPolicy(
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:37351 blink::mojom::InsecureRequestPolicy policy) {
mkwstf672e7ef2016-06-09 20:51:07352 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08353 return;
mkwstf672e7ef2016-06-09 20:51:07354 render_manager_.OnEnforceInsecureRequestPolicy(policy);
355 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08356}
357
arthursonzogni4b62a5cb2018-01-17 14:14:26358void FrameTreeNode::SetInsecureNavigationsSet(
359 const std::vector<uint32_t>& insecure_navigations_set) {
360 DCHECK(std::is_sorted(insecure_navigations_set.begin(),
361 insecure_navigations_set.end()));
362 if (insecure_navigations_set == replication_state_.insecure_navigations_set)
363 return;
364 render_manager_.OnEnforceInsecureNavigationsSet(insecure_navigations_set);
365 replication_state_.insecure_navigations_set = insecure_navigations_set;
366}
367
Luna Luc3fdacdf2017-11-08 04:48:53368void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Ian Clellandcdc4f312017-10-13 22:24:12369 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
Dave Tapuska9b153a942020-02-10 19:35:10370 pending_frame_policy_.disallow_document_access =
371 frame_policy.disallow_document_access;
alexmos6e940102016-01-19 22:47:25372
Ian Clellandcdc4f312017-10-13 22:24:12373 if (parent()) {
374 // Subframes should always inherit their parent's sandbox flags.
Ian Clelland5cbaaf82017-11-27 22:00:03375 pending_frame_policy_.sandbox_flags |= parent()->active_sandbox_flags();
Charlie Hue1b77ac2019-12-13 21:30:17376 // This is only applied on subframes; container policy and required document
377 // policy are not mutable on main frame.
Ian Clellandcdc4f312017-10-13 22:24:12378 pending_frame_policy_.container_policy = frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17379 pending_frame_policy_.required_document_policy =
380 frame_policy.required_document_policy;
Ian Clellandcdc4f312017-10-13 22:24:12381 }
iclelland92f8c0b2017-04-19 12:43:05382}
383
alexmos9f8705a2015-05-06 19:58:59384FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39385 return GetSibling(-1);
386}
alexmos9f8705a2015-05-06 19:58:59387
paulmeyer322777fb2016-05-16 23:15:39388FrameTreeNode* FrameTreeNode::NextSibling() const {
389 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59390}
391
fdegans4a49ce932015-03-12 17:11:37392bool FrameTreeNode::IsLoading() const {
393 RenderFrameHostImpl* current_frame_host =
394 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37395
396 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39397
clamy610c63b32017-12-22 15:05:18398 if (navigation_request_)
399 return true;
clamy11e11512015-07-07 16:42:17400
clamy610c63b32017-12-22 15:05:18401 RenderFrameHostImpl* speculative_frame_host =
402 render_manager_.speculative_frame_host();
403 if (speculative_frame_host && speculative_frame_host->is_loading())
404 return true;
fdegans4a49ce932015-03-12 17:11:37405 return current_frame_host->is_loading();
406}
407
Charlie Hu5ffc0152019-12-06 15:59:53408bool FrameTreeNode::CommitFramePolicy(
409 const blink::FramePolicy& new_frame_policy) {
410 bool did_change_flags = new_frame_policy.sandbox_flags !=
Ian Clellandcdc4f312017-10-13 22:24:12411 replication_state_.frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05412 bool did_change_container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53413 new_frame_policy.container_policy !=
Ian Clellandcdc4f312017-10-13 22:24:12414 replication_state_.frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17415 bool did_change_required_document_policy =
416 pending_frame_policy_.required_document_policy !=
417 replication_state_.frame_policy.required_document_policy;
Dave Tapuska9b153a942020-02-10 19:35:10418 bool did_change_document_access =
419 new_frame_policy.disallow_document_access !=
420 replication_state_.frame_policy.disallow_document_access;
iclelland92f8c0b2017-04-19 12:43:05421 if (did_change_flags)
Ian Clellandcdc4f312017-10-13 22:24:12422 replication_state_.frame_policy.sandbox_flags =
Charlie Hu5ffc0152019-12-06 15:59:53423 new_frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05424 if (did_change_container_policy)
Ian Clellandcdc4f312017-10-13 22:24:12425 replication_state_.frame_policy.container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53426 new_frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17427 if (did_change_required_document_policy)
428 replication_state_.frame_policy.required_document_policy =
429 new_frame_policy.required_document_policy;
Dave Tapuska9b153a942020-02-10 19:35:10430 if (did_change_document_access)
431 replication_state_.frame_policy.disallow_document_access =
432 new_frame_policy.disallow_document_access;
Charlie Hue1b77ac2019-12-13 21:30:17433
Charlie Hu5ffc0152019-12-06 15:59:53434 UpdateFramePolicyHeaders(new_frame_policy.sandbox_flags,
Ian Clellandedb8c5dd2018-03-01 17:01:37435 replication_state_.feature_policy_header);
Charlie Hue1b77ac2019-12-13 21:30:17436 return did_change_flags || did_change_container_policy ||
Dave Tapuska9b153a942020-02-10 19:35:10437 did_change_required_document_policy || did_change_document_access;
alexmos6b294562015-03-05 19:24:10438}
439
Arthur Hemeryc3380172018-01-22 14:00:17440void FrameTreeNode::TransferNavigationRequestOwnership(
441 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59442 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17443 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
444}
445
carloskc49005eb2015-06-16 11:25:07446void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57447 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37448 // This is never called when navigating to a Javascript URL. For the loading
449 // state, this matches what Blink is doing: Blink doesn't send throbber
450 // notifications for Javascript URLS.
451 DCHECK(!navigation_request->common_params().url.SchemeIs(
452 url::kJavaScriptScheme));
453
clamy44e84ce2016-02-22 15:38:25454 bool was_previously_loading = frame_tree()->IsLoading();
455
clamy82a2f4d2016-02-02 14:20:41456 // There's no need to reset the state: there's still an ongoing load, and the
457 // RenderFrameHostManager will take care of updates to the speculative
458 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05459 if (was_previously_loading) {
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31460 if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
jamcd0b7b22017-03-24 22:13:05461 // Mark the old request as aborted.
Mohamed Abdelhalimb4db22a2019-06-18 10:46:52462 navigation_request_->set_net_error(net::ERR_ABORTED);
jamcd0b7b22017-03-24 22:13:05463 }
Arthur Hemery241b9392019-10-24 11:08:41464 ResetNavigationRequest(true);
jamcd0b7b22017-03-24 22:13:05465 }
clamy44e84ce2016-02-22 15:38:25466
467 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06468 if (was_discarded_) {
469 navigation_request_->set_was_discarded();
470 was_discarded_ = false;
471 }
clamy8e2e299202016-04-05 11:44:59472 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39473
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51474 bool to_different_document = !NavigationTypeUtils::IsSameDocument(
arthursonzogni92f18682017-02-08 23:00:04475 navigation_request_->common_params().navigation_type);
476
477 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16478}
479
Arthur Hemery241b9392019-10-24 11:08:41480void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
fdegans39ff0382015-04-29 19:04:39481 if (!navigation_request_)
482 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23483
Andrey Kosyakovf2d4ff72018-10-29 20:09:59484 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
clamydcb434c12015-04-16 19:29:16485 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39486
clamy82a2f4d2016-02-02 14:20:41487 if (keep_state)
fdegans39ff0382015-04-29 19:04:39488 return;
489
clamy82a2f4d2016-02-02 14:20:41490 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
491 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39492 DidStopLoading();
493 render_manager_.CleanUpNavigation();
clamydcb434c12015-04-16 19:29:16494}
495
clamy44e84ce2016-02-22 15:38:25496void FrameTreeNode::DidStartLoading(bool to_different_document,
497 bool was_previously_loading) {
Camille Lamyefd54b02018-10-04 16:54:14498 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
499 "frame_tree_node", frame_tree_node_id(), "to different document",
500 to_different_document);
fdegansa696e5112015-04-17 01:57:59501 // Any main frame load to a new document should reset the load progress since
502 // it will replace the current page and any frames. The WebContents will
503 // be notified when DidChangeLoadProgress is called.
504 if (to_different_document && IsMainFrame())
505 frame_tree_->ResetLoadProgress();
506
507 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25508 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59509 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
510
511 // Set initial load progress and update overall progress. This will notify
512 // the WebContents of the load progress change.
513 DidChangeLoadProgress(kLoadingProgressMinimum);
514
515 // Notify the RenderFrameHostManager of the event.
516 render_manager()->OnDidStartLoading();
517}
518
519void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14520 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
521 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59522 // Set final load progress and update overall progress. This will notify
523 // the WebContents of the load progress change.
524 DidChangeLoadProgress(kLoadingProgressDone);
525
Lucas Furukawa Gadani6faef602019-05-06 21:16:03526 // Notify the RenderFrameHostManager of the event.
527 render_manager()->OnDidStopLoading();
528
fdegansa696e5112015-04-17 01:57:59529 // Notify the WebContents.
530 if (!frame_tree_->IsLoading())
531 navigator()->GetDelegate()->DidStopLoading();
fdegansa696e5112015-04-17 01:57:59532}
533
534void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Nate Chapin93536702018-02-07 00:12:21535 DCHECK_GE(load_progress, kLoadingProgressMinimum);
536 DCHECK_LE(load_progress, kLoadingProgressDone);
537 if (IsMainFrame())
538 frame_tree_->UpdateLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59539}
540
clamyf73862c42015-07-08 12:31:33541bool FrameTreeNode::StopLoading() {
arthursonzogni66f711c2019-10-08 14:40:36542 if (navigation_request_ && navigation_request_->IsNavigationStarted())
543 navigation_request_->set_net_error(net::ERR_ABORTED);
Arthur Hemery241b9392019-10-24 11:08:41544 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33545
546 // TODO(nasko): see if child frames should send IPCs in site-per-process
547 // mode.
548 if (!IsMainFrame())
549 return true;
550
551 render_manager_.Stop();
552 return true;
553}
554
alexmos21acae52015-11-07 01:04:43555void FrameTreeNode::DidFocus() {
556 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31557 for (auto& observer : observers_)
558 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43559}
560
clamy44e84ce2016-02-22 15:38:25561void FrameTreeNode::BeforeUnloadCanceled() {
562 // TODO(clamy): Support BeforeUnload in subframes.
563 if (!IsMainFrame())
564 return;
565
566 RenderFrameHostImpl* current_frame_host =
567 render_manager_.current_frame_host();
568 DCHECK(current_frame_host);
569 current_frame_host->ResetLoadingState();
570
clamy610c63b32017-12-22 15:05:18571 RenderFrameHostImpl* speculative_frame_host =
572 render_manager_.speculative_frame_host();
573 if (speculative_frame_host)
574 speculative_frame_host->ResetLoadingState();
575 // Note: there is no need to set an error code on the NavigationHandle here
576 // as it has not been created yet. It is only created when the
Antonio Gomes8678a202020-03-02 20:03:25577 // BeforeUnloadCompleted callback is invoked.
clamy610c63b32017-12-22 15:05:18578 if (navigation_request_)
Arthur Hemery241b9392019-10-24 11:08:41579 ResetNavigationRequest(false);
clamy44e84ce2016-02-22 15:38:25580}
581
Mustaq Ahmedc4cb7162018-06-05 16:28:36582bool FrameTreeNode::NotifyUserActivation() {
Alexander Timina1dfadaa2020-04-28 13:30:06583 for (RenderFrameHostImpl* rfh = current_frame_host(); rfh;
584 rfh = rfh->GetParent()) {
585 if (!rfh->frame_tree_node()->user_activation_state_.HasBeenActive())
586 rfh->DidReceiveFirstUserActivation();
587 rfh->frame_tree_node()->user_activation_state_.Activate();
John Delaneyedd8d6c2019-01-25 00:23:57588 }
japhet61835ae12017-01-20 01:25:39589 replication_state_.has_received_user_gesture = true;
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14590
Mustaq Ahmed0180320f2019-03-21 16:07:01591 // See the "Same-origin Visibility" section in |UserActivationState| class
592 // doc.
Mustaq Ahmede5f12562019-10-30 18:02:03593 if (base::FeatureList::IsEnabled(
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14594 features::kUserActivationSameOriginVisibility)) {
595 const url::Origin& current_origin =
596 this->current_frame_host()->GetLastCommittedOrigin();
597 for (FrameTreeNode* node : frame_tree()->Nodes()) {
598 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
599 current_origin)) {
600 node->user_activation_state_.Activate();
601 }
602 }
603 }
604
Shivani Sharma20749e922019-03-11 17:00:26605 NavigationControllerImpl* controller =
606 static_cast<NavigationControllerImpl*>(navigator()->GetController());
607 if (controller)
608 controller->NotifyUserActivation();
Shivani Sharma194877032019-03-07 17:52:47609
Mustaq Ahmedc4cb7162018-06-05 16:28:36610 return true;
611}
612
613bool FrameTreeNode::ConsumeTransientUserActivation() {
614 bool was_active = user_activation_state_.IsActive();
615 for (FrameTreeNode* node : frame_tree()->Nodes())
616 node->user_activation_state_.ConsumeIfActive();
617 return was_active;
618}
619
Shivani Sharmac4f561582018-11-15 15:58:39620bool FrameTreeNode::ClearUserActivation() {
Shivani Sharmac4f561582018-11-15 15:58:39621 for (FrameTreeNode* node : frame_tree()->SubtreeNodes(this))
622 node->user_activation_state_.Clear();
623 return true;
624}
625
Ella Ge9caed612019-08-09 16:17:25626bool FrameTreeNode::VerifyUserActivation() {
Ella Gea78f6772019-12-11 10:35:25627 DCHECK(base::FeatureList::IsEnabled(
628 features::kBrowserVerifiedUserActivationMouse) ||
629 base::FeatureList::IsEnabled(
630 features::kBrowserVerifiedUserActivationKeyboard));
631
Ella Ge9caed612019-08-09 16:17:25632 return render_manager_.current_frame_host()
633 ->GetRenderWidgetHost()
Mustaq Ahmed83bb1722019-10-22 20:00:10634 ->RemovePendingUserActivationIfAvailable();
Ella Ge9caed612019-08-09 16:17:25635}
636
Mustaq Ahmedc4cb7162018-06-05 16:28:36637bool FrameTreeNode::UpdateUserActivationState(
Antonio Gomes4b2c5132020-01-16 11:49:48638 blink::mojom::UserActivationUpdateType update_type) {
Ella Ge9caed612019-08-09 16:17:25639 bool update_result = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36640 switch (update_type) {
Antonio Gomes4b2c5132020-01-16 11:49:48641 case blink::mojom::UserActivationUpdateType::kConsumeTransientActivation:
Ella Ge9caed612019-08-09 16:17:25642 update_result = ConsumeTransientUserActivation();
643 break;
Antonio Gomes4b2c5132020-01-16 11:49:48644 case blink::mojom::UserActivationUpdateType::kNotifyActivation:
Ella Ge9caed612019-08-09 16:17:25645 update_result = NotifyUserActivation();
646 break;
Antonio Gomes4b2c5132020-01-16 11:49:48647 case blink::mojom::UserActivationUpdateType::
Ella Ge9caed612019-08-09 16:17:25648 kNotifyActivationPendingBrowserVerification:
649 if (VerifyUserActivation()) {
650 update_result = NotifyUserActivation();
Antonio Gomes4b2c5132020-01-16 11:49:48651 update_type = blink::mojom::UserActivationUpdateType::kNotifyActivation;
Ella Ge9caed612019-08-09 16:17:25652 } else {
653 // TODO(crbug.com/848778): We need to decide what to do when user
654 // activation verification failed. NOTREACHED here will make all
655 // unrelated tests that inject event to renderer fail.
656 return false;
657 }
658 break;
Antonio Gomes4b2c5132020-01-16 11:49:48659 case blink::mojom::UserActivationUpdateType::kClearActivation:
Ella Ge9caed612019-08-09 16:17:25660 update_result = ClearUserActivation();
661 break;
Mustaq Ahmedc4cb7162018-06-05 16:28:36662 }
Ella Ge9caed612019-08-09 16:17:25663 render_manager_.UpdateUserActivationState(update_type);
664 return update_result;
japhet61835ae12017-01-20 01:25:39665}
666
Mustaq Ahmed01261742019-12-16 15:49:06667void FrameTreeNode::OnSetHadStickyUserActivationBeforeNavigation(bool value) {
668 render_manager_.OnSetHadStickyUserActivationBeforeNavigation(value);
Becca Hughes60af7d42017-12-12 10:53:15669 replication_state_.has_received_user_gesture_before_nav = value;
670}
671
paulmeyer322777fb2016-05-16 23:15:39672FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19673 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39674 return nullptr;
675
676 for (size_t i = 0; i < parent_->child_count(); ++i) {
677 if (parent_->child_at(i) == this) {
678 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
679 i + relative_offset >= parent_->child_count()) {
680 return nullptr;
681 }
682 return parent_->child_at(i + relative_offset);
683 }
684 }
685
686 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
687 return nullptr;
688}
689
Ian Clellandedb8c5dd2018-03-01 17:01:37690void FrameTreeNode::UpdateFramePolicyHeaders(
arthursonzognib93a4472020-04-10 07:38:00691 network::mojom::WebSandboxFlags sandbox_flags,
Ian Clellandedb8c5dd2018-03-01 17:01:37692 const blink::ParsedFeaturePolicy& parsed_header) {
693 bool changed = false;
694 if (replication_state_.feature_policy_header != parsed_header) {
695 replication_state_.feature_policy_header = parsed_header;
696 changed = true;
697 }
Ian Clelland5cbaaf82017-11-27 22:00:03698 // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the
699 // currently effective sandbox flags from the frame. https://crbug.com/740556
arthursonzognib93a4472020-04-10 07:38:00700 network::mojom::WebSandboxFlags updated_flags =
Ian Clelland5cbaaf82017-11-27 22:00:03701 sandbox_flags | effective_frame_policy().sandbox_flags;
Ian Clellandedb8c5dd2018-03-01 17:01:37702 if (replication_state_.active_sandbox_flags != updated_flags) {
703 replication_state_.active_sandbox_flags = updated_flags;
704 changed = true;
705 }
706 // Notify any proxies if the policies have been changed.
707 if (changed)
708 render_manager()->OnDidSetFramePolicyHeaders();
Ian Clelland5cbaaf82017-11-27 22:00:03709}
710
Lan Weif0cb8e6e2019-04-19 00:14:53711void FrameTreeNode::TransferUserActivationFrom(
712 RenderFrameHostImpl* source_rfh) {
713 user_activation_state_.TransferFrom(
714 source_rfh->frame_tree_node()->user_activation_state_);
715
716 // Notify proxies in non-source and non-target renderer processes to
717 // transfer the activation state from the source proxy to the target
718 // so the user activation state of those proxies matches the source
719 // renderer and the target renderer (which are separately updated).
720 render_manager_.TransferUserActivationFrom(source_rfh);
Lan Wei550671a22019-03-19 00:59:24721}
722
Arthur Sonzognif8840b92018-11-07 14:10:35723void FrameTreeNode::PruneChildFrameNavigationEntries(
724 NavigationEntryImpl* entry) {
725 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
726 FrameTreeNode* child = current_frame_host()->child_at(i);
727 if (child->is_created_by_script_) {
728 entry->RemoveEntryForFrame(child,
729 /* only_if_different_position = */ false);
730 } else {
731 child->PruneChildFrameNavigationEntries(entry);
732 }
733 }
734}
735
Ehsan Karamad39407082019-02-19 23:38:19736void FrameTreeNode::SetOpenerFeaturePolicyState(
737 const blink::FeaturePolicy::FeatureState& feature_state) {
738 DCHECK(IsMainFrame());
739 if (base::FeatureList::IsEnabled(features::kFeaturePolicyForSandbox)) {
740 replication_state_.opener_feature_state = feature_state;
741 }
742}
743
Yao Xiao24ec9aa2020-01-28 16:36:00744void FrameTreeNode::SetAdFrameType(blink::mojom::AdFrameType ad_frame_type) {
745 DCHECK_NE(ad_frame_type, blink::mojom::AdFrameType::kNonAd);
746 if (replication_state_.ad_frame_type == blink::mojom::AdFrameType::kNonAd) {
747 replication_state_.ad_frame_type = ad_frame_type;
748 render_manager()->OnDidSetAdFrameType(ad_frame_type);
749 } else {
750 DCHECK_EQ(ad_frame_type, replication_state_.ad_frame_type);
751 }
752}
753
[email protected]9b159a52013-10-03 17:24:55754} // namespace content