blob: f22d52b0ccb63e0b8bc2a46a3594db5f98296bbd [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"
dcheng9bfa5162016-04-09 01:00:5714#include "base/memory/ptr_util.h"
dcheng23ca947d2016-05-04 20:04:1515#include "base/metrics/histogram_macros.h"
[email protected]9b159a52013-10-03 17:24:5516#include "base/stl_util.h"
Daniel Cheng6ca7f1c92017-08-09 21:45:4117#include "base/strings/string_util.h"
Pavel Feldmand8352ac2017-11-10 00:37:4118#include "content/browser/devtools/render_frame_devtools_agent_host.h"
[email protected]94d0cc12013-12-18 00:07:4119#include "content/browser/frame_host/frame_tree.h"
clamydcb434c12015-04-16 19:29:1620#include "content/browser/frame_host/navigation_request.h"
[email protected]190b8c52013-11-09 01:35:4421#include "content/browser/frame_host/navigator.h"
[email protected]d4a8ca482013-10-30 21:06:4022#include "content/browser/frame_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4123#include "content/browser/renderer_host/render_view_host_impl.h"
clamyf73862c42015-07-08 12:31:3324#include "content/common/frame_messages.h"
dmazzonie950ea232015-03-13 21:39:4525#include "content/public/browser/browser_thread.h"
carloskd80262f52015-12-16 14:40:3526#include "content/public/common/browser_side_navigation_policy.h"
Luna Luc3fdacdf2017-11-08 04:48:5327#include "third_party/WebKit/common/sandbox_flags.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.
43const double kLoadingProgressNotStarted = 0.0;
44const double kLoadingProgressMinimum = 0.1;
45const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4546
Daniel Cheng6ca7f1c92017-08-09 21:45:4147void RecordUniqueNameSize(FrameTreeNode* node) {
48 const auto& unique_name = node->current_replication_state().unique_name;
49
50 // Don't record numbers for the root node, which always has an empty unique
51 // name.
52 if (!node->parent()) {
53 DCHECK(unique_name.empty());
54 return;
55 }
56
57 // The original requested name is derived from the browsing context name and
58 // is essentially unbounded in size...
59 UMA_HISTOGRAM_COUNTS_1M(
60 "SessionRestore.FrameUniqueNameOriginalRequestedNameSize",
61 node->current_replication_state().name.size());
62 // If the name is a frame path, attempt to normalize the statistics based on
63 // the number of frames in the frame path.
64 if (base::StartsWith(unique_name, "<!--framePath //",
65 base::CompareCase::SENSITIVE)) {
66 size_t depth = 1;
67 while (node->parent()) {
68 ++depth;
69 node = node->parent();
70 }
71 // The max possible size of a unique name is 80 characters, so the expected
72 // size per component shouldn't be much more than that.
73 UMA_HISTOGRAM_COUNTS_100(
74 "SessionRestore.FrameUniqueNameWithFramePathSizePerComponent",
75 round(unique_name.size() / static_cast<float>(depth)));
76 // Blink allows a maximum of ~1024 subframes in a document, so this should
77 // be less than (80 character name + 1 character delimiter) * 1024.
78 UMA_HISTOGRAM_COUNTS_100000(
79 "SessionRestore.FrameUniqueNameWithFramePathSize", unique_name.size());
80 } else {
81 UMA_HISTOGRAM_COUNTS_100(
82 "SessionRestore.FrameUniqueNameFromRequestedNameSize",
83 unique_name.size());
84 }
dcheng23ca947d2016-05-04 20:04:1585}
86
fdegansa696e5112015-04-17 01:57:5987} // namespace
fdegans1d16355162015-03-26 11:58:3488
alexmose201c7cd2015-06-10 17:14:2189// This observer watches the opener of its owner FrameTreeNode and clears the
90// owner's opener if the opener is destroyed.
91class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
92 public:
jochen6004a362017-02-04 00:11:4093 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
94 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2195
96 // FrameTreeNode::Observer
97 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4098 if (observing_original_opener_) {
Avi Drissman36465f332017-09-11 20:49:3999 // The "original owner" is special. It's used for attribution, and clients
100 // walk down the original owner chain. Therefore, if a link in the chain
101 // is being destroyed, reconnect the observation to the parent of the link
102 // being destroyed.
jochen6004a362017-02-04 00:11:40103 CHECK_EQ(owner_->original_opener(), node);
Avi Drissman36465f332017-09-11 20:49:39104 owner_->SetOriginalOpener(node->original_opener());
105 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:40106 } else {
107 CHECK_EQ(owner_->opener(), node);
108 owner_->SetOpener(nullptr);
Avi Drissman36465f332017-09-11 20:49:39109 // |this| is deleted at this point.
jochen6004a362017-02-04 00:11:40110 }
alexmose201c7cd2015-06-10 17:14:21111 }
112
113 private:
114 FrameTreeNode* owner_;
jochen6004a362017-02-04 00:11:40115 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:21116
117 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
118};
119
vishal.b782eb5d2015-04-29 12:22:57120int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:55121
dmazzonie950ea232015-03-13 21:39:45122// static
vishal.b782eb5d2015-04-29 12:22:57123FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:19124 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:15125 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
126 FrameTreeNodeIdMap::iterator it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:45127 return it == nodes->end() ? nullptr : it->second;
128}
129
raymes31457802016-07-20 06:08:09130FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
131 Navigator* navigator,
132 RenderFrameHostDelegate* render_frame_delegate,
133 RenderWidgetHostDelegate* render_widget_delegate,
134 RenderFrameHostManager::Delegate* manager_delegate,
135 FrameTreeNode* parent,
136 blink::WebTreeScopeType scope,
137 const std::string& name,
138 const std::string& unique_name,
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45139 bool is_created_by_script,
Pavel Feldman25234722017-10-11 02:49:06140 const base::UnguessableToken& devtools_frame_token,
raymes31457802016-07-20 06:08:09141 const FrameOwnerProperties& frame_owner_properties)
[email protected]bffc8302014-01-23 20:52:16142 : frame_tree_(frame_tree),
143 navigator_(navigator),
144 render_manager_(this,
145 render_frame_delegate,
[email protected]bffc8302014-01-23 20:52:16146 render_widget_delegate,
147 manager_delegate),
148 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59149 parent_(parent),
alexmose201c7cd2015-06-10 17:14:21150 opener_(nullptr),
jochen6004a362017-02-04 00:11:40151 original_opener_(nullptr),
creisf0f069a2015-07-23 23:51:53152 has_committed_real_load_(false),
engedy6e2e0992017-05-25 18:58:42153 is_collapsed_(false),
estarka886b8d2015-12-18 21:53:08154 replication_state_(
155 scope,
156 name,
lukasza464d8692016-02-22 19:26:32157 unique_name,
estarkbd8e26f2016-03-16 23:30:37158 false /* should enforce strict mixed content checking */,
japhet61835ae12017-01-20 01:25:39159 false /* is a potentially trustworthy unique origin */,
Becca Hughes60af7d42017-12-12 10:53:15160 false /* has received a user gesture */,
161 false /* has received a user gesture before nav */),
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45162 is_created_by_script_(is_created_by_script),
Pavel Feldman25234722017-10-11 02:49:06163 devtools_frame_token_(devtools_frame_token),
lazyboy70605c32015-11-03 01:27:31164 frame_owner_properties_(frame_owner_properties),
xiaochenghb9554bb2016-05-21 14:20:48165 loading_progress_(kLoadingProgressNotStarted),
166 blame_context_(frame_tree_node_id_, parent) {
rob97250742015-12-10 17:45:15167 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45168 g_frame_tree_node_id_map.Get().insert(
169 std::make_pair(frame_tree_node_id_, this));
170 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33171
Daniel Cheng6ca7f1c92017-08-09 21:45:41172 RecordUniqueNameSize(this);
xiaochenghb9554bb2016-05-21 14:20:48173
174 // Note: this should always be done last in the constructor.
175 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59176}
[email protected]9b159a52013-10-03 17:24:55177
178FrameTreeNode::~FrameTreeNode() {
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45179 // Remove the children. See https://crbug.com/612450 for explanation why we
180 // don't just call the std::vector::clear method.
paulmeyerf3119f52016-05-17 17:37:19181 std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
Lukasz Anforowicz7bfb2e92017-11-22 17:19:45182
183 // If the removed frame was created by a script, then its history entry will
184 // never be reused - we can save some memory by removing the history entry.
185 // See also https://crbug.com/784356.
186 if (is_created_by_script_ && parent_) {
187 NavigationEntryImpl* nav_entry = static_cast<NavigationEntryImpl*>(
188 navigator()->GetController()->GetLastCommittedEntry());
189 if (nav_entry) {
190 nav_entry->RemoveEntryForFrame(this,
191 /* only_if_different_position = */ false);
192 }
193 }
194
dmazzonie950ea232015-03-13 21:39:45195 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31196 for (auto& observer : observers_)
197 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21198
199 if (opener_)
200 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40201 if (original_opener_)
202 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45203
204 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18205
206 if (navigation_request_) {
207 // PlzNavigate: if a frame with a pending navigation is detached, make sure
208 // the WebContents (and its observers) update their loading state.
209 navigation_request_.reset();
210 DidStopLoading();
211 }
[email protected]9b159a52013-10-03 17:24:55212}
213
alexmose201c7cd2015-06-10 17:14:21214void FrameTreeNode::AddObserver(Observer* observer) {
215 observers_.AddObserver(observer);
216}
217
218void FrameTreeNode::RemoveObserver(Observer* observer) {
219 observers_.RemoveObserver(observer);
220}
221
[email protected]94d0cc12013-12-18 00:07:41222bool FrameTreeNode::IsMainFrame() const {
223 return frame_tree_->root() == this;
224}
225
dcheng9bfa5162016-04-09 01:00:57226FrameTreeNode* FrameTreeNode::AddChild(std::unique_ptr<FrameTreeNode> child,
nick8814e652015-12-18 01:44:12227 int process_id,
228 int frame_routing_id) {
dgroganfb22f9a2014-10-20 21:32:32229 // Child frame must always be created in the same process as the parent.
230 CHECK_EQ(process_id, render_manager_.current_host()->GetProcess()->GetID());
231
[email protected]94d0cc12013-12-18 00:07:41232 // Initialize the RenderFrameHost for the new node. We always create child
233 // frames in the same SiteInstance as the current frame, and they can swap to
234 // a different one if they navigate away.
235 child->render_manager()->Init(
[email protected]94d0cc12013-12-18 00:07:41236 render_manager_.current_host()->GetSiteInstance(),
dcheng29f5a6c2015-08-31 21:43:27237 render_manager_.current_host()->GetRoutingID(), frame_routing_id,
jambaaab3a2016-11-05 00:46:18238 MSG_ROUTING_NONE, false);
alexmos46e85ec2015-04-03 21:04:35239
240 // Other renderer processes in this BrowsingInstance may need to find out
241 // about the new frame. Create a proxy for the child frame in all
242 // SiteInstances that have a proxy for the frame's parent, since all frames
243 // in a frame tree should have the same set of proxies.
Ken Buchanan077f50312017-08-23 15:34:47244 render_manager_.CreateProxiesForChildFrame(child.get());
alexmos46e85ec2015-04-03 21:04:35245
dcheng36b6aec92015-12-26 06:16:36246 children_.push_back(std::move(child));
nick8814e652015-12-18 01:44:12247 return children_.back().get();
[email protected]9b159a52013-10-03 17:24:55248}
249
[email protected]741fd682013-11-08 08:26:55250void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
nickb6769e632015-11-13 23:25:18251 for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
252 if (iter->get() == child) {
253 // Subtle: we need to make sure the node is gone from the tree before
254 // observers are notified of its deletion.
dcheng9bfa5162016-04-09 01:00:57255 std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
nickb6769e632015-11-13 23:25:18256 children_.erase(iter);
257 node_to_delete.reset();
258 return;
259 }
[email protected]bffc8302014-01-23 20:52:16260 }
[email protected]9b159a52013-10-03 17:24:55261}
262
[email protected]81c6c5e2014-02-13 20:20:07263void FrameTreeNode::ResetForNewProcess() {
Erik Chen173bf3042017-07-31 06:06:21264 current_frame_host()->SetLastCommittedUrl(GURL());
xiaochenghb9554bb2016-05-21 14:20:48265 blame_context_.TakeSnapshot();
[email protected]482ce3c2013-11-27 18:17:09266
nickb6769e632015-11-13 23:25:18267 // Remove child nodes from the tree, then delete them. This destruction
268 // operation will notify observers.
dcheng9bfa5162016-04-09 01:00:57269 std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
[email protected]9b159a52013-10-03 17:24:55270}
271
Ian Clelland5cbaaf82017-11-27 22:00:03272void FrameTreeNode::ResetForNavigation() {
273 // Discard any CSP headers from the previous document.
274 replication_state_.accumulated_csp_headers.clear();
275 render_manager_.OnDidResetContentSecurityPolicy();
276
277 // Clear the declared feature policy for the frame.
278 replication_state_.feature_policy_header.clear();
279
280 // Clear any CSP-set sandbox flags in the frame.
281 UpdateActiveSandboxFlags(blink::WebSandboxFlags::kNone);
282}
283
alexmose201c7cd2015-06-10 17:14:21284void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
285 if (opener_) {
286 opener_->RemoveObserver(opener_observer_.get());
287 opener_observer_.reset();
288 }
289
290 opener_ = opener;
291
292 if (opener_) {
Jeremy Roman04f27c372017-10-27 15:20:55293 opener_observer_ = std::make_unique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21294 opener_->AddObserver(opener_observer_.get());
295 }
296}
297
jochen6004a362017-02-04 00:11:40298void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
Avi Drissman36465f332017-09-11 20:49:39299 // The original opener tracks main frames only.
avi8d1aa162017-03-27 18:27:37300 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40301
Avi Drissman36465f332017-09-11 20:49:39302 if (original_opener_) {
303 original_opener_->RemoveObserver(original_opener_observer_.get());
304 original_opener_observer_.reset();
305 }
306
jochen6004a362017-02-04 00:11:40307 original_opener_ = opener;
308
309 if (original_opener_) {
jochen6004a362017-02-04 00:11:40310 original_opener_observer_ =
Jeremy Roman04f27c372017-10-27 15:20:55311 std::make_unique<OpenerDestroyedObserver>(this, true);
jochen6004a362017-02-04 00:11:40312 original_opener_->AddObserver(original_opener_observer_.get());
313 }
314}
315
creisf0f069a2015-07-23 23:51:53316void FrameTreeNode::SetCurrentURL(const GURL& url) {
csharrisona3bd0b32016-10-19 18:40:48317 if (!has_committed_real_load_ && url != url::kAboutBlankURL)
creisf0f069a2015-07-23 23:51:53318 has_committed_real_load_ = true;
Erik Chen173bf3042017-07-31 06:06:21319 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48320 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53321}
322
estarkbd8e26f2016-03-16 23:30:37323void FrameTreeNode::SetCurrentOrigin(
324 const url::Origin& origin,
325 bool is_potentially_trustworthy_unique_origin) {
326 if (!origin.IsSameOriginWith(replication_state_.origin) ||
327 replication_state_.has_potentially_trustworthy_unique_origin !=
328 is_potentially_trustworthy_unique_origin) {
329 render_manager_.OnDidUpdateOrigin(origin,
330 is_potentially_trustworthy_unique_origin);
331 }
alexmosa7a4ff822015-04-27 17:59:56332 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37333 replication_state_.has_potentially_trustworthy_unique_origin =
334 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56335}
alexmosbe2f4c32015-03-10 02:30:23336
engedy6e2e0992017-05-25 18:58:42337void FrameTreeNode::SetCollapsed(bool collapsed) {
338 DCHECK(!IsMainFrame());
339 if (is_collapsed_ == collapsed)
340 return;
341
342 is_collapsed_ = collapsed;
343 render_manager_.OnDidChangeCollapsedState(collapsed);
344}
345
lukasza464d8692016-02-22 19:26:32346void FrameTreeNode::SetFrameName(const std::string& name,
347 const std::string& unique_name) {
348 if (name == replication_state_.name) {
349 // |unique_name| shouldn't change unless |name| changes.
350 DCHECK_EQ(unique_name, replication_state_.unique_name);
351 return;
352 }
lukasza5140a412016-09-15 21:12:30353
354 if (parent()) {
355 // Non-main frames should have a non-empty unique name.
356 DCHECK(!unique_name.empty());
357 } else {
358 // Unique name of main frames should always stay empty.
359 DCHECK(unique_name.empty());
360 }
361
Daniel Cheng6ca7f1c92017-08-09 21:45:41362 // Note the unique name should only be able to change before the first real
363 // load is committed, but that's not strongly enforced here.
364 if (unique_name != replication_state_.unique_name)
365 RecordUniqueNameSize(this);
lukasza464d8692016-02-22 19:26:32366 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56367 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32368 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23369}
370
raymesd405a052016-12-05 23:41:34371void FrameTreeNode::SetFeaturePolicyHeader(
Luna Lu2e713992017-11-07 01:45:58372 const blink::ParsedFeaturePolicy& parsed_header) {
raymesd405a052016-12-05 23:41:34373 replication_state_.feature_policy_header = parsed_header;
iclellandab749ec92016-11-23 02:00:43374}
375
arthursonzogni662aa652017-03-28 11:09:50376void FrameTreeNode::AddContentSecurityPolicies(
377 const std::vector<ContentSecurityPolicyHeader>& headers) {
378 replication_state_.accumulated_csp_headers.insert(
379 replication_state_.accumulated_csp_headers.end(), headers.begin(),
380 headers.end());
381 render_manager_.OnDidAddContentSecurityPolicies(headers);
lukasza8e1c02e42016-05-17 20:05:10382}
383
mkwstf672e7ef2016-06-09 20:51:07384void FrameTreeNode::SetInsecureRequestPolicy(
385 blink::WebInsecureRequestPolicy policy) {
386 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08387 return;
mkwstf672e7ef2016-06-09 20:51:07388 render_manager_.OnEnforceInsecureRequestPolicy(policy);
389 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08390}
391
Luna Luc3fdacdf2017-11-08 04:48:53392void FrameTreeNode::SetPendingFramePolicy(blink::FramePolicy frame_policy) {
Ian Clellandcdc4f312017-10-13 22:24:12393 pending_frame_policy_.sandbox_flags = frame_policy.sandbox_flags;
alexmos6e940102016-01-19 22:47:25394
Ian Clellandcdc4f312017-10-13 22:24:12395 if (parent()) {
396 // Subframes should always inherit their parent's sandbox flags.
Ian Clelland5cbaaf82017-11-27 22:00:03397 pending_frame_policy_.sandbox_flags |= parent()->active_sandbox_flags();
Ian Clellandcdc4f312017-10-13 22:24:12398 // This is only applied on subframes; container policy is not mutable on
399 // main frame.
400 pending_frame_policy_.container_policy = frame_policy.container_policy;
401 }
iclelland92f8c0b2017-04-19 12:43:05402}
403
mlamouria85eb3f2015-01-26 17:36:27404bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
405 if (!other || !other->child_count())
406 return false;
407
408 for (FrameTreeNode* node = parent(); node; node = node->parent()) {
409 if (node == other)
410 return true;
411 }
412
413 return false;
414}
415
alexmos9f8705a2015-05-06 19:58:59416FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39417 return GetSibling(-1);
418}
alexmos9f8705a2015-05-06 19:58:59419
paulmeyer322777fb2016-05-16 23:15:39420FrameTreeNode* FrameTreeNode::NextSibling() const {
421 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59422}
423
fdegans4a49ce932015-03-12 17:11:37424bool FrameTreeNode::IsLoading() const {
425 RenderFrameHostImpl* current_frame_host =
426 render_manager_.current_frame_host();
fdegans4a49ce932015-03-12 17:11:37427
428 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39429
clamy610c63b32017-12-22 15:05:18430 if (navigation_request_)
431 return true;
clamy11e11512015-07-07 16:42:17432
clamy610c63b32017-12-22 15:05:18433 RenderFrameHostImpl* speculative_frame_host =
434 render_manager_.speculative_frame_host();
435 if (speculative_frame_host && speculative_frame_host->is_loading())
436 return true;
fdegans4a49ce932015-03-12 17:11:37437 return current_frame_host->is_loading();
438}
439
iclelland92f8c0b2017-04-19 12:43:05440bool FrameTreeNode::CommitPendingFramePolicy() {
Ian Clellandcdc4f312017-10-13 22:24:12441 bool did_change_flags = pending_frame_policy_.sandbox_flags !=
442 replication_state_.frame_policy.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05443 bool did_change_container_policy =
Ian Clellandcdc4f312017-10-13 22:24:12444 pending_frame_policy_.container_policy !=
445 replication_state_.frame_policy.container_policy;
iclelland92f8c0b2017-04-19 12:43:05446 if (did_change_flags)
Ian Clellandcdc4f312017-10-13 22:24:12447 replication_state_.frame_policy.sandbox_flags =
448 pending_frame_policy_.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05449 if (did_change_container_policy)
Ian Clellandcdc4f312017-10-13 22:24:12450 replication_state_.frame_policy.container_policy =
451 pending_frame_policy_.container_policy;
Ian Clelland5cbaaf82017-11-27 22:00:03452 UpdateActiveSandboxFlags(pending_frame_policy_.sandbox_flags);
iclelland92f8c0b2017-04-19 12:43:05453 return did_change_flags || did_change_container_policy;
alexmos6b294562015-03-05 19:24:10454}
455
carloskc49005eb2015-06-16 11:25:07456void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57457 std::unique_ptr<NavigationRequest> navigation_request) {
carloskd80262f52015-12-16 14:40:35458 CHECK(IsBrowserSideNavigationEnabled());
clamy82a2f4d2016-02-02 14:20:41459
arthursonzognic79c251c2016-08-18 15:00:37460 // This is never called when navigating to a Javascript URL. For the loading
461 // state, this matches what Blink is doing: Blink doesn't send throbber
462 // notifications for Javascript URLS.
463 DCHECK(!navigation_request->common_params().url.SchemeIs(
464 url::kJavaScriptScheme));
465
clamy44e84ce2016-02-22 15:38:25466 bool was_previously_loading = frame_tree()->IsLoading();
467
clamy82a2f4d2016-02-02 14:20:41468 // There's no need to reset the state: there's still an ongoing load, and the
469 // RenderFrameHostManager will take care of updates to the speculative
470 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05471 if (was_previously_loading) {
clamy080e7962017-05-25 00:44:18472 if (navigation_request_ && navigation_request_->navigation_handle()) {
jamcd0b7b22017-03-24 22:13:05473 // Mark the old request as aborted.
474 navigation_request_->navigation_handle()->set_net_error_code(
475 net::ERR_ABORTED);
476 }
clamya86695b2017-03-23 14:45:48477 ResetNavigationRequest(true, true);
jamcd0b7b22017-03-24 22:13:05478 }
clamy44e84ce2016-02-22 15:38:25479
480 navigation_request_ = std::move(navigation_request);
clamy8e2e299202016-04-05 11:44:59481 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39482
arthursonzogni92f18682017-02-08 23:00:04483 bool to_different_document = !FrameMsg_Navigate_Type::IsSameDocument(
484 navigation_request_->common_params().navigation_type);
485
486 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16487}
488
clamya86695b2017-03-23 14:45:48489void FrameTreeNode::ResetNavigationRequest(bool keep_state,
490 bool inform_renderer) {
carloskd80262f52015-12-16 14:40:35491 CHECK(IsBrowserSideNavigationEnabled());
fdegans39ff0382015-04-29 19:04:39492 if (!navigation_request_)
493 return;
John Abd-El-Malekdcc7bf42017-09-12 22:30:23494
Pavel Feldmand8352ac2017-11-10 00:37:41495 RenderFrameDevToolsAgentHost::OnResetNavigationRequest(
496 navigation_request_.get());
497
John Abd-El-Malekdcc7bf42017-09-12 22:30:23498 // The renderer should be informed if the caller allows to do so and the
499 // navigation came from a BeginNavigation IPC.
500 int need_to_inform_renderer =
501 inform_renderer && navigation_request_->from_begin_navigation();
502
clamy8e2e299202016-04-05 11:44:59503 NavigationRequest::AssociatedSiteInstanceType site_instance_type =
504 navigation_request_->associated_site_instance_type();
clamydcb434c12015-04-16 19:29:16505 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39506
clamy82a2f4d2016-02-02 14:20:41507 if (keep_state)
fdegans39ff0382015-04-29 19:04:39508 return;
509
clamy82a2f4d2016-02-02 14:20:41510 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
511 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39512 DidStopLoading();
513 render_manager_.CleanUpNavigation();
clamy2567242a2016-02-22 18:27:38514
clamy8e2e299202016-04-05 11:44:59515 // When reusing the same SiteInstance, a pending WebUI may have been created
516 // on behalf of the navigation in the current RenderFrameHost. Clear it.
517 if (site_instance_type ==
518 NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
519 current_frame_host()->ClearPendingWebUI();
520 }
521
clamy2567242a2016-02-22 18:27:38522 // If the navigation is renderer-initiated, the renderer should also be
clamya86695b2017-03-23 14:45:48523 // informed that the navigation stopped if needed. In the case the renderer
524 // process asked for the navigation to be aborted, e.g. following a
525 // document.open, do not send an IPC to the renderer process as it already
526 // expects the navigation to stop.
John Abd-El-Malekdcc7bf42017-09-12 22:30:23527 if (need_to_inform_renderer) {
clamy2567242a2016-02-22 18:27:38528 current_frame_host()->Send(
John Abd-El-Malekdcc7bf42017-09-12 22:30:23529 new FrameMsg_DroppedNavigation(current_frame_host()->GetRoutingID()));
clamy2567242a2016-02-22 18:27:38530 }
clamydcb434c12015-04-16 19:29:16531}
532
fdegansa696e5112015-04-17 01:57:59533bool FrameTreeNode::has_started_loading() const {
534 return loading_progress_ != kLoadingProgressNotStarted;
535}
536
537void FrameTreeNode::reset_loading_progress() {
538 loading_progress_ = kLoadingProgressNotStarted;
539}
540
clamy44e84ce2016-02-22 15:38:25541void FrameTreeNode::DidStartLoading(bool to_different_document,
542 bool was_previously_loading) {
fdegansa696e5112015-04-17 01:57:59543 // Any main frame load to a new document should reset the load progress since
544 // it will replace the current page and any frames. The WebContents will
545 // be notified when DidChangeLoadProgress is called.
546 if (to_different_document && IsMainFrame())
547 frame_tree_->ResetLoadProgress();
548
549 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25550 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59551 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
552
553 // Set initial load progress and update overall progress. This will notify
554 // the WebContents of the load progress change.
555 DidChangeLoadProgress(kLoadingProgressMinimum);
556
557 // Notify the RenderFrameHostManager of the event.
558 render_manager()->OnDidStartLoading();
559}
560
561void FrameTreeNode::DidStopLoading() {
fdegansa696e5112015-04-17 01:57:59562 // Set final load progress and update overall progress. This will notify
563 // the WebContents of the load progress change.
564 DidChangeLoadProgress(kLoadingProgressDone);
565
fdegansa696e5112015-04-17 01:57:59566 // Notify the WebContents.
567 if (!frame_tree_->IsLoading())
568 navigator()->GetDelegate()->DidStopLoading();
569
fdegansa696e5112015-04-17 01:57:59570 // Notify the RenderFrameHostManager of the event.
571 render_manager()->OnDidStopLoading();
Dominic Mazzoni3c7007a2017-12-12 07:34:05572
573 // Notify accessibility that the user is no longer trying to load or
574 // reload a page.
575 BrowserAccessibilityManager* manager =
576 current_frame_host()->browser_accessibility_manager();
577 if (manager)
578 manager->DidStopLoading();
fdegansa696e5112015-04-17 01:57:59579}
580
581void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
582 loading_progress_ = load_progress;
583 frame_tree_->UpdateLoadProgress();
584}
585
clamyf73862c42015-07-08 12:31:33586bool FrameTreeNode::StopLoading() {
jam0299edae2017-03-10 00:49:22587 if (IsBrowserSideNavigationEnabled()) {
588 if (navigation_request_) {
clamy080e7962017-05-25 00:44:18589 int expected_pending_nav_entry_id = navigation_request_->nav_entry_id();
590 if (navigation_request_->navigation_handle()) {
591 navigation_request_->navigation_handle()->set_net_error_code(
592 net::ERR_ABORTED);
593 expected_pending_nav_entry_id =
594 navigation_request_->navigation_handle()->pending_nav_entry_id();
595 }
596 navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
jam0299edae2017-03-10 00:49:22597 }
clamya86695b2017-03-23 14:45:48598 ResetNavigationRequest(false, true);
jam0299edae2017-03-10 00:49:22599 }
clamyf73862c42015-07-08 12:31:33600
601 // TODO(nasko): see if child frames should send IPCs in site-per-process
602 // mode.
603 if (!IsMainFrame())
604 return true;
605
606 render_manager_.Stop();
607 return true;
608}
609
alexmos21acae52015-11-07 01:04:43610void FrameTreeNode::DidFocus() {
611 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31612 for (auto& observer : observers_)
613 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43614}
615
clamy44e84ce2016-02-22 15:38:25616void FrameTreeNode::BeforeUnloadCanceled() {
617 // TODO(clamy): Support BeforeUnload in subframes.
618 if (!IsMainFrame())
619 return;
620
621 RenderFrameHostImpl* current_frame_host =
622 render_manager_.current_frame_host();
623 DCHECK(current_frame_host);
624 current_frame_host->ResetLoadingState();
625
clamy610c63b32017-12-22 15:05:18626 RenderFrameHostImpl* speculative_frame_host =
627 render_manager_.speculative_frame_host();
628 if (speculative_frame_host)
629 speculative_frame_host->ResetLoadingState();
630 // Note: there is no need to set an error code on the NavigationHandle here
631 // as it has not been created yet. It is only created when the
632 // BeforeUnloadACK is received.
633 if (navigation_request_)
634 ResetNavigationRequest(false, true);
clamy44e84ce2016-02-22 15:38:25635}
636
japhet61835ae12017-01-20 01:25:39637void FrameTreeNode::OnSetHasReceivedUserGesture() {
638 render_manager_.OnSetHasReceivedUserGesture();
639 replication_state_.has_received_user_gesture = true;
640}
641
Becca Hughes60af7d42017-12-12 10:53:15642void FrameTreeNode::OnSetHasReceivedUserGestureBeforeNavigation(bool value) {
643 render_manager_.OnSetHasReceivedUserGestureBeforeNavigation(value);
644 replication_state_.has_received_user_gesture_before_nav = value;
645}
646
paulmeyer322777fb2016-05-16 23:15:39647FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19648 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39649 return nullptr;
650
651 for (size_t i = 0; i < parent_->child_count(); ++i) {
652 if (parent_->child_at(i) == this) {
653 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
654 i + relative_offset >= parent_->child_count()) {
655 return nullptr;
656 }
657 return parent_->child_at(i + relative_offset);
658 }
659 }
660
661 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
662 return nullptr;
663}
664
Ian Clelland5cbaaf82017-11-27 22:00:03665void FrameTreeNode::UpdateActiveSandboxFlags(
666 blink::WebSandboxFlags sandbox_flags) {
667 // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the
668 // currently effective sandbox flags from the frame. https://crbug.com/740556
669 blink::WebSandboxFlags original_flags =
670 replication_state_.active_sandbox_flags;
671 replication_state_.active_sandbox_flags =
672 sandbox_flags | effective_frame_policy().sandbox_flags;
673 // Notify any proxies if the flags have been changed.
674 if (replication_state_.active_sandbox_flags != original_flags)
675 render_manager()->OnDidSetActiveSandboxFlags();
676}
677
[email protected]9b159a52013-10-03 17:24:55678} // namespace content