blob: f686af14b222496dec0f486d3f2a17d15001f68e [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"
Carlos Caballero101ac26b2021-03-24 11:54:0517#include "base/dcheck_is_on.h"
danakjc492bf82020-09-09 20:02:4418#include "base/gtest_prod_util.h"
19#include "base/macros.h"
20#include "content/browser/renderer_host/navigator.h"
21#include "content/browser/renderer_host/navigator_delegate.h"
22#include "content/browser/renderer_host/render_frame_host_manager.h"
23#include "content/common/content_export.h"
24#include "mojo/public/cpp/bindings/pending_receiver.h"
25#include "services/service_manager/public/mojom/interface_provider.mojom.h"
Chris Hamilton3ff6ed0e2021-02-19 03:54:0426#include "third_party/blink/public/common/tokens/tokens.h"
danakjc492bf82020-09-09 20:02:4427#include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
28#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-forward.h"
29
30namespace blink {
31struct FramePolicy;
32} // namespace blink
33
34namespace content {
35
Carlos Caballero40b0efd2021-01-26 11:55:0036class BrowserContext;
danakjc492bf82020-09-09 20:02:4437class RenderFrameHostDelegate;
38class RenderViewHostDelegate;
39class RenderViewHostImpl;
40class RenderFrameHostManager;
41class RenderWidgetHostDelegate;
Carlos Caballero40b0efd2021-01-26 11:55:0042class SiteInstance;
danakjc492bf82020-09-09 20:02:4443
44// Represents the frame tree for a page. With the exception of the main frame,
45// all FrameTreeNodes will be created/deleted in response to frame attach and
46// detach events in the DOM.
47//
48// The main frame's FrameTreeNode is special in that it is reused. This allows
49// it to serve as an anchor for state that needs to persist across top-level
50// page navigations.
51//
52// TODO(ajwong): Move NavigationController ownership to the main frame
53// FrameTreeNode. Possibly expose access to it from here.
54//
55// This object is only used on the UI thread.
56class CONTENT_EXPORT FrameTree {
57 public:
58 class NodeRange;
59
60 class CONTENT_EXPORT NodeIterator
61 : public std::iterator<std::forward_iterator_tag, FrameTreeNode> {
62 public:
63 NodeIterator(const NodeIterator& other);
64 ~NodeIterator();
65
66 NodeIterator& operator++();
67
68 bool operator==(const NodeIterator& rhs) const;
69 bool operator!=(const NodeIterator& rhs) const { return !(*this == rhs); }
70
71 FrameTreeNode* operator*() { return current_node_; }
72
73 private:
74 friend class NodeRange;
75
76 NodeIterator(FrameTreeNode* starting_node,
77 FrameTreeNode* root_of_subtree_to_skip);
78
79 FrameTreeNode* current_node_;
80 FrameTreeNode* const root_of_subtree_to_skip_;
81 base::queue<FrameTreeNode*> queue_;
82 };
83
84 class CONTENT_EXPORT NodeRange {
85 public:
86 NodeIterator begin();
87 NodeIterator end();
88
89 private:
90 friend class FrameTree;
91
92 NodeRange(FrameTreeNode* root, FrameTreeNode* root_of_subtree_to_skip);
93
94 FrameTreeNode* const root_;
95 FrameTreeNode* const root_of_subtree_to_skip_;
96 };
97
Carlos Caballero03262522021-02-05 14:49:5898 class CONTENT_EXPORT Delegate {
99 public:
100 // A RenderFrameHost in the specified |frame_tree_node| started loading a
101 // new document. This corresponds to browser UI starting to show a spinner
102 // or other visual indicator for loading. This method is only invoked if the
103 // FrameTree hadn't been previously loading. |to_different_document| will be
104 // true unless the load is a fragment navigation, or triggered by
105 // history.pushState/replaceState.
106 virtual void DidStartLoading(FrameTreeNode* frame_tree_node,
107 bool to_different_document) = 0;
108
Takashi Toyoshima74090df62021-03-09 14:34:57109 // This is called when all nodes in the FrameTree stopped loading. This
Carlos Caballero03262522021-02-05 14:49:58110 // corresponds to the browser UI stop showing a spinner or other visual
111 // indicator for loading.
112 virtual void DidStopLoading() = 0;
113
114 // The load progress was changed.
115 virtual void DidChangeLoadProgress() = 0;
Carlos Caballero6ff6ace2021-02-05 16:53:00116
117 // Returns true when the active RenderWidgetHostView should be hidden.
118 virtual bool IsHidden() = 0;
Carlos Caballero03262522021-02-05 14:49:58119 };
120
Sreeja Kamishetty74bacd522021-03-22 17:04:24121 // Type of FrameTree instance.
122 enum class Type {
123 // This FrameTree is the primary frame tree for the WebContents, whose main
124 // document URL is shown in the Omnibox.
125 kPrimary,
126
127 // This FrameTree is used to prerender a page in the background which is
128 // invisible to the user.
129 kPrerender
130 };
Sreeja Kamishetty837a10402021-04-23 12:41:59131
132 // A set of delegates are remembered here so that we can create
133 // RenderFrameHostManagers.
134 FrameTree(BrowserContext* browser_context,
135 Delegate* delegate,
136 NavigationControllerDelegate* navigation_controller_delegate,
137 NavigatorDelegate* navigator_delegate,
138 RenderFrameHostDelegate* render_frame_delegate,
139 RenderViewHostDelegate* render_view_delegate,
140 RenderWidgetHostDelegate* render_widget_delegate,
141 RenderFrameHostManager::Delegate* manager_delegate,
142 Type type);
143 ~FrameTree();
Sreeja Kamishetty74bacd522021-03-22 17:04:24144
Carlos Caballero40b0efd2021-01-26 11:55:00145 // Initializes the main frame for this FrameTree. That is it creates the
146 // initial RenderFrameHost in the root node's RenderFrameHostManager. This
147 // method will call back into the delegates so it should only be called once
148 // they have completed their initialization.
149 // TODO(carlscab): It would be great if initialization could happened in the
150 // constructor so we do not leave objects in a half initialized state.
151 void Init(SiteInstance* main_frame_site_instance,
152 bool renderer_initiated_creation,
Sreeja Kamishetty837a10402021-04-23 12:41:59153 const std::string& main_frame_name);
154
155 Type type() const { return type_; }
Carlos Caballero40b0efd2021-01-26 11:55:00156
danakjc492bf82020-09-09 20:02:44157 FrameTreeNode* root() const { return root_; }
158
Sreeja Kamishetty74bacd522021-03-22 17:04:24159 bool is_prerendering() const { return type_ == FrameTree::Type::kPrerender; }
Sreeja Kamishetty46f762c2021-02-05 07:52:46160
Carlos Caballero03262522021-02-05 14:49:58161 Delegate* delegate() { return delegate_; }
162
danakjc492bf82020-09-09 20:02:44163 // Delegates for RenderFrameHosts, RenderViewHosts, RenderWidgetHosts and
164 // RenderFrameHostManagers. These can be kept centrally on the FrameTree
165 // because they are expected to be the same for all frames on a given
166 // FrameTree.
167 RenderFrameHostDelegate* render_frame_delegate() {
168 return render_frame_delegate_;
169 }
170 RenderViewHostDelegate* render_view_delegate() {
171 return render_view_delegate_;
172 }
173 RenderWidgetHostDelegate* render_widget_delegate() {
174 return render_widget_delegate_;
175 }
176 RenderFrameHostManager::Delegate* manager_delegate() {
177 return manager_delegate_;
178 }
Aaron Colwell78b4bde2021-03-16 16:16:09179
180 using RenderViewHostMapId = util::IdType32<class RenderViewHostMap>;
181 using RenderViewHostMap = std::unordered_map<RenderViewHostMapId,
182 RenderViewHostImpl*,
183 RenderViewHostMapId::Hasher>;
184 const RenderViewHostMap& render_view_hosts() const {
danakjc492bf82020-09-09 20:02:44185 return render_view_host_map_;
186 }
187
188 // Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
189 // of this FrameTree.
190 FrameTreeNode* FindByID(int frame_tree_node_id);
191
192 // Returns the FrameTreeNode with the given renderer-specific |routing_id|.
193 FrameTreeNode* FindByRoutingID(int process_id, int routing_id);
194
195 // Returns the first frame in this tree with the given |name|, or the main
196 // frame if |name| is empty.
197 // Note that this does NOT support pseudo-names like _self, _top, and _blank,
198 // nor searching other FrameTrees (unlike blink::WebView::findFrameByName).
199 FrameTreeNode* FindByName(const std::string& name);
200
201 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
202 // breadth-first traversal order.
203 NodeRange Nodes();
204
205 // Returns a range to iterate over all FrameTreeNodes in a subtree of the
206 // frame tree, starting from |subtree_root|.
207 NodeRange SubtreeNodes(FrameTreeNode* subtree_root);
208
209 // Adds a new child frame to the frame tree. |process_id| is required to
210 // disambiguate |new_routing_id|, and it must match the process of the
211 // |parent| node. Otherwise no child is added and this method returns false.
212 // |interface_provider_receiver| is the receiver end of the InterfaceProvider
213 // interface through which the child RenderFrame can access Mojo services
214 // exposed by the corresponding RenderFrameHost. The caller takes care of
Antonio Sartoridb967c52021-01-20 09:54:30215 // sending the client end of the interface down to the
216 // RenderFrame. |policy_container_bind_params|, if not null, is used for
217 // binding Blink's policy container to the new RenderFrameHost's
218 // PolicyContainerHost. This is only needed if this frame is the result of the
219 // CreateChildFrame mojo call, which also delivers the
220 // |policy_container_bind_params|.
danakjc492bf82020-09-09 20:02:44221 FrameTreeNode* AddFrame(
222 RenderFrameHostImpl* parent,
223 int process_id,
224 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18225 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
danakjc492bf82020-09-09 20:02:44226 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
227 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30228 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
danakjc492bf82020-09-09 20:02:44229 blink::mojom::TreeScopeType scope,
230 const std::string& frame_name,
231 const std::string& frame_unique_name,
232 bool is_created_by_script,
Chris Hamilton3ff6ed0e2021-02-19 03:54:04233 const blink::LocalFrameToken& frame_token,
danakjc492bf82020-09-09 20:02:44234 const base::UnguessableToken& devtools_frame_token,
235 const blink::FramePolicy& frame_policy,
236 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
237 bool was_discarded,
238 blink::mojom::FrameOwnerElementType owner_type);
239
240 // Removes a frame from the frame tree. |child|, its children, and objects
241 // owned by their RenderFrameHostManagers are immediately deleted. The root
242 // node cannot be removed this way.
243 void RemoveFrame(FrameTreeNode* child);
244
245 // This method walks the entire frame tree and creates a RenderFrameProxyHost
246 // for the given |site_instance| in each node except the |source| one --
247 // the source will have a RenderFrameHost. |source| may be null if there is
248 // no node navigating in this frame tree (such as when this is called
249 // for an opener's frame tree), in which case no nodes are skipped for
250 // RenderFrameProxyHost creation.
251 void CreateProxiesForSiteInstance(FrameTreeNode* source,
252 SiteInstance* site_instance);
253
254 // Convenience accessor for the main frame's RenderFrameHostImpl.
255 RenderFrameHostImpl* GetMainFrame() const;
256
257 // Returns the focused frame.
258 FrameTreeNode* GetFocusedFrame();
259
260 // Sets the focused frame to |node|. |source| identifies the SiteInstance
261 // that initiated this focus change. If this FrameTree has SiteInstances
262 // other than |source|, those SiteInstances will be notified about the new
263 // focused frame. Note that |source| may differ from |node|'s current
264 // SiteInstance (e.g., this happens for cross-process window.focus() calls).
265 void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source);
266
danakjc492bf82020-09-09 20:02:44267 // Creates a RenderViewHostImpl for a given |site_instance| in the tree.
268 //
269 // The RenderFrameHostImpls and the RenderFrameProxyHosts will share ownership
270 // of this object.
271 scoped_refptr<RenderViewHostImpl> CreateRenderViewHost(
272 SiteInstance* site_instance,
273 int32_t main_frame_routing_id,
danakj08eb51d2020-12-30 20:15:23274 bool swapped_out,
275 bool renderer_initiated_creation);
danakjc492bf82020-09-09 20:02:44276
277 // Returns the existing RenderViewHost for a new RenderFrameHost.
278 // There should always be such a RenderViewHost, because the main frame
279 // RenderFrameHost for each SiteInstance should be created before subframes.
280 scoped_refptr<RenderViewHostImpl> GetRenderViewHost(
281 SiteInstance* site_instance);
282
Aaron Colwell78b4bde2021-03-16 16:16:09283 // Returns the ID used for the RenderViewHost associated with |site_instance|.
284 // Note: Callers should not assume that there is a 1:1 mapping between
285 // SiteInstances and IDs returned by this function, since several
286 // SiteInstances may share a RenderViewHost.
287 RenderViewHostMapId GetRenderViewHostMapId(SiteInstance* site_instance) const;
288
danakjc492bf82020-09-09 20:02:44289 // Registers a RenderViewHost so that it can be reused by other frames
Aaron Colwell78b4bde2021-03-16 16:16:09290 // whose SiteInstance maps to the same RenderViewHostMapId.
danakjc492bf82020-09-09 20:02:44291 //
292 // This method does not take ownership of|rvh|.
293 //
294 // NOTE: This method CHECK fails if a RenderViewHost is already registered for
295 // |rvh|'s SiteInstance.
296 //
297 // ALSO NOTE: After calling RegisterRenderViewHost, UnregisterRenderViewHost
298 // *must* be called for |rvh| when it is destroyed or put into the
299 // BackForwardCache, to prevent FrameTree::CreateRenderViewHost from trying to
300 // reuse it.
Aaron Colwell78b4bde2021-03-16 16:16:09301 void RegisterRenderViewHost(RenderViewHostMapId id, RenderViewHostImpl* rvh);
danakjc492bf82020-09-09 20:02:44302
303 // Unregisters the RenderViewHostImpl that's available for reuse for a
Aaron Colwell78b4bde2021-03-16 16:16:09304 // particular RenderViewHostMapId. NOTE: This method CHECK fails if it is
305 // called for a |render_view_host| that is not currently set for reuse.
306 void UnregisterRenderViewHost(RenderViewHostMapId id,
Aaron Colwellc4bd7d62021-01-29 04:23:13307 RenderViewHostImpl* render_view_host);
danakjc492bf82020-09-09 20:02:44308
309 // This is called when the frame is about to be removed and started to run
310 // unload handlers.
311 void FrameUnloading(FrameTreeNode* frame);
312
313 // This is only meant to be called by FrameTreeNode. Triggers calling
314 // the listener installed by SetFrameRemoveListener.
315 void FrameRemoved(FrameTreeNode* frame);
316
Carlos Caballero03262522021-02-05 14:49:58317 void DidStartLoadingNode(FrameTreeNode& node,
318 bool to_different_document,
319 bool was_previously_loading);
320 void DidStopLoadingNode(FrameTreeNode& node);
321 void DidChangeLoadProgressForNode(FrameTreeNode& node, double load_progress);
322 void DidCancelLoading();
danakjc492bf82020-09-09 20:02:44323
324 // Returns this FrameTree's total load progress.
325 double load_progress() const { return load_progress_; }
326
327 // Resets the load progress on all nodes in this FrameTree.
328 void ResetLoadProgress();
329
330 // Returns true if at least one of the nodes in this FrameTree is loading.
331 bool IsLoading() const;
332
333 // Set page-level focus in all SiteInstances involved in rendering
334 // this FrameTree, not including the current main frame's
335 // SiteInstance. The focus update will be sent via the main frame's proxies
336 // in those SiteInstances.
337 void ReplicatePageFocus(bool is_focused);
338
339 // Updates page-level focus for this FrameTree in the subframe renderer
340 // identified by |instance|.
341 void SetPageFocus(SiteInstance* instance, bool is_focused);
342
343 // Walks the current frame tree and registers any origins matching |origin|,
344 // either the last committed origin of a RenderFrameHost or the origin
345 // associated with a NavigationRequest that has been assigned to a
346 // SiteInstance, as not-opted-in for origin isolation.
347 void RegisterExistingOriginToPreventOptInIsolation(
348 const url::Origin& previously_visited_origin,
349 NavigationRequest* navigation_request_to_exclude);
350
Carlos Caballero40b0efd2021-01-26 11:55:00351 NavigationControllerImpl& controller() { return navigator_.controller(); }
danakjc492bf82020-09-09 20:02:44352 Navigator& navigator() { return navigator_; }
353
Carlos Caballeroede6f8c2021-01-28 11:01:50354 // Another page accessed the initial empty main document, which means it
355 // is no longer safe to display a pending URL without risking a URL spoof.
356 void DidAccessInitialMainDocument();
357
358 bool has_accessed_initial_main_document() const {
359 return has_accessed_initial_main_document_;
360 }
361
362 void ResetHasAccessedInitialMainDocument() {
363 has_accessed_initial_main_document_ = false;
364 }
365
Carlos Caballero6ff6ace2021-02-05 16:53:00366 bool IsHidden() const { return delegate_->IsHidden(); }
367
Carlos Caballero03262522021-02-05 14:49:58368 // Stops all ongoing navigations in each of the nodes of this FrameTree.
369 void StopLoading();
370
Carlos Caballero101ac26b2021-03-24 11:54:05371 // Prepares this frame tree for destruction, cleaning up the internal state
372 // and firing the appropriate events like FrameDeleted.
373 // Must be called before FrameTree is destroyed.
374 void Shutdown();
375
danakjc492bf82020-09-09 20:02:44376 private:
377 friend class FrameTreeTest;
378 FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame);
379
380 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
381 // breadth-first traversal order, skipping the subtree rooted at
382 // |node|, but including |node| itself.
383 NodeRange NodesExceptSubtree(FrameTreeNode* node);
384
Carlos Caballero03262522021-02-05 14:49:58385 Delegate* const delegate_;
386
danakjc492bf82020-09-09 20:02:44387 // These delegates are installed into all the RenderViewHosts and
388 // RenderFrameHosts that we create.
389 RenderFrameHostDelegate* render_frame_delegate_;
390 RenderViewHostDelegate* render_view_delegate_;
391 RenderWidgetHostDelegate* render_widget_delegate_;
392 RenderFrameHostManager::Delegate* manager_delegate_;
393
394 // The Navigator object responsible for managing navigations on this frame
Carlos Caballero40b0efd2021-01-26 11:55:00395 // tree. Each FrameTreeNode will default to using it for navigation tasks in
396 // the frame.
danakjc492bf82020-09-09 20:02:44397 Navigator navigator_;
398
Aaron Colwell78b4bde2021-03-16 16:16:09399 // Map of RenderViewHostMapId to RenderViewHost. This allows us to look up the
danakjc492bf82020-09-09 20:02:44400 // RenderViewHost for a given SiteInstance when creating RenderFrameHosts.
401 // Each RenderViewHost maintains a refcount and is deleted when there are no
402 // more RenderFrameHosts or RenderFrameProxyHosts using it.
Aaron Colwell78b4bde2021-03-16 16:16:09403 RenderViewHostMap render_view_host_map_;
danakjc492bf82020-09-09 20:02:44404
405 // This is an owned ptr to the root FrameTreeNode, which never changes over
406 // the lifetime of the FrameTree. It is not a scoped_ptr because we need the
407 // pointer to remain valid even while the FrameTreeNode is being destroyed,
408 // since it's common for a node to test whether it's the root node.
409 FrameTreeNode* root_;
410
411 int focused_frame_tree_node_id_;
412
danakjc492bf82020-09-09 20:02:44413 // Overall load progress.
414 double load_progress_;
415
Carlos Caballeroede6f8c2021-01-28 11:01:50416 // Whether the initial empty page has been accessed by another page, making it
417 // unsafe to show the pending URL. Usually false unless another window tries
418 // to modify the blank page. Always false after the first commit.
419 bool has_accessed_initial_main_document_ = false;
420
Sreeja Kamishetty837a10402021-04-23 12:41:59421 // Indicates type of frame tree.
422 const Type type_;
Sreeja Kamishetty74bacd522021-03-22 17:04:24423
Carlos Caballero101ac26b2021-03-24 11:54:05424#if DCHECK_IS_ON()
425 // Whether Shutdown() was called.
426 bool was_shut_down_ = false;
427#endif
428
danakjc492bf82020-09-09 20:02:44429 DISALLOW_COPY_AND_ASSIGN(FrameTree);
430};
431
432} // namespace content
433
434#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_