blob: 69265732010c988cb7dcac6d8716a2a133b021bf [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);
alexmose201c7cd2015-06-10 17:14:21124 FOR_EACH_OBSERVER(Observer, observers_, OnFrameTreeNodeDestroyed(this));
125
126 if (opener_)
127 opener_->RemoveObserver(opener_observer_.get());
dmazzonie950ea232015-03-13 21:39:45128
129 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
[email protected]9b159a52013-10-03 17:24:55130}
131
alexmose201c7cd2015-06-10 17:14:21132void FrameTreeNode::AddObserver(Observer* observer) {
133 observers_.AddObserver(observer);
134}
135
136void FrameTreeNode::RemoveObserver(Observer* observer) {
137 observers_.RemoveObserver(observer);
138}
139
[email protected]94d0cc12013-12-18 00:07:41140bool FrameTreeNode::IsMainFrame() const {
141 return frame_tree_->root() == this;
142}
143
dcheng9bfa5162016-04-09 01:00:57144FrameTreeNode* FrameTreeNode::AddChild(std::unique_ptr<FrameTreeNode> child,
nick8814e652015-12-18 01:44:12145 int process_id,
146 int frame_routing_id) {
dgroganfb22f9a2014-10-20 21:32:32147 // Child frame must always be created in the same process as the parent.
148 CHECK_EQ(process_id, render_manager_.current_host()->GetProcess()->GetID());
149
[email protected]94d0cc12013-12-18 00:07:41150 // Initialize the RenderFrameHost for the new node. We always create child
151 // frames in the same SiteInstance as the current frame, and they can swap to
152 // a different one if they navigate away.
153 child->render_manager()->Init(
[email protected]94d0cc12013-12-18 00:07:41154 render_manager_.current_host()->GetSiteInstance(),
dcheng29f5a6c2015-08-31 21:43:27155 render_manager_.current_host()->GetRoutingID(), frame_routing_id,
piman5d36dae2015-09-24 22:47:05156 MSG_ROUTING_NONE);
alexmos46e85ec2015-04-03 21:04:35157
158 // Other renderer processes in this BrowsingInstance may need to find out
159 // about the new frame. Create a proxy for the child frame in all
160 // SiteInstances that have a proxy for the frame's parent, since all frames
161 // in a frame tree should have the same set of proxies.
nickd30fd962015-07-27 21:51:08162 // TODO(alexmos, nick): We ought to do this for non-oopif too, for openers.
163 if (SiteIsolationPolicy::AreCrossProcessFramesPossible())
alexmos46e85ec2015-04-03 21:04:35164 render_manager_.CreateProxiesForChildFrame(child.get());
165
dcheng36b6aec92015-12-26 06:16:36166 children_.push_back(std::move(child));
nick8814e652015-12-18 01:44:12167 return children_.back().get();
[email protected]9b159a52013-10-03 17:24:55168}
169
[email protected]741fd682013-11-08 08:26:55170void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
nickb6769e632015-11-13 23:25:18171 for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
172 if (iter->get() == child) {
173 // Subtle: we need to make sure the node is gone from the tree before
174 // observers are notified of its deletion.
dcheng9bfa5162016-04-09 01:00:57175 std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
nickb6769e632015-11-13 23:25:18176 children_.erase(iter);
177 node_to_delete.reset();
178 return;
179 }
[email protected]bffc8302014-01-23 20:52:16180 }
[email protected]9b159a52013-10-03 17:24:55181}
182
[email protected]81c6c5e2014-02-13 20:20:07183void FrameTreeNode::ResetForNewProcess() {
creis9f1ab5a2016-02-26 01:30:31184 current_frame_host()->set_last_committed_url(GURL());
xiaochenghb9554bb2016-05-21 14:20:48185 blame_context_.TakeSnapshot();
[email protected]482ce3c2013-11-27 18:17:09186
nickb6769e632015-11-13 23:25:18187 // Remove child nodes from the tree, then delete them. This destruction
188 // operation will notify observers.
dcheng9bfa5162016-04-09 01:00:57189 std::vector<std::unique_ptr<FrameTreeNode>>().swap(children_);
[email protected]9b159a52013-10-03 17:24:55190}
191
alexmose201c7cd2015-06-10 17:14:21192void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
193 if (opener_) {
194 opener_->RemoveObserver(opener_observer_.get());
195 opener_observer_.reset();
196 }
197
198 opener_ = opener;
199
200 if (opener_) {
201 if (!opener_observer_)
dcheng9bfa5162016-04-09 01:00:57202 opener_observer_ = base::WrapUnique(new OpenerDestroyedObserver(this));
alexmose201c7cd2015-06-10 17:14:21203 opener_->AddObserver(opener_observer_.get());
204 }
205}
206
creisf0f069a2015-07-23 23:51:53207void FrameTreeNode::SetCurrentURL(const GURL& url) {
208 if (!has_committed_real_load_ && url != GURL(url::kAboutBlankURL))
209 has_committed_real_load_ = true;
creis9f1ab5a2016-02-26 01:30:31210 current_frame_host()->set_last_committed_url(url);
xiaochenghb9554bb2016-05-21 14:20:48211 blame_context_.TakeSnapshot();
creisf0f069a2015-07-23 23:51:53212}
213
estarkbd8e26f2016-03-16 23:30:37214void FrameTreeNode::SetCurrentOrigin(
215 const url::Origin& origin,
216 bool is_potentially_trustworthy_unique_origin) {
217 if (!origin.IsSameOriginWith(replication_state_.origin) ||
218 replication_state_.has_potentially_trustworthy_unique_origin !=
219 is_potentially_trustworthy_unique_origin) {
220 render_manager_.OnDidUpdateOrigin(origin,
221 is_potentially_trustworthy_unique_origin);
222 }
alexmosa7a4ff822015-04-27 17:59:56223 replication_state_.origin = origin;
estarkbd8e26f2016-03-16 23:30:37224 replication_state_.has_potentially_trustworthy_unique_origin =
225 is_potentially_trustworthy_unique_origin;
alexmosa7a4ff822015-04-27 17:59:56226}
alexmosbe2f4c32015-03-10 02:30:23227
lukasza464d8692016-02-22 19:26:32228void FrameTreeNode::SetFrameName(const std::string& name,
229 const std::string& unique_name) {
230 if (name == replication_state_.name) {
231 // |unique_name| shouldn't change unless |name| changes.
232 DCHECK_EQ(unique_name, replication_state_.unique_name);
233 return;
234 }
dcheng23ca947d2016-05-04 20:04:15235 RecordUniqueNameLength(unique_name.size());
lukasza464d8692016-02-22 19:26:32236 render_manager_.OnDidUpdateName(name, unique_name);
alexmosa7a4ff822015-04-27 17:59:56237 replication_state_.name = name;
lukasza464d8692016-02-22 19:26:32238 replication_state_.unique_name = unique_name;
alexmosbe2f4c32015-03-10 02:30:23239}
240
lukasza8e1c02e42016-05-17 20:05:10241void FrameTreeNode::AddContentSecurityPolicy(
242 const ContentSecurityPolicyHeader& header) {
243 replication_state_.accumulated_csp_headers.push_back(header);
244 render_manager_.OnDidAddContentSecurityPolicy(header);
245}
246
247void FrameTreeNode::ResetContentSecurityPolicy() {
248 replication_state_.accumulated_csp_headers.clear();
249 render_manager_.OnDidResetContentSecurityPolicy();
250}
251
mkwstf672e7ef2016-06-09 20:51:07252void FrameTreeNode::SetInsecureRequestPolicy(
253 blink::WebInsecureRequestPolicy policy) {
254 if (policy == replication_state_.insecure_request_policy)
estarka886b8d2015-12-18 21:53:08255 return;
mkwstf672e7ef2016-06-09 20:51:07256 render_manager_.OnEnforceInsecureRequestPolicy(policy);
257 replication_state_.insecure_request_policy = policy;
estarka886b8d2015-12-18 21:53:08258}
259
alexmos6e940102016-01-19 22:47:25260void FrameTreeNode::SetPendingSandboxFlags(
261 blink::WebSandboxFlags sandbox_flags) {
262 pending_sandbox_flags_ = sandbox_flags;
263
264 // Subframes should always inherit their parent's sandbox flags.
265 if (parent())
266 pending_sandbox_flags_ |= parent()->effective_sandbox_flags();
267}
268
mlamouria85eb3f2015-01-26 17:36:27269bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
270 if (!other || !other->child_count())
271 return false;
272
273 for (FrameTreeNode* node = parent(); node; node = node->parent()) {
274 if (node == other)
275 return true;
276 }
277
278 return false;
279}
280
alexmos9f8705a2015-05-06 19:58:59281FrameTreeNode* FrameTreeNode::PreviousSibling() const {
paulmeyer322777fb2016-05-16 23:15:39282 return GetSibling(-1);
283}
alexmos9f8705a2015-05-06 19:58:59284
paulmeyer322777fb2016-05-16 23:15:39285FrameTreeNode* FrameTreeNode::NextSibling() const {
286 return GetSibling(1);
alexmos9f8705a2015-05-06 19:58:59287}
288
fdegans4a49ce932015-03-12 17:11:37289bool FrameTreeNode::IsLoading() const {
290 RenderFrameHostImpl* current_frame_host =
291 render_manager_.current_frame_host();
292 RenderFrameHostImpl* pending_frame_host =
293 render_manager_.pending_frame_host();
294
295 DCHECK(current_frame_host);
fdegans39ff0382015-04-29 19:04:39296
carloskd80262f52015-12-16 14:40:35297 if (IsBrowserSideNavigationEnabled()) {
fdegans39ff0382015-04-29 19:04:39298 if (navigation_request_)
299 return true;
clamy11e11512015-07-07 16:42:17300
301 RenderFrameHostImpl* speculative_frame_host =
302 render_manager_.speculative_frame_host();
303 if (speculative_frame_host && speculative_frame_host->is_loading())
304 return true;
fdegans39ff0382015-04-29 19:04:39305 } else {
306 if (pending_frame_host && pending_frame_host->is_loading())
307 return true;
308 }
fdegans4a49ce932015-03-12 17:11:37309 return current_frame_host->is_loading();
310}
311
alexmos6b294562015-03-05 19:24:10312bool FrameTreeNode::CommitPendingSandboxFlags() {
313 bool did_change_flags =
alexmos6e940102016-01-19 22:47:25314 pending_sandbox_flags_ != replication_state_.sandbox_flags;
315 replication_state_.sandbox_flags = pending_sandbox_flags_;
alexmos6b294562015-03-05 19:24:10316 return did_change_flags;
317}
318
carloskc49005eb2015-06-16 11:25:07319void FrameTreeNode::CreatedNavigationRequest(
dcheng9bfa5162016-04-09 01:00:57320 std::unique_ptr<NavigationRequest> navigation_request) {
carloskd80262f52015-12-16 14:40:35321 CHECK(IsBrowserSideNavigationEnabled());
clamy82a2f4d2016-02-02 14:20:41322
arthursonzognic79c251c2016-08-18 15:00:37323 // This is never called when navigating to a Javascript URL. For the loading
324 // state, this matches what Blink is doing: Blink doesn't send throbber
325 // notifications for Javascript URLS.
326 DCHECK(!navigation_request->common_params().url.SchemeIs(
327 url::kJavaScriptScheme));
328
clamy44e84ce2016-02-22 15:38:25329 bool was_previously_loading = frame_tree()->IsLoading();
330
clamy82a2f4d2016-02-02 14:20:41331 // There's no need to reset the state: there's still an ongoing load, and the
332 // RenderFrameHostManager will take care of updates to the speculative
333 // RenderFrameHost in DidCreateNavigationRequest below.
clamy44e84ce2016-02-22 15:38:25334 if (was_previously_loading)
335 ResetNavigationRequest(true);
336
337 navigation_request_ = std::move(navigation_request);
clamy8e2e299202016-04-05 11:44:59338 render_manager()->DidCreateNavigationRequest(navigation_request_.get());
fdegans39ff0382015-04-29 19:04:39339
arthursonzognic79c251c2016-08-18 15:00:37340 // TODO(fdegans): Check if this is a same-document navigation and set the
341 // proper argument.
342 DidStartLoading(true, was_previously_loading);
clamydcb434c12015-04-16 19:29:16343}
344
clamy82a2f4d2016-02-02 14:20:41345void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
carloskd80262f52015-12-16 14:40:35346 CHECK(IsBrowserSideNavigationEnabled());
fdegans39ff0382015-04-29 19:04:39347 if (!navigation_request_)
348 return;
clamy2567242a2016-02-22 18:27:38349 bool was_renderer_initiated = !navigation_request_->browser_initiated();
clamy8e2e299202016-04-05 11:44:59350 NavigationRequest::AssociatedSiteInstanceType site_instance_type =
351 navigation_request_->associated_site_instance_type();
clamydcb434c12015-04-16 19:29:16352 navigation_request_.reset();
fdegans39ff0382015-04-29 19:04:39353
clamy82a2f4d2016-02-02 14:20:41354 if (keep_state)
fdegans39ff0382015-04-29 19:04:39355 return;
356
clamy82a2f4d2016-02-02 14:20:41357 // The RenderFrameHostManager should clean up any speculative RenderFrameHost
358 // it created for the navigation. Also register that the load stopped.
fdegans39ff0382015-04-29 19:04:39359 DidStopLoading();
360 render_manager_.CleanUpNavigation();
clamy2567242a2016-02-22 18:27:38361
clamy8e2e299202016-04-05 11:44:59362 // When reusing the same SiteInstance, a pending WebUI may have been created
363 // on behalf of the navigation in the current RenderFrameHost. Clear it.
364 if (site_instance_type ==
365 NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
366 current_frame_host()->ClearPendingWebUI();
367 }
368
clamy2567242a2016-02-22 18:27:38369 // If the navigation is renderer-initiated, the renderer should also be
370 // informed that the navigation stopped.
371 if (was_renderer_initiated) {
372 current_frame_host()->Send(
373 new FrameMsg_Stop(current_frame_host()->GetRoutingID()));
374 }
375
clamydcb434c12015-04-16 19:29:16376}
377
fdegansa696e5112015-04-17 01:57:59378bool FrameTreeNode::has_started_loading() const {
379 return loading_progress_ != kLoadingProgressNotStarted;
380}
381
382void FrameTreeNode::reset_loading_progress() {
383 loading_progress_ = kLoadingProgressNotStarted;
384}
385
clamy44e84ce2016-02-22 15:38:25386void FrameTreeNode::DidStartLoading(bool to_different_document,
387 bool was_previously_loading) {
fdegansa696e5112015-04-17 01:57:59388 // Any main frame load to a new document should reset the load progress since
389 // it will replace the current page and any frames. The WebContents will
390 // be notified when DidChangeLoadProgress is called.
391 if (to_different_document && IsMainFrame())
392 frame_tree_->ResetLoadProgress();
393
394 // Notify the WebContents.
clamy44e84ce2016-02-22 15:38:25395 if (!was_previously_loading)
fdegansa696e5112015-04-17 01:57:59396 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
397
398 // Set initial load progress and update overall progress. This will notify
399 // the WebContents of the load progress change.
400 DidChangeLoadProgress(kLoadingProgressMinimum);
401
402 // Notify the RenderFrameHostManager of the event.
403 render_manager()->OnDidStartLoading();
404}
405
406void FrameTreeNode::DidStopLoading() {
407 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
408 tracked_objects::ScopedTracker tracking_profile1(
409 FROM_HERE_WITH_EXPLICIT_FUNCTION(
410 "465796 FrameTreeNode::DidStopLoading::Start"));
411
412 // Set final load progress and update overall progress. This will notify
413 // the WebContents of the load progress change.
414 DidChangeLoadProgress(kLoadingProgressDone);
415
416 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
417 tracked_objects::ScopedTracker tracking_profile2(
418 FROM_HERE_WITH_EXPLICIT_FUNCTION(
419 "465796 FrameTreeNode::DidStopLoading::WCIDidStopLoading"));
420
421 // Notify the WebContents.
422 if (!frame_tree_->IsLoading())
423 navigator()->GetDelegate()->DidStopLoading();
424
425 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
426 tracked_objects::ScopedTracker tracking_profile3(
427 FROM_HERE_WITH_EXPLICIT_FUNCTION(
428 "465796 FrameTreeNode::DidStopLoading::RFHMDidStopLoading"));
429
430 // Notify the RenderFrameHostManager of the event.
431 render_manager()->OnDidStopLoading();
432
433 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
434 tracked_objects::ScopedTracker tracking_profile4(
435 FROM_HERE_WITH_EXPLICIT_FUNCTION(
436 "465796 FrameTreeNode::DidStopLoading::End"));
437}
438
439void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
440 loading_progress_ = load_progress;
441 frame_tree_->UpdateLoadProgress();
442}
443
clamyf73862c42015-07-08 12:31:33444bool FrameTreeNode::StopLoading() {
carloskd80262f52015-12-16 14:40:35445 if (IsBrowserSideNavigationEnabled())
clamyf73862c42015-07-08 12:31:33446 ResetNavigationRequest(false);
clamyf73862c42015-07-08 12:31:33447
448 // TODO(nasko): see if child frames should send IPCs in site-per-process
449 // mode.
450 if (!IsMainFrame())
451 return true;
452
453 render_manager_.Stop();
454 return true;
455}
456
alexmos21acae52015-11-07 01:04:43457void FrameTreeNode::DidFocus() {
458 last_focus_time_ = base::TimeTicks::Now();
459 FOR_EACH_OBSERVER(Observer, observers_, OnFrameTreeNodeFocused(this));
460}
461
clamy44e84ce2016-02-22 15:38:25462void FrameTreeNode::BeforeUnloadCanceled() {
463 // TODO(clamy): Support BeforeUnload in subframes.
464 if (!IsMainFrame())
465 return;
466
467 RenderFrameHostImpl* current_frame_host =
468 render_manager_.current_frame_host();
469 DCHECK(current_frame_host);
470 current_frame_host->ResetLoadingState();
471
472 if (IsBrowserSideNavigationEnabled()) {
473 RenderFrameHostImpl* speculative_frame_host =
474 render_manager_.speculative_frame_host();
475 if (speculative_frame_host)
476 speculative_frame_host->ResetLoadingState();
477 } else {
478 RenderFrameHostImpl* pending_frame_host =
479 render_manager_.pending_frame_host();
480 if (pending_frame_host)
481 pending_frame_host->ResetLoadingState();
482 }
483}
484
paulmeyer322777fb2016-05-16 23:15:39485FrameTreeNode* FrameTreeNode::GetSibling(int relative_offset) const {
paulmeyerf3119f52016-05-17 17:37:19486 if (!parent_ || !parent_->child_count())
paulmeyer322777fb2016-05-16 23:15:39487 return nullptr;
488
489 for (size_t i = 0; i < parent_->child_count(); ++i) {
490 if (parent_->child_at(i) == this) {
491 if ((relative_offset < 0 && static_cast<size_t>(-relative_offset) > i) ||
492 i + relative_offset >= parent_->child_count()) {
493 return nullptr;
494 }
495 return parent_->child_at(i + relative_offset);
496 }
497 }
498
499 NOTREACHED() << "FrameTreeNode not found in its parent's children.";
500 return nullptr;
501}
502
[email protected]9b159a52013-10-03 17:24:55503} // namespace content