blob: d4d00597cd05957af9c5facf5975ce7f30e68efe [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
avib7348942015-12-25 20:57:1010#include "base/macros.h"
dcheng9bfa5162016-04-09 01:00:5711#include "base/memory/ptr_util.h"
dcheng23ca947d2016-05-04 20:04:1512#include "base/metrics/histogram_macros.h"
fdegansa696e5112015-04-17 01:57:5913#include "base/profiler/scoped_tracker.h"
[email protected]9b159a52013-10-03 17:24:5514#include "base/stl_util.h"
[email protected]94d0cc12013-12-18 00:07:4115#include "content/browser/frame_host/frame_tree.h"
clamydcb434c12015-04-16 19:29:1616#include "content/browser/frame_host/navigation_request.h"
[email protected]190b8c52013-11-09 01:35:4417#include "content/browser/frame_host/navigator.h"
[email protected]d4a8ca482013-10-30 21:06:4018#include "content/browser/frame_host/render_frame_host_impl.h"
[email protected]94d0cc12013-12-18 00:07:4119#include "content/browser/renderer_host/render_view_host_impl.h"
clamyf73862c42015-07-08 12:31:3320#include "content/common/frame_messages.h"
nickd30fd962015-07-27 21:51:0821#include "content/common/site_isolation_policy.h"
dmazzonie950ea232015-03-13 21:39:4522#include "content/public/browser/browser_thread.h"
carloskd80262f52015-12-16 14:40:3523#include "content/public/common/browser_side_navigation_policy.h"
alexmos6e940102016-01-19 22:47:2524#include "third_party/WebKit/public/web/WebSandboxFlags.h"
[email protected]9b159a52013-10-03 17:24:5525
26namespace content {
27
dmazzonie950ea232015-03-13 21:39:4528namespace {
29
30// This is a global map between frame_tree_node_ids and pointers to
31// FrameTreeNodes.
rob97250742015-12-10 17:45:1532typedef base::hash_map<int, FrameTreeNode*> FrameTreeNodeIdMap;
dmazzonie950ea232015-03-13 21:39:4533
rob97250742015-12-10 17:45:1534base::LazyInstance<FrameTreeNodeIdMap> g_frame_tree_node_id_map =
dmazzonie950ea232015-03-13 21:39:4535 LAZY_INSTANCE_INITIALIZER;
36
fdegansa696e5112015-04-17 01:57:5937// These values indicate the loading progress status. The minimum progress
38// value matches what Blink's ProgressTracker has traditionally used for a
39// minimum progress value.
40const double kLoadingProgressNotStarted = 0.0;
41const double kLoadingProgressMinimum = 0.1;
42const double kLoadingProgressDone = 1.0;
dmazzonie950ea232015-03-13 21:39:4543
dcheng23ca947d2016-05-04 20:04:1544void RecordUniqueNameLength(size_t length) {
45 UMA_HISTOGRAM_COUNTS("SessionRestore.FrameUniqueNameLength", length);
46}
47
fdegansa696e5112015-04-17 01:57:5948} // namespace
fdegans1d16355162015-03-26 11:58:3449
alexmose201c7cd2015-06-10 17:14:2150// This observer watches the opener of its owner FrameTreeNode and clears the
51// owner's opener if the opener is destroyed.
52class FrameTreeNode::OpenerDestroyedObserver : public FrameTreeNode::Observer {
53 public:
54 OpenerDestroyedObserver(FrameTreeNode* owner) : owner_(owner) {}
55
56 // FrameTreeNode::Observer
57 void OnFrameTreeNodeDestroyed(FrameTreeNode* node) override {
58 CHECK_EQ(owner_->opener(), node);
59 owner_->SetOpener(nullptr);
60 }
61
62 private:
63 FrameTreeNode* owner_;
64
65 DISALLOW_COPY_AND_ASSIGN(OpenerDestroyedObserver);
66};
67
vishal.b782eb5d2015-04-29 12:22:5768int FrameTreeNode::next_frame_tree_node_id_ = 1;
[email protected]9b159a52013-10-03 17:24:5569
dmazzonie950ea232015-03-13 21:39:4570// static
vishal.b782eb5d2015-04-29 12:22:5771FrameTreeNode* FrameTreeNode::GloballyFindByID(int frame_tree_node_id) {
mostynb366eaf12015-03-26 00:51:1972 DCHECK_CURRENTLY_ON(BrowserThread::UI);
rob97250742015-12-10 17:45:1573 FrameTreeNodeIdMap* nodes = g_frame_tree_node_id_map.Pointer();
74 FrameTreeNodeIdMap::iterator it = nodes->find(frame_tree_node_id);
dmazzonie950ea232015-03-13 21:39:4575 return it == nodes->end() ? nullptr : it->second;
76}
77
raymes31457802016-07-20 06:08:0978FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
79 Navigator* navigator,
80 RenderFrameHostDelegate* render_frame_delegate,
81 RenderWidgetHostDelegate* render_widget_delegate,
82 RenderFrameHostManager::Delegate* manager_delegate,
83 FrameTreeNode* parent,
84 blink::WebTreeScopeType scope,
85 const std::string& name,
86 const std::string& unique_name,
87 const FrameOwnerProperties& frame_owner_properties)
[email protected]bffc8302014-01-23 20:52:1688 : frame_tree_(frame_tree),
89 navigator_(navigator),
90 render_manager_(this,
91 render_frame_delegate,
[email protected]bffc8302014-01-23 20:52:1692 render_widget_delegate,
93 manager_delegate),
94 frame_tree_node_id_(next_frame_tree_node_id_++),
xiaochengh98488162016-05-19 15:17:5995 parent_(parent),
alexmose201c7cd2015-06-10 17:14:2196 opener_(nullptr),
97 opener_observer_(nullptr),
creisf0f069a2015-07-23 23:51:5398 has_committed_real_load_(false),
estarka886b8d2015-12-18 21:53:0899 replication_state_(
100 scope,
101 name,
lukasza464d8692016-02-22 19:26:32102 unique_name,
alexmos6e940102016-01-19 22:47:25103 blink::WebSandboxFlags::None,
estarkbd8e26f2016-03-16 23:30:37104 false /* should enforce strict mixed content checking */,
105 false /* is a potentially trustworthy unique origin */),
alexmos6e940102016-01-19 22:47:25106 pending_sandbox_flags_(blink::WebSandboxFlags::None),
lazyboy70605c32015-11-03 01:27:31107 frame_owner_properties_(frame_owner_properties),
xiaochenghb9554bb2016-05-21 14:20:48108 loading_progress_(kLoadingProgressNotStarted),
109 blame_context_(frame_tree_node_id_, parent) {
rob97250742015-12-10 17:45:15110 std::pair<FrameTreeNodeIdMap::iterator, bool> result =
dmazzonie950ea232015-03-13 21:39:45111 g_frame_tree_node_id_map.Get().insert(
112 std::make_pair(frame_tree_node_id_, this));
113 CHECK(result.second);
benjhaydend4da63d2016-03-11 21:29:33114
dcheng23ca947d2016-05-04 20:04:15115 RecordUniqueNameLength(unique_name.size());
xiaochenghb9554bb2016-05-21 14:20:48116
117 // Note: this should always be done last in the constructor.
118 blame_context_.Initialize();
alexmos998581d2015-01-22 01:01:59119}
[email protected]9b159a52013-10-03 17:24:55120
121FrameTreeNode::~FrameTreeNode() {
paulmeyerf3119f52016-05-17 17:37:19122 std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
dmazzonie950ea232015-03-13 21:39:45123 frame_tree_->FrameRemoved(this);
ericwilligers254597b2016-10-17 10:32:31124 for (auto& observer : observers_)
125 observer.OnFrameTreeNodeDestroyed(this);
alexmose201c7cd2015-06-10 17:14:21126
127 if (opener_)
128 opener_->RemoveObserver(opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45129
130 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
jam39258caf2016-11-02 14:48:18131
132 if (navigation_request_) {
133 // PlzNavigate: if a frame with a pending navigation is detached, make sure
134 // the WebContents (and its observers) update their loading state.
135 navigation_request_.reset();
136 DidStopLoading();
137 }
[email protected]9b159a52013-10-03 17:24:55138}
139
alexmose201c7cd2015-06-10 17:14:21140void FrameTreeNode::AddObserver(Observer* observer) {
141 observers_.AddObserver(observer);
142}
143
144void FrameTreeNode::RemoveObserver(Observer* observer) {
145 observers_.RemoveObserver(observer);
146}
147
[email protected]94d0cc12013-12-18 00:07:41148bool FrameTreeNode::IsMainFrame() const {
149 return frame_tree_->root() == this;
150}
151
dcheng9bfa5162016-04-09 01:00:57152FrameTreeNode* FrameTreeNode::AddChild(std::unique_ptr<FrameTreeNode> child,
nick8814e652015-12-18 01:44:12153 int process_id,
154 int frame_routing_id) {
dgroganfb22f9a2014-10-20 21:32:32155 // Child frame must always be created in the same process as the parent.
156 CHECK_EQ(process_id, render_manager_.current_host()->GetProcess()->GetID());
157
[email protected]94d0cc12013-12-18 00:07:41158 // Initialize the RenderFrameHost for the new node. We always create child
159 // frames in the same SiteInstance as the current frame, and they can swap to
160 // a different one if they navigate away.
161 child->render_manager()->Init(
[email protected]94d0cc12013-12-18 00:07:41162 render_manager_.current_host()->GetSiteInstance(),
dcheng29f5a6c2015-08-31 21:43:27163 render_manager_.current_host()->GetRoutingID(), frame_routing_id,
jambaaab3a2016-11-05 00:46:18164 MSG_ROUTING_NONE, false);
alexmos46e85ec2015-04-03 21:04:35165
166 // Other renderer processes in this BrowsingInstance may need to find out
167 // about the new frame. Create a proxy for the child frame in all
168 // SiteInstances that have a proxy for the frame's parent, since all frames
169 // in a frame tree should have the same set of proxies.
nickd30fd962015-07-27 21:51:08170 // TODO(alexmos, nick): We ought to do this for non-oopif too, for openers.
171 if (SiteIsolationPolicy::AreCrossProcessFramesPossible())
alexmos46e85ec2015-04-03 21:04:35172 render_manager_.CreateProxiesForChildFrame(child.get());
173
dcheng36b6aec92015-12-26 06:16:36174 children_.push_back(std::move(child));
nick8814e652015-12-18 01:44:12175 return children_.back().get();
[email protected]9b159a52013-10-03 17:24:55176}
177
[email protected]741fd682013-11-08 08:26:55178void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
nickb6769e632015-11-13 23:25:18179 for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
180 if (iter->get() == child) {
181 // Subtle: we need to make sure the node is gone from the tree before
182 // observers are notified of its deletion.
dcheng9bfa5162016-04-09 01:00:57183 std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
nickb6769e632015-11-13 23:25:18184 children_.erase(iter);
185 node_to_delete.reset();
186 return;
187 }
[email protected]bffc8302014-01-23 20:52:16188 }
[email protected]9b159a52013-10-03 17:24:55189}
190
[email protected]81c6c5e2014-02-13 20:20:07191void FrameTreeNode::ResetForNewProcess() {
creis9f1ab5a2016-02-26 01:30:31192 current_frame_host()->set_last_committed_url(GURL());
xiaochenghb9554bb2016-05-21 14:20:48193 blame_context_.TakeSnapshot();
[email protected]482ce3c2013-11-27 18:17:09194
nickb6769e632015-11-13 23:25:18195 // Remove child nodes from the tree, then delete them. This destruction
196 // operation will notify observers.
dcheng9bfa5162016-04-09 01:00:57197 std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
[email protected]9b159a52013-10-03 17:24:55198}
199
alexmose201c7cd2015-06-10 17:14:21200void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
201 if (opener_) {
202 opener_->RemoveObserver(opener_observer_.get());
203 opener_observer_.reset();
204 }
205
206 opener_ = opener;
207
208 if (opener_) {
209 if (!opener_observer_)
ricea641bb022016-09-02 02:51:09210 opener_observer_ = base::MakeUnique<OpenerDestroyedObserver>(this);
alexmose201c7cd2015-06-10 17:14:21211 opener_->AddObserver(opener_observer_.get());
212 }
213}
214
creisf0f069a2015-07-23 23:51:53215void FrameTreeNode::SetCurrentURL(const GURL& url) {
csharrisona3bd0b32016-10-19 18:40:48216 if (!has_committed_real_load_ && url != url::kAboutBlankURL)
creisf0f069a2015-07-23 23:51:53217 has_committed_real_load_ = true;
creis9f1ab5a2016-02-26 01:30:31218 current_frame_host()->set_last_committed_url(url);
xiaochenghb9554bb2016-05-21 14:20:48219 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53220}
221
estarkbd8e26f2016-03-16 23:30:37222void FrameTreeNode::SetCurrentOrigin(
223 const url::Origin& origin,
224 bool is_potentially_trustworthy_unique_origin) {
225 if (!origin.IsSameOriginWith(replication_state_.origin) ||
226 replication_state_.has_potentially_trustworthy_unique_origin !=
227 is_potentially_trustworthy_unique_origin) {
228 render_manager_.OnDidUpdateOrigin(origin,
229 is_potentially_trustworthy_unique_origin);
230 }
alexmosa7a4ff822015-04-27 17:59:56231 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37232 replication_state_.has_potentially_trustworthy_unique_origin =
233 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56234}
alexmosbe2f4c32015-03-10 02:30:23235
lukasza464d8692016-02-22 19:26:32236void FrameTreeNode::SetFrameName(const std::string& name,
237 const std::string& unique_name) {
238 if (name == replication_state_.name) {
239 // |unique_name| shouldn't change unless |name| changes.
240 DCHECK_EQ(unique_name, replication_state_.unique_name);
241 return;
242 }
lukasza5140a412016-09-15 21:12:30243
244 if (parent()) {
245 // Non-main frames should have a non-empty unique name.
246 DCHECK(!unique_name.empty());
247 } else {
248 // Unique name of main frames should always stay empty.
249 DCHECK(unique_name.empty());
250 }
251
dcheng23ca947d2016-05-04 20:04:15252 RecordUniqueNameLength(unique_name.size());
lukasza464d8692016-02-22 19:26:32253 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56254 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32255 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23256}
257
iclellandab749ec92016-11-23 02:00:43258void FrameTreeNode::SetFeaturePolicyHeader(const std::string& header) {
259 replication_state_.feature_policy_header = header;
260}
261
262void FrameTreeNode::ResetFeaturePolicy() {
263 replication_state_.feature_policy_header.clear();
264}
265
lukasza8e1c02e42016-05-17 20:05:10266void FrameTreeNode::AddContentSecurityPolicy(
267 const ContentSecurityPolicyHeader& header) {
268 replication_state_.accumulated_csp_headers.push_back(header);
269 render_manager_.OnDidAddContentSecurityPolicy(header);
270}
271
272void FrameTreeNode::ResetContentSecurityPolicy() {
273 replication_state_.accumulated_csp_headers.clear();
274 render_manager_.OnDidResetContentSecurityPolicy();
275}
276
mkwstf672e7ef2016-06-09 20:51:07277void FrameTreeNode::SetInsecureRequestPolicy(
278 blink::WebInsecureRequestPolicy policy) {
279 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08280 return;
mkwstf672e7ef2016-06-09 20:51:07281 render_manager_.OnEnforceInsecureRequestPolicy(policy);
282 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08283}
284
alexmos6e940102016-01-19 22:47:25285void FrameTreeNode::SetPendingSandboxFlags(
286 blink::WebSandboxFlags sandbox_flags) {
287 pending_sandbox_flags_ = sandbox_flags;
288
289 // Subframes should always inherit their parent's sandbox flags.
290 if (parent())
291 pending_sandbox_flags_ |= parent()->effective_sandbox_flags();
292}
293
mlamouria85eb3f2015-01-26 17:36:27294bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
295 if (!other || !other->child_count())
296 return false;
297
298 for (FrameTreeNode* node = parent(); node; node = node->parent()) {
299 if (node == other)
300 return true;
301 }
302
303 return false;
304}
305
alexmos9f8705a2015-05-06 19:58:59306FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39307 return GetSibling(-1);
308}
alexmos9f8705a2015-05-06 19:58:59309
paulmeyer322777fb2016-05-16 23:15:39310FrameTreeNode* FrameTreeNode::NextSibling() const {
311 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59312}
313
fdegans4a49ce932015-03-12 17:11:37314bool FrameTreeNode::IsLoading() const {
315 RenderFrameHostImpl* current_frame_host =
316 render_manager_.current_frame_host();
317 RenderFrameHostImpl* pending_frame_host =
318 render_manager_.pending_frame_host();
319
320 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39321
carloskd80262f52015-12-16 14:40:35322 if (IsBrowserSideNavigationEnabled()) {
fdegans39ff0382015-04-29 19:04:39323 if (navigation_request_)
324 return true;
clamy11e11512015-07-07 16:42:17325
326 RenderFrameHostImpl* speculative_frame_host =
327 render_manager_.speculative_frame_host();
328 if (speculative_frame_host && speculative_frame_host->is_loading())
329 return true;
fdegans39ff0382015-04-29 19:04:39330 } else {
331 if (pending_frame_host && pending_frame_host->is_loading())
332 return true;
333 }
fdegans4a49ce932015-03-12 17:11:37334 return current_frame_host->is_loading();
335}
336
alexmos6b294562015-03-05 19:24:10337bool FrameTreeNode::CommitPendingSandboxFlags() {
338 bool did_change_flags =
alexmos6e940102016-01-19 22:47:25339 pending_sandbox_flags_ != replication_state_.sandbox_flags;
340 replication_state_.sandbox_flags = pending_sandbox_flags_;
alexmos6b294562015-03-05 19:24:10341 return did_change_flags;
342}
343
carloskc49005eb2015-06-16 11:25:07344void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57345 std::unique_ptr<NavigationRequest> navigation_request) {
carloskd80262f52015-12-16 14:40:35346 CHECK(IsBrowserSideNavigationEnabled());
clamy82a2f4d2016-02-02 14:20:41347
arthursonzognic79c251c2016-08-18 15:00:37348 // This is never called when navigating to a Javascript URL. For the loading
349 // state, this matches what Blink is doing: Blink doesn't send throbber
350 // notifications for Javascript URLS.
351 DCHECK(!navigation_request->common_params().url.SchemeIs(
352 url::kJavaScriptScheme));
353
clamy44e84ce2016-02-22 15:38:25354 bool was_previously_loading = frame_tree()->IsLoading();
355
clamy82a2f4d2016-02-02 14:20:41356 // There's no need to reset the state: there's still an ongoing load, and the
357 // RenderFrameHostManager will take care of updates to the speculative
358 // RenderFrameHost in DidCreateNavigationRequest below.
clamy44e84ce2016-02-22 15:38:25359 if (was_previously_loading)
360 ResetNavigationRequest(true);
361
362 navigation_request_ = std::move(navigation_request);
clamy8e2e299202016-04-05 11:44:59363 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39364
arthursonzognic79c251c2016-08-18 15:00:37365 // TODO(fdegans): Check if this is a same-document navigation and set the
366 // proper argument.
367 DidStartLoading(true, was_previously_loading);
clamydcb434c12015-04-16 19:29:16368}
369
clamy82a2f4d2016-02-02 14:20:41370void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
carloskd80262f52015-12-16 14:40:35371 CHECK(IsBrowserSideNavigationEnabled());
fdegans39ff0382015-04-29 19:04:39372 if (!navigation_request_)
373 return;
clamy2567242a2016-02-22 18:27:38374 bool was_renderer_initiated = !navigation_request_->browser_initiated();
clamy8e2e299202016-04-05 11:44:59375 NavigationRequest::AssociatedSiteInstanceType site_instance_type =
376 navigation_request_->associated_site_instance_type();
clamydcb434c12015-04-16 19:29:16377 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39378
clamy82a2f4d2016-02-02 14:20:41379 if (keep_state)
fdegans39ff0382015-04-29 19:04:39380 return;
381
clamy82a2f4d2016-02-02 14:20:41382 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
383 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39384 DidStopLoading();
385 render_manager_.CleanUpNavigation();
clamy2567242a2016-02-22 18:27:38386
clamy8e2e299202016-04-05 11:44:59387 // When reusing the same SiteInstance, a pending WebUI may have been created
388 // on behalf of the navigation in the current RenderFrameHost. Clear it.
389 if (site_instance_type ==
390 NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
391 current_frame_host()->ClearPendingWebUI();
392 }
393
clamy2567242a2016-02-22 18:27:38394 // If the navigation is renderer-initiated, the renderer should also be
395 // informed that the navigation stopped.
396 if (was_renderer_initiated) {
397 current_frame_host()->Send(
398 new FrameMsg_Stop(current_frame_host()->GetRoutingID()));
399 }
400
clamydcb434c12015-04-16 19:29:16401}
402
fdegansa696e5112015-04-17 01:57:59403bool FrameTreeNode::has_started_loading() const {
404 return loading_progress_ != kLoadingProgressNotStarted;
405}
406
407void FrameTreeNode::reset_loading_progress() {
408 loading_progress_ = kLoadingProgressNotStarted;
409}
410
clamy44e84ce2016-02-22 15:38:25411void FrameTreeNode::DidStartLoading(bool to_different_document,
412 bool was_previously_loading) {
fdegansa696e5112015-04-17 01:57:59413 // Any main frame load to a new document should reset the load progress since
414 // it will replace the current page and any frames. The WebContents will
415 // be notified when DidChangeLoadProgress is called.
416 if (to_different_document && IsMainFrame())
417 frame_tree_->ResetLoadProgress();
418
419 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25420 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59421 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
422
423 // Set initial load progress and update overall progress. This will notify
424 // the WebContents of the load progress change.
425 DidChangeLoadProgress(kLoadingProgressMinimum);
426
427 // Notify the RenderFrameHostManager of the event.
428 render_manager()->OnDidStartLoading();
429}
430
431void FrameTreeNode::DidStopLoading() {
432 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
433 tracked_objects::ScopedTracker tracking_profile1(
434 FROM_HERE_WITH_EXPLICIT_FUNCTION(
435 "465796 FrameTreeNode::DidStopLoading::Start"));
436
437 // Set final load progress and update overall progress. This will notify
438 // the WebContents of the load progress change.
439 DidChangeLoadProgress(kLoadingProgressDone);
440
441 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
442 tracked_objects::ScopedTracker tracking_profile2(
443 FROM_HERE_WITH_EXPLICIT_FUNCTION(
444 "465796 FrameTreeNode::DidStopLoading::WCIDidStopLoading"));
445
446 // Notify the WebContents.
447 if (!frame_tree_->IsLoading())
448 navigator()->GetDelegate()->DidStopLoading();
449
450 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
451 tracked_objects::ScopedTracker tracking_profile3(
452 FROM_HERE_WITH_EXPLICIT_FUNCTION(
453 "465796 FrameTreeNode::DidStopLoading::RFHMDidStopLoading"));
454
455 // Notify the RenderFrameHostManager of the event.
456 render_manager()->OnDidStopLoading();
457
458 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
459 tracked_objects::ScopedTracker tracking_profile4(
460 FROM_HERE_WITH_EXPLICIT_FUNCTION(
461 "465796 FrameTreeNode::DidStopLoading::End"));
462}
463
464void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
465 loading_progress_ = load_progress;
466 frame_tree_->UpdateLoadProgress();
467}
468
clamyf73862c42015-07-08 12:31:33469bool FrameTreeNode::StopLoading() {
carloskd80262f52015-12-16 14:40:35470 if (IsBrowserSideNavigationEnabled())
clamyf73862c42015-07-08 12:31:33471 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33472
473 // TODO(nasko): see if child frames should send IPCs in site-per-process
474 // mode.
475 if (!IsMainFrame())
476 return true;
477
478 render_manager_.Stop();
479 return true;
480}
481
alexmos21acae52015-11-07 01:04:43482void FrameTreeNode::DidFocus() {
483 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31484 for (auto& observer : observers_)
485 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43486}
487
clamy44e84ce2016-02-22 15:38:25488void FrameTreeNode::BeforeUnloadCanceled() {
489 // TODO(clamy): Support BeforeUnload in subframes.
490 if (!IsMainFrame())
491 return;
492
493 RenderFrameHostImpl* current_frame_host =
494 render_manager_.current_frame_host();
495 DCHECK(current_frame_host);
496 current_frame_host->ResetLoadingState();
497
498 if (IsBrowserSideNavigationEnabled()) {
499 RenderFrameHostImpl* speculative_frame_host =
500 render_manager_.speculative_frame_host();
501 if (speculative_frame_host)
502 speculative_frame_host->ResetLoadingState();
503 } else {
504 RenderFrameHostImpl* pending_frame_host =
505 render_manager_.pending_frame_host();
506 if (pending_frame_host)
507 pending_frame_host->ResetLoadingState();
508 }
509}
510
paulmeyer322777fb2016-05-16 23:15:39511FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19512 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39513 return nullptr;
514
515 for (size_t i = 0; i < parent_->child_count(); ++i) {
516 if (parent_->child_at(i) == this) {
517 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
518 i + relative_offset >= parent_->child_count()) {
519 return nullptr;
520 }
521 return parent_->child_at(i + relative_offset);
522 }
523 }
524
525 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
526 return nullptr;
527}
528
[email protected]9b159a52013-10-03 17:24:55529} // namespace content