1 // 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_RENDER_FRAME_HOST_MANAGER_H_
6 #define CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_HOST_MANAGER_H_
7 
8 #include <stdint.h>
9 
10 #include <list>
11 #include <map>
12 #include <memory>
13 #include <set>
14 #include <unordered_map>
15 #include <unordered_set>
16 
17 #include "base/containers/unique_ptr_adapters.h"
18 #include "base/macros.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/optional.h"
21 #include "content/browser/coop_coep_cross_origin_isolated_info.h"
22 #include "content/browser/renderer_host/back_forward_cache_impl.h"
23 #include "content/browser/renderer_host/render_frame_host_impl.h"
24 #include "content/browser/renderer_host/should_swap_browsing_instance.h"
25 #include "content/browser/site_instance_impl.h"
26 #include "content/common/content_export.h"
27 #include "content/public/browser/global_request_id.h"
28 #include "content/public/common/referrer.h"
29 #include "services/network/public/mojom/content_security_policy.mojom-forward.h"
30 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-forward.h"
31 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
32 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-forward.h"
33 #include "ui/base/page_transition_types.h"
34 #include "url/origin.h"
35 
36 namespace content {
37 class FrameTree;
38 class FrameTreeNode;
39 class NavigationControllerImpl;
40 class NavigationEntry;
41 class NavigationRequest;
42 class NavigatorTest;
43 class RenderFrameHostManagerTest;
44 class RenderFrameProxyHost;
45 class RenderViewHost;
46 class RenderViewHostImpl;
47 class RenderWidgetHostView;
48 class TestWebContents;
49 
50 using PageBroadcastMethodCallback =
51     base::RepeatingCallback<void(RenderViewHostImpl*)>;
52 
53 using RemoteFramesBroadcastMethodCallback =
54     base::RepeatingCallback<void(RenderFrameProxyHost*)>;
55 
56 // Manages RenderFrameHosts for a FrameTreeNode. It maintains a
57 // current_frame_host() which is the content currently visible to the user. When
58 // a frame is told to navigate to a different web site (as determined by
59 // SiteInstance), it will replace its current RenderFrameHost with a new
60 // RenderFrameHost dedicated to the new SiteInstance, possibly in a new process.
61 //
62 // Cross-process navigation works like this:
63 //
64 // - RFHM::Navigate determines whether the destination is cross-site, and if so,
65 //   it creates a pending_render_frame_host_.
66 //
67 // - The pending RFH is created in the "navigations suspended" state, meaning no
68 //   navigation messages are sent to its renderer until the beforeunload handler
69 //   has a chance to run in the current RFH.
70 //
71 // - The current RFH runs its beforeunload handler. If it returns false, we
72 //   cancel all the pending logic. Otherwise we allow the pending RFH to send
73 //   the navigation request to its renderer.
74 //
75 // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
76 //   main resource load from the pending RFH. It creates a
77 //   CrossSiteResourceHandler to check whether a process transfer is needed when
78 //   the request is ready to commit.
79 //
80 // - When RDH receives a response, the MimeTypeResourceHandler determines
81 //   whether it is a navigation type that doesn't commit (e.g. download, 204 or
82 //   error page). If so, it sends a message to the new renderer causing it to
83 //   cancel the request, and the request (e.g. the download) proceeds. In this
84 //   case, the pending RFH will never become the current RFH, but it remains
85 //   until the next DidNavigate event for this WebContentsImpl.
86 //
87 // - After RDH receives a response and determines that it is safe and not a
88 //   download, the CrossSiteResourceHandler checks whether a transfer for a
89 //   redirect is needed. If so, it pauses the network response and starts an
90 //   identical navigation in a new pending RFH. When the identical request is
91 //   later received by RDH, the response is transferred and unpaused.
92 //
93 // - Otherwise, the network response commits in the pending RFH's renderer,
94 //   which sends a DidCommitProvisionalLoad message back to the browser process.
95 //
96 // - RFHM::CommitPending makes visible the new RFH, and initiates the unload
97 //   handler in the old RFH. The unload handler will complete in the background.
98 //
99 // - RenderFrameHostManager may keep the previous RFH alive as a
100 //   RenderFrameProxyHost, to be used (for example) if the user goes back. The
101 //   process only stays live if another tab is using it, but if so, the existing
102 //   frame relationships will be maintained.
103 class CONTENT_EXPORT RenderFrameHostManager
104     : public SiteInstanceImpl::Observer {
105  public:
106   using RenderFrameProxyHostMap =
107       std::unordered_map<int32_t /* SiteInstance id */,
108                          std::unique_ptr<RenderFrameProxyHost>>;
109 
110   // Functions implemented by our owner that we need.
111   //
112   // TODO(brettw) Clean this up! These are all the functions in WebContentsImpl
113   // that are required to run this class. The design should probably be better
114   // such that these are more clear.
115   //
116   // There is additional complexity that some of the functions we need in
117   // WebContentsImpl are inherited and non-virtual. These are named with
118   // "RenderManager" so that the duplicate implementation of them will be clear.
119   class CONTENT_EXPORT Delegate {
120    public:
121     // Initializes the given renderer if necessary and creates the view ID
122     // corresponding to this view host. If this method is not called and the
123     // process is not shared, then the WebContentsImpl will act as though the
124     // renderer is not running (i.e., it will render "sad tab"). This method is
125     // automatically called from LoadURL.
126     virtual bool CreateRenderViewForRenderManager(
127         RenderViewHost* render_view_host,
128         const base::Optional<base::UnguessableToken>& opener_frame_token,
129         int proxy_routing_id) = 0;
130     virtual void CreateRenderWidgetHostViewForRenderManager(
131         RenderViewHost* render_view_host) = 0;
132     virtual void BeforeUnloadFiredFromRenderManager(
133         bool proceed,
134         const base::TimeTicks& proceed_time,
135         bool* proceed_to_fire_unload) = 0;
136     virtual void RenderProcessGoneFromRenderManager(
137         RenderViewHost* render_view_host) = 0;
138     virtual void CancelModalDialogsForRenderManager() = 0;
139     virtual void NotifySwappedFromRenderManager(RenderFrameHost* old_frame,
140                                                 RenderFrameHost* new_frame,
141                                                 bool is_main_frame) = 0;
142     // TODO(nasko): This should be removed once extensions no longer use
143     // NotificationService. See https://crbug.com/462682.
144     virtual void NotifyMainFrameSwappedFromRenderManager(
145         RenderFrameHost* old_frame,
146         RenderFrameHost* new_frame) = 0;
147     virtual NavigationControllerImpl& GetControllerForRenderManager() = 0;
148 
149     // Returns true if the location bar should be focused by default rather than
150     // the page contents. The view calls this function when the tab is focused
151     // to see what it should do.
152     virtual bool FocusLocationBarByDefault() = 0;
153 
154     // Returns true if views created for this delegate should be created in a
155     // hidden state.
156     virtual bool IsHidden() = 0;
157 
158     // If the delegate is an inner WebContents, this method returns the
159     // FrameTreeNode ID of the frame in the outer WebContents which hosts
160     // the inner WebContents. Returns FrameTreeNode::kFrameTreeNodeInvalidId
161     // if the delegate does not have an outer WebContents.
162     virtual int GetOuterDelegateFrameTreeNodeId() = 0;
163 
164     // If the delegate is an inner WebContents, reattach it to the outer
165     // WebContents.
166     virtual void ReattachOuterDelegateIfNeeded() = 0;
167 
168    protected:
169     virtual ~Delegate() = default;
170   };
171 
172   // The delegate pointer must be non-null and is not owned by this class. It
173   // must outlive this class.
174   //
175   // You must call one of the Init*() methods before using this class.
176   RenderFrameHostManager(FrameTreeNode* frame_tree_node, Delegate* delegate);
177   ~RenderFrameHostManager();
178 
179   // Initialize this frame as the root of a new FrameTree.
180   void InitRoot(SiteInstance* site_instance, bool renderer_initiated_creation);
181 
182   // Initialize this frame as the child of another frame.
183   void InitChild(SiteInstance* site_instance,
184                  int32_t frame_routing_id,
185                  const base::UnguessableToken& frame_token);
186 
187   // Returns the currently active RenderFrameHost.
188   //
189   // This will be non-null between Init() and Shutdown(). You may want to null
190   // check it in many cases, however. Windows can send us messages during the
191   // destruction process after it has been shut down.
current_frame_host()192   RenderFrameHostImpl* current_frame_host() const {
193     return render_frame_host_.get();
194   }
195 
196   // TODO(creis): Remove this when we no longer use RVH for navigation.
197   RenderViewHostImpl* current_host() const;
198 
199   // Returns the view associated with the current RenderViewHost, or null if
200   // there is no current one.
201   RenderWidgetHostView* GetRenderWidgetHostView() const;
202 
203   // Returns whether this manager is a main frame and belongs to a FrameTreeNode
204   // that belongs to an inner WebContents.
205   bool IsMainFrameForInnerDelegate();
206 
207   // If this is a RenderFrameHostManager for a main frame, this method returns
208   // the FrameTreeNode for the frame in the outer WebContents (if any) that
209   // contains the inner WebContents.
210   FrameTreeNode* GetOuterDelegateNode();
211 
212   // Return a proxy for this frame in the parent frame's SiteInstance.  Returns
213   // nullptr if this is a main frame or if such a proxy does not exist (for
214   // example, if this frame is same-site with its parent OR if this frame will
215   // be deleted soon and we are just waiting for the frame's unload handler).
216   RenderFrameProxyHost* GetProxyToParent();
217 
218   // If this is a RenderFrameHostManager for a main frame, returns the proxy to
219   // inner WebContents in the outer WebContents's SiteInstance. Returns nullptr
220   // if this WebContents isn't part of inner/outer relationship.
221   RenderFrameProxyHost* GetProxyToOuterDelegate();
222 
223   // If this is a RenderFrameHostManager for a main frame, removes the
224   // FrameTreeNode in the outer WebContents that represents this FrameTreeNode.
225   // TODO(lazyboy): This does not belong to RenderFrameHostManager, move it to
226   // somewhere else.
227   void RemoveOuterDelegateFrame();
228 
229   // Returns the speculative RenderFrameHost, or null if there is no speculative
230   // one.
speculative_frame_host()231   RenderFrameHostImpl* speculative_frame_host() const {
232     return speculative_render_frame_host_.get();
233   }
234 
235   // Instructs the various live views to stop. Called when the user directed the
236   // page to stop loading.
237   void Stop();
238 
239   // Notifies the regular and pending RenderViewHosts that a load is or is not
240   // happening. Even though the message is only for one of them, we don't know
241   // which one so we tell both.
242   void SetIsLoading(bool is_loading);
243 
244   // Confirms whether we should close the page. |proceed| indicates whether the
245   // user chose to proceed. |proceed_time| is the time when the request was
246   // allowed to proceed. This is called in one of the two *distinct* scenarios
247   // below:
248   //   1- The tab/window is closed after allowing the appropriate renderer to
249   //      show the beforeunload prompt.
250   //   2- The FrameTreeNode is being prepared for attaching an inner Delegate,
251   //      in which case beforeunload is triggered in the current frame. This
252   //      only happens for child frames.
253   void BeforeUnloadCompleted(bool proceed, const base::TimeTicks& proceed_time);
254 
255   // Called when a renderer's frame navigates.
256   void DidNavigateFrame(RenderFrameHostImpl* render_frame_host,
257                         bool was_caused_by_user_gesture,
258                         bool is_same_document_navigation,
259                         bool clear_proxies_on_commit,
260                         const blink::FramePolicy& frame_policy);
261 
262   // Called when this frame's opener is changed to the frame specified by
263   // |opener_frame_token| in |source_site_instance|'s process.  This change
264   // could come from either the current RenderFrameHost or one of the
265   // proxies (e.g., window.open that targets a RemoteFrame by name).  The
266   // updated opener will be forwarded to any other RenderFrameProxies and
267   // RenderFrames for this FrameTreeNode.
268   void DidChangeOpener(
269       const base::Optional<base::UnguessableToken>& opener_frame_token,
270       SiteInstance* source_site_instance);
271 
272   // Creates and initializes a RenderFrameHost. If |for_early_commit| is true
273   // then this RenderFrameHost and its RenderFrame will be prepared knowing that
274   // it will be committed immediately. If false the it will be committed later,
275   // following the usual navigation path.
276   std::unique_ptr<RenderFrameHostImpl> CreateSpeculativeRenderFrame(
277       SiteInstance* instance,
278       bool for_early_commit);
279 
280   // Helper method to create and initialize a RenderFrameProxyHost.
281   void CreateRenderFrameProxy(SiteInstance* instance);
282 
283   // Creates proxies for a new child frame at FrameTreeNode |child| in all
284   // SiteInstances for which the current frame has proxies.  This method is
285   // called on the parent of a new child frame before the child leaves the
286   // SiteInstance.
287   void CreateProxiesForChildFrame(FrameTreeNode* child);
288 
289   // Returns the RenderFrameProxyHost for the given SiteInstance, if any.
290   RenderFrameProxyHost* GetRenderFrameProxyHost(SiteInstance* instance) const;
291 
292   // If |render_frame_host| is on the pending deletion list, this deletes it.
293   // Returns whether it was deleted.
294   bool DeleteFromPendingList(RenderFrameHostImpl* render_frame_host);
295 
296   // BackForwardCache:
297   // During a history navigation, unfreezes and swaps in a document from the
298   // BackForwardCache, making it active.
299   void RestoreFromBackForwardCache(
300       std::unique_ptr<BackForwardCacheImpl::Entry>);
301 
302   // Deletes any proxy hosts associated with this node. Used during destruction
303   // of WebContentsImpl.
304   void ResetProxyHosts();
305 
306   void ClearRFHsPendingShutdown();
307   void ClearWebUIInstances();
308 
309   // Returns the routing id for a RenderFrameHost or RenderFrameProxyHost
310   // that has the given SiteInstance and is associated with this
311   // RenderFrameHostManager. Returns MSG_ROUTING_NONE if none is found.
312   int GetRoutingIdForSiteInstance(SiteInstance* site_instance);
313 
314   // Returns the frame token for a RenderFrameHost or RenderFrameProxyHost
315   // that has the given SiteInstance and is associated with this
316   // RenderFrameHostManager. Returns base::nullopt if none is found.
317   base::Optional<base::UnguessableToken> GetFrameTokenForSiteInstance(
318       SiteInstance* site_instance);
319 
320   // Notifies the RenderFrameHostManager that a new NavigationRequest has been
321   // created and set in the FrameTreeNode so that it can speculatively create a
322   // new RenderFrameHost (and potentially a new process) if needed.
323   void DidCreateNavigationRequest(NavigationRequest* request);
324 
325   // Called (possibly several times) during a navigation to select or create an
326   // appropriate RenderFrameHost for the provided URL. The returned pointer will
327   // be for the current or the speculative RenderFrameHost and the instance is
328   // owned by this manager.
329   //
330   // |reason| is an optional out-parameter that will be populated with
331   // engineer-readable information describing the reason for the method
332   // behavior.  The returned |reason| should fit into
333   // base::debug::CrashKeySize::Size256.
334   RenderFrameHostImpl* GetFrameHostForNavigation(NavigationRequest* request,
335                                                  std::string* reason = nullptr);
336 
337   // Clean up any state for any ongoing navigation.
338   void CleanUpNavigation();
339 
340   // Clears the speculative members, returning the RenderFrameHost to the caller
341   // for disposal.
342   std::unique_ptr<RenderFrameHostImpl> UnsetSpeculativeRenderFrameHost();
343 
344   // Notification methods to tell this RenderFrameHostManager that the frame it
345   // is responsible for has started or stopped loading a document.
346   void OnDidStartLoading();
347   void OnDidStopLoading();
348 
349   // OnDidUpdateName gets called when a frame changes its name - it gets the new
350   // |name| and the recalculated |unique_name| and replicates them into all
351   // frame proxies.
352   void OnDidUpdateName(const std::string& name, const std::string& unique_name);
353 
354   // Sends the newly added Content Security Policy headers to all the proxies.
355   void OnDidAddContentSecurityPolicies(
356       std::vector<network::mojom::ContentSecurityPolicyHeaderPtr> headers);
357 
358   // Resets Content Security Policy in all the proxies.
359   void OnDidResetContentSecurityPolicy();
360 
361   // Sends updated enforcement of insecure request policy to all frame proxies
362   // when the frame changes its setting.
363   void OnEnforceInsecureRequestPolicy(
364       blink::mojom::InsecureRequestPolicy policy);
365 
366   // Sends updated enforcement of upgrade insecure navigations set to all frame
367   // proxies when the frame changes its setting.
368   void OnEnforceInsecureNavigationsSet(
369       const std::vector<uint32_t>& insecure_navigations_set);
370 
371   // Called when the client changes whether the frame's owner element in the
372   // embedder document should be collapsed, that is, remove from the layout as
373   // if it did not exist. Never called for main frames. Only has an effect for
374   // <iframe> owner elements.
375   void OnDidChangeCollapsedState(bool collapsed);
376 
377   // Called on a frame to notify it that its out-of-process parent frame
378   // changed a property (such as allowFullscreen) on its <iframe> element.
379   // Sends updated FrameOwnerProperties to the RenderFrame and to all proxies,
380   // skipping the parent process.
381   void OnDidUpdateFrameOwnerProperties(
382       const blink::mojom::FrameOwnerProperties& properties);
383 
384   // Notify the proxies that the active sandbox flags or feature policy header
385   // on the frame have been changed during page load. Sandbox flags can change
386   // when set by a CSP header.
387   void OnDidSetFramePolicyHeaders();
388 
389   // Send updated origin to all frame proxies when the frame navigates to a new
390   // origin.
391   void OnDidUpdateOrigin(const url::Origin& origin,
392                          bool is_potentially_trustworthy_unique_origin);
393 
394   // Send updated ad frame type to all frame proxies at ready-to-commit time
395   // when the ad status gets updated.
396   void OnDidSetAdFrameType(blink::mojom::AdFrameType ad_frame_type);
397 
398   void EnsureRenderViewInitialized(RenderViewHostImpl* render_view_host,
399                                    SiteInstance* instance);
400 
401   // Creates RenderFrameProxies and inactive RenderViewHosts for this frame's
402   // FrameTree and for its opener chain in the given SiteInstance. This allows
403   // other tabs to send cross-process JavaScript calls to their opener(s) and
404   // to any other frames in the opener's FrameTree (e.g., supporting calls like
405   // window.opener.opener.frames[x][y]).  Does not create proxies for the
406   // subtree rooted at |skip_this_node| (e.g., if a node is being navigated, it
407   // can be passed here to prevent proxies from being created for it, in
408   // case it is in the same FrameTree as another node on its opener chain).
409   void CreateOpenerProxies(SiteInstance* instance,
410                            FrameTreeNode* skip_this_node);
411 
412   // Ensure that this frame has proxies in all SiteInstances that can discover
413   // this frame by name (e.g., via window.open("", "frame_name")).  See
414   // https://crbug.com/511474.
415   void CreateProxiesForNewNamedFrame();
416 
417   // Returns a base::UnguessableToken for the current FrameTreeNode's opener
418   // node in the given SiteInstance.  May return a frame token of either a
419   // RenderFrameHost (if opener's current or pending RFH has SiteInstance
420   // |instance|) or a RenderFrameProxyHost.  Returns base::nullopt if there is
421   // no opener, or if the opener node doesn't have a proxy for |instance|.
422   base::Optional<base::UnguessableToken> GetOpenerFrameToken(
423       SiteInstance* instance);
424 
425   // Called on the RFHM of the inner WebContents to create a
426   // RenderFrameProxyHost in its outer WebContents's SiteInstance,
427   // |outer_contents_site_instance|. The frame in outer WebContents that is
428   // hosting the inner WebContents is |render_frame_host|, and the frame will
429   // be swapped with the proxy. Note that this method must only be called for an
430   // OOPIF-based inner WebContents.
431   RenderFrameProxyHost* CreateOuterDelegateProxy(
432       SiteInstance* outer_contents_site_instance);
433 
434   // Called on an inner WebContents that's being detached from its outer
435   // WebContents. This will delete the proxy in the
436   // |outer_contents_site_instance|.
437   void DeleteOuterDelegateProxy(SiteInstance* outer_contents_site_instance);
438 
439   // Tells the |render_frame_host|'s renderer that its RenderFrame is being
440   // swapped for a frame in another process, and that it should create a
441   // RenderFrameProxy to replace it using the |proxy| RenderFrameProxyHost.
442   void SwapOuterDelegateFrame(RenderFrameHostImpl* render_frame_host,
443                               RenderFrameProxyHost* proxy);
444 
445   // Sets the child RenderWidgetHostView for this frame, which must be part of
446   // an inner WebContents.
447   void SetRWHViewForInnerContents(RenderWidgetHostView* child_rwhv);
448 
449   // Returns the number of RenderFrameProxyHosts for this frame.
450   size_t GetProxyCount();
451 
452   // Executes a PageBroadcast Mojo method to every RenderView in the FrameTree.
453   // This should only be called in the top-level RenderFrameHostManager.
454   // The |callback| is called synchronously and the |instance_to_skip| won't
455   // be referenced after this method returns.
456   void ExecutePageBroadcastMethod(PageBroadcastMethodCallback callback,
457                                   SiteInstance* instance_to_skip = nullptr);
458 
459   // Executes a RemoteMainFrame Mojo method to every instance in |proxy_hosts|.
460   // This should only be called in the top-level RenderFrameHostManager.
461   // The |callback| is called synchronously and the |instance_to_skip| won't
462   // be referenced after this method returns.
463   void ExecuteRemoteFramesBroadcastMethod(
464       RemoteFramesBroadcastMethodCallback callback,
465       SiteInstance* instance_to_skip = nullptr);
466 
467   // Returns a const reference to the map of proxy hosts. The keys are
468   // SiteInstance IDs, the values are RenderFrameProxyHosts.
GetAllProxyHostsForTesting()469   const RenderFrameProxyHostMap& GetAllProxyHostsForTesting() const {
470     return proxy_hosts_;
471   }
472 
473   // SiteInstanceImpl::Observer
474   void ActiveFrameCountIsZero(SiteInstanceImpl* site_instance) override;
475   void RenderProcessGone(SiteInstanceImpl* site_instance,
476                          const ChildProcessTerminationInfo& info) override;
477 
478   // Cancels and destroys the pending or speculative RenderFrameHost if they
479   // match the provided |render_frame_host|.
480   void CancelPendingIfNecessary(RenderFrameHostImpl* render_frame_host);
481 
482   // Updates the user activation state in all proxies of this frame.  For
483   // more details, see the comment on FrameTreeNode::user_activation_state_.
484   //
485   // The |notification_type| parameter is used for histograms, only for the case
486   // |update_state == kNotifyActivation|.
487   void UpdateUserActivationState(
488       blink::mojom::UserActivationUpdateType update_type,
489       blink::mojom::UserActivationNotificationType notification_type);
490 
491   void OnSetHadStickyUserActivationBeforeNavigation(bool value);
492 
493   // Sets up the necessary state for a new RenderViewHost.  If |proxy| is not
494   // null, it creates a RenderFrameProxy in the target renderer process which is
495   // used to route IPC messages.  Returns early if the RenderViewHost has
496   // already been initialized for another RenderFrameHost.
497   bool InitRenderView(RenderViewHostImpl* render_view_host,
498                       RenderFrameProxyHost* proxy);
499 
500   // Returns the SiteInstance that should be used to host the navigation handled
501   // by |navigation_request|.
502   // Note: the SiteInstance returned by this function may not have an
503   // initialized RenderProcessHost. It will only be initialized when
504   // GetProcess() is called on the SiteInstance. In particular, calling this
505   // function will never lead to a process being created for the navigation.
506   //
507   // |reason| is an optional out-parameter that will be populated with
508   // engineer-readable information describing the reason for the method
509   // behavior.  The returned |reason| should fit into
510   // base::debug::CrashKeySize::Size256.
511   scoped_refptr<SiteInstance> GetSiteInstanceForNavigationRequest(
512       NavigationRequest* navigation_request,
513       std::string* reason = nullptr);
514 
515   // Helper to initialize the main RenderFrame if it's not initialized.
516   // TODO(https://crbug.com/936696): Remove this. For now debug URLs and
517   // WebView JS execution are an exception to replacing all crashed frames for
518   // RenderDocument. This is a no-op if the frame is already initialized.
519   bool InitializeMainRenderFrameForImmediateUse();
520 
521   // Prepares the FrameTreeNode for attaching an inner WebContents. This step
522   // may involve replacing |current_frame_host()| with a new RenderFrameHost
523   // in the same SiteInstance as the parent frame. Calling this method will
524   // dispatch beforeunload event if necessary.
525   void PrepareForInnerDelegateAttach(
526       RenderFrameHost::PrepareForInnerWebContentsAttachCallback callback);
527 
528   // When true the FrameTreeNode is preparing a RenderFrameHost for attaching an
529   // inner Delegate. During this phase new navigation requests are ignored.
is_attaching_inner_delegate()530   bool is_attaching_inner_delegate() const {
531     return attach_to_inner_delegate_state_ != AttachToInnerDelegateState::NONE;
532   }
533 
534   // Called by the delegate at the end of the attaching process.
set_attach_complete()535   void set_attach_complete() {
536     attach_to_inner_delegate_state_ = AttachToInnerDelegateState::ATTACHED;
537   }
538 
539   // Computes the COOP/COEP information based on the |navigation_request|
540   // and current |frame_tree_node_| & |render_frame_host_| info.
541   CoopCoepCrossOriginIsolatedInfo GetCoopCoepCrossOriginIsolationInfo(
542       NavigationRequest* navigation_request);
543 
544  private:
545   friend class NavigatorTest;
546   friend class RenderFrameHostManagerTest;
547   friend class RenderFrameHostTester;
548   friend class TestWebContents;
549 
550   enum class SiteInstanceRelation {
551     // A SiteInstance in a different browsing instance from the current.
552     UNRELATED,
553     // A SiteInstance in the same browsing instance as the current.
554     RELATED,
555     // A pre-existing SiteInstance that might or might not be in the same
556     // browsing instance as the current. Only used when |existing_site_instance|
557     // is specified.
558     PREEXISTING,
559   };
560 
561   enum class AttachToInnerDelegateState {
562     // There is no inner delegate attached through FrameTreeNode and no
563     // attaching is in progress.
564     NONE,
565     // A frame is being prepared for attaching.
566     PREPARE_FRAME,
567     // An inner delegate attached to the delegate of this manager.
568     ATTACHED
569   };
570 
571   // Stores information regarding a SiteInstance targeted at a specific UrlInfo
572   // to allow for comparisons without having to actually create new instances.
573   // It can point to an existing one or store the details needed to create a new
574   // one.
575   struct CONTENT_EXPORT SiteInstanceDescriptor {
SiteInstanceDescriptorSiteInstanceDescriptor576     explicit SiteInstanceDescriptor(content::SiteInstance* site_instance)
577         : existing_site_instance(site_instance),
578           relation(SiteInstanceRelation::PREEXISTING),
579           cross_origin_isolated_info(
580               CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated()) {}
581 
582     SiteInstanceDescriptor(
583         UrlInfo dest_url_info,
584         SiteInstanceRelation relation_to_current,
585         const CoopCoepCrossOriginIsolatedInfo& cross_origin_isolated_info);
586 
587     // Set with an existing SiteInstance to be reused.
588     content::SiteInstance* existing_site_instance;
589 
590     // In case |existing_site_instance| is null, specify a destination URL.
591     UrlInfo dest_url_info;
592 
593     // Specifies how the new site is related to the current BrowsingInstance.
594     // This is PREEXISTING iff |existing_site_instance| is defined.
595     SiteInstanceRelation relation;
596 
597     // A cross-origin isolated page has its top level frame
598     // cross-origin-opener-policy set to "same-origin" and
599     // cross-origin-embedder-policy set to "require-corp".
600     // This allows the use of more powerful features such as SharedArrayBuffer.
601     // A cross-origin isolated SiteInstance hosts such pages and should only
602     // live in cross-origin isolated BrowsingInstances.
603     CoopCoepCrossOriginIsolatedInfo cross_origin_isolated_info;
604   };
605 
606   // Create a RenderFrameProxyHost owned by this object.
607   RenderFrameProxyHost* CreateRenderFrameProxyHost(
608       SiteInstance* site_instance,
609       scoped_refptr<RenderViewHostImpl> rvh);
610 
611   // Delete a RenderFrameProxyHost owned by this object.
612   void DeleteRenderFrameProxyHost(SiteInstance* site_instance);
613 
614   // Returns true if for the navigation from |current_effective_url| to
615   // |destination_url_info|, a new SiteInstance and BrowsingInstance should be
616   // created (even if we are in a process model that doesn't usually swap).
617   // This forces a process swap and severs script connections with existing
618   // tabs.  Cases where this can happen include transitions between WebUI and
619   // regular web pages.
620   //
621   // |source_instance| is the SiteInstance of the frame that initiated the
622   // navigation. |current_instance| is the SiteInstance of the frame that is
623   // currently navigating. |destination_instance| is a predetermined
624   // SiteInstance that will be used for |destination_url| if not
625   // null - we will swap BrowsingInstances if it's in a different
626   // BrowsingInstance than the current one.
627   //
628   // If there is no current NavigationEntry, then |current_is_view_source_mode|
629   // should be the same as |dest_is_view_source_mode|.
630   //
631   // UrlInfo uses the effective URL here, since that's what is used in the
632   // SiteInstance's site and when we later call IsSameSite.  If there is no
633   // current NavigationEntry, check the current SiteInstance's site, which might
634   // already be committed to a Web UI URL (such as the NTP). Note that we don't
635   // pass the effective URL for destination URL here and instead calculate the
636   // destination's effective URL within the function because some methods called
637   // in the function like IsNavigationSameSite expects a non-effective URL.
638   ShouldSwapBrowsingInstance ShouldSwapBrowsingInstancesForNavigation(
639       const GURL& current_effective_url,
640       bool current_is_view_source_mode,
641       SiteInstanceImpl* source_instance,
642       SiteInstanceImpl* current_instance,
643       SiteInstance* destination_instance,
644       const UrlInfo& destination_url_info,
645       const CoopCoepCrossOriginIsolatedInfo& cross_origin_isolated_info,
646       bool destination_is_view_source_mode,
647       ui::PageTransition transition,
648       bool is_failure,
649       bool is_reload,
650       bool is_same_document,
651       bool cross_origin_opener_policy_mismatch,
652       bool was_server_redirect,
653       bool should_replace_current_entry,
654       bool is_speculative);
655 
656   ShouldSwapBrowsingInstance ShouldProactivelySwapBrowsingInstance(
657       const UrlInfo& destination_url_info,
658       const CoopCoepCrossOriginIsolatedInfo& cross_origin_isolated_info,
659       bool is_reload,
660       bool should_replace_current_entry);
661 
662   // Returns the SiteInstance to use for the navigation.
663   //
664   // This is a helper function for GetSiteInstanceForNavigationRequest.
665   scoped_refptr<SiteInstance> GetSiteInstanceForNavigation(
666       const UrlInfo& dest_url_info,
667       const CoopCoepCrossOriginIsolatedInfo& cross_origin_isolated_info,
668       SiteInstanceImpl* source_instance,
669       SiteInstanceImpl* dest_instance,
670       SiteInstanceImpl* candidate_instance,
671       ui::PageTransition transition,
672       bool is_failure,
673       bool is_reload,
674       bool is_same_document,
675       bool dest_is_restore,
676       bool dest_is_view_source_mode,
677       bool was_server_redirect,
678       bool cross_origin_opener_policy_mismatch,
679       bool should_replace_current_entry,
680       bool is_speculative,
681       bool* did_same_site_proactive_browsing_instance_swap,
682       std::string* reason);
683 
684   // Returns a descriptor of the appropriate SiteInstance object for the given
685   // |dest_url_info|, possibly reusing the current, source or destination
686   // SiteInstance. The actual SiteInstance can then be obtained calling
687   // ConvertToSiteInstance with the descriptor.
688   //
689   // |cross_origin_isolated_info| reflects the cross-origin isolation
690   // information we got from the response for |dest_url|, more specifically the
691   // COOP and COEP headers.
692   //
693   // |source_instance| is the SiteInstance of the frame that initiated the
694   // navigation. |current_instance| is the SiteInstance of the frame that is
695   // currently navigating. |dest_instance| is a predetermined SiteInstance that
696   // will be used if not null.
697   // For example, if you have a parent frame A, which has a child frame B, and
698   // A is trying to change the src attribute of B, this will cause a navigation
699   // where the source SiteInstance is A and B is the current SiteInstance.
700   //
701   // |is_speculative| indicates that the SiteInstance is being computed for a
702   // speculative RenderFrameHost, which may change once response is received and
703   // a final RenderFrameHost/SiteInstance is computed. It is true at request
704   // start time, but false for redirects and at OnResponseStarted time.
705   //
706   // This is a helper function for GetSiteInstanceForNavigation.
707   SiteInstanceDescriptor DetermineSiteInstanceForURL(
708       const UrlInfo& dest_url_info,
709       const CoopCoepCrossOriginIsolatedInfo& cross_origin_isolated_info,
710       SiteInstance* source_instance,
711       SiteInstance* current_instance,
712       SiteInstance* dest_instance,
713       ui::PageTransition transition,
714       bool is_failure,
715       bool dest_is_restore,
716       bool dest_is_view_source_mode,
717       bool force_browsing_instance_swap,
718       bool was_server_redirect,
719       bool is_speculative,
720       std::string* reason);
721 
722   // Returns true if a navigation to |dest_url| that uses the specified
723   // PageTransition in the current frame is allowed to swap BrowsingInstances.
724   // DetermineSiteInstanceForURL() uses this helper to determine when it is
725   // allowed to swap BrowsingInstances to avoid unneeded process sharing.  See
726   // https://crbug.com/803367.
727   //
728   // Note that this is different from
729   // ShouldSwapBrowsingInstancesForNavigation(), which identifies cases in
730   // which a BrowsingInstance swap is *required* (e.g., for security). This
731   // function only identifies cases where a BrowsingInstance swap *may* be
732   // performed to optimize process placement.  In particular, this is true for
733   // certain browser-initiated transitions for main frame navigations.
734   //
735   // Returning true here doesn't imply that DetermineSiteInstanceForURL() will
736   // swap BrowsingInstances.  For example, this swap will not be done for
737   // same-site navigations, for history navigations, or when starting from an
738   // uninitialized SiteInstance.
739   bool IsBrowsingInstanceSwapAllowedForPageTransition(
740       ui::PageTransition transition,
741       const GURL& dest_url);
742 
743   // Returns true if we can use |source_instance| for |dest_url|.
744   bool CanUseSourceSiteInstance(
745       const GURL& dest_url,
746       SiteInstance* source_instance,
747       bool was_server_redirect,
748       bool is_failure,
749       const CoopCoepCrossOriginIsolatedInfo& cross_origin_isolated_info,
750       bool is_speculative);
751 
752   // Converts a SiteInstanceDescriptor to the actual SiteInstance it describes.
753   // If a |candidate_instance| is provided (is not nullptr) and it matches the
754   // description, it is returned as is.
755   // |is_speculative| indicates whether we are computing a SiteInstance for a
756   // speculative RenderFrameHost or if have already received a response.
757   scoped_refptr<SiteInstance> ConvertToSiteInstance(
758       const SiteInstanceDescriptor& descriptor,
759       SiteInstanceImpl* candidate_instance,
760       bool is_speculative);
761 
762   // Returns true if |candidate| is currently on the same web site as
763   // |dest_url_info|. This method is a special case for handling hosted apps in
764   // this object. Most code should call IsNavigationSameSite() on
765   // |candidate| instead of this method.
766   bool IsCandidateSameSite(
767       RenderFrameHostImpl* candidate,
768       const UrlInfo& dest_url_info,
769       const CoopCoepCrossOriginIsolatedInfo& cross_origin_isolated_info);
770 
771   // Ensure that we have created all needed proxies for a new RFH with
772   // SiteInstance |new_instance|: (1) create swapped-out RVHs and proxies for
773   // the new RFH's opener chain if we are staying in the same BrowsingInstance;
774   // (2) Create proxies for the new RFH's SiteInstance in its own frame tree.
775   // |recovering_without_early_commit| is true if we are reviving a crashed
776   // render frame by creating a proxy and committing later rather than doing an
777   // immediate commit.
778   void CreateProxiesForNewRenderFrameHost(SiteInstance* old_instance,
779                                           SiteInstance* new_instance,
780                                           bool recovering_without_early_commit);
781 
782   // Traverse the opener chain and populate |opener_frame_trees| with
783   // all FrameTrees accessible by following frame openers of nodes in the
784   // given node's FrameTree. |opener_frame_trees| is ordered so that openers
785   // of smaller-indexed entries point to larger-indexed entries (i.e., this
786   // node's FrameTree is at index 0, its opener's FrameTree is at index 1,
787   // etc). If the traversal encounters a node with an opener pointing to a
788   // FrameTree that has already been traversed (such as when there's a cycle),
789   // the node is added to |nodes_with_back_links|.
790   void CollectOpenerFrameTrees(
791       std::vector<FrameTree*>* opener_frame_trees,
792       std::unordered_set<FrameTreeNode*>* nodes_with_back_links);
793 
794   // Create RenderFrameProxies and inactive RenderViewHosts in the given
795   // SiteInstance for the current node's FrameTree.  Used as a helper function
796   // in CreateOpenerProxies for creating proxies in each FrameTree on the
797   // opener chain.  Don't create proxies for the subtree rooted at
798   // |skip_this_node|.
799   void CreateOpenerProxiesForFrameTree(SiteInstance* instance,
800                                        FrameTreeNode* skip_this_node);
801 
802   // The different types of RenderFrameHost creation that can occur.
803   // See CreateRenderFrameHost for how these influence creation.
804   enum class CreateFrameCase {
805     // Adding a child to an existing frame in the tree.
806     kInitChild,
807     // Creating the first frame in a frame tree.
808     kInitRoot,
809     // Preparing to navigate to another frame.
810     kCreateSpeculative,
811   };
812 
813   // Creates a RenderFrameHost. This uses an existing a RenderViewHost in the
814   // same SiteInstance if it exists or creates a new one (a new one will only be
815   // created if this is a root or child local root).
816   // TODO(https://crbug.com/1060082): Eliminate or rename
817   // renderer_initiated_creation.
818   std::unique_ptr<RenderFrameHostImpl> CreateRenderFrameHost(
819       CreateFrameCase create_frame_case,
820       SiteInstance* site_instance,
821       int32_t frame_routing_id,
822       const base::UnguessableToken& frame_token,
823       bool renderer_initiated_creation);
824 
825   // Create and initialize a speculative RenderFrameHost for an ongoing
826   // navigation. It might be destroyed and re-created later if the navigation is
827   // redirected to a different SiteInstance. |recovering_without_early_commit|
828   // is true if we are reviving a crashed render frame by creating a proxy and
829   // committing later rather than doing an immediate commit.
830   bool CreateSpeculativeRenderFrameHost(SiteInstance* old_instance,
831                                         SiteInstance* new_instance,
832                                         bool recovering_without_early_commit);
833 
834   // Initialization for RenderFrameHost uses the same sequence as InitRenderView
835   // above.
836   bool InitRenderFrame(RenderFrameHostImpl* render_frame_host);
837 
838   // Find the routing ID of the frame or proxy that this frame will replace or
839   // |MSG_ROUTING_NONE| if there is none. When initializing a new RenderFrame
840   // for |render_frame_host|, it may be replacing a RenderFrameProxy or another
841   // RenderFrame in the renderer or recovering from a crash. |existing_proxy| is
842   // the proxy for |this| in the destination renderer, nullptr if there is no
843   // proxy. |render_frame_host| is used only for sanity checking.
844   int GetReplacementRoutingId(RenderFrameProxyHost* existing_proxy,
845                               RenderFrameHostImpl* render_frame_host) const;
846 
847   // Helper to reinitialize the RenderFrame, RenderView, and the opener chain
848   // for the provided |render_frame_host|.  Used when the |render_frame_host|
849   // needs to be reused for a new navigation, but it is not live.
850   bool ReinitializeRenderFrame(RenderFrameHostImpl* render_frame_host);
851 
852   // Sets the |pending_rfh| to be the active one. Called when the pending
853   // RenderFrameHost commits.
854   //
855   // This function is also called when restoring an entry from BackForwardCache.
856   // In that case, |pending_rfh| is the RenderFrameHost to be restored, and
857   // |pending_bfcache_entry| provides additional state to be restored, such as
858   // proxies.
859   // |clear_proxies_on_commit| Indicates if the proxies and opener must be
860   // removed during the commit. This can happen following some BrowsingInstance
861   // swaps, such as those for COOP.
862   void CommitPending(
863       std::unique_ptr<RenderFrameHostImpl> pending_rfh,
864       std::unique_ptr<BackForwardCacheImpl::Entry> pending_bfcache_entry,
865       bool clear_proxies_on_commit);
866 
867   // Helper to call CommitPending() in all necessary cases.
868   void CommitPendingIfNecessary(RenderFrameHostImpl* render_frame_host,
869                                 bool was_caused_by_user_gesture,
870                                 bool is_same_document_navigation,
871                                 bool clear_proxies_on_commit);
872 
873   // Commits given frame policy when the renderer's frame navigates.
874   void CommitFramePolicy(const blink::FramePolicy& frame_policy);
875 
876   // Runs the unload handler in the old RenderFrameHost, after the new
877   // RenderFrameHost has committed.  |old_render_frame_host| will either be
878   // deleted or put on the pending delete list during this call.
879   void UnloadOldFrame(
880       std::unique_ptr<RenderFrameHostImpl> old_render_frame_host);
881 
882   // Discards a RenderFrameHost that was never made active (for active ones
883   // UnloadOldFrame is used instead).
884   void DiscardUnusedFrame(
885       std::unique_ptr<RenderFrameHostImpl> render_frame_host);
886 
887   // Helper method to set the active RenderFrameHost. Returns the old
888   // RenderFrameHost and updates counts.
889   std::unique_ptr<RenderFrameHostImpl> SetRenderFrameHost(
890       std::unique_ptr<RenderFrameHostImpl> render_frame_host);
891 
892   // After a renderer process crash we'd have marked the host as invisible, so
893   // we need to set the visibility of the new View to the correct value here
894   // after reload.
895   void EnsureRenderFrameHostVisibilityConsistent();
896 
897   // Similarly to visibility, we need to ensure RenderWidgetHost and
898   // RenderWidget know about page focus.
899   void EnsureRenderFrameHostPageFocusConsistent();
900 
901   // When current RenderFrameHost is not in its parent SiteInstance, this method
902   // will destroy the frame and replace it with a new RenderFrameHost in the
903   // parent frame's SiteInstance. Either way, this will eventually invoke
904   // |attach_inner_delegate_callback_| with a pointer to |render_frame_host_|
905   // which is then safe for use with WebContents::AttachToOuterWebContentsFrame.
906   void CreateNewFrameForInnerDelegateAttachIfNecessary();
907 
908   // Called when the result of preparing the FrameTreeNode for attaching an
909   // inner delegate is known. When successful, |render_frame_host_| can be used
910   // for attaching the inner Delegate.
911   void NotifyPrepareForInnerDelegateAttachComplete(bool success);
912 
913   // For use in creating RenderFrameHosts.
914   FrameTreeNode* frame_tree_node_;
915 
916   // Our delegate, not owned by us. Guaranteed non-null.
917   Delegate* delegate_;
918 
919   // Our RenderFrameHost which is responsible for all communication with a child
920   // RenderFrame instance.
921   // For now, RenderFrameHost keeps a RenderViewHost in its SiteInstance alive.
922   // Eventually, RenderViewHost will be replaced with a page context.
923   std::unique_ptr<RenderFrameHostImpl> render_frame_host_;
924 
925   // Proxy hosts, indexed by site instance ID.
926   RenderFrameProxyHostMap proxy_hosts_;
927 
928   // A set of RenderFrameHosts waiting to shut down after swapping out.
929   using RFHPendingDeleteSet =
930       std::set<std::unique_ptr<RenderFrameHostImpl>, base::UniquePtrComparator>;
931   RFHPendingDeleteSet pending_delete_hosts_;
932 
933   // Stores a speculative RenderFrameHost which is created early in a navigation
934   // so a renderer process can be started in parallel, if needed.
935   // This is purely a performance optimization and is not required for correct
936   // behavior. The speculative RenderFrameHost might be discarded later on if
937   // the final URL's SiteInstance isn't compatible with the one used to create
938   // it.
939   std::unique_ptr<RenderFrameHostImpl> speculative_render_frame_host_;
940 
941   // After being set in RestoreFromBackForwardCache(), the bfcache entry is
942   // immediately consumed in CommitPending().
943   std::unique_ptr<BackForwardCacheImpl::Entry> bfcache_entry_to_restore_;
944 
945   // This callback is used when attaching an inner Delegate to |delegate_|
946   // through |frame_tree_node_|.
947   RenderFrameHost::PrepareForInnerWebContentsAttachCallback
948       attach_inner_delegate_callback_;
949   AttachToInnerDelegateState attach_to_inner_delegate_state_ =
950       AttachToInnerDelegateState::NONE;
951 
952   base::WeakPtrFactory<RenderFrameHostManager> weak_factory_{this};
953 
954   DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManager);
955 };
956 
957 }  // namespace content
958 
959 #endif  // CONTENT_BROWSER_RENDERER_HOST_RENDER_FRAME_HOST_MANAGER_H_
960