blob: 74bc3f3195415b5fe461f59e5e62f15fae27ba63 [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++();
Kevin McNee5f594382021-05-06 23:18:2367 // Advances the iterator and excludes the children of the current node
68 NodeIterator& AdvanceSkippingChildren();
danakjc492bf82020-09-09 20:02:4469
70 bool operator==(const NodeIterator& rhs) const;
71 bool operator!=(const NodeIterator& rhs) const { return !(*this == rhs); }
72
73 FrameTreeNode* operator*() { return current_node_; }
74
75 private:
76 friend class NodeRange;
77
Kevin McNee5f594382021-05-06 23:18:2378 NodeIterator(const std::vector<FrameTreeNode*>& starting_nodes,
79 const FrameTreeNode* root_of_subtree_to_skip,
80 bool should_descend_into_inner_trees);
81
82 void AdvanceNode();
danakjc492bf82020-09-09 20:02:4483
84 FrameTreeNode* current_node_;
Kevin McNee5f594382021-05-06 23:18:2385 const FrameTreeNode* const root_of_subtree_to_skip_;
86 const bool should_descend_into_inner_trees_;
danakjc492bf82020-09-09 20:02:4487 base::queue<FrameTreeNode*> queue_;
88 };
89
90 class CONTENT_EXPORT NodeRange {
91 public:
Kevin McNee5f594382021-05-06 23:18:2392 NodeRange(const NodeRange&);
93 ~NodeRange();
94
danakjc492bf82020-09-09 20:02:4495 NodeIterator begin();
96 NodeIterator end();
97
98 private:
99 friend class FrameTree;
100
Kevin McNee5f594382021-05-06 23:18:23101 NodeRange(const std::vector<FrameTreeNode*>& starting_nodes,
102 const FrameTreeNode* root_of_subtree_to_skip,
103 bool should_descend_into_inner_trees);
danakjc492bf82020-09-09 20:02:44104
Kevin McNee5f594382021-05-06 23:18:23105 const std::vector<FrameTreeNode*> starting_nodes_;
106 const FrameTreeNode* const root_of_subtree_to_skip_;
107 const bool should_descend_into_inner_trees_;
danakjc492bf82020-09-09 20:02:44108 };
109
Carlos Caballero03262522021-02-05 14:49:58110 class CONTENT_EXPORT Delegate {
111 public:
112 // A RenderFrameHost in the specified |frame_tree_node| started loading a
113 // new document. This corresponds to browser UI starting to show a spinner
114 // or other visual indicator for loading. This method is only invoked if the
115 // FrameTree hadn't been previously loading. |to_different_document| will be
116 // true unless the load is a fragment navigation, or triggered by
117 // history.pushState/replaceState.
118 virtual void DidStartLoading(FrameTreeNode* frame_tree_node,
119 bool to_different_document) = 0;
120
Takashi Toyoshima74090df62021-03-09 14:34:57121 // This is called when all nodes in the FrameTree stopped loading. This
Carlos Caballero03262522021-02-05 14:49:58122 // corresponds to the browser UI stop showing a spinner or other visual
123 // indicator for loading.
124 virtual void DidStopLoading() = 0;
125
126 // The load progress was changed.
127 virtual void DidChangeLoadProgress() = 0;
Carlos Caballero6ff6ace2021-02-05 16:53:00128
129 // Returns true when the active RenderWidgetHostView should be hidden.
130 virtual bool IsHidden() = 0;
Sreeja Kamishettya21b4f62021-06-25 07:48:25131
132 // Called when current Page of this frame tree changes.
133 virtual void NotifyPageChanged() = 0;
Carlos Caballero03262522021-02-05 14:49:58134 };
135
Sreeja Kamishetty74bacd522021-03-22 17:04:24136 // Type of FrameTree instance.
137 enum class Type {
138 // This FrameTree is the primary frame tree for the WebContents, whose main
139 // document URL is shown in the Omnibox.
140 kPrimary,
141
142 // This FrameTree is used to prerender a page in the background which is
143 // invisible to the user.
144 kPrerender
145 };
Sreeja Kamishetty837a10402021-04-23 12:41:59146
147 // A set of delegates are remembered here so that we can create
148 // RenderFrameHostManagers.
149 FrameTree(BrowserContext* browser_context,
150 Delegate* delegate,
151 NavigationControllerDelegate* navigation_controller_delegate,
152 NavigatorDelegate* navigator_delegate,
153 RenderFrameHostDelegate* render_frame_delegate,
154 RenderViewHostDelegate* render_view_delegate,
155 RenderWidgetHostDelegate* render_widget_delegate,
156 RenderFrameHostManager::Delegate* manager_delegate,
157 Type type);
158 ~FrameTree();
Sreeja Kamishetty74bacd522021-03-22 17:04:24159
Carlos Caballero40b0efd2021-01-26 11:55:00160 // Initializes the main frame for this FrameTree. That is it creates the
161 // initial RenderFrameHost in the root node's RenderFrameHostManager. This
162 // method will call back into the delegates so it should only be called once
163 // they have completed their initialization.
164 // TODO(carlscab): It would be great if initialization could happened in the
165 // constructor so we do not leave objects in a half initialized state.
166 void Init(SiteInstance* main_frame_site_instance,
167 bool renderer_initiated_creation,
Sreeja Kamishetty837a10402021-04-23 12:41:59168 const std::string& main_frame_name);
169
170 Type type() const { return type_; }
Carlos Caballero40b0efd2021-01-26 11:55:00171
danakjc492bf82020-09-09 20:02:44172 FrameTreeNode* root() const { return root_; }
173
Sreeja Kamishetty74bacd522021-03-22 17:04:24174 bool is_prerendering() const { return type_ == FrameTree::Type::kPrerender; }
Sreeja Kamishetty46f762c2021-02-05 07:52:46175
Carlos Caballero03262522021-02-05 14:49:58176 Delegate* delegate() { return delegate_; }
177
danakjc492bf82020-09-09 20:02:44178 // Delegates for RenderFrameHosts, RenderViewHosts, RenderWidgetHosts and
179 // RenderFrameHostManagers. These can be kept centrally on the FrameTree
180 // because they are expected to be the same for all frames on a given
181 // FrameTree.
182 RenderFrameHostDelegate* render_frame_delegate() {
183 return render_frame_delegate_;
184 }
185 RenderViewHostDelegate* render_view_delegate() {
186 return render_view_delegate_;
187 }
188 RenderWidgetHostDelegate* render_widget_delegate() {
189 return render_widget_delegate_;
190 }
191 RenderFrameHostManager::Delegate* manager_delegate() {
192 return manager_delegate_;
193 }
Aaron Colwell78b4bde2021-03-16 16:16:09194
195 using RenderViewHostMapId = util::IdType32<class RenderViewHostMap>;
196 using RenderViewHostMap = std::unordered_map<RenderViewHostMapId,
197 RenderViewHostImpl*,
198 RenderViewHostMapId::Hasher>;
199 const RenderViewHostMap& render_view_hosts() const {
danakjc492bf82020-09-09 20:02:44200 return render_view_host_map_;
201 }
202
203 // Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
204 // of this FrameTree.
205 FrameTreeNode* FindByID(int frame_tree_node_id);
206
207 // Returns the FrameTreeNode with the given renderer-specific |routing_id|.
208 FrameTreeNode* FindByRoutingID(int process_id, int routing_id);
209
210 // Returns the first frame in this tree with the given |name|, or the main
211 // frame if |name| is empty.
212 // Note that this does NOT support pseudo-names like _self, _top, and _blank,
213 // nor searching other FrameTrees (unlike blink::WebView::findFrameByName).
214 FrameTreeNode* FindByName(const std::string& name);
215
216 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
217 // breadth-first traversal order.
218 NodeRange Nodes();
219
220 // Returns a range to iterate over all FrameTreeNodes in a subtree of the
221 // frame tree, starting from |subtree_root|.
222 NodeRange SubtreeNodes(FrameTreeNode* subtree_root);
223
Kevin McNee5f594382021-05-06 23:18:23224 // Returns a range to iterate over all FrameTreeNodes in a subtree, starting
225 // from, but not including |parent|, as well as any FrameTreeNodes of inner
226 // frame trees.
227 static NodeRange SubtreeAndInnerTreeNodes(RenderFrameHostImpl* parent);
228
danakjc492bf82020-09-09 20:02:44229 // Adds a new child frame to the frame tree. |process_id| is required to
230 // disambiguate |new_routing_id|, and it must match the process of the
231 // |parent| node. Otherwise no child is added and this method returns false.
232 // |interface_provider_receiver| is the receiver end of the InterfaceProvider
233 // interface through which the child RenderFrame can access Mojo services
234 // exposed by the corresponding RenderFrameHost. The caller takes care of
Antonio Sartoridb967c52021-01-20 09:54:30235 // sending the client end of the interface down to the
236 // RenderFrame. |policy_container_bind_params|, if not null, is used for
237 // binding Blink's policy container to the new RenderFrameHost's
238 // PolicyContainerHost. This is only needed if this frame is the result of the
239 // CreateChildFrame mojo call, which also delivers the
240 // |policy_container_bind_params|.
danakjc492bf82020-09-09 20:02:44241 FrameTreeNode* AddFrame(
242 RenderFrameHostImpl* parent,
243 int process_id,
244 int new_routing_id,
danakj0bdfacd2021-01-20 19:27:18245 mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
danakjc492bf82020-09-09 20:02:44246 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
247 browser_interface_broker_receiver,
Antonio Sartoridb967c52021-01-20 09:54:30248 blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
danakjc492bf82020-09-09 20:02:44249 blink::mojom::TreeScopeType scope,
250 const std::string& frame_name,
251 const std::string& frame_unique_name,
252 bool is_created_by_script,
Chris Hamilton3ff6ed0e2021-02-19 03:54:04253 const blink::LocalFrameToken& frame_token,
danakjc492bf82020-09-09 20:02:44254 const base::UnguessableToken& devtools_frame_token,
255 const blink::FramePolicy& frame_policy,
256 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
257 bool was_discarded,
258 blink::mojom::FrameOwnerElementType owner_type);
259
260 // Removes a frame from the frame tree. |child|, its children, and objects
261 // owned by their RenderFrameHostManagers are immediately deleted. The root
262 // node cannot be removed this way.
263 void RemoveFrame(FrameTreeNode* child);
264
265 // This method walks the entire frame tree and creates a RenderFrameProxyHost
266 // for the given |site_instance| in each node except the |source| one --
267 // the source will have a RenderFrameHost. |source| may be null if there is
268 // no node navigating in this frame tree (such as when this is called
269 // for an opener's frame tree), in which case no nodes are skipped for
270 // RenderFrameProxyHost creation.
271 void CreateProxiesForSiteInstance(FrameTreeNode* source,
272 SiteInstance* site_instance);
273
274 // Convenience accessor for the main frame's RenderFrameHostImpl.
275 RenderFrameHostImpl* GetMainFrame() const;
276
277 // Returns the focused frame.
278 FrameTreeNode* GetFocusedFrame();
279
280 // Sets the focused frame to |node|. |source| identifies the SiteInstance
281 // that initiated this focus change. If this FrameTree has SiteInstances
282 // other than |source|, those SiteInstances will be notified about the new
283 // focused frame. Note that |source| may differ from |node|'s current
284 // SiteInstance (e.g., this happens for cross-process window.focus() calls).
285 void SetFocusedFrame(FrameTreeNode* node, SiteInstance* source);
286
danakjc492bf82020-09-09 20:02:44287 // Creates a RenderViewHostImpl for a given |site_instance| in the tree.
288 //
289 // The RenderFrameHostImpls and the RenderFrameProxyHosts will share ownership
290 // of this object.
291 scoped_refptr<RenderViewHostImpl> CreateRenderViewHost(
292 SiteInstance* site_instance,
293 int32_t main_frame_routing_id,
danakj08eb51d2020-12-30 20:15:23294 bool swapped_out,
295 bool renderer_initiated_creation);
danakjc492bf82020-09-09 20:02:44296
297 // Returns the existing RenderViewHost for a new RenderFrameHost.
298 // There should always be such a RenderViewHost, because the main frame
299 // RenderFrameHost for each SiteInstance should be created before subframes.
300 scoped_refptr<RenderViewHostImpl> GetRenderViewHost(
301 SiteInstance* site_instance);
302
Aaron Colwell78b4bde2021-03-16 16:16:09303 // Returns the ID used for the RenderViewHost associated with |site_instance|.
304 // Note: Callers should not assume that there is a 1:1 mapping between
305 // SiteInstances and IDs returned by this function, since several
306 // SiteInstances may share a RenderViewHost.
307 RenderViewHostMapId GetRenderViewHostMapId(SiteInstance* site_instance) const;
308
danakjc492bf82020-09-09 20:02:44309 // Registers a RenderViewHost so that it can be reused by other frames
Aaron Colwell78b4bde2021-03-16 16:16:09310 // whose SiteInstance maps to the same RenderViewHostMapId.
danakjc492bf82020-09-09 20:02:44311 //
312 // This method does not take ownership of|rvh|.
313 //
314 // NOTE: This method CHECK fails if a RenderViewHost is already registered for
315 // |rvh|'s SiteInstance.
316 //
317 // ALSO NOTE: After calling RegisterRenderViewHost, UnregisterRenderViewHost
318 // *must* be called for |rvh| when it is destroyed or put into the
319 // BackForwardCache, to prevent FrameTree::CreateRenderViewHost from trying to
320 // reuse it.
Aaron Colwell78b4bde2021-03-16 16:16:09321 void RegisterRenderViewHost(RenderViewHostMapId id, RenderViewHostImpl* rvh);
danakjc492bf82020-09-09 20:02:44322
323 // Unregisters the RenderViewHostImpl that's available for reuse for a
Aaron Colwell78b4bde2021-03-16 16:16:09324 // particular RenderViewHostMapId. NOTE: This method CHECK fails if it is
325 // called for a |render_view_host| that is not currently set for reuse.
326 void UnregisterRenderViewHost(RenderViewHostMapId id,
Aaron Colwellc4bd7d62021-01-29 04:23:13327 RenderViewHostImpl* render_view_host);
danakjc492bf82020-09-09 20:02:44328
329 // This is called when the frame is about to be removed and started to run
330 // unload handlers.
331 void FrameUnloading(FrameTreeNode* frame);
332
333 // This is only meant to be called by FrameTreeNode. Triggers calling
334 // the listener installed by SetFrameRemoveListener.
335 void FrameRemoved(FrameTreeNode* frame);
336
Carlos Caballero03262522021-02-05 14:49:58337 void DidStartLoadingNode(FrameTreeNode& node,
338 bool to_different_document,
339 bool was_previously_loading);
340 void DidStopLoadingNode(FrameTreeNode& node);
341 void DidChangeLoadProgressForNode(FrameTreeNode& node, double load_progress);
342 void DidCancelLoading();
danakjc492bf82020-09-09 20:02:44343
344 // Returns this FrameTree's total load progress.
345 double load_progress() const { return load_progress_; }
346
347 // Resets the load progress on all nodes in this FrameTree.
348 void ResetLoadProgress();
349
350 // Returns true if at least one of the nodes in this FrameTree is loading.
351 bool IsLoading() const;
352
353 // Set page-level focus in all SiteInstances involved in rendering
354 // this FrameTree, not including the current main frame's
355 // SiteInstance. The focus update will be sent via the main frame's proxies
356 // in those SiteInstances.
357 void ReplicatePageFocus(bool is_focused);
358
359 // Updates page-level focus for this FrameTree in the subframe renderer
360 // identified by |instance|.
361 void SetPageFocus(SiteInstance* instance, bool is_focused);
362
363 // Walks the current frame tree and registers any origins matching |origin|,
364 // either the last committed origin of a RenderFrameHost or the origin
365 // associated with a NavigationRequest that has been assigned to a
366 // SiteInstance, as not-opted-in for origin isolation.
367 void RegisterExistingOriginToPreventOptInIsolation(
368 const url::Origin& previously_visited_origin,
369 NavigationRequest* navigation_request_to_exclude);
370
Carlos Caballero40b0efd2021-01-26 11:55:00371 NavigationControllerImpl& controller() { return navigator_.controller(); }
danakjc492bf82020-09-09 20:02:44372 Navigator& navigator() { return navigator_; }
373
Carlos Caballeroede6f8c2021-01-28 11:01:50374 // Another page accessed the initial empty main document, which means it
375 // is no longer safe to display a pending URL without risking a URL spoof.
376 void DidAccessInitialMainDocument();
377
378 bool has_accessed_initial_main_document() const {
379 return has_accessed_initial_main_document_;
380 }
381
382 void ResetHasAccessedInitialMainDocument() {
383 has_accessed_initial_main_document_ = false;
384 }
385
Carlos Caballero6ff6ace2021-02-05 16:53:00386 bool IsHidden() const { return delegate_->IsHidden(); }
387
Carlos Caballero03262522021-02-05 14:49:58388 // Stops all ongoing navigations in each of the nodes of this FrameTree.
389 void StopLoading();
390
Carlos Caballero101ac26b2021-03-24 11:54:05391 // Prepares this frame tree for destruction, cleaning up the internal state
392 // and firing the appropriate events like FrameDeleted.
393 // Must be called before FrameTree is destroyed.
394 void Shutdown();
395
shivanigithub93878d02021-06-15 11:37:53396 // Returns true if this is a fenced frame tree.
397 // TODO(crbug.com/1123606): Integrate this with the MPArch based fenced frame
398 // code once that lands.
399 bool IsFencedFrameTree() const { return is_fenced_frame_tree_; }
400 void SetFencedFrameTreeForTesting() { is_fenced_frame_tree_ = true; }
401
danakjc492bf82020-09-09 20:02:44402 private:
403 friend class FrameTreeTest;
404 FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame);
405
406 // Returns a range to iterate over all FrameTreeNodes in the frame tree in
407 // breadth-first traversal order, skipping the subtree rooted at
408 // |node|, but including |node| itself.
409 NodeRange NodesExceptSubtree(FrameTreeNode* node);
410
Carlos Caballero03262522021-02-05 14:49:58411 Delegate* const delegate_;
412
danakjc492bf82020-09-09 20:02:44413 // These delegates are installed into all the RenderViewHosts and
414 // RenderFrameHosts that we create.
415 RenderFrameHostDelegate* render_frame_delegate_;
416 RenderViewHostDelegate* render_view_delegate_;
417 RenderWidgetHostDelegate* render_widget_delegate_;
418 RenderFrameHostManager::Delegate* manager_delegate_;
419
420 // The Navigator object responsible for managing navigations on this frame
Carlos Caballero40b0efd2021-01-26 11:55:00421 // tree. Each FrameTreeNode will default to using it for navigation tasks in
422 // the frame.
danakjc492bf82020-09-09 20:02:44423 Navigator navigator_;
424
Aaron Colwell78b4bde2021-03-16 16:16:09425 // Map of RenderViewHostMapId to RenderViewHost. This allows us to look up the
danakjc492bf82020-09-09 20:02:44426 // RenderViewHost for a given SiteInstance when creating RenderFrameHosts.
427 // Each RenderViewHost maintains a refcount and is deleted when there are no
428 // more RenderFrameHosts or RenderFrameProxyHosts using it.
Aaron Colwell78b4bde2021-03-16 16:16:09429 RenderViewHostMap render_view_host_map_;
danakjc492bf82020-09-09 20:02:44430
431 // This is an owned ptr to the root FrameTreeNode, which never changes over
432 // the lifetime of the FrameTree. It is not a scoped_ptr because we need the
433 // pointer to remain valid even while the FrameTreeNode is being destroyed,
434 // since it's common for a node to test whether it's the root node.
435 FrameTreeNode* root_;
436
437 int focused_frame_tree_node_id_;
438
danakjc492bf82020-09-09 20:02:44439 // Overall load progress.
440 double load_progress_;
441
Carlos Caballeroede6f8c2021-01-28 11:01:50442 // Whether the initial empty page has been accessed by another page, making it
443 // unsafe to show the pending URL. Usually false unless another window tries
444 // to modify the blank page. Always false after the first commit.
445 bool has_accessed_initial_main_document_ = false;
446
Sreeja Kamishetty837a10402021-04-23 12:41:59447 // Indicates type of frame tree.
448 const Type type_;
Sreeja Kamishetty74bacd522021-03-22 17:04:24449
shivanigithub93878d02021-06-15 11:37:53450 // TODO(crbug.com/1123606): Integrate this with the MPArch based fenced frame
451 // code once that lands. Possibly this will then be part of |type_|.
452 bool is_fenced_frame_tree_ = false;
453
Carlos Caballero101ac26b2021-03-24 11:54:05454#if DCHECK_IS_ON()
455 // Whether Shutdown() was called.
456 bool was_shut_down_ = false;
457#endif
458
danakjc492bf82020-09-09 20:02:44459 DISALLOW_COPY_AND_ASSIGN(FrameTree);
460};
461
462} // namespace content
463
464#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_TREE_H_