Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / content / browser / frame_host / frame_tree_node.cc
blob15679805e80deb41c13d12ad670af4db0ea014df
1 // 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.
5 #include "content/browser/frame_host/frame_tree_node.h"
7 #include <queue>
9 #include "base/command_line.h"
10 #include "base/profiler/scoped_tracker.h"
11 #include "base/stl_util.h"
12 #include "content/browser/frame_host/frame_tree.h"
13 #include "content/browser/frame_host/navigation_request.h"
14 #include "content/browser/frame_host/navigator.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/common/content_switches.h"
20 namespace content {
22 namespace {
24 // This is a global map between frame_tree_node_ids and pointers to
25 // FrameTreeNodes.
26 typedef base::hash_map<int64, FrameTreeNode*> FrameTreeNodeIDMap;
28 base::LazyInstance<FrameTreeNodeIDMap> g_frame_tree_node_id_map =
29 LAZY_INSTANCE_INITIALIZER;
31 // These values indicate the loading progress status. The minimum progress
32 // value matches what Blink's ProgressTracker has traditionally used for a
33 // minimum progress value.
34 const double kLoadingProgressNotStarted = 0.0;
35 const double kLoadingProgressMinimum = 0.1;
36 const double kLoadingProgressDone = 1.0;
38 } // namespace
40 int64 FrameTreeNode::next_frame_tree_node_id_ = 1;
42 // static
43 FrameTreeNode* FrameTreeNode::GloballyFindByID(int64 frame_tree_node_id) {
44 DCHECK_CURRENTLY_ON(BrowserThread::UI);
45 FrameTreeNodeIDMap* nodes = g_frame_tree_node_id_map.Pointer();
46 FrameTreeNodeIDMap::iterator it = nodes->find(frame_tree_node_id);
47 return it == nodes->end() ? nullptr : it->second;
50 FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
51 Navigator* navigator,
52 RenderFrameHostDelegate* render_frame_delegate,
53 RenderViewHostDelegate* render_view_delegate,
54 RenderWidgetHostDelegate* render_widget_delegate,
55 RenderFrameHostManager::Delegate* manager_delegate,
56 const std::string& name)
57 : frame_tree_(frame_tree),
58 navigator_(navigator),
59 render_manager_(this,
60 render_frame_delegate,
61 render_view_delegate,
62 render_widget_delegate,
63 manager_delegate),
64 frame_tree_node_id_(next_frame_tree_node_id_++),
65 parent_(NULL),
66 replication_state_(name),
67 effective_sandbox_flags_(SandboxFlags::NONE),
68 loading_progress_(kLoadingProgressNotStarted) {
69 std::pair<FrameTreeNodeIDMap::iterator, bool> result =
70 g_frame_tree_node_id_map.Get().insert(
71 std::make_pair(frame_tree_node_id_, this));
72 CHECK(result.second);
75 FrameTreeNode::~FrameTreeNode() {
76 frame_tree_->FrameRemoved(this);
78 g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
81 bool FrameTreeNode::IsMainFrame() const {
82 return frame_tree_->root() == this;
85 void FrameTreeNode::AddChild(scoped_ptr<FrameTreeNode> child,
86 int process_id,
87 int frame_routing_id) {
88 // Child frame must always be created in the same process as the parent.
89 CHECK_EQ(process_id, render_manager_.current_host()->GetProcess()->GetID());
91 // Initialize the RenderFrameHost for the new node. We always create child
92 // frames in the same SiteInstance as the current frame, and they can swap to
93 // a different one if they navigate away.
94 child->render_manager()->Init(
95 render_manager_.current_host()->GetSiteInstance()->GetBrowserContext(),
96 render_manager_.current_host()->GetSiteInstance(),
97 render_manager_.current_host()->GetRoutingID(),
98 frame_routing_id);
99 child->set_parent(this);
101 // Other renderer processes in this BrowsingInstance may need to find out
102 // about the new frame. Create a proxy for the child frame in all
103 // SiteInstances that have a proxy for the frame's parent, since all frames
104 // in a frame tree should have the same set of proxies.
105 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
106 switches::kSitePerProcess))
107 render_manager_.CreateProxiesForChildFrame(child.get());
109 children_.push_back(child.release());
112 void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
113 std::vector<FrameTreeNode*>::iterator iter;
114 for (iter = children_.begin(); iter != children_.end(); ++iter) {
115 if ((*iter) == child)
116 break;
119 if (iter != children_.end()) {
120 // Subtle: we need to make sure the node is gone from the tree before
121 // observers are notified of its deletion.
122 scoped_ptr<FrameTreeNode> node_to_delete(*iter);
123 children_.weak_erase(iter);
124 node_to_delete.reset();
128 void FrameTreeNode::ResetForNewProcess() {
129 current_url_ = GURL();
131 // The children may not have been cleared if a cross-process navigation
132 // commits before the old process cleans everything up. Make sure the child
133 // nodes get deleted before swapping to a new process.
134 ScopedVector<FrameTreeNode> old_children = children_.Pass();
135 old_children.clear(); // May notify observers.
138 void FrameTreeNode::SetFrameName(const std::string& name) {
139 replication_state_.name = name;
141 // Notify this frame's proxies about the updated name.
142 render_manager_.OnDidUpdateName(name);
145 bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
146 if (!other || !other->child_count())
147 return false;
149 for (FrameTreeNode* node = parent(); node; node = node->parent()) {
150 if (node == other)
151 return true;
154 return false;
157 bool FrameTreeNode::IsLoading() const {
158 RenderFrameHostImpl* current_frame_host =
159 render_manager_.current_frame_host();
160 RenderFrameHostImpl* pending_frame_host =
161 render_manager_.pending_frame_host();
163 DCHECK(current_frame_host);
164 // TODO(fdegans): Change the implementation logic for PlzNavigate once
165 // DidStartLoading and DidStopLoading are properly called.
166 if (pending_frame_host && pending_frame_host->is_loading())
167 return true;
168 return current_frame_host->is_loading();
171 bool FrameTreeNode::CommitPendingSandboxFlags() {
172 bool did_change_flags =
173 effective_sandbox_flags_ != replication_state_.sandbox_flags;
174 effective_sandbox_flags_ = replication_state_.sandbox_flags;
175 return did_change_flags;
178 void FrameTreeNode::SetNavigationRequest(
179 scoped_ptr<NavigationRequest> navigation_request) {
180 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
181 switches::kEnableBrowserSideNavigation));
182 ResetNavigationRequest(false);
183 // TODO(clamy): perform the StartLoading logic here.
184 navigation_request_ = navigation_request.Pass();
187 void FrameTreeNode::ResetNavigationRequest(bool is_commit) {
188 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
189 switches::kEnableBrowserSideNavigation));
190 // Upon commit the current NavigationRequest will be reset. There should be no
191 // cleanup performed since the navigation is still ongoing. If the reset
192 // corresponds to a cancelation, the RenderFrameHostManager should clean up
193 // any speculative RenderFrameHost it created for the navigation.
194 if (navigation_request_ && !is_commit) {
195 // TODO(clamy): perform the StopLoading logic.
196 render_manager_.CleanUpNavigation();
198 navigation_request_.reset();
201 bool FrameTreeNode::has_started_loading() const {
202 return loading_progress_ != kLoadingProgressNotStarted;
205 void FrameTreeNode::reset_loading_progress() {
206 loading_progress_ = kLoadingProgressNotStarted;
209 void FrameTreeNode::DidStartLoading(bool to_different_document) {
210 // Any main frame load to a new document should reset the load progress since
211 // it will replace the current page and any frames. The WebContents will
212 // be notified when DidChangeLoadProgress is called.
213 if (to_different_document && IsMainFrame())
214 frame_tree_->ResetLoadProgress();
216 // Notify the WebContents.
217 if (!frame_tree_->IsLoading())
218 navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
220 // Set initial load progress and update overall progress. This will notify
221 // the WebContents of the load progress change.
222 DidChangeLoadProgress(kLoadingProgressMinimum);
224 // Notify the RenderFrameHostManager of the event.
225 render_manager()->OnDidStartLoading();
228 void FrameTreeNode::DidStopLoading() {
229 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
230 tracked_objects::ScopedTracker tracking_profile1(
231 FROM_HERE_WITH_EXPLICIT_FUNCTION(
232 "465796 FrameTreeNode::DidStopLoading::Start"));
234 // Set final load progress and update overall progress. This will notify
235 // the WebContents of the load progress change.
236 DidChangeLoadProgress(kLoadingProgressDone);
238 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
239 tracked_objects::ScopedTracker tracking_profile2(
240 FROM_HERE_WITH_EXPLICIT_FUNCTION(
241 "465796 FrameTreeNode::DidStopLoading::WCIDidStopLoading"));
243 // Notify the WebContents.
244 if (!frame_tree_->IsLoading())
245 navigator()->GetDelegate()->DidStopLoading();
247 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
248 tracked_objects::ScopedTracker tracking_profile3(
249 FROM_HERE_WITH_EXPLICIT_FUNCTION(
250 "465796 FrameTreeNode::DidStopLoading::RFHMDidStopLoading"));
252 // Notify the RenderFrameHostManager of the event.
253 render_manager()->OnDidStopLoading();
255 // TODO(erikchen): Remove ScopedTracker below once crbug.com/465796 is fixed.
256 tracked_objects::ScopedTracker tracking_profile4(
257 FROM_HERE_WITH_EXPLICIT_FUNCTION(
258 "465796 FrameTreeNode::DidStopLoading::End"));
261 void FrameTreeNode::DidChangeLoadProgress(double load_progress) {
262 loading_progress_ = load_progress;
263 frame_tree_->UpdateLoadProgress();
266 } // namespace content