blob: 8b82ac44770ac7af9ab3675bd5b4e34314c25d07 [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
danakjc492bf82020-09-09 20:02:4496 // A set of delegates are remembered here so that we can create
97 // RenderFrameHostManagers.
Carlos Caballero40b0efd2021-01-26 11:55:0098 FrameTree(BrowserContext* browser_context,
99 NavigationControllerDelegate* navigation_controller_delegate,
danakjc492bf82020-09-09 20:02:44100 NavigatorDelegate* navigator_delegate,
101 RenderFrameHostDelegate* render_frame_delegate,
102 RenderViewHostDelegate* render_view_delegate,
103 RenderWidgetHostDelegate* render_widget_delegate,
104 RenderFrameHostManager::Delegate* manager_delegate);
105 ~FrameTree();
106
Carlos Caballero40b0efd2021-01-26 11:55:00107 // Initializes the main frame for this FrameTree. That is it creates the
108 // initial RenderFrameHost in the root node's RenderFrameHostManager. This
109 // method will call back into the delegates so it should only be called once
110 // they have completed their initialization.
111 // TODO(carlscab): It would be great if initialization could happened in the
112 // constructor so we do not leave objects in a half initialized state.
113 void Init(SiteInstance* main_frame_site_instance,
114 bool renderer_initiated_creation,
115 const std::string& main_frame_name);
116
danakjc492bf82020-09-09 20:02:44117 FrameTreeNode* root() const { return root_; }
118
119 // Delegates for RenderFrameHosts, RenderViewHosts, RenderWidgetHosts and
120 // RenderFrameHostManagers. These can be kept centrally on the FrameTree
121 // because they are expected to be the same for all frames on a given
122 // FrameTree.
123 RenderFrameHostDelegate* render_frame_delegate() {
124 return render_frame_delegate_;
125 }
126 RenderViewHostDelegate* render_view_delegate() {
127 return render_view_delegate_;
128 }
129 RenderWidgetHostDelegate* render_widget_delegate() {
130 return render_widget_delegate_;
131 }
132 RenderFrameHostManager::Delegate* manager_delegate() {
133 return manager_delegate_;
134 }
135 const std::unordered_map<int /* SiteInstance ID */, RenderViewHostImpl*>&
136 render_view_hosts() const {
137 return render_view_host_map_;
138 }
139
140 // Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
141 // of this FrameTree.
142 FrameTreeNode* FindByID(int frame_tree_node_id);
143
144 // Returns the FrameTreeNode with the given renderer-specific |routing_id|.
145 FrameTreeNode* FindByRoutingID(int process_id, int routing_id);
146
147 // Returns the first frame in this tree with the given |name|, or the main
148 // frame if |name| is empty.
149 // Note that this does NOT support pseudo-names like _self, _top, and _blank,
150 // nor searching other FrameTrees (unlike blink::WebView::findFrameByName).
151 FrameTreeNode* FindByName(const std::string& name);
152
153 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
154 // breadth-first traversal order.
155 NodeRange Nodes();
156
157 // Returns a range to iterate over all FrameTreeNodes in a subtree of the
158 // frame tree, starting from |subtree_root|.
159 NodeRange SubtreeNodes(FrameTreeNode* subtree_root);
160
161 // Adds a new child frame to the frame tree. |process_id| is required to
162 // disambiguate |new_routing_id|, and it must match the process of the
163 // |parent| node. Otherwise no child is added and this method returns false.
164 // |interface_provider_receiver| is the receiver end of the InterfaceProvider
165 // interface through which the child RenderFrame can access Mojo services
166 // exposed by the corresponding RenderFrameHost. The caller takes care of
Antonio Sartoridb967c52021-01-20 09:54:30167 // sending the client end of the interface down to the
168 // RenderFrame. |policy_container_bind_params|, if not null, is used for
169 // binding Blink's policy container to the new RenderFrameHost's
170 // PolicyContainerHost. This is only needed if this frame is the result of the
171 // CreateChildFrame mojo call, which also delivers the
172 // |policy_container_bind_params|.
danakjc492bf82020-09-09 20:02:44173 FrameTreeNode* AddFrame(
174 RenderFrameHostImpl* parent,
175 int process_id,
176 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18177 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
danakjc492bf82020-09-09 20:02:44178 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
179 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30180 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
danakjc492bf82020-09-09 20:02:44181 blink::mojom::TreeScopeType scope,
182 const std::string& frame_name,
183 const std::string& frame_unique_name,
184 bool is_created_by_script,
185 const base::UnguessableToken& frame_token,
186 const base::UnguessableToken& devtools_frame_token,
187 const blink::FramePolicy& frame_policy,
188 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
189 bool was_discarded,
190 blink::mojom::FrameOwnerElementType owner_type);
191
192 // Removes a frame from the frame tree. |child|, its children, and objects
193 // owned by their RenderFrameHostManagers are immediately deleted. The root
194 // node cannot be removed this way.
195 void RemoveFrame(FrameTreeNode* child);
196
197 // This method walks the entire frame tree and creates a RenderFrameProxyHost
198 // for the given |site_instance| in each node except the |source| one --
199 // the source will have a RenderFrameHost. |source| may be null if there is
200 // no node navigating in this frame tree (such as when this is called
201 // for an opener's frame tree), in which case no nodes are skipped for
202 // RenderFrameProxyHost creation.
203 void CreateProxiesForSiteInstance(FrameTreeNode* source,
204 SiteInstance* site_instance);
205
206 // Convenience accessor for the main frame's RenderFrameHostImpl.
207 RenderFrameHostImpl* GetMainFrame() const;
208
209 // Returns the focused frame.
210 FrameTreeNode* GetFocusedFrame();
211
212 // Sets the focused frame to |node|. |source| identifies the SiteInstance
213 // that initiated this focus change. If this FrameTree has SiteInstances
214 // other than |source|, those SiteInstances will be notified about the new
215 // focused frame. Note that |source| may differ from |node|'s current
216 // SiteInstance (e.g., this happens for cross-process window.focus() calls).
217 void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source);
218
219 // Allows a client to listen for frame removal. The listener should expect
220 // to receive the RenderViewHostImpl containing the frame and the renderer-
221 // specific frame routing ID of the removed frame.
222 void SetFrameRemoveListener(
223 base::RepeatingCallback<void(RenderFrameHost*)> on_frame_removed);
224
225 // Creates a RenderViewHostImpl for a given |site_instance| in the tree.
226 //
227 // The RenderFrameHostImpls and the RenderFrameProxyHosts will share ownership
228 // of this object.
229 scoped_refptr<RenderViewHostImpl> CreateRenderViewHost(
230 SiteInstance* site_instance,
231 int32_t main_frame_routing_id,
danakj08eb51d2020-12-30 20:15:23232 bool swapped_out,
233 bool renderer_initiated_creation);
danakjc492bf82020-09-09 20:02:44234
235 // Returns the existing RenderViewHost for a new RenderFrameHost.
236 // There should always be such a RenderViewHost, because the main frame
237 // RenderFrameHost for each SiteInstance should be created before subframes.
238 scoped_refptr<RenderViewHostImpl> GetRenderViewHost(
239 SiteInstance* site_instance);
240
241 // Registers a RenderViewHost so that it can be reused by other frames
242 // belonging to the same SiteInstance.
243 //
244 // This method does not take ownership of|rvh|.
245 //
246 // NOTE: This method CHECK fails if a RenderViewHost is already registered for
247 // |rvh|'s SiteInstance.
248 //
249 // ALSO NOTE: After calling RegisterRenderViewHost, UnregisterRenderViewHost
250 // *must* be called for |rvh| when it is destroyed or put into the
251 // BackForwardCache, to prevent FrameTree::CreateRenderViewHost from trying to
252 // reuse it.
Aaron Colwellc4bd7d62021-01-29 04:23:13253 void RegisterRenderViewHost(SiteInstance* site_instance,
254 RenderViewHostImpl* rvh);
danakjc492bf82020-09-09 20:02:44255
256 // Unregisters the RenderViewHostImpl that's available for reuse for a
257 // particular SiteInstance. NOTE: This method CHECK fails if it is called for
258 // a |render_view_host| that is not currently set for reuse.
Aaron Colwellc4bd7d62021-01-29 04:23:13259 void UnregisterRenderViewHost(SiteInstance* site_instance,
260 RenderViewHostImpl* render_view_host);
danakjc492bf82020-09-09 20:02:44261
262 // This is called when the frame is about to be removed and started to run
263 // unload handlers.
264 void FrameUnloading(FrameTreeNode* frame);
265
266 // This is only meant to be called by FrameTreeNode. Triggers calling
267 // the listener installed by SetFrameRemoveListener.
268 void FrameRemoved(FrameTreeNode* frame);
269
270 // Updates the overall load progress and notifies the WebContents.
271 // Set based on the main frame's progress only.
272 void UpdateLoadProgress(double progress);
273
274 // Returns this FrameTree's total load progress.
275 double load_progress() const { return load_progress_; }
276
277 // Resets the load progress on all nodes in this FrameTree.
278 void ResetLoadProgress();
279
280 // Returns true if at least one of the nodes in this FrameTree is loading.
281 bool IsLoading() const;
282
283 // Set page-level focus in all SiteInstances involved in rendering
284 // this FrameTree, not including the current main frame's
285 // SiteInstance. The focus update will be sent via the main frame's proxies
286 // in those SiteInstances.
287 void ReplicatePageFocus(bool is_focused);
288
289 // Updates page-level focus for this FrameTree in the subframe renderer
290 // identified by |instance|.
291 void SetPageFocus(SiteInstance* instance, bool is_focused);
292
293 // Walks the current frame tree and registers any origins matching |origin|,
294 // either the last committed origin of a RenderFrameHost or the origin
295 // associated with a NavigationRequest that has been assigned to a
296 // SiteInstance, as not-opted-in for origin isolation.
297 void RegisterExistingOriginToPreventOptInIsolation(
298 const url::Origin& previously_visited_origin,
299 NavigationRequest* navigation_request_to_exclude);
300
Carlos Caballero40b0efd2021-01-26 11:55:00301 NavigationControllerImpl& controller() { return navigator_.controller(); }
danakjc492bf82020-09-09 20:02:44302 Navigator& navigator() { return navigator_; }
303
Carlos Caballeroede6f8c2021-01-28 11:01:50304 // Another page accessed the initial empty main document, which means it
305 // is no longer safe to display a pending URL without risking a URL spoof.
306 void DidAccessInitialMainDocument();
307
308 bool has_accessed_initial_main_document() const {
309 return has_accessed_initial_main_document_;
310 }
311
312 void ResetHasAccessedInitialMainDocument() {
313 has_accessed_initial_main_document_ = false;
314 }
315
danakjc492bf82020-09-09 20:02:44316 private:
317 friend class FrameTreeTest;
318 FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame);
319
320 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
321 // breadth-first traversal order, skipping the subtree rooted at
322 // |node|, but including |node| itself.
323 NodeRange NodesExceptSubtree(FrameTreeNode* node);
324
325 // These delegates are installed into all the RenderViewHosts and
326 // RenderFrameHosts that we create.
327 RenderFrameHostDelegate* render_frame_delegate_;
328 RenderViewHostDelegate* render_view_delegate_;
329 RenderWidgetHostDelegate* render_widget_delegate_;
330 RenderFrameHostManager::Delegate* manager_delegate_;
331
332 // The Navigator object responsible for managing navigations on this frame
Carlos Caballero40b0efd2021-01-26 11:55:00333 // tree. Each FrameTreeNode will default to using it for navigation tasks in
334 // the frame.
danakjc492bf82020-09-09 20:02:44335 Navigator navigator_;
336
337 // Map of SiteInstance ID to RenderViewHost. This allows us to look up the
338 // RenderViewHost for a given SiteInstance when creating RenderFrameHosts.
339 // Each RenderViewHost maintains a refcount and is deleted when there are no
340 // more RenderFrameHosts or RenderFrameProxyHosts using it.
341 std::unordered_map<int /* SiteInstance ID */, RenderViewHostImpl*>
342 render_view_host_map_;
343
344 // This is an owned ptr to the root FrameTreeNode, which never changes over
345 // the lifetime of the FrameTree. It is not a scoped_ptr because we need the
346 // pointer to remain valid even while the FrameTreeNode is being destroyed,
347 // since it's common for a node to test whether it's the root node.
348 FrameTreeNode* root_;
349
350 int focused_frame_tree_node_id_;
351
352 base::RepeatingCallback<void(RenderFrameHost*)> on_frame_removed_;
353
354 // Overall load progress.
355 double load_progress_;
356
Carlos Caballeroede6f8c2021-01-28 11:01:50357 // Whether the initial empty page has been accessed by another page, making it
358 // unsafe to show the pending URL. Usually false unless another window tries
359 // to modify the blank page. Always false after the first commit.
360 bool has_accessed_initial_main_document_ = false;
361
danakjc492bf82020-09-09 20:02:44362 DISALLOW_COPY_AND_ASSIGN(FrameTree);
363};
364
365} // namespace content
366
367#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_