blob: c4682bd5bbeb6484acce9ef149fe7fff58aa7854 [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
7#include <queue>
dcheng36b6aec92015-12-26 06:16:368#include <utility>
[email protected]9b159a52013-10-03 17:24:559
scottmg6ece5ae2017-02-01 18:25:1910#include "base/lazy_instance.h"
avib7348942015-12-25 20:57:1011#include "base/macros.h"
dcheng9bfa5162016-04-09 01:00:5712#include "base/memory/ptr_util.h"
dcheng23ca947d2016-05-04 20:04:1513#include "base/metrics/histogram_macros.h"
fdegansa696e5112015-04-17 01:57:5914#include "base/profiler/scoped_tracker.h"
[email protected]9b159a52013-10-03 17:24:5515#include "base/stl_util.h"
[email protected]94d0cc12013-12-18 00:07:4116#include "content/browser/frame_host/frame_tree.h"
clamydcb434c12015-04-16 19:29:1617#include "content/browser/frame_host/navigation_request.h"
[email protected]190b8c52013-11-09 01:35:4418#include "content/browser/frame_host/navigator.h"
[email protected]d4a8ca482013-10-30 21:06:4019#include "content/browser/frame_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4120#include "content/browser/renderer_host/render_view_host_impl.h"
clamyf73862c42015-07-08 12:31:3321#include "content/common/frame_messages.h"
nickd30fd962015-07-27 21:51:0822#include "content/common/site_isolation_policy.h"
dmazzonie950ea232015-03-13 21:39:4523#include "content/public/browser/browser_thread.h"
carloskd80262f52015-12-16 14:40:3524#include "content/public/common/browser_side_navigation_policy.h"
alexmos6e940102016-01-19 22:47:2525#include "third_party/WebKit/public/web/WebSandboxFlags.h"
[email protected]9b159a52013-10-03 17:24:5526
27namespace content {
28
dmazzonie950ea232015-03-13 21:39:4529namespace {
30
31// This is a global map between frame_tree_node_ids and pointers to
32// FrameTreeNodes.
rob97250742015-12-10 17:45:1533typedef base::hash_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4534
scottmg5e65e3a2017-03-08 08:48:4635base::LazyInstance<FrameTreeNodeIdMap>::DestructorAtExit
36 g_frame_tree_node_id_map = LAZY_INSTANCE_INITIALIZER;
dmazzonie950ea232015-03-13 21:39:4537
fdegansa696e5112015-04-17 01:57:5938// These values indicate the loading progress status. The minimum progress
39// value matches what Blink's ProgressTracker has traditionally used for a
40// minimum progress value.
41const double kLoadingProgressNotStarted = 0.0;
42const double kLoadingProgressMinimum = 0.1;
43const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4544
dcheng23ca947d2016-05-04 20:04:1545void RecordUniqueNameLength(size_t length) {
46 UMA_HISTOGRAM_COUNTS("SessionRestore.FrameUniqueNameLength", length);
47}
48
fdegansa696e5112015-04-17 01:57:5949} // namespace
fdegans1d16355162015-03-26 11:58:3450
alexmose201c7cd2015-06-10 17:14:2151// This observer watches the opener of its owner FrameTreeNode and clears the
52// owner's opener if the opener is destroyed.
53class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
54 public:
jochen6004a362017-02-04 00:11:4055 OpenerDestroyedObserver(FrameTreeNode* owner, bool observing_original_opener)
56 : owner_(owner), observing_original_opener_(observing_original_opener) {}
alexmose201c7cd2015-06-10 17:14:2157
58 // FrameTreeNode::Observer
59 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
jochen6004a362017-02-04 00:11:4060 if (observing_original_opener_) {
61 CHECK_EQ(owner_->original_opener(), node);
62 owner_->SetOriginalOpener(nullptr);
63 } else {
64 CHECK_EQ(owner_->opener(), node);
65 owner_->SetOpener(nullptr);
66 }
alexmose201c7cd2015-06-10 17:14:2167 }
68
69 private:
70 FrameTreeNode* owner_;
jochen6004a362017-02-04 00:11:4071 bool observing_original_opener_;
alexmose201c7cd2015-06-10 17:14:2172
73 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
74};
75
vishal.b782eb5d2015-04-29 12:22:5776int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5577
dmazzonie950ea232015-03-13 21:39:4578// static
vishal.b782eb5d2015-04-29 12:22:5779FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1980 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1581 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
82 FrameTreeNodeIdMap::iterator it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4583 return it == nodes->end() ? nullptr : it->second;
84}
85
raymes31457802016-07-20 06:08:0986FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
87 Navigator* navigator,
88 RenderFrameHostDelegate* render_frame_delegate,
89 RenderWidgetHostDelegate* render_widget_delegate,
90 RenderFrameHostManager::Delegate* manager_delegate,
91 FrameTreeNode* parent,
92 blink::WebTreeScopeType scope,
93 const std::string& name,
94 const std::string& unique_name,
95 const FrameOwnerProperties& frame_owner_properties)
[email protected]bffc8302014-01-23 20:52:1696 : frame_tree_(frame_tree),
97 navigator_(navigator),
98 render_manager_(this,
99 render_frame_delegate,
[email protected]bffc8302014-01-23 20:52:16100 render_widget_delegate,
101 manager_delegate),
102 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:59103 parent_(parent),
alexmose201c7cd2015-06-10 17:14:21104 opener_(nullptr),
105 opener_observer_(nullptr),
jochen6004a362017-02-04 00:11:40106 original_opener_(nullptr),
107 original_opener_observer_(nullptr),
creisf0f069a2015-07-23 23:51:53108 has_committed_real_load_(false),
engedy6e2e0992017-05-25 18:58:42109 is_collapsed_(false),
estarka886b8d2015-12-18 21:53:08110 replication_state_(
111 scope,
112 name,
lukasza464d8692016-02-22 19:26:32113 unique_name,
Blink Reformat1c4d759e2017-04-09 16:34:54114 blink::WebSandboxFlags::kNone,
estarkbd8e26f2016-03-16 23:30:37115 false /* should enforce strict mixed content checking */,
japhet61835ae12017-01-20 01:25:39116 false /* is a potentially trustworthy unique origin */,
117 false /* has received a user gesture */),
Blink Reformat1c4d759e2017-04-09 16:34:54118 pending_sandbox_flags_(blink::WebSandboxFlags::kNone),
lazyboy70605c32015-11-03 01:27:31119 frame_owner_properties_(frame_owner_properties),
xiaochenghb9554bb2016-05-21 14:20:48120 loading_progress_(kLoadingProgressNotStarted),
121 blame_context_(frame_tree_node_id_, parent) {
rob97250742015-12-10 17:45:15122 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45123 g_frame_tree_node_id_map.Get().insert(
124 std::make_pair(frame_tree_node_id_, this));
125 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33126
dcheng23ca947d2016-05-04 20:04:15127 RecordUniqueNameLength(unique_name.size());
xiaochenghb9554bb2016-05-21 14:20:48128
129 // Note: this should always be done last in the constructor.
130 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59131}
[email protected]9b159a52013-10-03 17:24:55132
133FrameTreeNode::~FrameTreeNode() {
paulmeyerf3119f52016-05-17 17:37:19134 std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
dmazzonie950ea232015-03-13 21:39:45135 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31136 for (auto& observer : observers_)
137 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21138
139 if (opener_)
140 opener_->RemoveObserver(opener_observer_.get());
jochen6004a362017-02-04 00:11:40141 if (original_opener_)
142 original_opener_->RemoveObserver(original_opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45143
144 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18145
146 if (navigation_request_) {
147 // PlzNavigate: if a frame with a pending navigation is detached, make sure
148 // the WebContents (and its observers) update their loading state.
149 navigation_request_.reset();
150 DidStopLoading();
151 }
[email protected]9b159a52013-10-03 17:24:55152}
153
alexmose201c7cd2015-06-10 17:14:21154void FrameTreeNode::AddObserver(Observer* observer) {
155 observers_.AddObserver(observer);
156}
157
158void FrameTreeNode::RemoveObserver(Observer* observer) {
159 observers_.RemoveObserver(observer);
160}
161
[email protected]94d0cc12013-12-18 00:07:41162bool FrameTreeNode::IsMainFrame() const {
163 return frame_tree_->root() == this;
164}
165
dcheng9bfa5162016-04-09 01:00:57166FrameTreeNode* FrameTreeNode::AddChild(std::unique_ptr<FrameTreeNode> child,
nick8814e652015-12-18 01:44:12167 int process_id,
168 int frame_routing_id) {
dgroganfb22f9a2014-10-20 21:32:32169 // Child frame must always be created in the same process as the parent.
170 CHECK_EQ(process_id, render_manager_.current_host()->GetProcess()->GetID());
171
[email protected]94d0cc12013-12-18 00:07:41172 // Initialize the RenderFrameHost for the new node. We always create child
173 // frames in the same SiteInstance as the current frame, and they can swap to
174 // a different one if they navigate away.
175 child->render_manager()->Init(
[email protected]94d0cc12013-12-18 00:07:41176 render_manager_.current_host()->GetSiteInstance(),
dcheng29f5a6c2015-08-31 21:43:27177 render_manager_.current_host()->GetRoutingID(), frame_routing_id,
jambaaab3a2016-11-05 00:46:18178 MSG_ROUTING_NONE, false);
alexmos46e85ec2015-04-03 21:04:35179
180 // Other renderer processes in this BrowsingInstance may need to find out
181 // about the new frame. Create a proxy for the child frame in all
182 // SiteInstances that have a proxy for the frame's parent, since all frames
183 // in a frame tree should have the same set of proxies.
nickd30fd962015-07-27 21:51:08184 // TODO(alexmos, nick): We ought to do this for non-oopif too, for openers.
185 if (SiteIsolationPolicy::AreCrossProcessFramesPossible())
alexmos46e85ec2015-04-03 21:04:35186 render_manager_.CreateProxiesForChildFrame(child.get());
187
dcheng36b6aec92015-12-26 06:16:36188 children_.push_back(std::move(child));
nick8814e652015-12-18 01:44:12189 return children_.back().get();
[email protected]9b159a52013-10-03 17:24:55190}
191
[email protected]741fd682013-11-08 08:26:55192void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
nickb6769e632015-11-13 23:25:18193 for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
194 if (iter->get() == child) {
195 // Subtle: we need to make sure the node is gone from the tree before
196 // observers are notified of its deletion.
dcheng9bfa5162016-04-09 01:00:57197 std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
nickb6769e632015-11-13 23:25:18198 children_.erase(iter);
199 node_to_delete.reset();
200 return;
201 }
[email protected]bffc8302014-01-23 20:52:16202 }
[email protected]9b159a52013-10-03 17:24:55203}
204
[email protected]81c6c5e2014-02-13 20:20:07205void FrameTreeNode::ResetForNewProcess() {
Erik Chen173bf3042017-07-31 06:06:21206 current_frame_host()->SetLastCommittedUrl(GURL());
xiaochenghb9554bb2016-05-21 14:20:48207 blame_context_.TakeSnapshot();
[email protected]482ce3c2013-11-27 18:17:09208
nickb6769e632015-11-13 23:25:18209 // Remove child nodes from the tree, then delete them. This destruction
210 // operation will notify observers.
dcheng9bfa5162016-04-09 01:00:57211 std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
[email protected]9b159a52013-10-03 17:24:55212}
213
alexmose201c7cd2015-06-10 17:14:21214void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
215 if (opener_) {
216 opener_->RemoveObserver(opener_observer_.get());
217 opener_observer_.reset();
218 }
219
220 opener_ = opener;
221
222 if (opener_) {
223 if (!opener_observer_)
jochen6004a362017-02-04 00:11:40224 opener_observer_ = base::MakeUnique<OpenerDestroyedObserver>(this, false);
alexmose201c7cd2015-06-10 17:14:21225 opener_->AddObserver(opener_observer_.get());
226 }
227}
228
jochen6004a362017-02-04 00:11:40229void FrameTreeNode::SetOriginalOpener(FrameTreeNode* opener) {
230 DCHECK(!original_opener_ || !opener);
avi8d1aa162017-03-27 18:27:37231 DCHECK(opener == nullptr || !opener->parent());
jochen6004a362017-02-04 00:11:40232
233 original_opener_ = opener;
234
235 if (original_opener_) {
236 DCHECK(!original_opener_observer_);
237 original_opener_observer_ =
238 base::MakeUnique<OpenerDestroyedObserver>(this, true);
239 original_opener_->AddObserver(original_opener_observer_.get());
240 }
241}
242
creisf0f069a2015-07-23 23:51:53243void FrameTreeNode::SetCurrentURL(const GURL& url) {
csharrisona3bd0b32016-10-19 18:40:48244 if (!has_committed_real_load_ && url != url::kAboutBlankURL)
creisf0f069a2015-07-23 23:51:53245 has_committed_real_load_ = true;
Erik Chen173bf3042017-07-31 06:06:21246 current_frame_host()->SetLastCommittedUrl(url);
xiaochenghb9554bb2016-05-21 14:20:48247 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53248}
249
estarkbd8e26f2016-03-16 23:30:37250void FrameTreeNode::SetCurrentOrigin(
251 const url::Origin& origin,
252 bool is_potentially_trustworthy_unique_origin) {
253 if (!origin.IsSameOriginWith(replication_state_.origin) ||
254 replication_state_.has_potentially_trustworthy_unique_origin !=
255 is_potentially_trustworthy_unique_origin) {
256 render_manager_.OnDidUpdateOrigin(origin,
257 is_potentially_trustworthy_unique_origin);
258 }
alexmosa7a4ff822015-04-27 17:59:56259 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37260 replication_state_.has_potentially_trustworthy_unique_origin =
261 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56262}
alexmosbe2f4c32015-03-10 02:30:23263
engedy6e2e0992017-05-25 18:58:42264void FrameTreeNode::SetCollapsed(bool collapsed) {
265 DCHECK(!IsMainFrame());
266 if (is_collapsed_ == collapsed)
267 return;
268
269 is_collapsed_ = collapsed;
270 render_manager_.OnDidChangeCollapsedState(collapsed);
271}
272
lukasza464d8692016-02-22 19:26:32273void FrameTreeNode::SetFrameName(const std::string& name,
274 const std::string& unique_name) {
275 if (name == replication_state_.name) {
276 // |unique_name| shouldn't change unless |name| changes.
277 DCHECK_EQ(unique_name, replication_state_.unique_name);
278 return;
279 }
lukasza5140a412016-09-15 21:12:30280
281 if (parent()) {
282 // Non-main frames should have a non-empty unique name.
283 DCHECK(!unique_name.empty());
284 } else {
285 // Unique name of main frames should always stay empty.
286 DCHECK(unique_name.empty());
287 }
288
dcheng23ca947d2016-05-04 20:04:15289 RecordUniqueNameLength(unique_name.size());
lukasza464d8692016-02-22 19:26:32290 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56291 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32292 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23293}
294
raymesd405a052016-12-05 23:41:34295void FrameTreeNode::SetFeaturePolicyHeader(
iclelland4dbcfdcb2017-02-02 23:51:49296 const ParsedFeaturePolicyHeader& parsed_header) {
raymesd405a052016-12-05 23:41:34297 replication_state_.feature_policy_header = parsed_header;
iclellandab749ec92016-11-23 02:00:43298}
299
iclelland2c79efe22017-02-09 22:44:03300void FrameTreeNode::ResetFeaturePolicyHeader() {
iclellandab749ec92016-11-23 02:00:43301 replication_state_.feature_policy_header.clear();
302}
303
arthursonzogni662aa652017-03-28 11:09:50304void FrameTreeNode::AddContentSecurityPolicies(
305 const std::vector<ContentSecurityPolicyHeader>& headers) {
306 replication_state_.accumulated_csp_headers.insert(
307 replication_state_.accumulated_csp_headers.end(), headers.begin(),
308 headers.end());
309 render_manager_.OnDidAddContentSecurityPolicies(headers);
lukasza8e1c02e42016-05-17 20:05:10310}
311
arthursonzogni7fed384c2017-03-18 03:07:34312void FrameTreeNode::ResetCspHeaders() {
lukasza8e1c02e42016-05-17 20:05:10313 replication_state_.accumulated_csp_headers.clear();
314 render_manager_.OnDidResetContentSecurityPolicy();
315}
316
mkwstf672e7ef2016-06-09 20:51:07317void FrameTreeNode::SetInsecureRequestPolicy(
318 blink::WebInsecureRequestPolicy policy) {
319 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08320 return;
mkwstf672e7ef2016-06-09 20:51:07321 render_manager_.OnEnforceInsecureRequestPolicy(policy);
322 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08323}
324
alexmos6e940102016-01-19 22:47:25325void FrameTreeNode::SetPendingSandboxFlags(
326 blink::WebSandboxFlags sandbox_flags) {
327 pending_sandbox_flags_ = sandbox_flags;
328
329 // Subframes should always inherit their parent's sandbox flags.
330 if (parent())
331 pending_sandbox_flags_ |= parent()->effective_sandbox_flags();
332}
333
iclelland92f8c0b2017-04-19 12:43:05334void FrameTreeNode::SetPendingContainerPolicy(
335 const ParsedFeaturePolicyHeader& container_policy) {
336 // This should only be called on subframes; container policy is not mutable on
337 // main frame.
338 DCHECK(!IsMainFrame());
339 pending_container_policy_ = container_policy;
340}
341
mlamouria85eb3f2015-01-26 17:36:27342bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
343 if (!other || !other->child_count())
344 return false;
345
346 for (FrameTreeNode* node = parent(); node; node = node->parent()) {
347 if (node == other)
348 return true;
349 }
350
351 return false;
352}
353
alexmos9f8705a2015-05-06 19:58:59354FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39355 return GetSibling(-1);
356}
alexmos9f8705a2015-05-06 19:58:59357
paulmeyer322777fb2016-05-16 23:15:39358FrameTreeNode* FrameTreeNode::NextSibling() const {
359 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59360}
361
fdegans4a49ce932015-03-12 17:11:37362bool FrameTreeNode::IsLoading() const {
363 RenderFrameHostImpl* current_frame_host =
364 render_manager_.current_frame_host();
365 RenderFrameHostImpl* pending_frame_host =
366 render_manager_.pending_frame_host();
367
368 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39369
carloskd80262f52015-12-16 14:40:35370 if (IsBrowserSideNavigationEnabled()) {
fdegans39ff0382015-04-29 19:04:39371 if (navigation_request_)
372 return true;
clamy11e11512015-07-07 16:42:17373
374 RenderFrameHostImpl* speculative_frame_host =
375 render_manager_.speculative_frame_host();
376 if (speculative_frame_host && speculative_frame_host->is_loading())
377 return true;
fdegans39ff0382015-04-29 19:04:39378 } else {
379 if (pending_frame_host && pending_frame_host->is_loading())
380 return true;
381 }
fdegans4a49ce932015-03-12 17:11:37382 return current_frame_host->is_loading();
383}
384
iclelland92f8c0b2017-04-19 12:43:05385bool FrameTreeNode::CommitPendingFramePolicy() {
alexmos6b294562015-03-05 19:24:10386 bool did_change_flags =
alexmos6e940102016-01-19 22:47:25387 pending_sandbox_flags_ != replication_state_.sandbox_flags;
iclelland92f8c0b2017-04-19 12:43:05388 bool did_change_container_policy =
389 pending_container_policy_ != replication_state_.container_policy;
390 if (did_change_flags)
391 replication_state_.sandbox_flags = pending_sandbox_flags_;
392 if (did_change_container_policy)
393 replication_state_.container_policy = pending_container_policy_;
394 return did_change_flags || did_change_container_policy;
alexmos6b294562015-03-05 19:24:10395}
396
carloskc49005eb2015-06-16 11:25:07397void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57398 std::unique_ptr<NavigationRequest> navigation_request) {
carloskd80262f52015-12-16 14:40:35399 CHECK(IsBrowserSideNavigationEnabled());
clamy82a2f4d2016-02-02 14:20:41400
arthursonzognic79c251c2016-08-18 15:00:37401 // This is never called when navigating to a Javascript URL. For the loading
402 // state, this matches what Blink is doing: Blink doesn't send throbber
403 // notifications for Javascript URLS.
404 DCHECK(!navigation_request->common_params().url.SchemeIs(
405 url::kJavaScriptScheme));
406
clamy44e84ce2016-02-22 15:38:25407 bool was_previously_loading = frame_tree()->IsLoading();
408
clamy82a2f4d2016-02-02 14:20:41409 // There's no need to reset the state: there's still an ongoing load, and the
410 // RenderFrameHostManager will take care of updates to the speculative
411 // RenderFrameHost in DidCreateNavigationRequest below.
jamcd0b7b22017-03-24 22:13:05412 if (was_previously_loading) {
clamy080e7962017-05-25 00:44:18413 if (navigation_request_ && navigation_request_->navigation_handle()) {
jamcd0b7b22017-03-24 22:13:05414 // Mark the old request as aborted.
415 navigation_request_->navigation_handle()->set_net_error_code(
416 net::ERR_ABORTED);
417 }
clamya86695b2017-03-23 14:45:48418 ResetNavigationRequest(true, true);
jamcd0b7b22017-03-24 22:13:05419 }
clamy44e84ce2016-02-22 15:38:25420
421 navigation_request_ = std::move(navigation_request);
clamy8e2e299202016-04-05 11:44:59422 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39423
arthursonzogni92f18682017-02-08 23:00:04424 bool to_different_document = !FrameMsg_Navigate_Type::IsSameDocument(
425 navigation_request_->common_params().navigation_type);
426
427 DidStartLoading(to_different_document, was_previously_loading);
clamydcb434c12015-04-16 19:29:16428}
429
clamya86695b2017-03-23 14:45:48430void FrameTreeNode::ResetNavigationRequest(bool keep_state,
431 bool inform_renderer) {
carloskd80262f52015-12-16 14:40:35432 CHECK(IsBrowserSideNavigationEnabled());
fdegans39ff0382015-04-29 19:04:39433 if (!navigation_request_)
434 return;
clamy2567242a2016-02-22 18:27:38435 bool was_renderer_initiated = !navigation_request_->browser_initiated();
clamy8e2e299202016-04-05 11:44:59436 NavigationRequest::AssociatedSiteInstanceType site_instance_type =
437 navigation_request_->associated_site_instance_type();
clamydcb434c12015-04-16 19:29:16438 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39439
clamy82a2f4d2016-02-02 14:20:41440 if (keep_state)
fdegans39ff0382015-04-29 19:04:39441 return;
442
clamy82a2f4d2016-02-02 14:20:41443 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
444 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39445 DidStopLoading();
446 render_manager_.CleanUpNavigation();
clamy2567242a2016-02-22 18:27:38447
clamy8e2e299202016-04-05 11:44:59448 // When reusing the same SiteInstance, a pending WebUI may have been created
449 // on behalf of the navigation in the current RenderFrameHost. Clear it.
450 if (site_instance_type ==
451 NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
452 current_frame_host()->ClearPendingWebUI();
453 }
454
clamy2567242a2016-02-22 18:27:38455 // If the navigation is renderer-initiated, the renderer should also be
clamya86695b2017-03-23 14:45:48456 // informed that the navigation stopped if needed. In the case the renderer
457 // process asked for the navigation to be aborted, e.g. following a
458 // document.open, do not send an IPC to the renderer process as it already
459 // expects the navigation to stop.
460 if (was_renderer_initiated && inform_renderer) {
clamy2567242a2016-02-22 18:27:38461 current_frame_host()->Send(
462 new FrameMsg_Stop(current_frame_host()->GetRoutingID()));
463 }
464
clamydcb434c12015-04-16 19:29:16465}
466
fdegansa696e5112015-04-17 01:57:59467bool FrameTreeNode::has_started_loading() const {
468 return loading_progress_ != kLoadingProgressNotStarted;
469}
470
471void FrameTreeNode::reset_loading_progress() {
472 loading_progress_ = kLoadingProgressNotStarted;
473}
474
clamy44e84ce2016-02-22 15:38:25475void FrameTreeNode::DidStartLoading(bool to_different_document,
476 bool was_previously_loading) {
fdegansa696e5112015-04-17 01:57:59477 // Any main frame load to a new document should reset the load progress since
478 // it will replace the current page and any frames. The WebContents will
479 // be notified when DidChangeLoadProgress is called.
480 if (to_different_document && IsMainFrame())
481 frame_tree_->ResetLoadProgress();
482
483 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25484 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59485 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
486
487 // Set initial load progress and update overall progress. This will notify
488 // the WebContents of the load progress change.
489 DidChangeLoadProgress(kLoadingProgressMinimum);
490
491 // Notify the RenderFrameHostManager of the event.
492 render_manager()->OnDidStartLoading();
493}
494
495void FrameTreeNode::DidStopLoading() {
fdegansa696e5112015-04-17 01:57:59496 // Set final load progress and update overall progress. This will notify
497 // the WebContents of the load progress change.
498 DidChangeLoadProgress(kLoadingProgressDone);
499
fdegansa696e5112015-04-17 01:57:59500 // Notify the WebContents.
501 if (!frame_tree_->IsLoading())
502 navigator()->GetDelegate()->DidStopLoading();
503
fdegansa696e5112015-04-17 01:57:59504 // Notify the RenderFrameHostManager of the event.
505 render_manager()->OnDidStopLoading();
fdegansa696e5112015-04-17 01:57:59506}
507
508void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
509 loading_progress_ = load_progress;
510 frame_tree_->UpdateLoadProgress();
511}
512
clamyf73862c42015-07-08 12:31:33513bool FrameTreeNode::StopLoading() {
jam0299edae2017-03-10 00:49:22514 if (IsBrowserSideNavigationEnabled()) {
515 if (navigation_request_) {
clamy080e7962017-05-25 00:44:18516 int expected_pending_nav_entry_id = navigation_request_->nav_entry_id();
517 if (navigation_request_->navigation_handle()) {
518 navigation_request_->navigation_handle()->set_net_error_code(
519 net::ERR_ABORTED);
520 expected_pending_nav_entry_id =
521 navigation_request_->navigation_handle()->pending_nav_entry_id();
522 }
523 navigator_->DiscardPendingEntryIfNeeded(expected_pending_nav_entry_id);
jam0299edae2017-03-10 00:49:22524 }
clamya86695b2017-03-23 14:45:48525 ResetNavigationRequest(false, true);
jam0299edae2017-03-10 00:49:22526 }
clamyf73862c42015-07-08 12:31:33527
528 // TODO(nasko): see if child frames should send IPCs in site-per-process
529 // mode.
530 if (!IsMainFrame())
531 return true;
532
533 render_manager_.Stop();
534 return true;
535}
536
alexmos21acae52015-11-07 01:04:43537void FrameTreeNode::DidFocus() {
538 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31539 for (auto& observer : observers_)
540 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43541}
542
clamy44e84ce2016-02-22 15:38:25543void FrameTreeNode::BeforeUnloadCanceled() {
544 // TODO(clamy): Support BeforeUnload in subframes.
545 if (!IsMainFrame())
546 return;
547
548 RenderFrameHostImpl* current_frame_host =
549 render_manager_.current_frame_host();
550 DCHECK(current_frame_host);
551 current_frame_host->ResetLoadingState();
552
553 if (IsBrowserSideNavigationEnabled()) {
554 RenderFrameHostImpl* speculative_frame_host =
555 render_manager_.speculative_frame_host();
556 if (speculative_frame_host)
557 speculative_frame_host->ResetLoadingState();
clamy080e7962017-05-25 00:44:18558 // Note: there is no need to set an error code on the NavigationHandle here
559 // as it has not been created yet. It is only created when the
560 // BeforeUnloadACK is received.
561 if (navigation_request_)
562 ResetNavigationRequest(false, true);
clamy44e84ce2016-02-22 15:38:25563 } else {
564 RenderFrameHostImpl* pending_frame_host =
565 render_manager_.pending_frame_host();
566 if (pending_frame_host)
567 pending_frame_host->ResetLoadingState();
568 }
569}
570
japhet61835ae12017-01-20 01:25:39571void FrameTreeNode::OnSetHasReceivedUserGesture() {
572 render_manager_.OnSetHasReceivedUserGesture();
573 replication_state_.has_received_user_gesture = true;
574}
575
paulmeyer322777fb2016-05-16 23:15:39576FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19577 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39578 return nullptr;
579
580 for (size_t i = 0; i < parent_->child_count(); ++i) {
581 if (parent_->child_at(i) == this) {
582 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
583 i + relative_offset >= parent_->child_count()) {
584 return nullptr;
585 }
586 return parent_->child_at(i + relative_offset);
587 }
588 }
589
590 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
591 return nullptr;
592}
593
[email protected]9b159a52013-10-03 17:24:55594} // namespace content