blob: 45a9e98075162eba6c9e75ac282bf93cc2241ab9 [file] [log] [blame]
danakjc492bf82020-09-09 20:02:441// 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
5#ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_
6#define CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_
7
8#include <stdint.h>
9
10#include <iterator>
11#include <memory>
12#include <string>
13#include <unordered_map>
14
15#include "base/callback.h"
16#include "base/containers/queue.h"
17#include "base/gtest_prod_util.h"
18#include "base/macros.h"
19#include "content/browser/renderer_host/navigator.h"
20#include "content/browser/renderer_host/navigator_delegate.h"
21#include "content/browser/renderer_host/render_frame_host_manager.h"
22#include "content/common/content_export.h"
23#include "mojo/public/cpp/bindings/pending_receiver.h"
24#include "services/service_manager/public/mojom/interface_provider.mojom.h"
25#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
26#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-forward.h"
27
28namespace blink {
29struct FramePolicy;
30} // namespace blink
31
32namespace content {
33
Carlos Caballero40b0efd2021-01-26 11:55:0034class BrowserContext;
danakjc492bf82020-09-09 20:02:4435class RenderFrameHostDelegate;
36class RenderViewHostDelegate;
37class RenderViewHostImpl;
38class RenderFrameHostManager;
39class RenderWidgetHostDelegate;
Carlos Caballero40b0efd2021-01-26 11:55:0040class SiteInstance;
danakjc492bf82020-09-09 20:02:4441
42// Represents the frame tree for a page. With the exception of the main frame,
43// all FrameTreeNodes will be created/deleted in response to frame attach and
44// detach events in the DOM.
45//
46// The main frame's FrameTreeNode is special in that it is reused. This allows
47// it to serve as an anchor for state that needs to persist across top-level
48// page navigations.
49//
50// TODO(ajwong): Move NavigationController ownership to the main frame
51// FrameTreeNode. Possibly expose access to it from here.
52//
53// This object is only used on the UI thread.
54class CONTENT_EXPORT FrameTree {
55 public:
56 class NodeRange;
57
58 class CONTENT_EXPORT NodeIterator
59 : public std::iterator<std::forward_iterator_tag, FrameTreeNode> {
60 public:
61 NodeIterator(const NodeIterator& other);
62 ~NodeIterator();
63
64 NodeIterator& operator++();
65
66 bool operator==(const NodeIterator& rhs) const;
67 bool operator!=(const NodeIterator& rhs) const { return !(*this == rhs); }
68
69 FrameTreeNode* operator*() { return current_node_; }
70
71 private:
72 friend class NodeRange;
73
74 NodeIterator(FrameTreeNode* starting_node,
75 FrameTreeNode* root_of_subtree_to_skip);
76
77 FrameTreeNode* current_node_;
78 FrameTreeNode* const root_of_subtree_to_skip_;
79 base::queue<FrameTreeNode*> queue_;
80 };
81
82 class CONTENT_EXPORT NodeRange {
83 public:
84 NodeIterator begin();
85 NodeIterator end();
86
87 private:
88 friend class FrameTree;
89
90 NodeRange(FrameTreeNode* root, FrameTreeNode* root_of_subtree_to_skip);
91
92 FrameTreeNode* const root_;
93 FrameTreeNode* const root_of_subtree_to_skip_;
94 };
95
Carlos Caballero03262522021-02-05 14:49:5896 class CONTENT_EXPORT Delegate {
97 public:
98 // A RenderFrameHost in the specified |frame_tree_node| started loading a
99 // new document. This corresponds to browser UI starting to show a spinner
100 // or other visual indicator for loading. This method is only invoked if the
101 // FrameTree hadn't been previously loading. |to_different_document| will be
102 // true unless the load is a fragment navigation, or triggered by
103 // history.pushState/replaceState.
104 virtual void DidStartLoading(FrameTreeNode* frame_tree_node,
105 bool to_different_document) = 0;
106
107 // This is called when all nodes in the FrameTreestoppedloading. This
108 // corresponds to the browser UI stop showing a spinner or other visual
109 // indicator for loading.
110 virtual void DidStopLoading() = 0;
111
112 // The load progress was changed.
113 virtual void DidChangeLoadProgress() = 0;
Carlos Caballero6ff6ace2021-02-05 16:53:00114
115 // Returns true when the active RenderWidgetHostView should be hidden.
116 virtual bool IsHidden() = 0;
Carlos Caballero03262522021-02-05 14:49:58117 };
118
danakjc492bf82020-09-09 20:02:44119 // A set of delegates are remembered here so that we can create
120 // RenderFrameHostManagers.
Carlos Caballero40b0efd2021-01-26 11:55:00121 FrameTree(BrowserContext* browser_context,
Carlos Caballero03262522021-02-05 14:49:58122 Delegate* delegate,
Carlos Caballero40b0efd2021-01-26 11:55:00123 NavigationControllerDelegate* navigation_controller_delegate,
danakjc492bf82020-09-09 20:02:44124 NavigatorDelegate* navigator_delegate,
125 RenderFrameHostDelegate* render_frame_delegate,
126 RenderViewHostDelegate* render_view_delegate,
127 RenderWidgetHostDelegate* render_widget_delegate,
128 RenderFrameHostManager::Delegate* manager_delegate);
129 ~FrameTree();
130
Carlos Caballero40b0efd2021-01-26 11:55:00131 // Initializes the main frame for this FrameTree. That is it creates the
132 // initial RenderFrameHost in the root node's RenderFrameHostManager. This
133 // method will call back into the delegates so it should only be called once
134 // they have completed their initialization.
135 // TODO(carlscab): It would be great if initialization could happened in the
136 // constructor so we do not leave objects in a half initialized state.
137 void Init(SiteInstance* main_frame_site_instance,
138 bool renderer_initiated_creation,
139 const std::string& main_frame_name);
140
danakjc492bf82020-09-09 20:02:44141 FrameTreeNode* root() const { return root_; }
142
Sreeja Kamishetty46f762c2021-02-05 07:52:46143 void set_is_prerendering(bool is_prerendering);
144
145 bool is_prerendering() const { return is_prerendering_; }
146
Carlos Caballero03262522021-02-05 14:49:58147 Delegate* delegate() { return delegate_; }
148
danakjc492bf82020-09-09 20:02:44149 // Delegates for RenderFrameHosts, RenderViewHosts, RenderWidgetHosts and
150 // RenderFrameHostManagers. These can be kept centrally on the FrameTree
151 // because they are expected to be the same for all frames on a given
152 // FrameTree.
153 RenderFrameHostDelegate* render_frame_delegate() {
154 return render_frame_delegate_;
155 }
156 RenderViewHostDelegate* render_view_delegate() {
157 return render_view_delegate_;
158 }
159 RenderWidgetHostDelegate* render_widget_delegate() {
160 return render_widget_delegate_;
161 }
162 RenderFrameHostManager::Delegate* manager_delegate() {
163 return manager_delegate_;
164 }
165 const std::unordered_map<int /* SiteInstance ID */, RenderViewHostImpl*>&
166 render_view_hosts() const {
167 return render_view_host_map_;
168 }
169
170 // Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
171 // of this FrameTree.
172 FrameTreeNode* FindByID(int frame_tree_node_id);
173
174 // Returns the FrameTreeNode with the given renderer-specific |routing_id|.
175 FrameTreeNode* FindByRoutingID(int process_id, int routing_id);
176
177 // Returns the first frame in this tree with the given |name|, or the main
178 // frame if |name| is empty.
179 // Note that this does NOT support pseudo-names like _self, _top, and _blank,
180 // nor searching other FrameTrees (unlike blink::WebView::findFrameByName).
181 FrameTreeNode* FindByName(const std::string& name);
182
183 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
184 // breadth-first traversal order.
185 NodeRange Nodes();
186
187 // Returns a range to iterate over all FrameTreeNodes in a subtree of the
188 // frame tree, starting from |subtree_root|.
189 NodeRange SubtreeNodes(FrameTreeNode* subtree_root);
190
191 // Adds a new child frame to the frame tree. |process_id| is required to
192 // disambiguate |new_routing_id|, and it must match the process of the
193 // |parent| node. Otherwise no child is added and this method returns false.
194 // |interface_provider_receiver| is the receiver end of the InterfaceProvider
195 // interface through which the child RenderFrame can access Mojo services
196 // exposed by the corresponding RenderFrameHost. The caller takes care of
Antonio Sartoridb967c52021-01-20 09:54:30197 // sending the client end of the interface down to the
198 // RenderFrame. |policy_container_bind_params|, if not null, is used for
199 // binding Blink's policy container to the new RenderFrameHost's
200 // PolicyContainerHost. This is only needed if this frame is the result of the
201 // CreateChildFrame mojo call, which also delivers the
202 // |policy_container_bind_params|.
danakjc492bf82020-09-09 20:02:44203 FrameTreeNode* AddFrame(
204 RenderFrameHostImpl* parent,
205 int process_id,
206 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18207 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
danakjc492bf82020-09-09 20:02:44208 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
209 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30210 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
danakjc492bf82020-09-09 20:02:44211 blink::mojom::TreeScopeType scope,
212 const std::string& frame_name,
213 const std::string& frame_unique_name,
214 bool is_created_by_script,
215 const base::UnguessableToken& frame_token,
216 const base::UnguessableToken& devtools_frame_token,
217 const blink::FramePolicy& frame_policy,
218 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
219 bool was_discarded,
220 blink::mojom::FrameOwnerElementType owner_type);
221
222 // Removes a frame from the frame tree. |child|, its children, and objects
223 // owned by their RenderFrameHostManagers are immediately deleted. The root
224 // node cannot be removed this way.
225 void RemoveFrame(FrameTreeNode* child);
226
227 // This method walks the entire frame tree and creates a RenderFrameProxyHost
228 // for the given |site_instance| in each node except the |source| one --
229 // the source will have a RenderFrameHost. |source| may be null if there is
230 // no node navigating in this frame tree (such as when this is called
231 // for an opener's frame tree), in which case no nodes are skipped for
232 // RenderFrameProxyHost creation.
233 void CreateProxiesForSiteInstance(FrameTreeNode* source,
234 SiteInstance* site_instance);
235
236 // Convenience accessor for the main frame's RenderFrameHostImpl.
237 RenderFrameHostImpl* GetMainFrame() const;
238
239 // Returns the focused frame.
240 FrameTreeNode* GetFocusedFrame();
241
242 // Sets the focused frame to |node|. |source| identifies the SiteInstance
243 // that initiated this focus change. If this FrameTree has SiteInstances
244 // other than |source|, those SiteInstances will be notified about the new
245 // focused frame. Note that |source| may differ from |node|'s current
246 // SiteInstance (e.g., this happens for cross-process window.focus() calls).
247 void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source);
248
danakjc492bf82020-09-09 20:02:44249 // Creates a RenderViewHostImpl for a given |site_instance| in the tree.
250 //
251 // The RenderFrameHostImpls and the RenderFrameProxyHosts will share ownership
252 // of this object.
253 scoped_refptr<RenderViewHostImpl> CreateRenderViewHost(
254 SiteInstance* site_instance,
255 int32_t main_frame_routing_id,
danakj08eb51d2020-12-30 20:15:23256 bool swapped_out,
257 bool renderer_initiated_creation);
danakjc492bf82020-09-09 20:02:44258
259 // Returns the existing RenderViewHost for a new RenderFrameHost.
260 // There should always be such a RenderViewHost, because the main frame
261 // RenderFrameHost for each SiteInstance should be created before subframes.
262 scoped_refptr<RenderViewHostImpl> GetRenderViewHost(
263 SiteInstance* site_instance);
264
265 // Registers a RenderViewHost so that it can be reused by other frames
266 // belonging to the same SiteInstance.
267 //
268 // This method does not take ownership of|rvh|.
269 //
270 // NOTE: This method CHECK fails if a RenderViewHost is already registered for
271 // |rvh|'s SiteInstance.
272 //
273 // ALSO NOTE: After calling RegisterRenderViewHost, UnregisterRenderViewHost
274 // *must* be called for |rvh| when it is destroyed or put into the
275 // BackForwardCache, to prevent FrameTree::CreateRenderViewHost from trying to
276 // reuse it.
Aaron Colwellc4bd7d62021-01-29 04:23:13277 void RegisterRenderViewHost(SiteInstance* site_instance,
278 RenderViewHostImpl* rvh);
danakjc492bf82020-09-09 20:02:44279
280 // Unregisters the RenderViewHostImpl that's available for reuse for a
281 // particular SiteInstance. NOTE: This method CHECK fails if it is called for
282 // a |render_view_host| that is not currently set for reuse.
Aaron Colwellc4bd7d62021-01-29 04:23:13283 void UnregisterRenderViewHost(SiteInstance* site_instance,
284 RenderViewHostImpl* render_view_host);
danakjc492bf82020-09-09 20:02:44285
286 // This is called when the frame is about to be removed and started to run
287 // unload handlers.
288 void FrameUnloading(FrameTreeNode* frame);
289
290 // This is only meant to be called by FrameTreeNode. Triggers calling
291 // the listener installed by SetFrameRemoveListener.
292 void FrameRemoved(FrameTreeNode* frame);
293
Carlos Caballero03262522021-02-05 14:49:58294 void DidStartLoadingNode(FrameTreeNode& node,
295 bool to_different_document,
296 bool was_previously_loading);
297 void DidStopLoadingNode(FrameTreeNode& node);
298 void DidChangeLoadProgressForNode(FrameTreeNode& node, double load_progress);
299 void DidCancelLoading();
danakjc492bf82020-09-09 20:02:44300
301 // Returns this FrameTree's total load progress.
302 double load_progress() const { return load_progress_; }
303
304 // Resets the load progress on all nodes in this FrameTree.
305 void ResetLoadProgress();
306
307 // Returns true if at least one of the nodes in this FrameTree is loading.
308 bool IsLoading() const;
309
310 // Set page-level focus in all SiteInstances involved in rendering
311 // this FrameTree, not including the current main frame's
312 // SiteInstance. The focus update will be sent via the main frame's proxies
313 // in those SiteInstances.
314 void ReplicatePageFocus(bool is_focused);
315
316 // Updates page-level focus for this FrameTree in the subframe renderer
317 // identified by |instance|.
318 void SetPageFocus(SiteInstance* instance, bool is_focused);
319
320 // Walks the current frame tree and registers any origins matching |origin|,
321 // either the last committed origin of a RenderFrameHost or the origin
322 // associated with a NavigationRequest that has been assigned to a
323 // SiteInstance, as not-opted-in for origin isolation.
324 void RegisterExistingOriginToPreventOptInIsolation(
325 const url::Origin& previously_visited_origin,
326 NavigationRequest* navigation_request_to_exclude);
327
Carlos Caballero40b0efd2021-01-26 11:55:00328 NavigationControllerImpl& controller() { return navigator_.controller(); }
danakjc492bf82020-09-09 20:02:44329 Navigator& navigator() { return navigator_; }
330
Carlos Caballeroede6f8c2021-01-28 11:01:50331 // Another page accessed the initial empty main document, which means it
332 // is no longer safe to display a pending URL without risking a URL spoof.
333 void DidAccessInitialMainDocument();
334
335 bool has_accessed_initial_main_document() const {
336 return has_accessed_initial_main_document_;
337 }
338
339 void ResetHasAccessedInitialMainDocument() {
340 has_accessed_initial_main_document_ = false;
341 }
342
Carlos Caballero6ff6ace2021-02-05 16:53:00343 bool IsHidden() const { return delegate_->IsHidden(); }
344
Carlos Caballero03262522021-02-05 14:49:58345 // Stops all ongoing navigations in each of the nodes of this FrameTree.
346 void StopLoading();
347
danakjc492bf82020-09-09 20:02:44348 private:
349 friend class FrameTreeTest;
350 FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame);
351
Sreeja Kamishetty46f762c2021-02-05 07:52:46352 // Prerender2:
353 // Indicates whether this frame tree is being prerendered.
354 // Set to true when frame tree is created (PrerenderHost()) and to false once
355 // the prerendered page is activated
356 // (PrerenderHost::ActivatePrerenderedContents()).
357 // TODO(https://crbug.com/1174926): Migrate this parameter to FrameTreeType
358 // once activation path is migrated onto MPArch and WebContents-swap-based
359 // activation logic is removed.
360 bool is_prerendering_ = false;
361
danakjc492bf82020-09-09 20:02:44362 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
363 // breadth-first traversal order, skipping the subtree rooted at
364 // |node|, but including |node| itself.
365 NodeRange NodesExceptSubtree(FrameTreeNode* node);
366
Carlos Caballero03262522021-02-05 14:49:58367 Delegate* const delegate_;
368
danakjc492bf82020-09-09 20:02:44369 // These delegates are installed into all the RenderViewHosts and
370 // RenderFrameHosts that we create.
371 RenderFrameHostDelegate* render_frame_delegate_;
372 RenderViewHostDelegate* render_view_delegate_;
373 RenderWidgetHostDelegate* render_widget_delegate_;
374 RenderFrameHostManager::Delegate* manager_delegate_;
375
376 // The Navigator object responsible for managing navigations on this frame
Carlos Caballero40b0efd2021-01-26 11:55:00377 // tree. Each FrameTreeNode will default to using it for navigation tasks in
378 // the frame.
danakjc492bf82020-09-09 20:02:44379 Navigator navigator_;
380
381 // Map of SiteInstance ID to RenderViewHost. This allows us to look up the
382 // RenderViewHost for a given SiteInstance when creating RenderFrameHosts.
383 // Each RenderViewHost maintains a refcount and is deleted when there are no
384 // more RenderFrameHosts or RenderFrameProxyHosts using it.
385 std::unordered_map<int /* SiteInstance ID */, RenderViewHostImpl*>
386 render_view_host_map_;
387
388 // This is an owned ptr to the root FrameTreeNode, which never changes over
389 // the lifetime of the FrameTree. It is not a scoped_ptr because we need the
390 // pointer to remain valid even while the FrameTreeNode is being destroyed,
391 // since it's common for a node to test whether it's the root node.
392 FrameTreeNode* root_;
393
394 int focused_frame_tree_node_id_;
395
danakjc492bf82020-09-09 20:02:44396 // Overall load progress.
397 double load_progress_;
398
Carlos Caballeroede6f8c2021-01-28 11:01:50399 // Whether the initial empty page has been accessed by another page, making it
400 // unsafe to show the pending URL. Usually false unless another window tries
401 // to modify the blank page. Always false after the first commit.
402 bool has_accessed_initial_main_document_ = false;
403
danakjc492bf82020-09-09 20:02:44404 DISALLOW_COPY_AND_ASSIGN(FrameTree);
405};
406
407} // namespace content
408
409#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_