blob: d9a39dd0e099774d55d006a726a8c87d2da6c87b [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"
Chris Hamilton3ff6ed0e2021-02-19 03:54:0425#include "third_party/blink/public/common/tokens/tokens.h"
danakjc492bf82020-09-09 20:02:4426#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
27#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-forward.h"
28
29namespace blink {
30struct FramePolicy;
31} // namespace blink
32
33namespace content {
34
Carlos Caballero40b0efd2021-01-26 11:55:0035class BrowserContext;
danakjc492bf82020-09-09 20:02:4436class RenderFrameHostDelegate;
37class RenderViewHostDelegate;
38class RenderViewHostImpl;
39class RenderFrameHostManager;
40class RenderWidgetHostDelegate;
Carlos Caballero40b0efd2021-01-26 11:55:0041class SiteInstance;
danakjc492bf82020-09-09 20:02:4442
43// Represents the frame tree for a page. With the exception of the main frame,
44// all FrameTreeNodes will be created/deleted in response to frame attach and
45// detach events in the DOM.
46//
47// The main frame's FrameTreeNode is special in that it is reused. This allows
48// it to serve as an anchor for state that needs to persist across top-level
49// page navigations.
50//
51// TODO(ajwong): Move NavigationController ownership to the main frame
52// FrameTreeNode. Possibly expose access to it from here.
53//
54// This object is only used on the UI thread.
55class CONTENT_EXPORT FrameTree {
56 public:
57 class NodeRange;
58
59 class CONTENT_EXPORT NodeIterator
60 : public std::iterator<std::forward_iterator_tag, FrameTreeNode> {
61 public:
62 NodeIterator(const NodeIterator& other);
63 ~NodeIterator();
64
65 NodeIterator& operator++();
66
67 bool operator==(const NodeIterator& rhs) const;
68 bool operator!=(const NodeIterator& rhs) const { return !(*this == rhs); }
69
70 FrameTreeNode* operator*() { return current_node_; }
71
72 private:
73 friend class NodeRange;
74
75 NodeIterator(FrameTreeNode* starting_node,
76 FrameTreeNode* root_of_subtree_to_skip);
77
78 FrameTreeNode* current_node_;
79 FrameTreeNode* const root_of_subtree_to_skip_;
80 base::queue<FrameTreeNode*> queue_;
81 };
82
83 class CONTENT_EXPORT NodeRange {
84 public:
85 NodeIterator begin();
86 NodeIterator end();
87
88 private:
89 friend class FrameTree;
90
91 NodeRange(FrameTreeNode* root, FrameTreeNode* root_of_subtree_to_skip);
92
93 FrameTreeNode* const root_;
94 FrameTreeNode* const root_of_subtree_to_skip_;
95 };
96
Carlos Caballero03262522021-02-05 14:49:5897 class CONTENT_EXPORT Delegate {
98 public:
99 // A RenderFrameHost in the specified |frame_tree_node| started loading a
100 // new document. This corresponds to browser UI starting to show a spinner
101 // or other visual indicator for loading. This method is only invoked if the
102 // FrameTree hadn't been previously loading. |to_different_document| will be
103 // true unless the load is a fragment navigation, or triggered by
104 // history.pushState/replaceState.
105 virtual void DidStartLoading(FrameTreeNode* frame_tree_node,
106 bool to_different_document) = 0;
107
Takashi Toyoshima74090df62021-03-09 14:34:57108 // This is called when all nodes in the FrameTree stopped loading. This
Carlos Caballero03262522021-02-05 14:49:58109 // corresponds to the browser UI stop showing a spinner or other visual
110 // indicator for loading.
111 virtual void DidStopLoading() = 0;
112
113 // The load progress was changed.
114 virtual void DidChangeLoadProgress() = 0;
Carlos Caballero6ff6ace2021-02-05 16:53:00115
116 // Returns true when the active RenderWidgetHostView should be hidden.
117 virtual bool IsHidden() = 0;
Carlos Caballero03262522021-02-05 14:49:58118 };
119
danakjc492bf82020-09-09 20:02:44120 // A set of delegates are remembered here so that we can create
121 // RenderFrameHostManagers.
Carlos Caballero40b0efd2021-01-26 11:55:00122 FrameTree(BrowserContext* browser_context,
Carlos Caballero03262522021-02-05 14:49:58123 Delegate* delegate,
Carlos Caballero40b0efd2021-01-26 11:55:00124 NavigationControllerDelegate* navigation_controller_delegate,
danakjc492bf82020-09-09 20:02:44125 NavigatorDelegate* navigator_delegate,
126 RenderFrameHostDelegate* render_frame_delegate,
127 RenderViewHostDelegate* render_view_delegate,
128 RenderWidgetHostDelegate* render_widget_delegate,
129 RenderFrameHostManager::Delegate* manager_delegate);
130 ~FrameTree();
131
Carlos Caballero40b0efd2021-01-26 11:55:00132 // Initializes the main frame for this FrameTree. That is it creates the
133 // initial RenderFrameHost in the root node's RenderFrameHostManager. This
134 // method will call back into the delegates so it should only be called once
135 // they have completed their initialization.
136 // TODO(carlscab): It would be great if initialization could happened in the
137 // constructor so we do not leave objects in a half initialized state.
138 void Init(SiteInstance* main_frame_site_instance,
139 bool renderer_initiated_creation,
Sreeja Kamishetty3699c35f2021-02-12 15:10:58140 const std::string& main_frame_name,
141 bool is_prerendering);
Carlos Caballero40b0efd2021-01-26 11:55:00142
danakjc492bf82020-09-09 20:02:44143 FrameTreeNode* root() const { return root_; }
144
Sreeja Kamishetty3699c35f2021-02-12 15:10:58145 // Sets |is_prerendering_| to false and activates the Prerendered page.
146 void ActivatePrerenderedFrameTree();
Sreeja Kamishetty46f762c2021-02-05 07:52:46147
148 bool is_prerendering() const { return is_prerendering_; }
149
Carlos Caballero03262522021-02-05 14:49:58150 Delegate* delegate() { return delegate_; }
151
danakjc492bf82020-09-09 20:02:44152 // Delegates for RenderFrameHosts, RenderViewHosts, RenderWidgetHosts and
153 // RenderFrameHostManagers. These can be kept centrally on the FrameTree
154 // because they are expected to be the same for all frames on a given
155 // FrameTree.
156 RenderFrameHostDelegate* render_frame_delegate() {
157 return render_frame_delegate_;
158 }
159 RenderViewHostDelegate* render_view_delegate() {
160 return render_view_delegate_;
161 }
162 RenderWidgetHostDelegate* render_widget_delegate() {
163 return render_widget_delegate_;
164 }
165 RenderFrameHostManager::Delegate* manager_delegate() {
166 return manager_delegate_;
167 }
Aaron Colwell78b4bde2021-03-16 16:16:09168
169 using RenderViewHostMapId = util::IdType32<class RenderViewHostMap>;
170 using RenderViewHostMap = std::unordered_map<RenderViewHostMapId,
171 RenderViewHostImpl*,
172 RenderViewHostMapId::Hasher>;
173 const RenderViewHostMap& render_view_hosts() const {
danakjc492bf82020-09-09 20:02:44174 return render_view_host_map_;
175 }
176
177 // Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
178 // of this FrameTree.
179 FrameTreeNode* FindByID(int frame_tree_node_id);
180
181 // Returns the FrameTreeNode with the given renderer-specific |routing_id|.
182 FrameTreeNode* FindByRoutingID(int process_id, int routing_id);
183
184 // Returns the first frame in this tree with the given |name|, or the main
185 // frame if |name| is empty.
186 // Note that this does NOT support pseudo-names like _self, _top, and _blank,
187 // nor searching other FrameTrees (unlike blink::WebView::findFrameByName).
188 FrameTreeNode* FindByName(const std::string& name);
189
190 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
191 // breadth-first traversal order.
192 NodeRange Nodes();
193
194 // Returns a range to iterate over all FrameTreeNodes in a subtree of the
195 // frame tree, starting from |subtree_root|.
196 NodeRange SubtreeNodes(FrameTreeNode* subtree_root);
197
198 // Adds a new child frame to the frame tree. |process_id| is required to
199 // disambiguate |new_routing_id|, and it must match the process of the
200 // |parent| node. Otherwise no child is added and this method returns false.
201 // |interface_provider_receiver| is the receiver end of the InterfaceProvider
202 // interface through which the child RenderFrame can access Mojo services
203 // exposed by the corresponding RenderFrameHost. The caller takes care of
Antonio Sartoridb967c52021-01-20 09:54:30204 // sending the client end of the interface down to the
205 // RenderFrame. |policy_container_bind_params|, if not null, is used for
206 // binding Blink's policy container to the new RenderFrameHost's
207 // PolicyContainerHost. This is only needed if this frame is the result of the
208 // CreateChildFrame mojo call, which also delivers the
209 // |policy_container_bind_params|.
danakjc492bf82020-09-09 20:02:44210 FrameTreeNode* AddFrame(
211 RenderFrameHostImpl* parent,
212 int process_id,
213 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18214 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
danakjc492bf82020-09-09 20:02:44215 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
216 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30217 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
danakjc492bf82020-09-09 20:02:44218 blink::mojom::TreeScopeType scope,
219 const std::string& frame_name,
220 const std::string& frame_unique_name,
221 bool is_created_by_script,
Chris Hamilton3ff6ed0e2021-02-19 03:54:04222 const blink::LocalFrameToken& frame_token,
danakjc492bf82020-09-09 20:02:44223 const base::UnguessableToken& devtools_frame_token,
224 const blink::FramePolicy& frame_policy,
225 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
226 bool was_discarded,
227 blink::mojom::FrameOwnerElementType owner_type);
228
229 // Removes a frame from the frame tree. |child|, its children, and objects
230 // owned by their RenderFrameHostManagers are immediately deleted. The root
231 // node cannot be removed this way.
232 void RemoveFrame(FrameTreeNode* child);
233
234 // This method walks the entire frame tree and creates a RenderFrameProxyHost
235 // for the given |site_instance| in each node except the |source| one --
236 // the source will have a RenderFrameHost. |source| may be null if there is
237 // no node navigating in this frame tree (such as when this is called
238 // for an opener's frame tree), in which case no nodes are skipped for
239 // RenderFrameProxyHost creation.
240 void CreateProxiesForSiteInstance(FrameTreeNode* source,
241 SiteInstance* site_instance);
242
243 // Convenience accessor for the main frame's RenderFrameHostImpl.
244 RenderFrameHostImpl* GetMainFrame() const;
245
246 // Returns the focused frame.
247 FrameTreeNode* GetFocusedFrame();
248
249 // Sets the focused frame to |node|. |source| identifies the SiteInstance
250 // that initiated this focus change. If this FrameTree has SiteInstances
251 // other than |source|, those SiteInstances will be notified about the new
252 // focused frame. Note that |source| may differ from |node|'s current
253 // SiteInstance (e.g., this happens for cross-process window.focus() calls).
254 void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source);
255
danakjc492bf82020-09-09 20:02:44256 // Creates a RenderViewHostImpl for a given |site_instance| in the tree.
257 //
258 // The RenderFrameHostImpls and the RenderFrameProxyHosts will share ownership
259 // of this object.
260 scoped_refptr<RenderViewHostImpl> CreateRenderViewHost(
261 SiteInstance* site_instance,
262 int32_t main_frame_routing_id,
danakj08eb51d2020-12-30 20:15:23263 bool swapped_out,
264 bool renderer_initiated_creation);
danakjc492bf82020-09-09 20:02:44265
266 // Returns the existing RenderViewHost for a new RenderFrameHost.
267 // There should always be such a RenderViewHost, because the main frame
268 // RenderFrameHost for each SiteInstance should be created before subframes.
269 scoped_refptr<RenderViewHostImpl> GetRenderViewHost(
270 SiteInstance* site_instance);
271
Aaron Colwell78b4bde2021-03-16 16:16:09272 // Returns the ID used for the RenderViewHost associated with |site_instance|.
273 // Note: Callers should not assume that there is a 1:1 mapping between
274 // SiteInstances and IDs returned by this function, since several
275 // SiteInstances may share a RenderViewHost.
276 RenderViewHostMapId GetRenderViewHostMapId(SiteInstance* site_instance) const;
277
danakjc492bf82020-09-09 20:02:44278 // Registers a RenderViewHost so that it can be reused by other frames
Aaron Colwell78b4bde2021-03-16 16:16:09279 // whose SiteInstance maps to the same RenderViewHostMapId.
danakjc492bf82020-09-09 20:02:44280 //
281 // This method does not take ownership of|rvh|.
282 //
283 // NOTE: This method CHECK fails if a RenderViewHost is already registered for
284 // |rvh|'s SiteInstance.
285 //
286 // ALSO NOTE: After calling RegisterRenderViewHost, UnregisterRenderViewHost
287 // *must* be called for |rvh| when it is destroyed or put into the
288 // BackForwardCache, to prevent FrameTree::CreateRenderViewHost from trying to
289 // reuse it.
Aaron Colwell78b4bde2021-03-16 16:16:09290 void RegisterRenderViewHost(RenderViewHostMapId id, RenderViewHostImpl* rvh);
danakjc492bf82020-09-09 20:02:44291
292 // Unregisters the RenderViewHostImpl that's available for reuse for a
Aaron Colwell78b4bde2021-03-16 16:16:09293 // particular RenderViewHostMapId. NOTE: This method CHECK fails if it is
294 // called for a |render_view_host| that is not currently set for reuse.
295 void UnregisterRenderViewHost(RenderViewHostMapId id,
Aaron Colwellc4bd7d62021-01-29 04:23:13296 RenderViewHostImpl* render_view_host);
danakjc492bf82020-09-09 20:02:44297
298 // This is called when the frame is about to be removed and started to run
299 // unload handlers.
300 void FrameUnloading(FrameTreeNode* frame);
301
302 // This is only meant to be called by FrameTreeNode. Triggers calling
303 // the listener installed by SetFrameRemoveListener.
304 void FrameRemoved(FrameTreeNode* frame);
305
Carlos Caballero03262522021-02-05 14:49:58306 void DidStartLoadingNode(FrameTreeNode& node,
307 bool to_different_document,
308 bool was_previously_loading);
309 void DidStopLoadingNode(FrameTreeNode& node);
310 void DidChangeLoadProgressForNode(FrameTreeNode& node, double load_progress);
311 void DidCancelLoading();
danakjc492bf82020-09-09 20:02:44312
313 // Returns this FrameTree's total load progress.
314 double load_progress() const { return load_progress_; }
315
316 // Resets the load progress on all nodes in this FrameTree.
317 void ResetLoadProgress();
318
319 // Returns true if at least one of the nodes in this FrameTree is loading.
320 bool IsLoading() const;
321
322 // Set page-level focus in all SiteInstances involved in rendering
323 // this FrameTree, not including the current main frame's
324 // SiteInstance. The focus update will be sent via the main frame's proxies
325 // in those SiteInstances.
326 void ReplicatePageFocus(bool is_focused);
327
328 // Updates page-level focus for this FrameTree in the subframe renderer
329 // identified by |instance|.
330 void SetPageFocus(SiteInstance* instance, bool is_focused);
331
332 // Walks the current frame tree and registers any origins matching |origin|,
333 // either the last committed origin of a RenderFrameHost or the origin
334 // associated with a NavigationRequest that has been assigned to a
335 // SiteInstance, as not-opted-in for origin isolation.
336 void RegisterExistingOriginToPreventOptInIsolation(
337 const url::Origin& previously_visited_origin,
338 NavigationRequest* navigation_request_to_exclude);
339
Carlos Caballero40b0efd2021-01-26 11:55:00340 NavigationControllerImpl& controller() { return navigator_.controller(); }
danakjc492bf82020-09-09 20:02:44341 Navigator& navigator() { return navigator_; }
342
Carlos Caballeroede6f8c2021-01-28 11:01:50343 // Another page accessed the initial empty main document, which means it
344 // is no longer safe to display a pending URL without risking a URL spoof.
345 void DidAccessInitialMainDocument();
346
347 bool has_accessed_initial_main_document() const {
348 return has_accessed_initial_main_document_;
349 }
350
351 void ResetHasAccessedInitialMainDocument() {
352 has_accessed_initial_main_document_ = false;
353 }
354
Carlos Caballero6ff6ace2021-02-05 16:53:00355 bool IsHidden() const { return delegate_->IsHidden(); }
356
Carlos Caballero03262522021-02-05 14:49:58357 // Stops all ongoing navigations in each of the nodes of this FrameTree.
358 void StopLoading();
359
danakjc492bf82020-09-09 20:02:44360 private:
361 friend class FrameTreeTest;
362 FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame);
363
Sreeja Kamishetty46f762c2021-02-05 07:52:46364 // Prerender2:
365 // Indicates whether this frame tree is being prerendered.
366 // Set to true when frame tree is created (PrerenderHost()) and to false once
367 // the prerendered page is activated
368 // (PrerenderHost::ActivatePrerenderedContents()).
369 // TODO(https://crbug.com/1174926): Migrate this parameter to FrameTreeType
370 // once activation path is migrated onto MPArch and WebContents-swap-based
371 // activation logic is removed.
372 bool is_prerendering_ = false;
373
danakjc492bf82020-09-09 20:02:44374 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
375 // breadth-first traversal order, skipping the subtree rooted at
376 // |node|, but including |node| itself.
377 NodeRange NodesExceptSubtree(FrameTreeNode* node);
378
Carlos Caballero03262522021-02-05 14:49:58379 Delegate* const delegate_;
380
danakjc492bf82020-09-09 20:02:44381 // These delegates are installed into all the RenderViewHosts and
382 // RenderFrameHosts that we create.
383 RenderFrameHostDelegate* render_frame_delegate_;
384 RenderViewHostDelegate* render_view_delegate_;
385 RenderWidgetHostDelegate* render_widget_delegate_;
386 RenderFrameHostManager::Delegate* manager_delegate_;
387
388 // The Navigator object responsible for managing navigations on this frame
Carlos Caballero40b0efd2021-01-26 11:55:00389 // tree. Each FrameTreeNode will default to using it for navigation tasks in
390 // the frame.
danakjc492bf82020-09-09 20:02:44391 Navigator navigator_;
392
Aaron Colwell78b4bde2021-03-16 16:16:09393 // Map of RenderViewHostMapId to RenderViewHost. This allows us to look up the
danakjc492bf82020-09-09 20:02:44394 // RenderViewHost for a given SiteInstance when creating RenderFrameHosts.
395 // Each RenderViewHost maintains a refcount and is deleted when there are no
396 // more RenderFrameHosts or RenderFrameProxyHosts using it.
Aaron Colwell78b4bde2021-03-16 16:16:09397 RenderViewHostMap render_view_host_map_;
danakjc492bf82020-09-09 20:02:44398
399 // This is an owned ptr to the root FrameTreeNode, which never changes over
400 // the lifetime of the FrameTree. It is not a scoped_ptr because we need the
401 // pointer to remain valid even while the FrameTreeNode is being destroyed,
402 // since it's common for a node to test whether it's the root node.
403 FrameTreeNode* root_;
404
405 int focused_frame_tree_node_id_;
406
danakjc492bf82020-09-09 20:02:44407 // Overall load progress.
408 double load_progress_;
409
Carlos Caballeroede6f8c2021-01-28 11:01:50410 // Whether the initial empty page has been accessed by another page, making it
411 // unsafe to show the pending URL. Usually false unless another window tries
412 // to modify the blank page. Always false after the first commit.
413 bool has_accessed_initial_main_document_ = false;
414
danakjc492bf82020-09-09 20:02:44415 DISALLOW_COPY_AND_ASSIGN(FrameTree);
416};
417
418} // namespace content
419
420#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_