blob: c036cc99c72c7e70e1919187b4c4e0d4fb357be5 [file] [log] [blame]
[email protected]9b159a52013-10-03 17:24:551// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_host/frame_tree_node.h"
[email protected]9b159a52013-10-03 17:24:556
Daniel Cheng6ca7f1c92017-08-09 21:45:417#include <math.h>
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"
Liviu Tintad9391fb92020-09-28 23:50:0716#include "base/metrics/histogram_functions.h"
dcheng23ca947d2016-05-04 20:04:1517#include "base/metrics/histogram_macros.h"
[email protected]9b159a52013-10-03 17:24:5518#include "base/stl_util.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4119#include "base/strings/string_util.h"
Andrey Kosyakovf2d4ff72018-10-29 20:09:5920#include "content/browser/devtools/devtools_instrumentation.h"
danakjc492bf82020-09-09 20:02:4421#include "content/browser/renderer_host/navigation_controller_impl.h"
22#include "content/browser/renderer_host/navigation_request.h"
23#include "content/browser/renderer_host/navigator.h"
24#include "content/browser/renderer_host/navigator_delegate.h"
25#include "content/browser/renderer_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4126#include "content/browser/renderer_host/render_view_host_impl.h"
clamyf73862c42015-07-08 12:31:3327#include "content/common/frame_messages.h"
Lucas Furukawa Gadanief8290a2019-07-29 20:27:5128#include "content/common/navigation_params.h"
29#include "content/common/navigation_params_utils.h"
dmazzonie950ea232015-03-13 21:39:4530#include "content/public/browser/browser_thread.h"
Mustaq Ahmeda5dfa60b2018-12-08 00:30:1431#include "content/public/common/content_features.h"
Arthur Sonzognif21fb512018-11-06 09:31:5832#include "content/public/common/navigation_policy.h"
arthursonzognib93a4472020-04-10 07:38:0033#include "services/network/public/cpp/web_sandbox_flags.h"
34#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
Antonio Gomes4b2c5132020-01-16 11:49:4835#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:3736#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
[email protected]9b159a52013-10-03 17:24:5537
38namespace content {
39
dmazzonie950ea232015-03-13 21:39:4540namespace {
41
42// This is a global map between frame_tree_node_ids and pointers to
43// FrameTreeNodes.
Takuto Ikutaadf31eb2019-01-05 00:32:4844typedef std::unordered_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4545
scottmg5e65e3a2017-03-08 08:48:4646base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
47 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4548
fdegansa696e5112015-04-17 01:57:5949// These values indicate the loading progress status. The minimum progress
50// value matches what Blink's ProgressTracker has traditionally used for a
51// minimum progress value.
fdegansa696e5112015-04-17 01:57:5952const double kLoadingProgressMinimum = 0.1;
53const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4554
fdegansa696e5112015-04-17 01:57:5955} // namespace
fdegans1d16355162015-03-26 11:58:3456
Tsuyoshi Horof36fc4ef2019-10-16 10:02:1257const int FrameTreeNode::kFrameTreeNodeInvalidId = -1;
58
alexmose201c7cd2015-06-10 17:14:2159// This observer watches the opener of its owner FrameTreeNode and clears the
60// owner's opener if the opener is destroyed.
61class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
62 public:
jochen6004a362017-02-04 00:11:4063 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
64 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2165
66 // FrameTreeNode::Observer
67 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4068 if (observing_original_opener_) {
Avi Drissman36465f332017-09-11 20:49:3969 // The "original owner" is special. It's used for attribution, and clients
70 // walk down the original owner chain. Therefore, if a link in the chain
71 // is being destroyed, reconnect the observation to the parent of the link
72 // being destroyed.
jochen6004a362017-02-04 00:11:4073 CHECK_EQ(owner_->original_opener(), node);
Avi Drissman36465f332017-09-11 20:49:3974 owner_->SetOriginalOpener(node->original_opener());
75 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4076 } else {
77 CHECK_EQ(owner_->opener(), node);
78 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:3979 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:4080 }
alexmose201c7cd2015-06-10 17:14:2181 }
82
83 private:
84 FrameTreeNode* owner_;
jochen6004a362017-02-04 00:11:4085 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2186
87 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
88};
89
vishal.b782eb5d2015-04-29 12:22:5790int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5591
dmazzonie950ea232015-03-13 21:39:4592// static
vishal.b782eb5d2015-04-29 12:22:5793FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1994 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1595 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
jdoerrie55ec69d2018-10-08 13:34:4696 auto it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4597 return it == nodes->end() ? nullptr : it->second;
98}
99
Alexander Timin381e7e182020-04-28 19:04:03100// static
101FrameTreeNode* FrameTreeNode::From(RenderFrameHost* rfh) {
102 if (!rfh)
103 return nullptr;
104 return static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
105}
106
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54107FrameTreeNode::FrameTreeNode(
108 FrameTree* frame_tree,
Alexander Timin381e7e182020-04-28 19:04:03109 RenderFrameHostImpl* parent,
Antonio Gomes9d5c1ef2020-04-30 20:56:41110 blink::mojom::TreeScopeType scope,
Julie Jeongeun Kim70a2e4e2020-02-21 05:09:54111 const std::string& name,
112 const std::string& unique_name,
113 bool is_created_by_script,
114 const base::UnguessableToken& devtools_frame_token,
115 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
Antonio Gomes58d38062020-04-30 01:50:14116 blink::mojom::FrameOwnerElementType owner_type)
[email protected]bffc8302014-01-23 20:52:16117 : frame_tree_(frame_tree),
Lucas Furukawa Gadani72cc21c2018-09-04 18:50:46118 render_manager_(this, frame_tree->manager_delegate()),
[email protected]bffc8302014-01-23 20:52:16119 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59120 parent_(parent),
Alexander Timin381e7e182020-04-28 19:04:03121 depth_(parent ? parent->frame_tree_node()->depth_ + 1 : 0u),
alexmose201c7cd2015-06-10 17:14:21122 opener_(nullptr),
jochen6004a362017-02-04 00:11:40123 original_opener_(nullptr),
creisf0f069a2015-07-23 23:51:53124 has_committed_real_load_(false),
engedy6e2e0992017-05-25 18:58:42125 is_collapsed_(false),
estarka886b8d2015-12-18 21:53:08126 replication_state_(
127 scope,
128 name,
lukasza464d8692016-02-22 19:26:32129 unique_name,
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:37130 blink::mojom::InsecureRequestPolicy::
131 kLeaveInsecureRequestsAlone /* should enforce strict mixed content
132 checking */
133 ,
arthursonzogni4b62a5cb2018-01-17 14:14:26134 std::vector<uint32_t>()
135 /* hashes of hosts for insecure request upgrades */,
japhet61835ae12017-01-20 01:25:39136 false /* is a potentially trustworthy unique origin */,
danakj359a4342020-05-29 20:38:39137 false /* has an active user gesture */,
Ehsan Karamad192a8da2018-10-21 03:48:08138 false /* has received a user gesture before nav */,
139 owner_type),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45140 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06141 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31142 frame_owner_properties_(frame_owner_properties),
Shubhie Panickerddf2a4e2018-03-06 00:09:06143 was_discarded_(false),
Alexander Timin381e7e182020-04-28 19:04:03144 blame_context_(frame_tree_node_id_, FrameTreeNode::From(parent)) {
rob97250742015-12-10 17:45:15145 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45146 g_frame_tree_node_id_map.Get().insert(
147 std::make_pair(frame_tree_node_id_, this));
148 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33149
xiaochenghb9554bb2016-05-21 14:20:48150 // Note: this should always be done last in the constructor.
151 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59152}
[email protected]9b159a52013-10-03 17:24:55153
154FrameTreeNode::~FrameTreeNode() {
Nasko Oskov252ae042018-10-04 21:44:12155 // Remove the children.
156 current_frame_host()->ResetChildren();
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45157
Nate Chapin22ea6592019-03-05 22:29:02158 current_frame_host()->ResetLoadingState();
159
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45160 // If the removed frame was created by a script, then its history entry will
161 // never be reused - we can save some memory by removing the history entry.
162 // See also https://crbug.com/784356.
163 if (is_created_by_script_ && parent_) {
164 NavigationEntryImpl* nav_entry = static_cast<NavigationEntryImpl*>(
Fergal Daly09d6c762020-05-29 02:05:18165 navigator().GetController()->GetLastCommittedEntry());
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45166 if (nav_entry) {
167 nav_entry->RemoveEntryForFrame(this,
168 /* only_if_different_position = */ false);
169 }
170 }
171
dmazzonie950ea232015-03-13 21:39:45172 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31173 for (auto& observer : observers_)
174 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21175
176 if (opener_)
177 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40178 if (original_opener_)
179 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45180
181 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18182
danakjf9400602019-06-07 15:44:58183 bool did_stop_loading = false;
184
jam39258caf2016-11-02 14:48:18185 if (navigation_request_) {
danakjf9400602019-06-07 15:44:58186 navigation_request_.reset();
Arthur Hemery0dd65812019-08-01 14:18:45187 // If a frame with a pending navigation is detached, make sure the
188 // WebContents (and its observers) update their loading state.
danakjf9400602019-06-07 15:44:58189 did_stop_loading = true;
jam39258caf2016-11-02 14:48:18190 }
Nate Chapin22ea6592019-03-05 22:29:02191
danakjf9400602019-06-07 15:44:58192 // ~SiteProcessCountTracker DCHECKs in some tests if the speculative
193 // RenderFrameHostImpl is not destroyed last. Ideally this would be closer to
194 // (possible before) the ResetLoadingState() call above.
195 //
196 // There is an inherent race condition causing bugs 838348/915179/et al, where
197 // the renderer may have committed the speculative main frame and the browser
198 // has not heard about it yet. If this is a main frame, then in that case the
199 // speculative RenderFrame was unable to be deleted (it is owned by the
200 // renderer) and we should not be able to cancel the navigation at this point.
201 // CleanUpNavigation() would normally be called here but it will try to undo
202 // the navigation and expose the race condition. When it replaces the main
203 // frame with a RenderFrameProxy, that leaks the committed main frame, leaving
204 // the frame and its friend group with pointers that will become invalid
205 // shortly as we are shutting everything down and deleting the RenderView etc.
206 // We avoid this problematic situation by not calling CleanUpNavigation() or
207 // DiscardUnusedFrame() here. The speculative RenderFrameHost is simply
208 // returned and deleted immediately. This satisfies the requirement that the
209 // speculative RenderFrameHost is removed from the RenderFrameHostManager
210 // before it is destroyed.
211 if (render_manager_.speculative_frame_host()) {
212 did_stop_loading |= render_manager_.speculative_frame_host()->is_loading();
213 render_manager_.UnsetSpeculativeRenderFrameHost();
214 }
215
216 if (did_stop_loading)
217 DidStopLoading();
218
Nate Chapin22ea6592019-03-05 22:29:02219 DCHECK(!IsLoading());
[email protected]9b159a52013-10-03 17:24:55220}
221
alexmose201c7cd2015-06-10 17:14:21222void FrameTreeNode::AddObserver(Observer* observer) {
223 observers_.AddObserver(observer);
224}
225
226void FrameTreeNode::RemoveObserver(Observer* observer) {
227 observers_.RemoveObserver(observer);
228}
229
[email protected]94d0cc12013-12-18 00:07:41230bool FrameTreeNode::IsMainFrame() const {
231 return frame_tree_->root() == this;
232}
233
Ian Clelland5cbaaf82017-11-27 22:00:03234void FrameTreeNode::ResetForNavigation() {
235 // Discard any CSP headers from the previous document.
236 replication_state_.accumulated_csp_headers.clear();
237 render_manager_.OnDidResetContentSecurityPolicy();
238
Ian Clellandedb8c5dd2018-03-01 17:01:37239 // Clear any CSP-set sandbox flags, and the declared feature policy for the
240 // frame.
arthursonzognib93a4472020-04-10 07:38:00241 UpdateFramePolicyHeaders(network::mojom::WebSandboxFlags::kNone, {});
Shivani Sharmac4f561582018-11-15 15:58:39242
Mustaq Ahmedc53e4c562019-01-29 19:05:09243 // This frame has had its user activation bits cleared in the renderer
244 // before arriving here. We just need to clear them here and in the other
245 // renderer processes that may have a reference to this frame.
Antonio Gomes4b2c5132020-01-16 11:49:48246 UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11247 blink::mojom::UserActivationUpdateType::kClearActivation,
248 blink::mojom::UserActivationNotificationType::kNone);
Ian Clelland5cbaaf82017-11-27 22:00:03249}
250
yilkal34a3d752019-08-30 18:20:30251size_t FrameTreeNode::GetFrameTreeSize() const {
252 if (is_collapsed())
253 return 0;
254
255 size_t size = 0;
256 for (size_t i = 0; i < child_count(); i++) {
257 size += child_at(i)->GetFrameTreeSize();
258 }
259
260 // Account for this node.
261 size++;
262 return size;
263}
264
alexmose201c7cd2015-06-10 17:14:21265void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
266 if (opener_) {
267 opener_->RemoveObserver(opener_observer_.get());
268 opener_observer_.reset();
269 }
270
271 opener_ = opener;
272
273 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55274 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21275 opener_->AddObserver(opener_observer_.get());
276 }
277}
278
jochen6004a362017-02-04 00:11:40279void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39280 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37281 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40282
Avi Drissman36465f332017-09-11 20:49:39283 if (original_opener_) {
284 original_opener_->RemoveObserver(original_opener_observer_.get());
285 original_opener_observer_.reset();
286 }
287
jochen6004a362017-02-04 00:11:40288 original_opener_ = opener;
289
290 if (original_opener_) {
jochen6004a362017-02-04 00:11:40291 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55292 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40293 original_opener_->AddObserver(original_opener_observer_.get());
294 }
295}
296
creisf0f069a2015-07-23 23:51:53297void FrameTreeNode::SetCurrentURL(const GURL& url) {
Balazs Engedyc8a7cccf2018-03-12 23:00:49298 if (!has_committed_real_load_ && !url.IsAboutBlank())
creisf0f069a2015-07-23 23:51:53299 has_committed_real_load_ = true;
Erik Chen173bf3042017-07-31 06:06:21300 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48301 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53302}
303
estarkbd8e26f2016-03-16 23:30:37304void FrameTreeNode::SetCurrentOrigin(
305 const url::Origin& origin,
306 bool is_potentially_trustworthy_unique_origin) {
307 if (!origin.IsSameOriginWith(replication_state_.origin) ||
308 replication_state_.has_potentially_trustworthy_unique_origin !=
309 is_potentially_trustworthy_unique_origin) {
310 render_manager_.OnDidUpdateOrigin(origin,
311 is_potentially_trustworthy_unique_origin);
312 }
alexmosa7a4ff822015-04-27 17:59:56313 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37314 replication_state_.has_potentially_trustworthy_unique_origin =
315 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56316}
alexmosbe2f4c32015-03-10 02:30:23317
engedy6e2e0992017-05-25 18:58:42318void FrameTreeNode::SetCollapsed(bool collapsed) {
319 DCHECK(!IsMainFrame());
320 if (is_collapsed_ == collapsed)
321 return;
322
323 is_collapsed_ = collapsed;
324 render_manager_.OnDidChangeCollapsedState(collapsed);
325}
326
lukasza464d8692016-02-22 19:26:32327void FrameTreeNode::SetFrameName(const std::string& name,
328 const std::string& unique_name) {
329 if (name == replication_state_.name) {
330 // |unique_name| shouldn't change unless |name| changes.
331 DCHECK_EQ(unique_name, replication_state_.unique_name);
332 return;
333 }
lukasza5140a412016-09-15 21:12:30334
335 if (parent()) {
336 // Non-main frames should have a non-empty unique name.
337 DCHECK(!unique_name.empty());
338 } else {
339 // Unique name of main frames should always stay empty.
340 DCHECK(unique_name.empty());
341 }
342
Daniel Cheng6ca7f1c92017-08-09 21:45:41343 // Note the unique name should only be able to change before the first real
344 // load is committed, but that's not strongly enforced here.
lukasza464d8692016-02-22 19:26:32345 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56346 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32347 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23348}
349
arthursonzogni662aa652017-03-28 11:09:50350void FrameTreeNode::AddContentSecurityPolicies(
arthursonzogni35a95c72020-01-15 17:49:43351 std::vector<network::mojom::ContentSecurityPolicyHeaderPtr> headers) {
352 for (auto& header : headers)
353 replication_state_.accumulated_csp_headers.push_back(*header);
354 render_manager_.OnDidAddContentSecurityPolicies(std::move(headers));
lukasza8e1c02e42016-05-17 20:05:10355}
356
mkwstf672e7ef2016-06-09 20:51:07357void FrameTreeNode::SetInsecureRequestPolicy(
Julie Jeongeun Kimd90e2dd2020-03-03 11:45:37358 blink::mojom::InsecureRequestPolicy policy) {
mkwstf672e7ef2016-06-09 20:51:07359 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08360 return;
mkwstf672e7ef2016-06-09 20:51:07361 render_manager_.OnEnforceInsecureRequestPolicy(policy);
362 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08363}
364
arthursonzogni4b62a5cb2018-01-17 14:14:26365void FrameTreeNode::SetInsecureNavigationsSet(
366 const std::vector<uint32_t>& insecure_navigations_set) {
367 DCHECK(std::is_sorted(insecure_navigations_set.begin(),
368 insecure_navigations_set.end()));
369 if (insecure_navigations_set == replication_state_.insecure_navigations_set)
370 return;
371 render_manager_.OnEnforceInsecureNavigationsSet(insecure_navigations_set);
372 replication_state_.insecure_navigations_set = insecure_navigations_set;
373}
374
Luna Luc3fdacdf2017-11-08 04:48:53375void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Ian Clellandcdc4f312017-10-13 22:24:12376 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
Dave Tapuska9b153a942020-02-10 19:35:10377 pending_frame_policy_.disallow_document_access =
378 frame_policy.disallow_document_access;
alexmos6e940102016-01-19 22:47:25379
Ian Clellandcdc4f312017-10-13 22:24:12380 if (parent()) {
381 // Subframes should always inherit their parent's sandbox flags.
Alexander Timin381e7e182020-04-28 19:04:03382 pending_frame_policy_.sandbox_flags |=
383 parent()->frame_tree_node()->active_sandbox_flags();
Charlie Hue1b77ac2019-12-13 21:30:17384 // This is only applied on subframes; container policy and required document
385 // policy are not mutable on main frame.
Ian Clellandcdc4f312017-10-13 22:24:12386 pending_frame_policy_.container_policy = frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17387 pending_frame_policy_.required_document_policy =
388 frame_policy.required_document_policy;
Ian Clellandcdc4f312017-10-13 22:24:12389 }
iclelland92f8c0b2017-04-19 12:43:05390}
391
alexmos9f8705a2015-05-06 19:58:59392FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39393 return GetSibling(-1);
394}
alexmos9f8705a2015-05-06 19:58:59395
paulmeyer322777fb2016-05-16 23:15:39396FrameTreeNode* FrameTreeNode::NextSibling() const {
397 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59398}
399
fdegans4a49ce932015-03-12 17:11:37400bool FrameTreeNode::IsLoading() const {
401 RenderFrameHostImpl* current_frame_host =
402 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37403
404 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39405
clamy610c63b32017-12-22 15:05:18406 if (navigation_request_)
407 return true;
clamy11e11512015-07-07 16:42:17408
clamy610c63b32017-12-22 15:05:18409 RenderFrameHostImpl* speculative_frame_host =
410 render_manager_.speculative_frame_host();
411 if (speculative_frame_host && speculative_frame_host->is_loading())
412 return true;
fdegans4a49ce932015-03-12 17:11:37413 return current_frame_host->is_loading();
414}
415
Charlie Hu5ffc0152019-12-06 15:59:53416bool FrameTreeNode::CommitFramePolicy(
417 const blink::FramePolicy& new_frame_policy) {
418 bool did_change_flags = new_frame_policy.sandbox_flags !=
Ian Clellandcdc4f312017-10-13 22:24:12419 replication_state_.frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05420 bool did_change_container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53421 new_frame_policy.container_policy !=
Ian Clellandcdc4f312017-10-13 22:24:12422 replication_state_.frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17423 bool did_change_required_document_policy =
424 pending_frame_policy_.required_document_policy !=
425 replication_state_.frame_policy.required_document_policy;
Dave Tapuska9b153a942020-02-10 19:35:10426 bool did_change_document_access =
427 new_frame_policy.disallow_document_access !=
428 replication_state_.frame_policy.disallow_document_access;
iclelland92f8c0b2017-04-19 12:43:05429 if (did_change_flags)
Ian Clellandcdc4f312017-10-13 22:24:12430 replication_state_.frame_policy.sandbox_flags =
Charlie Hu5ffc0152019-12-06 15:59:53431 new_frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05432 if (did_change_container_policy)
Ian Clellandcdc4f312017-10-13 22:24:12433 replication_state_.frame_policy.container_policy =
Charlie Hu5ffc0152019-12-06 15:59:53434 new_frame_policy.container_policy;
Charlie Hue1b77ac2019-12-13 21:30:17435 if (did_change_required_document_policy)
436 replication_state_.frame_policy.required_document_policy =
437 new_frame_policy.required_document_policy;
Dave Tapuska9b153a942020-02-10 19:35:10438 if (did_change_document_access)
439 replication_state_.frame_policy.disallow_document_access =
440 new_frame_policy.disallow_document_access;
Charlie Hue1b77ac2019-12-13 21:30:17441
Charlie Hu5ffc0152019-12-06 15:59:53442 UpdateFramePolicyHeaders(new_frame_policy.sandbox_flags,
Ian Clellandedb8c5dd2018-03-01 17:01:37443 replication_state_.feature_policy_header);
Charlie Hue1b77ac2019-12-13 21:30:17444 return did_change_flags || did_change_container_policy ||
Dave Tapuska9b153a942020-02-10 19:35:10445 did_change_required_document_policy || did_change_document_access;
alexmos6b294562015-03-05 19:24:10446}
447
Arthur Hemeryc3380172018-01-22 14:00:17448void FrameTreeNode::TransferNavigationRequestOwnership(
449 RenderFrameHostImpl* render_frame_host) {
Andrey Kosyakovf2d4ff72018-10-29 20:09:59450 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
Arthur Hemeryc3380172018-01-22 14:00:17451 render_frame_host->SetNavigationRequest(std::move(navigation_request_));
452}
453
carloskc49005eb2015-06-16 11:25:07454void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57455 std::unique_ptr<NavigationRequest> navigation_request) {
arthursonzognic79c251c2016-08-18 15:00:37456 // This is never called when navigating to a Javascript URL. For the loading
457 // state, this matches what Blink is doing: Blink doesn't send throbber
458 // notifications for Javascript URLS.
459 DCHECK(!navigation_request->common_params().url.SchemeIs(
460 url::kJavaScriptScheme));
461
clamy44e84ce2016-02-22 15:38:25462 bool was_previously_loading = frame_tree()->IsLoading();
463
clamy82a2f4d2016-02-02 14:20:41464 // There's no need to reset the state: there's still an ongoing load, and the
465 // RenderFrameHostManager will take care of updates to the speculative
466 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05467 if (was_previously_loading) {
Mohamed Abdelhalimf03d4a22019-10-01 13:34:31468 if (navigation_request_ && navigation_request_->IsNavigationStarted()) {
jamcd0b7b22017-03-24 22:13:05469 // Mark the old request as aborted.
Mohamed Abdelhalimb4db22a2019-06-18 10:46:52470 navigation_request_->set_net_error(net::ERR_ABORTED);
jamcd0b7b22017-03-24 22:13:05471 }
Arthur Hemery241b9392019-10-24 11:08:41472 ResetNavigationRequest(true);
jamcd0b7b22017-03-24 22:13:05473 }
clamy44e84ce2016-02-22 15:38:25474
475 navigation_request_ = std::move(navigation_request);
Shubhie Panickerddf2a4e2018-03-06 00:09:06476 if (was_discarded_) {
477 navigation_request_->set_was_discarded();
478 was_discarded_ = false;
479 }
clamy8e2e299202016-04-05 11:44:59480 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39481
Lucas Furukawa Gadanief8290a2019-07-29 20:27:51482 bool to_different_document = !NavigationTypeUtils::IsSameDocument(
arthursonzogni92f18682017-02-08 23:00:04483 navigation_request_->common_params().navigation_type);
484
485 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16486}
487
Arthur Hemery241b9392019-10-24 11:08:41488void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
fdegans39ff0382015-04-29 19:04:39489 if (!navigation_request_)
490 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23491
Andrey Kosyakovf2d4ff72018-10-29 20:09:59492 devtools_instrumentation::OnResetNavigationRequest(navigation_request_.get());
clamydcb434c12015-04-16 19:29:16493 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39494
clamy82a2f4d2016-02-02 14:20:41495 if (keep_state)
fdegans39ff0382015-04-29 19:04:39496 return;
497
clamy82a2f4d2016-02-02 14:20:41498 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
499 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39500 DidStopLoading();
501 render_manager_.CleanUpNavigation();
clamydcb434c12015-04-16 19:29:16502}
503
clamy44e84ce2016-02-22 15:38:25504void FrameTreeNode::DidStartLoading(bool to_different_document,
505 bool was_previously_loading) {
Camille Lamyefd54b02018-10-04 16:54:14506 TRACE_EVENT2("navigation", "FrameTreeNode::DidStartLoading",
507 "frame_tree_node", frame_tree_node_id(), "to different document",
508 to_different_document);
fdegansa696e5112015-04-17 01:57:59509 // Any main frame load to a new document should reset the load progress since
510 // it will replace the current page and any frames. The WebContents will
511 // be notified when DidChangeLoadProgress is called.
512 if (to_different_document && IsMainFrame())
513 frame_tree_->ResetLoadProgress();
514
515 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25516 if (!was_previously_loading)
Fergal Daly09d6c762020-05-29 02:05:18517 navigator().GetDelegate()->DidStartLoading(this, to_different_document);
fdegansa696e5112015-04-17 01:57:59518
519 // Set initial load progress and update overall progress. This will notify
520 // the WebContents of the load progress change.
521 DidChangeLoadProgress(kLoadingProgressMinimum);
522
523 // Notify the RenderFrameHostManager of the event.
524 render_manager()->OnDidStartLoading();
525}
526
527void FrameTreeNode::DidStopLoading() {
Camille Lamyefd54b02018-10-04 16:54:14528 TRACE_EVENT1("navigation", "FrameTreeNode::DidStopLoading", "frame_tree_node",
529 frame_tree_node_id());
fdegansa696e5112015-04-17 01:57:59530 // Set final load progress and update overall progress. This will notify
531 // the WebContents of the load progress change.
532 DidChangeLoadProgress(kLoadingProgressDone);
533
Lucas Furukawa Gadani6faef602019-05-06 21:16:03534 // Notify the RenderFrameHostManager of the event.
535 render_manager()->OnDidStopLoading();
536
fdegansa696e5112015-04-17 01:57:59537 // Notify the WebContents.
538 if (!frame_tree_->IsLoading())
Fergal Daly09d6c762020-05-29 02:05:18539 navigator().GetDelegate()->DidStopLoading();
fdegansa696e5112015-04-17 01:57:59540}
541
542void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
Nate Chapin93536702018-02-07 00:12:21543 DCHECK_GE(load_progress, kLoadingProgressMinimum);
544 DCHECK_LE(load_progress, kLoadingProgressDone);
545 if (IsMainFrame())
546 frame_tree_->UpdateLoadProgress(load_progress);
fdegansa696e5112015-04-17 01:57:59547}
548
clamyf73862c42015-07-08 12:31:33549bool FrameTreeNode::StopLoading() {
arthursonzogni66f711c2019-10-08 14:40:36550 if (navigation_request_ && navigation_request_->IsNavigationStarted())
551 navigation_request_->set_net_error(net::ERR_ABORTED);
Arthur Hemery241b9392019-10-24 11:08:41552 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33553
554 // TODO(nasko): see if child frames should send IPCs in site-per-process
555 // mode.
556 if (!IsMainFrame())
557 return true;
558
559 render_manager_.Stop();
560 return true;
561}
562
alexmos21acae52015-11-07 01:04:43563void FrameTreeNode::DidFocus() {
564 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31565 for (auto& observer : observers_)
566 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43567}
568
clamy44e84ce2016-02-22 15:38:25569void FrameTreeNode::BeforeUnloadCanceled() {
570 // TODO(clamy): Support BeforeUnload in subframes.
571 if (!IsMainFrame())
572 return;
573
574 RenderFrameHostImpl* current_frame_host =
575 render_manager_.current_frame_host();
576 DCHECK(current_frame_host);
577 current_frame_host->ResetLoadingState();
578
clamy610c63b32017-12-22 15:05:18579 RenderFrameHostImpl* speculative_frame_host =
580 render_manager_.speculative_frame_host();
581 if (speculative_frame_host)
582 speculative_frame_host->ResetLoadingState();
583 // Note: there is no need to set an error code on the NavigationHandle here
584 // as it has not been created yet. It is only created when the
Antonio Gomes8678a202020-03-02 20:03:25585 // BeforeUnloadCompleted callback is invoked.
clamy610c63b32017-12-22 15:05:18586 if (navigation_request_)
Arthur Hemery241b9392019-10-24 11:08:41587 ResetNavigationRequest(false);
clamy44e84ce2016-02-22 15:38:25588}
589
Mustaq Ahmedecb5c38e2020-07-29 00:34:30590bool FrameTreeNode::NotifyUserActivation(
591 blink::mojom::UserActivationNotificationType notification_type) {
Alexander Timina1dfadaa2020-04-28 13:30:06592 for (RenderFrameHostImpl* rfh = current_frame_host(); rfh;
593 rfh = rfh->GetParent()) {
594 if (!rfh->frame_tree_node()->user_activation_state_.HasBeenActive())
595 rfh->DidReceiveFirstUserActivation();
Mustaq Ahmedecb5c38e2020-07-29 00:34:30596 rfh->frame_tree_node()->user_activation_state_.Activate(notification_type);
John Delaneyedd8d6c2019-01-25 00:23:57597 }
danakj359a4342020-05-29 20:38:39598 replication_state_.has_active_user_gesture = true;
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14599
Mustaq Ahmed0180320f2019-03-21 16:07:01600 // See the "Same-origin Visibility" section in |UserActivationState| class
601 // doc.
Mustaq Ahmede5f12562019-10-30 18:02:03602 if (base::FeatureList::IsEnabled(
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14603 features::kUserActivationSameOriginVisibility)) {
604 const url::Origin& current_origin =
605 this->current_frame_host()->GetLastCommittedOrigin();
606 for (FrameTreeNode* node : frame_tree()->Nodes()) {
607 if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
608 current_origin)) {
Mustaq Ahmedecb5c38e2020-07-29 00:34:30609 node->user_activation_state_.Activate(notification_type);
Mustaq Ahmeda5dfa60b2018-12-08 00:30:14610 }
611 }
612 }
613
Shivani Sharma20749e922019-03-11 17:00:26614 NavigationControllerImpl* controller =
Fergal Daly09d6c762020-05-29 02:05:18615 static_cast<NavigationControllerImpl*>(navigator().GetController());
Shivani Sharma20749e922019-03-11 17:00:26616 if (controller)
617 controller->NotifyUserActivation();
Shivani Sharma194877032019-03-07 17:52:47618
Mustaq Ahmedc4cb7162018-06-05 16:28:36619 return true;
620}
621
622bool FrameTreeNode::ConsumeTransientUserActivation() {
623 bool was_active = user_activation_state_.IsActive();
624 for (FrameTreeNode* node : frame_tree()->Nodes())
625 node->user_activation_state_.ConsumeIfActive();
danakj359a4342020-05-29 20:38:39626 replication_state_.has_active_user_gesture = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36627 return was_active;
628}
629
Shivani Sharmac4f561582018-11-15 15:58:39630bool FrameTreeNode::ClearUserActivation() {
Shivani Sharmac4f561582018-11-15 15:58:39631 for (FrameTreeNode* node : frame_tree()->SubtreeNodes(this))
632 node->user_activation_state_.Clear();
danakj359a4342020-05-29 20:38:39633 replication_state_.has_active_user_gesture = false;
Shivani Sharmac4f561582018-11-15 15:58:39634 return true;
635}
636
Ella Ge9caed612019-08-09 16:17:25637bool FrameTreeNode::VerifyUserActivation() {
Ella Gea78f6772019-12-11 10:35:25638 DCHECK(base::FeatureList::IsEnabled(
639 features::kBrowserVerifiedUserActivationMouse) ||
640 base::FeatureList::IsEnabled(
641 features::kBrowserVerifiedUserActivationKeyboard));
642
Ella Ge9caed612019-08-09 16:17:25643 return render_manager_.current_frame_host()
644 ->GetRenderWidgetHost()
Mustaq Ahmed83bb1722019-10-22 20:00:10645 ->RemovePendingUserActivationIfAvailable();
Ella Ge9caed612019-08-09 16:17:25646}
647
Mustaq Ahmedc4cb7162018-06-05 16:28:36648bool FrameTreeNode::UpdateUserActivationState(
Mustaq Ahmeddc195e5b2020-08-04 18:45:11649 blink::mojom::UserActivationUpdateType update_type,
650 blink::mojom::UserActivationNotificationType notification_type) {
Ella Ge9caed612019-08-09 16:17:25651 bool update_result = false;
Mustaq Ahmedc4cb7162018-06-05 16:28:36652 switch (update_type) {
Antonio Gomes4b2c5132020-01-16 11:49:48653 case blink::mojom::UserActivationUpdateType::kConsumeTransientActivation:
Ella Ge9caed612019-08-09 16:17:25654 update_result = ConsumeTransientUserActivation();
655 break;
Antonio Gomes4b2c5132020-01-16 11:49:48656 case blink::mojom::UserActivationUpdateType::kNotifyActivation:
Mustaq Ahmeddc195e5b2020-08-04 18:45:11657 update_result = NotifyUserActivation(notification_type);
Ella Ge9caed612019-08-09 16:17:25658 break;
Antonio Gomes4b2c5132020-01-16 11:49:48659 case blink::mojom::UserActivationUpdateType::
Liviu Tintad9391fb92020-09-28 23:50:07660 kNotifyActivationPendingBrowserVerification: {
661 const bool user_activation_verified = VerifyUserActivation();
662 // Add UMA metric for when browser user activation verification succeeds
663 base::UmaHistogramBoolean("Event.BrowserVerifiedUserActivation",
664 user_activation_verified);
665 if (user_activation_verified) {
Mustaq Ahmedecb5c38e2020-07-29 00:34:30666 update_result = NotifyUserActivation(
667 blink::mojom::UserActivationNotificationType::kNone);
Antonio Gomes4b2c5132020-01-16 11:49:48668 update_type = blink::mojom::UserActivationUpdateType::kNotifyActivation;
Ella Ge9caed612019-08-09 16:17:25669 } else {
670 // TODO(crbug.com/848778): We need to decide what to do when user
671 // activation verification failed. NOTREACHED here will make all
672 // unrelated tests that inject event to renderer fail.
673 return false;
674 }
Liviu Tintad9391fb92020-09-28 23:50:07675 } break;
Antonio Gomes4b2c5132020-01-16 11:49:48676 case blink::mojom::UserActivationUpdateType::kClearActivation:
Ella Ge9caed612019-08-09 16:17:25677 update_result = ClearUserActivation();
678 break;
Mustaq Ahmedc4cb7162018-06-05 16:28:36679 }
Mustaq Ahmeddc195e5b2020-08-04 18:45:11680 render_manager_.UpdateUserActivationState(update_type, notification_type);
Ella Ge9caed612019-08-09 16:17:25681 return update_result;
japhet61835ae12017-01-20 01:25:39682}
683
Mustaq Ahmed01261742019-12-16 15:49:06684void FrameTreeNode::OnSetHadStickyUserActivationBeforeNavigation(bool value) {
685 render_manager_.OnSetHadStickyUserActivationBeforeNavigation(value);
Becca Hughes60af7d42017-12-12 10:53:15686 replication_state_.has_received_user_gesture_before_nav = value;
687}
688
paulmeyer322777fb2016-05-16 23:15:39689FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19690 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39691 return nullptr;
692
693 for (size_t i = 0; i < parent_->child_count(); ++i) {
694 if (parent_->child_at(i) == this) {
695 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
696 i + relative_offset >= parent_->child_count()) {
697 return nullptr;
698 }
699 return parent_->child_at(i + relative_offset);
700 }
701 }
702
703 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
704 return nullptr;
705}
706
Ian Clellandedb8c5dd2018-03-01 17:01:37707void FrameTreeNode::UpdateFramePolicyHeaders(
arthursonzognib93a4472020-04-10 07:38:00708 network::mojom::WebSandboxFlags sandbox_flags,
Ian Clellandedb8c5dd2018-03-01 17:01:37709 const blink::ParsedFeaturePolicy& parsed_header) {
710 bool changed = false;
711 if (replication_state_.feature_policy_header != parsed_header) {
712 replication_state_.feature_policy_header = parsed_header;
713 changed = true;
714 }
Ian Clelland5cbaaf82017-11-27 22:00:03715 // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the
716 // currently effective sandbox flags from the frame. https://crbug.com/740556
arthursonzognib93a4472020-04-10 07:38:00717 network::mojom::WebSandboxFlags updated_flags =
Ian Clelland5cbaaf82017-11-27 22:00:03718 sandbox_flags | effective_frame_policy().sandbox_flags;
Ian Clellandedb8c5dd2018-03-01 17:01:37719 if (replication_state_.active_sandbox_flags != updated_flags) {
720 replication_state_.active_sandbox_flags = updated_flags;
721 changed = true;
722 }
723 // Notify any proxies if the policies have been changed.
724 if (changed)
725 render_manager()->OnDidSetFramePolicyHeaders();
Ian Clelland5cbaaf82017-11-27 22:00:03726}
727
Arthur Sonzognif8840b92018-11-07 14:10:35728void FrameTreeNode::PruneChildFrameNavigationEntries(
729 NavigationEntryImpl* entry) {
730 for (size_t i = 0; i < current_frame_host()->child_count(); ++i) {
731 FrameTreeNode* child = current_frame_host()->child_at(i);
732 if (child->is_created_by_script_) {
733 entry->RemoveEntryForFrame(child,
734 /* only_if_different_position = */ false);
735 } else {
736 child->PruneChildFrameNavigationEntries(entry);
737 }
738 }
739}
740
Ehsan Karamad39407082019-02-19 23:38:19741void FrameTreeNode::SetOpenerFeaturePolicyState(
Kent Tamura326c2db2020-07-20 06:28:05742 const blink::FeaturePolicyFeatureState& feature_state) {
Ehsan Karamad39407082019-02-19 23:38:19743 DCHECK(IsMainFrame());
744 if (base::FeatureList::IsEnabled(features::kFeaturePolicyForSandbox)) {
745 replication_state_.opener_feature_state = feature_state;
746 }
747}
748
Yao Xiao24ec9aa2020-01-28 16:36:00749void FrameTreeNode::SetAdFrameType(blink::mojom::AdFrameType ad_frame_type) {
750 DCHECK_NE(ad_frame_type, blink::mojom::AdFrameType::kNonAd);
751 if (replication_state_.ad_frame_type == blink::mojom::AdFrameType::kNonAd) {
752 replication_state_.ad_frame_type = ad_frame_type;
753 render_manager()->OnDidSetAdFrameType(ad_frame_type);
754 } else {
755 DCHECK_EQ(ad_frame_type, replication_state_.ad_frame_type);
756 }
757}
758
[email protected]9b159a52013-10-03 17:24:55759} // namespace content