blob: ab36e8cddb8d9cefe4b1e2a9018071e91cf5ffe9 [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
108 // This is called when all nodes in the FrameTreestoppedloading. This
109 // 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 }
168 const std::unordered_map<int /* SiteInstance ID */, RenderViewHostImpl*>&
169 render_view_hosts() const {
170 return render_view_host_map_;
171 }
172
173 // Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
174 // of this FrameTree.
175 FrameTreeNode* FindByID(int frame_tree_node_id);
176
177 // Returns the FrameTreeNode with the given renderer-specific |routing_id|.
178 FrameTreeNode* FindByRoutingID(int process_id, int routing_id);
179
180 // Returns the first frame in this tree with the given |name|, or the main
181 // frame if |name| is empty.
182 // Note that this does NOT support pseudo-names like _self, _top, and _blank,
183 // nor searching other FrameTrees (unlike blink::WebView::findFrameByName).
184 FrameTreeNode* FindByName(const std::string& name);
185
186 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
187 // breadth-first traversal order.
188 NodeRange Nodes();
189
190 // Returns a range to iterate over all FrameTreeNodes in a subtree of the
191 // frame tree, starting from |subtree_root|.
192 NodeRange SubtreeNodes(FrameTreeNode* subtree_root);
193
194 // Adds a new child frame to the frame tree. |process_id| is required to
195 // disambiguate |new_routing_id|, and it must match the process of the
196 // |parent| node. Otherwise no child is added and this method returns false.
197 // |interface_provider_receiver| is the receiver end of the InterfaceProvider
198 // interface through which the child RenderFrame can access Mojo services
199 // exposed by the corresponding RenderFrameHost. The caller takes care of
Antonio Sartoridb967c52021-01-20 09:54:30200 // sending the client end of the interface down to the
201 // RenderFrame. |policy_container_bind_params|, if not null, is used for
202 // binding Blink's policy container to the new RenderFrameHost's
203 // PolicyContainerHost. This is only needed if this frame is the result of the
204 // CreateChildFrame mojo call, which also delivers the
205 // |policy_container_bind_params|.
danakjc492bf82020-09-09 20:02:44206 FrameTreeNode* AddFrame(
207 RenderFrameHostImpl* parent,
208 int process_id,
209 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18210 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
danakjc492bf82020-09-09 20:02:44211 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
212 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30213 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
danakjc492bf82020-09-09 20:02:44214 blink::mojom::TreeScopeType scope,
215 const std::string& frame_name,
216 const std::string& frame_unique_name,
217 bool is_created_by_script,
Chris Hamilton3ff6ed0e2021-02-19 03:54:04218 const blink::LocalFrameToken& frame_token,
danakjc492bf82020-09-09 20:02:44219 const base::UnguessableToken& devtools_frame_token,
220 const blink::FramePolicy& frame_policy,
221 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
222 bool was_discarded,
223 blink::mojom::FrameOwnerElementType owner_type);
224
225 // Removes a frame from the frame tree. |child|, its children, and objects
226 // owned by their RenderFrameHostManagers are immediately deleted. The root
227 // node cannot be removed this way.
228 void RemoveFrame(FrameTreeNode* child);
229
230 // This method walks the entire frame tree and creates a RenderFrameProxyHost
231 // for the given |site_instance| in each node except the |source| one --
232 // the source will have a RenderFrameHost. |source| may be null if there is
233 // no node navigating in this frame tree (such as when this is called
234 // for an opener's frame tree), in which case no nodes are skipped for
235 // RenderFrameProxyHost creation.
236 void CreateProxiesForSiteInstance(FrameTreeNode* source,
237 SiteInstance* site_instance);
238
239 // Convenience accessor for the main frame's RenderFrameHostImpl.
240 RenderFrameHostImpl* GetMainFrame() const;
241
242 // Returns the focused frame.
243 FrameTreeNode* GetFocusedFrame();
244
245 // Sets the focused frame to |node|. |source| identifies the SiteInstance
246 // that initiated this focus change. If this FrameTree has SiteInstances
247 // other than |source|, those SiteInstances will be notified about the new
248 // focused frame. Note that |source| may differ from |node|'s current
249 // SiteInstance (e.g., this happens for cross-process window.focus() calls).
250 void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source);
251
danakjc492bf82020-09-09 20:02:44252 // Creates a RenderViewHostImpl for a given |site_instance| in the tree.
253 //
254 // The RenderFrameHostImpls and the RenderFrameProxyHosts will share ownership
255 // of this object.
256 scoped_refptr<RenderViewHostImpl> CreateRenderViewHost(
257 SiteInstance* site_instance,
258 int32_t main_frame_routing_id,
danakj08eb51d2020-12-30 20:15:23259 bool swapped_out,
260 bool renderer_initiated_creation);
danakjc492bf82020-09-09 20:02:44261
262 // Returns the existing RenderViewHost for a new RenderFrameHost.
263 // There should always be such a RenderViewHost, because the main frame
264 // RenderFrameHost for each SiteInstance should be created before subframes.
265 scoped_refptr<RenderViewHostImpl> GetRenderViewHost(
266 SiteInstance* site_instance);
267
268 // Registers a RenderViewHost so that it can be reused by other frames
269 // belonging to the same SiteInstance.
270 //
271 // This method does not take ownership of|rvh|.
272 //
273 // NOTE: This method CHECK fails if a RenderViewHost is already registered for
274 // |rvh|'s SiteInstance.
275 //
276 // ALSO NOTE: After calling RegisterRenderViewHost, UnregisterRenderViewHost
277 // *must* be called for |rvh| when it is destroyed or put into the
278 // BackForwardCache, to prevent FrameTree::CreateRenderViewHost from trying to
279 // reuse it.
Aaron Colwellc4bd7d62021-01-29 04:23:13280 void RegisterRenderViewHost(SiteInstance* site_instance,
281 RenderViewHostImpl* rvh);
danakjc492bf82020-09-09 20:02:44282
283 // Unregisters the RenderViewHostImpl that's available for reuse for a
284 // particular SiteInstance. NOTE: This method CHECK fails if it is called for
285 // a |render_view_host| that is not currently set for reuse.
Aaron Colwellc4bd7d62021-01-29 04:23:13286 void UnregisterRenderViewHost(SiteInstance* site_instance,
287 RenderViewHostImpl* render_view_host);
danakjc492bf82020-09-09 20:02:44288
289 // This is called when the frame is about to be removed and started to run
290 // unload handlers.
291 void FrameUnloading(FrameTreeNode* frame);
292
293 // This is only meant to be called by FrameTreeNode. Triggers calling
294 // the listener installed by SetFrameRemoveListener.
295 void FrameRemoved(FrameTreeNode* frame);
296
Carlos Caballero03262522021-02-05 14:49:58297 void DidStartLoadingNode(FrameTreeNode& node,
298 bool to_different_document,
299 bool was_previously_loading);
300 void DidStopLoadingNode(FrameTreeNode& node);
301 void DidChangeLoadProgressForNode(FrameTreeNode& node, double load_progress);
302 void DidCancelLoading();
danakjc492bf82020-09-09 20:02:44303
304 // Returns this FrameTree's total load progress.
305 double load_progress() const { return load_progress_; }
306
307 // Resets the load progress on all nodes in this FrameTree.
308 void ResetLoadProgress();
309
310 // Returns true if at least one of the nodes in this FrameTree is loading.
311 bool IsLoading() const;
312
313 // Set page-level focus in all SiteInstances involved in rendering
314 // this FrameTree, not including the current main frame's
315 // SiteInstance. The focus update will be sent via the main frame's proxies
316 // in those SiteInstances.
317 void ReplicatePageFocus(bool is_focused);
318
319 // Updates page-level focus for this FrameTree in the subframe renderer
320 // identified by |instance|.
321 void SetPageFocus(SiteInstance* instance, bool is_focused);
322
323 // Walks the current frame tree and registers any origins matching |origin|,
324 // either the last committed origin of a RenderFrameHost or the origin
325 // associated with a NavigationRequest that has been assigned to a
326 // SiteInstance, as not-opted-in for origin isolation.
327 void RegisterExistingOriginToPreventOptInIsolation(
328 const url::Origin& previously_visited_origin,
329 NavigationRequest* navigation_request_to_exclude);
330
Carlos Caballero40b0efd2021-01-26 11:55:00331 NavigationControllerImpl& controller() { return navigator_.controller(); }
danakjc492bf82020-09-09 20:02:44332 Navigator& navigator() { return navigator_; }
333
Carlos Caballeroede6f8c2021-01-28 11:01:50334 // Another page accessed the initial empty main document, which means it
335 // is no longer safe to display a pending URL without risking a URL spoof.
336 void DidAccessInitialMainDocument();
337
338 bool has_accessed_initial_main_document() const {
339 return has_accessed_initial_main_document_;
340 }
341
342 void ResetHasAccessedInitialMainDocument() {
343 has_accessed_initial_main_document_ = false;
344 }
345
Carlos Caballero6ff6ace2021-02-05 16:53:00346 bool IsHidden() const { return delegate_->IsHidden(); }
347
Carlos Caballero03262522021-02-05 14:49:58348 // Stops all ongoing navigations in each of the nodes of this FrameTree.
349 void StopLoading();
350
danakjc492bf82020-09-09 20:02:44351 private:
352 friend class FrameTreeTest;
353 FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame);
354
Sreeja Kamishetty46f762c2021-02-05 07:52:46355 // Prerender2:
356 // Indicates whether this frame tree is being prerendered.
357 // Set to true when frame tree is created (PrerenderHost()) and to false once
358 // the prerendered page is activated
359 // (PrerenderHost::ActivatePrerenderedContents()).
360 // TODO(https://crbug.com/1174926): Migrate this parameter to FrameTreeType
361 // once activation path is migrated onto MPArch and WebContents-swap-based
362 // activation logic is removed.
363 bool is_prerendering_ = false;
364
danakjc492bf82020-09-09 20:02:44365 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
366 // breadth-first traversal order, skipping the subtree rooted at
367 // |node|, but including |node| itself.
368 NodeRange NodesExceptSubtree(FrameTreeNode* node);
369
Carlos Caballero03262522021-02-05 14:49:58370 Delegate* const delegate_;
371
danakjc492bf82020-09-09 20:02:44372 // These delegates are installed into all the RenderViewHosts and
373 // RenderFrameHosts that we create.
374 RenderFrameHostDelegate* render_frame_delegate_;
375 RenderViewHostDelegate* render_view_delegate_;
376 RenderWidgetHostDelegate* render_widget_delegate_;
377 RenderFrameHostManager::Delegate* manager_delegate_;
378
379 // The Navigator object responsible for managing navigations on this frame
Carlos Caballero40b0efd2021-01-26 11:55:00380 // tree. Each FrameTreeNode will default to using it for navigation tasks in
381 // the frame.
danakjc492bf82020-09-09 20:02:44382 Navigator navigator_;
383
384 // Map of SiteInstance ID to RenderViewHost. This allows us to look up the
385 // RenderViewHost for a given SiteInstance when creating RenderFrameHosts.
386 // Each RenderViewHost maintains a refcount and is deleted when there are no
387 // more RenderFrameHosts or RenderFrameProxyHosts using it.
388 std::unordered_map<int /* SiteInstance ID */, RenderViewHostImpl*>
389 render_view_host_map_;
390
391 // This is an owned ptr to the root FrameTreeNode, which never changes over
392 // the lifetime of the FrameTree. It is not a scoped_ptr because we need the
393 // pointer to remain valid even while the FrameTreeNode is being destroyed,
394 // since it's common for a node to test whether it's the root node.
395 FrameTreeNode* root_;
396
397 int focused_frame_tree_node_id_;
398
danakjc492bf82020-09-09 20:02:44399 // Overall load progress.
400 double load_progress_;
401
Carlos Caballeroede6f8c2021-01-28 11:01:50402 // Whether the initial empty page has been accessed by another page, making it
403 // unsafe to show the pending URL. Usually false unless another window tries
404 // to modify the blank page. Always false after the first commit.
405 bool has_accessed_initial_main_document_ = false;
406
danakjc492bf82020-09-09 20:02:44407 DISALLOW_COPY_AND_ASSIGN(FrameTree);
408};
409
410} // namespace content
411
412#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_