| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_ |
| #define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_ |
| |
| #include <stdint.h> |
| |
| #include <list> |
| #include <map> |
| #include <memory> |
| #include <unordered_map> |
| #include <unordered_set> |
| |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/browser/site_instance_impl.h" |
| #include "content/common/content_export.h" |
| #include "content/public/browser/global_request_id.h" |
| #include "content/public/common/referrer.h" |
| #include "third_party/blink/public/common/frame/user_activation_update_type.h" |
| #include "ui/base/page_transition_types.h" |
| #include "url/origin.h" |
| |
| namespace content { |
| class BrowserContext; |
| class FrameTreeNode; |
| class InterstitialPageImpl; |
| class NavigationControllerImpl; |
| class NavigationEntry; |
| class NavigationRequest; |
| class NavigatorTest; |
| class RenderFrameHostManagerTest; |
| class RenderFrameProxyHost; |
| class RenderViewHost; |
| class RenderViewHostImpl; |
| class RenderWidgetHostView; |
| class TestWebContents; |
| class WebUIImpl; |
| struct ContentSecurityPolicyHeader; |
| struct FrameOwnerProperties; |
| struct FrameReplicationState; |
| |
| // Manages RenderFrameHosts for a FrameTreeNode. It maintains a |
| // current_frame_host() which is the content currently visible to the user. When |
| // a frame is told to navigate to a different web site (as determined by |
| // SiteInstance), it will replace its current RenderFrameHost with a new |
| // RenderFrameHost dedicated to the new SiteInstance, possibly in a new process. |
| // |
| // Cross-process navigation works like this: |
| // |
| // - RFHM::Navigate determines whether the destination is cross-site, and if so, |
| // it creates a pending_render_frame_host_. |
| // |
| // - The pending RFH is created in the "navigations suspended" state, meaning no |
| // navigation messages are sent to its renderer until the beforeunload handler |
| // has a chance to run in the current RFH. |
| // |
| // - The current RFH runs its beforeunload handler. If it returns false, we |
| // cancel all the pending logic. Otherwise we allow the pending RFH to send |
| // the navigation request to its renderer. |
| // |
| // - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the |
| // main resource load from the pending RFH. It creates a |
| // CrossSiteResourceHandler to check whether a process transfer is needed when |
| // the request is ready to commit. |
| // |
| // - When RDH receives a response, the MimeTypeResourceHandler determines |
| // whether it is a navigation type that doesn't commit (e.g. download, 204 or |
| // error page). If so, it sends a message to the new renderer causing it to |
| // cancel the request, and the request (e.g. the download) proceeds. In this |
| // case, the pending RFH will never become the current RFH, but it remains |
| // until the next DidNavigate event for this WebContentsImpl. |
| // |
| // - After RDH receives a response and determines that it is safe and not a |
| // download, the CrossSiteResourceHandler checks whether a transfer for a |
| // redirect is needed. If so, it pauses the network response and starts an |
| // identical navigation in a new pending RFH. When the identical request is |
| // later received by RDH, the response is transferred and unpaused. |
| // |
| // - Otherwise, the network response commits in the pending RFH's renderer, |
| // which sends a DidCommitProvisionalLoad message back to the browser process. |
| // |
| // - RFHM::CommitPending makes visible the new RFH, and initiates the unload |
| // handler in the old RFH. The unload handler will complete in the background. |
| // |
| // - RenderFrameHostManager may keep the previous RFH alive as a |
| // RenderFrameProxyHost, to be used (for example) if the user goes back. The |
| // process only stays live if another tab is using it, but if so, the existing |
| // frame relationships will be maintained. |
| class CONTENT_EXPORT RenderFrameHostManager |
| : public SiteInstanceImpl::Observer { |
| public: |
| // Functions implemented by our owner that we need. |
| // |
| // TODO(brettw) Clean this up! These are all the functions in WebContentsImpl |
| // that are required to run this class. The design should probably be better |
| // such that these are more clear. |
| // |
| // There is additional complexity that some of the functions we need in |
| // WebContentsImpl are inherited and non-virtual. These are named with |
| // "RenderManager" so that the duplicate implementation of them will be clear. |
| class CONTENT_EXPORT Delegate { |
| public: |
| // Initializes the given renderer if necessary and creates the view ID |
| // corresponding to this view host. If this method is not called and the |
| // process is not shared, then the WebContentsImpl will act as though the |
| // renderer is not running (i.e., it will render "sad tab"). This method is |
| // automatically called from LoadURL. |
| virtual bool CreateRenderViewForRenderManager( |
| RenderViewHost* render_view_host, |
| int opener_frame_routing_id, |
| int proxy_routing_id, |
| const base::UnguessableToken& devtools_frame_token, |
| const FrameReplicationState& replicated_frame_state) = 0; |
| virtual void CreateRenderWidgetHostViewForRenderManager( |
| RenderViewHost* render_view_host) = 0; |
| virtual bool CreateRenderFrameForRenderManager( |
| RenderFrameHost* render_frame_host, |
| int proxy_routing_id, |
| int opener_routing_id, |
| int parent_routing_id, |
| int previous_sibling_routing_id) = 0; |
| virtual void BeforeUnloadFiredFromRenderManager( |
| bool proceed, const base::TimeTicks& proceed_time, |
| bool* proceed_to_fire_unload) = 0; |
| virtual void RenderProcessGoneFromRenderManager( |
| RenderViewHost* render_view_host) = 0; |
| virtual void UpdateRenderViewSizeForRenderManager(bool is_main_frame) = 0; |
| virtual void CancelModalDialogsForRenderManager() = 0; |
| virtual void NotifySwappedFromRenderManager(RenderFrameHost* old_host, |
| RenderFrameHost* new_host, |
| bool is_main_frame) = 0; |
| // TODO(nasko): This should be removed once extensions no longer use |
| // NotificationService. See https://crbug.com/462682. |
| virtual void NotifyMainFrameSwappedFromRenderManager( |
| RenderFrameHost* old_host, |
| RenderFrameHost* new_host) = 0; |
| virtual NavigationControllerImpl& |
| GetControllerForRenderManager() = 0; |
| |
| // Returns the navigation entry of the current navigation, or NULL if there |
| // is none. |
| virtual NavigationEntry* |
| GetLastCommittedNavigationEntryForRenderManager() = 0; |
| |
| // Returns the interstitial page showing in the delegate, or null if there |
| // is none. |
| virtual InterstitialPageImpl* GetInterstitialForRenderManager() = 0; |
| |
| // Returns true if the location bar should be focused by default rather than |
| // the page contents. The view calls this function when the tab is focused |
| // to see what it should do. |
| virtual bool FocusLocationBarByDefault() = 0; |
| |
| // Focuses the location bar. |
| virtual void SetFocusToLocationBar() = 0; |
| |
| // Returns true if views created for this delegate should be created in a |
| // hidden state. |
| virtual bool IsHidden() = 0; |
| |
| // If the delegate is an inner WebContents, this method returns the |
| // FrameTreeNode ID of the frame in the outer WebContents which hosts |
| // the inner WebContents. Returns FrameTreeNode::kFrameTreeNodeInvalidId |
| // if the delegate does not have an outer WebContents. |
| virtual int GetOuterDelegateFrameTreeNodeId() = 0; |
| |
| protected: |
| virtual ~Delegate() {} |
| }; |
| |
| // The delegate pointer must be non-NULL and is not owned by this class. It |
| // must outlive this class. |
| // |
| // You must call Init() before using this class. |
| RenderFrameHostManager(FrameTreeNode* frame_tree_node, Delegate* delegate); |
| ~RenderFrameHostManager(); |
| |
| // For arguments, see WebContentsImpl constructor. |
| void Init(SiteInstance* site_instance, |
| int32_t view_routing_id, |
| int32_t frame_routing_id, |
| int32_t widget_routing_id, |
| bool renderer_initiated_creation); |
| |
| // Returns the currently active RenderFrameHost. |
| // |
| // This will be non-NULL between Init() and Shutdown(). You may want to NULL |
| // check it in many cases, however. Windows can send us messages during the |
| // destruction process after it has been shut down. |
| RenderFrameHostImpl* current_frame_host() const { |
| return render_frame_host_.get(); |
| } |
| |
| // TODO(creis): Remove this when we no longer use RVH for navigation. |
| RenderViewHostImpl* current_host() const; |
| |
| // Returns the view associated with the current RenderViewHost, or NULL if |
| // there is no current one. |
| RenderWidgetHostView* GetRenderWidgetHostView() const; |
| |
| // Returns whether this manager is a main frame and belongs to a FrameTreeNode |
| // that belongs to an inner WebContents. |
| bool IsMainFrameForInnerDelegate(); |
| |
| // If this is a RenderFrameHostManager for a main frame, this method returns |
| // the FrameTreeNode for the frame in the outer WebContents (if any) that |
| // contains the inner WebContents. |
| FrameTreeNode* GetOuterDelegateNode(); |
| |
| // Return a proxy for this frame in the parent frame's SiteInstance. Returns |
| // nullptr if this is a main frame or if such a proxy does not exist (for |
| // example, if this frame is same-site with its parent OR if this frame will |
| // be deleted soon and we are just waiting for the frame's unload handler). |
| RenderFrameProxyHost* GetProxyToParent(); |
| |
| // If this is a RenderFrameHostManager for a main frame, returns the proxy to |
| // inner WebContents in the outer WebContents's SiteInstance. Returns nullptr |
| // if this WebContents isn't part of inner/outer relationship. |
| RenderFrameProxyHost* GetProxyToOuterDelegate(); |
| |
| // If this is a RenderFrameHostManager for a main frame, removes the |
| // FrameTreeNode in the outer WebContents that represents this FrameTreeNode. |
| // TODO(lazyboy): This does not belong to RenderFrameHostManager, move it to |
| // somehwere else. |
| void RemoveOuterDelegateFrame(); |
| |
| // Returns the speculative RenderFrameHost, or null if there is no speculative |
| // one. |
| RenderFrameHostImpl* speculative_frame_host() const { |
| return speculative_render_frame_host_.get(); |
| } |
| |
| // Returns the WebUI associated with the ongoing navigation, it being either |
| // the active or the pending one from the navigating RenderFrameHost. Returns |
| // null if there's no ongoing navigation or if no WebUI applies. |
| WebUIImpl* GetNavigatingWebUI() const; |
| |
| // Instructs the various live views to stop. Called when the user directed the |
| // page to stop loading. |
| void Stop(); |
| |
| // Notifies the regular and pending RenderViewHosts that a load is or is not |
| // happening. Even though the message is only for one of them, we don't know |
| // which one so we tell both. |
| void SetIsLoading(bool is_loading); |
| |
| // Confirms whether we should close the page. |proceed| indicates whether the |
| // user chose to proceed. |proceed_time| is the time when the request was |
| // allowed to proceed. This is called in one of the two *distinct* scenarios |
| // below: |
| // 1- The tab/window is closed after allowing the appropriate renderer to |
| // show the beforeunload prompt. |
| // 2- The FrameTreeNode is being prepared for attaching an inner Delegate, |
| // in which case beforeunload is triggered in the current frame. This |
| // only happens for child frames. |
| void OnBeforeUnloadACK(bool proceed, const base::TimeTicks& proceed_time); |
| |
| // Determines whether a navigation to |dest_url| may be completed using an |
| // existing RenderFrameHost, or whether transferring to a new RenderFrameHost |
| // backed by a different render process is required. This is a security policy |
| // check determined by the current site isolation mode, and must be done |
| // before the resource at |dest_url| is delivered to |existing_rfh|. |
| // |
| // |existing_rfh| must belong to this RFHM, but it can be a pending or current |
| // host. |
| // |
| // When this function returns true for a subframe, an out-of-process iframe |
| // must be created. |
| bool IsRendererTransferNeededForNavigation(RenderFrameHostImpl* existing_rfh, |
| const GURL& dest_url); |
| |
| // Called when a renderer's frame navigates. |
| void DidNavigateFrame(RenderFrameHostImpl* render_frame_host, |
| bool was_caused_by_user_gesture, |
| bool is_same_document_navigation); |
| |
| // Called when this frame's opener is changed to the frame specified by |
| // |opener_routing_id| in |source_site_instance|'s process. This change |
| // could come from either the current RenderFrameHost or one of the |
| // proxies (e.g., window.open that targets a RemoteFrame by name). The |
| // updated opener will be forwarded to any other RenderFrameProxies and |
| // RenderFrames for this FrameTreeNode. |
| void DidChangeOpener(int opener_routing_id, |
| SiteInstance* source_site_instance); |
| |
| // Creates and initializes a RenderFrameHost. |
| std::unique_ptr<RenderFrameHostImpl> CreateRenderFrame( |
| SiteInstance* instance); |
| |
| // Helper method to create and initialize a RenderFrameProxyHost. |
| void CreateRenderFrameProxy(SiteInstance* instance); |
| |
| // Creates proxies for a new child frame at FrameTreeNode |child| in all |
| // SiteInstances for which the current frame has proxies. This method is |
| // called on the parent of a new child frame before the child leaves the |
| // SiteInstance. |
| void CreateProxiesForChildFrame(FrameTreeNode* child); |
| |
| // Returns the swapped out RenderViewHost for the given SiteInstance, if any. |
| // This method is *deprecated* and GetRenderFrameProxyHost should be used. |
| RenderViewHostImpl* GetSwappedOutRenderViewHost(SiteInstance* instance) const; |
| |
| // Returns the RenderFrameProxyHost for the given SiteInstance, if any. |
| RenderFrameProxyHost* GetRenderFrameProxyHost( |
| SiteInstance* instance) const; |
| |
| // If |render_frame_host| is on the pending deletion list, this deletes it. |
| // Returns whether it was deleted. |
| bool DeleteFromPendingList(RenderFrameHostImpl* render_frame_host); |
| |
| // BackForwardCache: |
| // During a history navigation, unfreezes and swaps in a document from the |
| // BackForwardCache, making it active. |
| void RestoreFromBackForwardCache(std::unique_ptr<RenderFrameHostImpl>); |
| void EvictFromBackForwardCache(RenderFrameHostImpl*); |
| |
| // BackForwardCache: |
| // Unfreezes the current frame host. This is called after committing a |
| // navigation to a frame that was restored from the back-forward cache. |
| void UnfreezeCurrentFrameHost(); |
| |
| // Deletes any proxy hosts associated with this node. Used during destruction |
| // of WebContentsImpl. |
| void ResetProxyHosts(); |
| |
| void ClearRFHsPendingShutdown(); |
| void ClearWebUIInstances(); |
| |
| // Returns the routing id for a RenderFrameHost or RenderFrameProxyHost |
| // that has the given SiteInstance and is associated with this |
| // RenderFrameHostManager. Returns MSG_ROUTING_NONE if none is found. |
| int GetRoutingIdForSiteInstance(SiteInstance* site_instance); |
| |
| // Notifies the RenderFrameHostManager that a new NavigationRequest has been |
| // created and set in the FrameTreeNode so that it can speculatively create a |
| // new RenderFrameHost (and potentially a new process) if needed. |
| void DidCreateNavigationRequest(NavigationRequest* request); |
| |
| // Called (possibly several times) during a navigation to select or create an |
| // appropriate RenderFrameHost for the provided URL. The returned pointer will |
| // be for the current or the speculative RenderFrameHost and the instance is |
| // owned by this manager. |
| RenderFrameHostImpl* GetFrameHostForNavigation( |
| const NavigationRequest& request); |
| |
| // Clean up any state for any ongoing navigation. |
| void CleanUpNavigation(); |
| |
| // Clears the speculative members, returning the RenderFrameHost to the caller |
| // for disposal. |
| std::unique_ptr<RenderFrameHostImpl> UnsetSpeculativeRenderFrameHost(); |
| |
| // Notification methods to tell this RenderFrameHostManager that the frame it |
| // is responsible for has started or stopped loading a document. |
| void OnDidStartLoading(); |
| void OnDidStopLoading(); |
| |
| // OnDidUpdateName gets called when a frame changes its name - it gets the new |
| // |name| and the recalculated |unique_name| and replicates them into all |
| // frame proxies. |
| void OnDidUpdateName(const std::string& name, const std::string& unique_name); |
| |
| // Sends the newly added Content Security Policy headers to all the proxies. |
| void OnDidAddContentSecurityPolicies( |
| const std::vector<ContentSecurityPolicyHeader>& headers); |
| |
| // Resets Content Security Policy in all the proxies. |
| void OnDidResetContentSecurityPolicy(); |
| |
| // Sends updated enforcement of insecure request policy to all frame proxies |
| // when the frame changes its setting. |
| void OnEnforceInsecureRequestPolicy(blink::WebInsecureRequestPolicy policy); |
| |
| // Sends updated enforcement of upgrade insecure navigations set to all frame |
| // proxies when the frame changes its setting. |
| void OnEnforceInsecureNavigationsSet( |
| const std::vector<uint32_t>& insecure_navigations_set); |
| |
| // Called when the client changes whether the frame's owner element in the |
| // embedder document should be collapsed, that is, remove from the layout as |
| // if it did not exist. Never called for main frames. Only has an effect for |
| // <iframe> owner elements. |
| void OnDidChangeCollapsedState(bool collapsed); |
| |
| // Called on a frame to notify it that its out-of-process parent frame |
| // changed a property (such as allowFullscreen) on its <iframe> element. |
| // Sends updated FrameOwnerProperties to the RenderFrame and to all proxies, |
| // skipping the parent process. |
| void OnDidUpdateFrameOwnerProperties(const FrameOwnerProperties& properties); |
| |
| // Notify the proxies that the active sandbox flags or feature policy header |
| // on the frame have been changed during page load. Sandbox flags can change |
| // when set by a CSP header. |
| void OnDidSetFramePolicyHeaders(); |
| |
| // Send updated origin to all frame proxies when the frame navigates to a new |
| // origin. |
| void OnDidUpdateOrigin(const url::Origin& origin, |
| bool is_potentially_trustworthy_unique_origin); |
| |
| void EnsureRenderViewInitialized(RenderViewHostImpl* render_view_host, |
| SiteInstance* instance); |
| |
| // Creates swapped out RenderViews and RenderFrameProxies for this frame's |
| // FrameTree and for its opener chain in the given SiteInstance. This allows |
| // other tabs to send cross-process JavaScript calls to their opener(s) and |
| // to any other frames in the opener's FrameTree (e.g., supporting calls like |
| // window.opener.opener.frames[x][y]). Does not create proxies for the |
| // subtree rooted at |skip_this_node| (e.g., if a node is being navigated, it |
| // can be passed here to prevent proxies from being created for it, in |
| // case it is in the same FrameTree as another node on its opener chain). |
| void CreateOpenerProxies(SiteInstance* instance, |
| FrameTreeNode* skip_this_node); |
| |
| // Ensure that this frame has proxies in all SiteInstances that can discover |
| // this frame by name (e.g., via window.open("", "frame_name")). See |
| // https://crbug.com/511474. |
| void CreateProxiesForNewNamedFrame(); |
| |
| // Returns a routing ID for the current FrameTreeNode's opener node in the |
| // given SiteInstance. May return a routing ID of either a RenderFrameHost |
| // (if opener's current or pending RFH has SiteInstance |instance|) or a |
| // RenderFrameProxyHost. Returns MSG_ROUTING_NONE if there is no opener, or |
| // if the opener node doesn't have a proxy for |instance|. |
| int GetOpenerRoutingID(SiteInstance* instance); |
| |
| // Called on the RFHM of the inner WebContents to create a |
| // RenderFrameProxyHost in its outer WebContents's SiteInstance, |
| // |outer_contents_site_instance|. The frame in outer WebContents that is |
| // hosting the inner WebContents is |render_frame_host|, and the frame will |
| // be swapped out with the proxy. Note that this method must only be called |
| // for an OOPIF-based inner WebContents. |
| RenderFrameProxyHost* CreateOuterDelegateProxy( |
| SiteInstance* outer_contents_site_instance); |
| |
| // Called on an inner WebContents that's being detached from its outer |
| // WebContents. This will delete the proxy in the |
| // |outer_contents_site_instance|. |
| void DeleteOuterDelegateProxy(SiteInstance* outer_contents_site_instance); |
| |
| // Tells the |render_frame_host|'s renderer that its RenderFrame is being |
| // swapped for a frame in another process, and that it should create a |
| // RenderFrameProxy to replace it using the |proxy| RenderFrameProxyHost. |
| void SwapOuterDelegateFrame(RenderFrameHostImpl* render_frame_host, |
| RenderFrameProxyHost* proxy); |
| |
| // Sets the child RenderWidgetHostView for this frame, which must be part of |
| // an inner WebContents. |
| void SetRWHViewForInnerContents(RenderWidgetHostView* child_rwhv); |
| |
| // Returns the number of RenderFrameProxyHosts for this frame. |
| size_t GetProxyCount(); |
| |
| // Sends an IPC message to every process in the FrameTree. This should only be |
| // called in the top-level RenderFrameHostManager. |instance_to_skip|, if |
| // not null, specifies the SiteInstance to which the message should not be |
| // sent. |
| void SendPageMessage(IPC::Message* msg, SiteInstance* instance_to_skip); |
| |
| // Returns a const reference to the map of proxy hosts. The keys are |
| // SiteInstance IDs, the values are RenderFrameProxyHosts. |
| const std::unordered_map<int32_t, std::unique_ptr<RenderFrameProxyHost>>& |
| GetAllProxyHostsForTesting() const { |
| return proxy_hosts_; |
| } |
| |
| // SiteInstanceImpl::Observer |
| void ActiveFrameCountIsZero(SiteInstanceImpl* site_instance) override; |
| void RenderProcessGone(SiteInstanceImpl* site_instance) override; |
| |
| // Cancels and destroys the pending or speculative RenderFrameHost if they |
| // match the provided |render_frame_host|. |
| void CancelPendingIfNecessary(RenderFrameHostImpl* render_frame_host); |
| |
| // Updates the user activation state in all proxies of this frame. For |
| // more details, see the comment on FrameTreeNode::user_activation_state_. |
| void UpdateUserActivationState(blink::UserActivationUpdateType update_type); |
| |
| // When a frame transfers user activation to another frame via postMessage, |
| // this is used to inform proxies of the target frame (via IPC) about the |
| // transfer, namely that |source_rfh| is transferring user activation to this |
| // frame. Note that the IPC isn't sent to |source_rfh|'s process, since it |
| // already knows about the transfer, and it also isn't sent to this frame's |
| // RenderFrame, since that will be handled as part of postMessage. |
| void TransferUserActivationFrom(RenderFrameHostImpl* source_rfh); |
| |
| void OnSetHasReceivedUserGestureBeforeNavigation(bool value); |
| |
| // Sets up the necessary state for a new RenderViewHost. If |proxy| is not |
| // null, it creates a RenderFrameProxy in the target renderer process which is |
| // used to route IPC messages when in swapped out state. Returns early if the |
| // RenderViewHost has already been initialized for another RenderFrameHost. |
| bool InitRenderView(RenderViewHostImpl* render_view_host, |
| RenderFrameProxyHost* proxy); |
| |
| // Returns the SiteInstance that should be used to host the navigation handled |
| // by |navigation_request|. |
| // Note: the SiteInstance returned by this function may not have an |
| // initialized RenderProcessHost. It will only be initialized when |
| // GetProcess() is called on the SiteInstance. In particular, calling this |
| // function will never lead to a process being created for the navigation. |
| scoped_refptr<SiteInstance> GetSiteInstanceForNavigationRequest( |
| const NavigationRequest& navigation_request); |
| |
| // Helper to initialize the RenderFrame if it's not initialized. |
| void InitializeRenderFrameIfNecessary(RenderFrameHostImpl* render_frame_host); |
| |
| // Prepares the FrameTreeNode for attaching an inner WebContents. This step |
| // may involve replacing |current_frame_host()| with a new RenderFrameHost |
| // in the same SiteInstance as the parent frame. Calling this method will |
| // dispatch beforeunload event if necessary. |
| void PrepareForInnerDelegateAttach( |
| RenderFrameHost::PrepareForInnerWebContentsAttachCallback callback); |
| |
| // When true the FrameTreeNode is preparing a RenderFrameHost for attaching an |
| // inner Delegate. During this phase new navigation requests are ignored. |
| bool is_attaching_inner_delegate() const { |
| return attach_to_inner_delegate_state_ != AttachToInnerDelegateState::NONE; |
| } |
| |
| // Called by the delegate at the end of the attaching process. |
| void set_attach_complete() { |
| attach_to_inner_delegate_state_ = AttachToInnerDelegateState::ATTACHED; |
| } |
| |
| private: |
| friend class NavigatorTest; |
| friend class RenderFrameHostManagerTest; |
| friend class RenderFrameHostTester; |
| friend class TestWebContents; |
| |
| enum class SiteInstanceRelation { |
| // A SiteInstance in a different browsing instance from the current. |
| UNRELATED, |
| // A SiteInstance in the same browsing instance as the current. |
| RELATED, |
| }; |
| |
| enum class AttachToInnerDelegateState { |
| // There is no inner delegate attached through FrameTreeNode and no |
| // attaching is in progress. |
| NONE, |
| // A frame is being prepared for attaching. |
| PREPARE_FRAME, |
| // An inner delegate attached to the delegate of this manager. |
| ATTACHED |
| }; |
| |
| // Stores information regarding a SiteInstance targeted at a specific URL to |
| // allow for comparisons without having to actually create new instances. It |
| // can point to an existing one or store the details needed to create a new |
| // one. |
| struct CONTENT_EXPORT SiteInstanceDescriptor { |
| explicit SiteInstanceDescriptor(content::SiteInstance* site_instance) |
| : existing_site_instance(site_instance), |
| relation(SiteInstanceRelation::UNRELATED) {} |
| |
| SiteInstanceDescriptor(BrowserContext* browser_context, |
| GURL dest_url, |
| SiteInstanceRelation relation_to_current); |
| |
| // Set with an existing SiteInstance to be reused. |
| content::SiteInstance* existing_site_instance; |
| |
| // In case |existing_site_instance| is null, specify a destination URL. |
| GURL dest_url; |
| |
| // In case |existing_site_instance| is null, specify a BrowsingContext, to |
| // be used with |dest_url| to resolve the site URL. |
| BrowserContext* browser_context; |
| |
| // In case |existing_site_instance| is null, specify how the new site is |
| // related to the current BrowsingInstance. |
| SiteInstanceRelation relation; |
| }; |
| |
| // Create a RenderFrameProxyHost owned by this object. |
| RenderFrameProxyHost* CreateRenderFrameProxyHost( |
| SiteInstance* site_instance, |
| scoped_refptr<RenderViewHostImpl> rvh); |
| |
| // Delete a RenderFrameProxyHost owned by this object. |
| void DeleteRenderFrameProxyHost(SiteInstance* site_instance); |
| |
| // Returns whether this tab should transition to a new renderer for |
| // cross-site URLs. Enabled unless we see the --single-process command line |
| // switch. |
| bool ShouldTransitionCrossSite(); |
| |
| // Returns true if for the navigation from |current_effective_url| to |
| // |new_effective_url|, a new SiteInstance and BrowsingInstance should be |
| // created (even if we are in a process model that doesn't usually swap). |
| // This forces a process swap and severs script connections with existing |
| // tabs. Cases where this can happen include transitions between WebUI and |
| // regular web pages. |new_site_instance| may be null. |
| // If there is no current NavigationEntry, then |current_is_view_source_mode| |
| // should be the same as |new_is_view_source_mode|. |
| // |
| // We use the effective URL here, since that's what is used in the |
| // SiteInstance's site and when we later call IsSameWebSite. If there is no |
| // current NavigationEntry, check the current SiteInstance's site, which might |
| // already be committed to a Web UI URL (such as the NTP). |
| bool ShouldSwapBrowsingInstancesForNavigation( |
| const GURL& current_effective_url, |
| bool current_is_view_source_mode, |
| SiteInstance* new_site_instance, |
| const GURL& new_effective_url, |
| bool new_is_view_source_mode, |
| bool is_failure) const; |
| |
| // Returns the SiteInstance to use for the navigation. |
| scoped_refptr<SiteInstance> GetSiteInstanceForNavigation( |
| const GURL& dest_url, |
| SiteInstanceImpl* source_instance, |
| SiteInstanceImpl* dest_instance, |
| SiteInstanceImpl* candidate_instance, |
| ui::PageTransition transition, |
| bool is_failure, |
| bool dest_is_restore, |
| bool dest_is_view_source_mode, |
| bool was_server_redirect); |
| |
| // Returns a descriptor of the appropriate SiteInstance object for the given |
| // |dest_url|, possibly reusing the current, source or destination |
| // SiteInstance. The actual SiteInstance can then be obtained calling |
| // ConvertToSiteInstance with the descriptor. |
| // |
| // |source_instance| is the SiteInstance of the frame that initiated the |
| // navigation. |current_instance| is the SiteInstance of the frame that is |
| // currently navigating. |dest_instance| is a predetermined SiteInstance that |
| // will be used if not null. |
| // For example, if you have a parent frame A, which has a child frame B, and |
| // A is trying to change the src attribute of B, this will cause a navigation |
| // where the source SiteInstance is A and B is the current SiteInstance. |
| // |
| // This is a helper function for GetSiteInstanceForNavigation. |
| SiteInstanceDescriptor DetermineSiteInstanceForURL( |
| const GURL& dest_url, |
| SiteInstance* source_instance, |
| SiteInstance* current_instance, |
| SiteInstance* dest_instance, |
| ui::PageTransition transition, |
| bool is_failure, |
| bool dest_is_restore, |
| bool dest_is_view_source_mode, |
| bool force_browsing_instance_swap, |
| bool was_server_redirect); |
| |
| // Returns true if a navigation to |dest_url| that uses the specified |
| // PageTransition in the current frame is allowed to swap BrowsingInstances. |
| // DetermineSiteInstanceForURL() uses this helper to determine when it is |
| // allowed to swap BrowsingInstances to avoid unneeded process sharing. See |
| // https://crbug.com/803367. |
| // |
| // Note that this is different from |
| // ShouldSwapBrowsingInstancesForNavigation(), which identifies cases in |
| // which a BrowsingInstance swap is *required* (e.g., for security). This |
| // function only identifies cases where a BrowsingInstance swap *may* be |
| // performed to optimize process placement. In particular, this is true for |
| // certain browser-initiated transitions for main frame navigations. |
| // |
| // Returning true here doesn't imply that DetermineSiteInstanceForURL() will |
| // swap BrowsingInstances. For example, this swap will not be done for |
| // same-site navigations, for history navigations, or when starting from an |
| // uninitialized SiteInstance. |
| bool IsBrowsingInstanceSwapAllowedForPageTransition( |
| ui::PageTransition transition, |
| const GURL& dest_url); |
| |
| // Converts a SiteInstanceDescriptor to the actual SiteInstance it describes. |
| // If a |candidate_instance| is provided (is not nullptr) and it matches the |
| // description, it is returned as is. |
| scoped_refptr<SiteInstance> ConvertToSiteInstance( |
| const SiteInstanceDescriptor& descriptor, |
| SiteInstanceImpl* candidate_instance); |
| |
| // Returns true if |candidate| is currently on the same web site as dest_url. |
| bool IsCurrentlySameSite(RenderFrameHostImpl* candidate, |
| const GURL& dest_url); |
| |
| // Ensure that we have created all needed proxies for a new RFH with |
| // SiteInstance |new_instance|: (1) create swapped-out RVHs and proxies for |
| // the new RFH's opener chain if we are staying in the same BrowsingInstance; |
| // (2) Create proxies for the new RFH's SiteInstance in its own frame tree. |
| void CreateProxiesForNewRenderFrameHost(SiteInstance* old_instance, |
| SiteInstance* new_instance); |
| |
| // Traverse the opener chain and populate |opener_frame_trees| with |
| // all FrameTrees accessible by following frame openers of nodes in the |
| // given node's FrameTree. |opener_frame_trees| is ordered so that openers |
| // of smaller-indexed entries point to larger-indexed entries (i.e., this |
| // node's FrameTree is at index 0, its opener's FrameTree is at index 1, |
| // etc). If the traversal encounters a node with an opener pointing to a |
| // FrameTree that has already been traversed (such as when there's a cycle), |
| // the node is added to |nodes_with_back_links|. |
| void CollectOpenerFrameTrees( |
| std::vector<FrameTree*>* opener_frame_trees, |
| std::unordered_set<FrameTreeNode*>* nodes_with_back_links); |
| |
| // Create swapped out RenderViews and RenderFrameProxies in the given |
| // SiteInstance for the current node's FrameTree. Used as a helper function |
| // in CreateOpenerProxies for creating proxies in each FrameTree on the |
| // opener chain. Don't create proxies for the subtree rooted at |
| // |skip_this_node|. |
| void CreateOpenerProxiesForFrameTree(SiteInstance* instance, |
| FrameTreeNode* skip_this_node); |
| |
| // Creates a RenderFrameHost and corresponding RenderViewHost if necessary. |
| std::unique_ptr<RenderFrameHostImpl> CreateRenderFrameHost( |
| SiteInstance* instance, |
| int32_t view_routing_id, |
| int32_t frame_routing_id, |
| int32_t widget_routing_id, |
| bool renderer_initiated_creation); |
| |
| // Create and initialize a speculative RenderFrameHost for an ongoing |
| // navigation. It might be destroyed and re-created later if the navigation |
| // is redirected to a different SiteInstance. |
| bool CreateSpeculativeRenderFrameHost(SiteInstance* old_instance, |
| SiteInstance* new_instance); |
| |
| // Initialization for RenderFrameHost uses the same sequence as InitRenderView |
| // above. |
| bool InitRenderFrame(RenderFrameHostImpl* render_frame_host); |
| |
| // Helper to reinitialize the RenderFrame, RenderView, and the opener chain |
| // for the provided |render_frame_host|. Used when the |render_frame_host| |
| // needs to be reused for a new navigation, but it is not live. |
| bool ReinitializeRenderFrame(RenderFrameHostImpl* render_frame_host); |
| |
| // Makes the pending WebUI on the current RenderFrameHost active. Call this |
| // when the current RenderFrameHost commits and it has a pending WebUI. |
| void CommitPendingWebUI(); |
| |
| // Sets the |pending_rfh| to be the active one. Called when the pending |
| // RenderFrameHost commits. |
| // BackForwardCache: Called to restore a RenderFrameHost. |
| void CommitPending(std::unique_ptr<RenderFrameHostImpl> pending_rfh); |
| |
| // Helper to call CommitPending() in all necessary cases. |
| void CommitPendingIfNecessary(RenderFrameHostImpl* render_frame_host, |
| bool was_caused_by_user_gesture, |
| bool is_same_document_navigation); |
| |
| // Commits any pending sandbox flag or feature policy updates when the |
| // renderer's frame navigates. |
| void CommitPendingFramePolicy(); |
| |
| // Runs the unload handler in the old RenderFrameHost, after the new |
| // RenderFrameHost has committed. |old_render_frame_host| will either be |
| // deleted or put on the pending delete list during this call. |
| void SwapOutOldFrame( |
| std::unique_ptr<RenderFrameHostImpl> old_render_frame_host); |
| |
| // Discards a RenderFrameHost that was never made active (for active ones |
| // SwapOutOldFrame is used instead). |
| void DiscardUnusedFrame( |
| std::unique_ptr<RenderFrameHostImpl> render_frame_host); |
| |
| // Helper method to set the active RenderFrameHost. Returns the old |
| // RenderFrameHost and updates counts. |
| std::unique_ptr<RenderFrameHostImpl> SetRenderFrameHost( |
| std::unique_ptr<RenderFrameHostImpl> render_frame_host); |
| |
| // Updates the pending WebUI of the current RenderFrameHost for a same-site |
| // navigation. |
| void UpdatePendingWebUIOnCurrentFrameHost(const GURL& dest_url, |
| int entry_bindings); |
| |
| // Returns true if a subframe can navigate cross-process. |
| bool CanSubframeSwapProcess(const GURL& dest_url, |
| SiteInstance* source_instance, |
| SiteInstance* dest_instance); |
| |
| // After a renderer process crash we'd have marked the host as invisible, so |
| // we need to set the visibility of the new View to the correct value here |
| // after reload. |
| void EnsureRenderFrameHostVisibilityConsistent(); |
| |
| // Similarly to visibility, we need to ensure RenderWidgetHost and |
| // RenderWidget know about page focus. |
| void EnsureRenderFrameHostPageFocusConsistent(); |
| |
| // When current RenderFrameHost is not in its parent SiteInstance, this method |
| // will destroy the frame and replace it with a new RenderFrameHost in the |
| // parent frame's SiteInstance. Either way, this will eventually invoke |
| // |attach_inner_delegate_callback_| with a pointer to |render_frame_host_| |
| // which is then safe for use with WebContents::AttachToOuterWebContentsFrame. |
| void CreateNewFrameForInnerDelegateAttachIfNecessary(); |
| |
| // Called when the result of preparing the FrameTreeNode for attaching an |
| // inner delegate is known. When successful, |render_frame_host_| can be used |
| // for attaching the inner Delegate. |
| void NotifyPrepareForInnerDelegateAttachComplete(bool success); |
| |
| // For use in creating RenderFrameHosts. |
| FrameTreeNode* frame_tree_node_; |
| |
| // Our delegate, not owned by us. Guaranteed non-NULL. |
| Delegate* delegate_; |
| |
| // Our RenderFrameHost which is responsible for all communication with a child |
| // RenderFrame instance. |
| // For now, RenderFrameHost keeps a RenderViewHost in its SiteInstance alive. |
| // Eventually, RenderViewHost will be replaced with a page context. |
| std::unique_ptr<RenderFrameHostImpl> render_frame_host_; |
| |
| // Proxy hosts, indexed by site instance ID. |
| std::unordered_map<int32_t, std::unique_ptr<RenderFrameProxyHost>> |
| proxy_hosts_; |
| |
| // A list of RenderFrameHosts waiting to shut down after swapping out. |
| using RFHPendingDeleteList = std::list<std::unique_ptr<RenderFrameHostImpl>>; |
| RFHPendingDeleteList pending_delete_hosts_; |
| |
| // Stores a speculative RenderFrameHost which is created early in a navigation |
| // so a renderer process can be started in parallel, if needed. |
| // This is purely a performance optimization and is not required for correct |
| // behavior. The speculative RenderFrameHost might be discarded later on if |
| // the final URL's SiteInstance isn't compatible with the one used to create |
| // it. |
| // |
| // This is also used by the BackForwardCache, which |
| // sets speculative_render_frame_host_ to the restored frame before |
| // committing. |
| std::unique_ptr<RenderFrameHostImpl> speculative_render_frame_host_; |
| |
| // This callback is used when attaching an inner Delegate to |delegate_| |
| // through |frame_tree_node_|. |
| RenderFrameHost::PrepareForInnerWebContentsAttachCallback |
| attach_inner_delegate_callback_; |
| AttachToInnerDelegateState attach_to_inner_delegate_state_ = |
| AttachToInnerDelegateState::NONE; |
| |
| base::WeakPtrFactory<RenderFrameHostManager> weak_factory_{this}; |
| |
| DISALLOW_COPY_AND_ASSIGN(RenderFrameHostManager); |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_ |