blob: 7e35d15a35d93ba893837274a80aaf68347467ed [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,
piman5d36dae2015-09-24 22:47:05164 MSG_ROUTING_NONE);
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
lukasza8e1c02e42016-05-17 20:05:10258void FrameTreeNode::AddContentSecurityPolicy(
259 const ContentSecurityPolicyHeader& header) {
260 replication_state_.accumulated_csp_headers.push_back(header);
261 render_manager_.OnDidAddContentSecurityPolicy(header);
262}
263
264void FrameTreeNode::ResetContentSecurityPolicy() {
265 replication_state_.accumulated_csp_headers.clear();
266 render_manager_.OnDidResetContentSecurityPolicy();
267}
268
mkwstf672e7ef2016-06-09 20:51:07269void FrameTreeNode::SetInsecureRequestPolicy(
270 blink::WebInsecureRequestPolicy policy) {
271 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08272 return;
mkwstf672e7ef2016-06-09 20:51:07273 render_manager_.OnEnforceInsecureRequestPolicy(policy);
274 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08275}
276
alexmos6e940102016-01-19 22:47:25277void FrameTreeNode::SetPendingSandboxFlags(
278 blink::WebSandboxFlags sandbox_flags) {
279 pending_sandbox_flags_ = sandbox_flags;
280
281 // Subframes should always inherit their parent's sandbox flags.
282 if (parent())
283 pending_sandbox_flags_ |= parent()->effective_sandbox_flags();
284}
285
mlamouria85eb3f2015-01-26 17:36:27286bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
287 if (!other || !other->child_count())
288 return false;
289
290 for (FrameTreeNode* node = parent(); node; node = node->parent()) {
291 if (node == other)
292 return true;
293 }
294
295 return false;
296}
297
alexmos9f8705a2015-05-06 19:58:59298FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39299 return GetSibling(-1);
300}
alexmos9f8705a2015-05-06 19:58:59301
paulmeyer322777fb2016-05-16 23:15:39302FrameTreeNode* FrameTreeNode::NextSibling() const {
303 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59304}
305
fdegans4a49ce932015-03-12 17:11:37306bool FrameTreeNode::IsLoading() const {
307 RenderFrameHostImpl* current_frame_host =
308 render_manager_.current_frame_host();
309 RenderFrameHostImpl* pending_frame_host =
310 render_manager_.pending_frame_host();
311
312 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39313
carloskd80262f52015-12-16 14:40:35314 if (IsBrowserSideNavigationEnabled()) {
fdegans39ff0382015-04-29 19:04:39315 if (navigation_request_)
316 return true;
clamy11e11512015-07-07 16:42:17317
318 RenderFrameHostImpl* speculative_frame_host =
319 render_manager_.speculative_frame_host();
320 if (speculative_frame_host && speculative_frame_host->is_loading())
321 return true;
fdegans39ff0382015-04-29 19:04:39322 } else {
323 if (pending_frame_host && pending_frame_host->is_loading())
324 return true;
325 }
fdegans4a49ce932015-03-12 17:11:37326 return current_frame_host->is_loading();
327}
328
alexmos6b294562015-03-05 19:24:10329bool FrameTreeNode::CommitPendingSandboxFlags() {
330 bool did_change_flags =
alexmos6e940102016-01-19 22:47:25331 pending_sandbox_flags_ != replication_state_.sandbox_flags;
332 replication_state_.sandbox_flags = pending_sandbox_flags_;
alexmos6b294562015-03-05 19:24:10333 return did_change_flags;
334}
335
carloskc49005eb2015-06-16 11:25:07336void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57337 std::unique_ptr<NavigationRequest> navigation_request) {
carloskd80262f52015-12-16 14:40:35338 CHECK(IsBrowserSideNavigationEnabled());
clamy82a2f4d2016-02-02 14:20:41339
arthursonzognic79c251c2016-08-18 15:00:37340 // This is never called when navigating to a Javascript URL. For the loading
341 // state, this matches what Blink is doing: Blink doesn't send throbber
342 // notifications for Javascript URLS.
343 DCHECK(!navigation_request->common_params().url.SchemeIs(
344 url::kJavaScriptScheme));
345
clamy44e84ce2016-02-22 15:38:25346 bool was_previously_loading = frame_tree()->IsLoading();
347
clamy82a2f4d2016-02-02 14:20:41348 // There's no need to reset the state: there's still an ongoing load, and the
349 // RenderFrameHostManager will take care of updates to the speculative
350 // RenderFrameHost in DidCreateNavigationRequest below.
clamy44e84ce2016-02-22 15:38:25351 if (was_previously_loading)
352 ResetNavigationRequest(true);
353
354 navigation_request_ = std::move(navigation_request);
clamy8e2e299202016-04-05 11:44:59355 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39356
arthursonzognic79c251c2016-08-18 15:00:37357 // TODO(fdegans): Check if this is a same-document navigation and set the
358 // proper argument.
359 DidStartLoading(true, was_previously_loading);
clamydcb434c12015-04-16 19:29:16360}
361
clamy82a2f4d2016-02-02 14:20:41362void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
carloskd80262f52015-12-16 14:40:35363 CHECK(IsBrowserSideNavigationEnabled());
fdegans39ff0382015-04-29 19:04:39364 if (!navigation_request_)
365 return;
clamy2567242a2016-02-22 18:27:38366 bool was_renderer_initiated = !navigation_request_->browser_initiated();
clamy8e2e299202016-04-05 11:44:59367 NavigationRequest::AssociatedSiteInstanceType site_instance_type =
368 navigation_request_->associated_site_instance_type();
clamydcb434c12015-04-16 19:29:16369 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39370
clamy82a2f4d2016-02-02 14:20:41371 if (keep_state)
fdegans39ff0382015-04-29 19:04:39372 return;
373
clamy82a2f4d2016-02-02 14:20:41374 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
375 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39376 DidStopLoading();
377 render_manager_.CleanUpNavigation();
clamy2567242a2016-02-22 18:27:38378
clamy8e2e299202016-04-05 11:44:59379 // When reusing the same SiteInstance, a pending WebUI may have been created
380 // on behalf of the navigation in the current RenderFrameHost. Clear it.
381 if (site_instance_type ==
382 NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
383 current_frame_host()->ClearPendingWebUI();
384 }
385
clamy2567242a2016-02-22 18:27:38386 // If the navigation is renderer-initiated, the renderer should also be
387 // informed that the navigation stopped.
388 if (was_renderer_initiated) {
389 current_frame_host()->Send(
390 new FrameMsg_Stop(current_frame_host()->GetRoutingID()));
391 }
392
clamydcb434c12015-04-16 19:29:16393}
394
fdegansa696e5112015-04-17 01:57:59395bool FrameTreeNode::has_started_loading() const {
396 return loading_progress_ != kLoadingProgressNotStarted;
397}
398
399void FrameTreeNode::reset_loading_progress() {
400 loading_progress_ = kLoadingProgressNotStarted;
401}
402
clamy44e84ce2016-02-22 15:38:25403void FrameTreeNode::DidStartLoading(bool to_different_document,
404 bool was_previously_loading) {
fdegansa696e5112015-04-17 01:57:59405 // Any main frame load to a new document should reset the load progress since
406 // it will replace the current page and any frames. The WebContents will
407 // be notified when DidChangeLoadProgress is called.
408 if (to_different_document && IsMainFrame())
409 frame_tree_->ResetLoadProgress();
410
411 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25412 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59413 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
414
415 // Set initial load progress and update overall progress. This will notify
416 // the WebContents of the load progress change.
417 DidChangeLoadProgress(kLoadingProgressMinimum);
418
419 // Notify the RenderFrameHostManager of the event.
420 render_manager()->OnDidStartLoading();
421}
422
423void FrameTreeNode::DidStopLoading() {
424 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
425 tracked_objects::ScopedTracker tracking_profile1(
426 FROM_HERE_WITH_EXPLICIT_FUNCTION(
427 "465796 FrameTreeNode::DidStopLoading::Start"));
428
429 // Set final load progress and update overall progress. This will notify
430 // the WebContents of the load progress change.
431 DidChangeLoadProgress(kLoadingProgressDone);
432
433 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
434 tracked_objects::ScopedTracker tracking_profile2(
435 FROM_HERE_WITH_EXPLICIT_FUNCTION(
436 "465796 FrameTreeNode::DidStopLoading::WCIDidStopLoading"));
437
438 // Notify the WebContents.
439 if (!frame_tree_->IsLoading())
440 navigator()->GetDelegate()->DidStopLoading();
441
442 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
443 tracked_objects::ScopedTracker tracking_profile3(
444 FROM_HERE_WITH_EXPLICIT_FUNCTION(
445 "465796 FrameTreeNode::DidStopLoading::RFHMDidStopLoading"));
446
447 // Notify the RenderFrameHostManager of the event.
448 render_manager()->OnDidStopLoading();
449
450 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
451 tracked_objects::ScopedTracker tracking_profile4(
452 FROM_HERE_WITH_EXPLICIT_FUNCTION(
453 "465796 FrameTreeNode::DidStopLoading::End"));
454}
455
456void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
457 loading_progress_ = load_progress;
458 frame_tree_->UpdateLoadProgress();
459}
460
clamyf73862c42015-07-08 12:31:33461bool FrameTreeNode::StopLoading() {
carloskd80262f52015-12-16 14:40:35462 if (IsBrowserSideNavigationEnabled())
clamyf73862c42015-07-08 12:31:33463 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33464
465 // TODO(nasko): see if child frames should send IPCs in site-per-process
466 // mode.
467 if (!IsMainFrame())
468 return true;
469
470 render_manager_.Stop();
471 return true;
472}
473
alexmos21acae52015-11-07 01:04:43474void FrameTreeNode::DidFocus() {
475 last_focus_time_ = base::TimeTicks::Now();
ericwilligers254597b2016-10-17 10:32:31476 for (auto& observer : observers_)
477 observer.OnFrameTreeNodeFocused(this);
alexmos21acae52015-11-07 01:04:43478}
479
clamy44e84ce2016-02-22 15:38:25480void FrameTreeNode::BeforeUnloadCanceled() {
481 // TODO(clamy): Support BeforeUnload in subframes.
482 if (!IsMainFrame())
483 return;
484
485 RenderFrameHostImpl* current_frame_host =
486 render_manager_.current_frame_host();
487 DCHECK(current_frame_host);
488 current_frame_host->ResetLoadingState();
489
490 if (IsBrowserSideNavigationEnabled()) {
491 RenderFrameHostImpl* speculative_frame_host =
492 render_manager_.speculative_frame_host();
493 if (speculative_frame_host)
494 speculative_frame_host->ResetLoadingState();
495 } else {
496 RenderFrameHostImpl* pending_frame_host =
497 render_manager_.pending_frame_host();
498 if (pending_frame_host)
499 pending_frame_host->ResetLoadingState();
500 }
501}
502
paulmeyer322777fb2016-05-16 23:15:39503FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19504 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39505 return nullptr;
506
507 for (size_t i = 0; i < parent_->child_count(); ++i) {
508 if (parent_->child_at(i) == this) {
509 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
510 i + relative_offset >= parent_->child_count()) {
511 return nullptr;
512 }
513 return parent_->child_at(i + relative_offset);
514 }
515 }
516
517 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
518 return nullptr;
519}
520
[email protected]9b159a52013-10-03 17:24:55521} // namespace content