| // Copyright 2020 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_PRERENDER_PRERENDER_HOST_REGISTRY_H_ |
| #define CONTENT_BROWSER_PRERENDER_PRERENDER_HOST_REGISTRY_H_ |
| |
| #include <map> |
| |
| #include "base/observer_list_types.h" |
| #include "base/types/pass_key.h" |
| #include "content/browser/prerender/prerender_host.h" |
| #include "content/browser/renderer_host/back_forward_cache_impl.h" |
| #include "content/common/content_export.h" |
| #include "third_party/blink/public/common/tokens/tokens.h" |
| #include "third_party/blink/public/mojom/prerender/prerender.mojom.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| |
| namespace content { |
| |
| class FrameTreeNode; |
| class RenderFrameHostImpl; |
| |
| // Prerender2: |
| // PrerenderHostRegistry creates and retains a prerender host, and reserves it |
| // for NavigationRequest to activate the prerendered page. This is created and |
| // owned by WebContentsImpl. |
| // |
| // The APIs of this class are categorized into two: APIs for triggers and APIs |
| // for activators. |
| // |
| // - Triggers (e.g., PrerenderProcessor) can request to create a new prerender |
| // host by CreateAndStartHost() and cancel it by AbandonHost(Async)(). |
| // Triggers cannot cancel the host after it's preserved by an activator. |
| // - Activators (i.e., NavigationRequest) can reserve the prerender host on |
| // activation start by ReserveHostToActivate() and activate it by |
| // ActivateReservedHost(). They can abandon the host by |
| // AbandonPreservedHost(). |
| class CONTENT_EXPORT PrerenderHostRegistry { |
| public: |
| using PassKey = base::PassKey<PrerenderHostRegistry>; |
| |
| PrerenderHostRegistry(); |
| ~PrerenderHostRegistry(); |
| |
| PrerenderHostRegistry(const PrerenderHostRegistry&) = delete; |
| PrerenderHostRegistry& operator=(const PrerenderHostRegistry&) = delete; |
| PrerenderHostRegistry(PrerenderHostRegistry&&) = delete; |
| PrerenderHostRegistry& operator=(PrerenderHostRegistry&&) = delete; |
| |
| class Observer : public base::CheckedObserver { |
| public: |
| // Called once per CreateAndStartHost() call. Does not necessarily |
| // mean a host was created. |
| virtual void OnTrigger(const GURL& url) {} |
| |
| // Called from the registry's destructor. The observer |
| // should drop any reference to the registry. |
| virtual void OnRegistryDestroyed() {} |
| }; |
| |
| void AddObserver(Observer* observer); |
| void RemoveObserver(Observer* observer); |
| |
| // For triggers. |
| // Creates and starts a host. Returns the root frame tree node id of the |
| // prerendered page, which can be used as the id of the host. |
| int CreateAndStartHost(blink::mojom::PrerenderAttributesPtr attributes, |
| RenderFrameHostImpl& initiator_render_frame_host); |
| |
| // For triggers. |
| // Destroys the host registered for `frame_tree_node_id`. |
| // TODO(https://crbug.com/1169594): Distinguish two paths that cancel |
| // prerendering. A prerender can be canceled due to the following reasons: |
| // 1. Initiator was no longer interested. Since one prerender may have several |
| // initiators, PrerenderHostRegistry should not destroy a PrerenderHost |
| // instance if one of the initiators is still alive. |
| // 2. Prerendering page did something undesirable. The same behavior always |
| // happens regardless of which caller calls it. So PrerenderHostRegistry |
| // should destroy the PrerenderHost. |
| void AbandonHost(int frame_tree_node_id); |
| |
| // For triggers. |
| // This is the same with AbandonHost but destroys the prerender host |
| // asynchronously so that the prerendered page itself can cancel prerendering |
| // without concern for self destruction. |
| void AbandonHostAsync(int frame_tree_node_id, |
| PrerenderHost::FinalStatus final_status); |
| |
| // For activators. |
| // Reserves the host to activate for a navigation for the given FrameTreeNode. |
| // Returns the root frame tree node id of the prerendered page, which can be |
| // used as the id of the host. Returns RenderFrameHost::kNoFrameTreeNodeId if |
| // it's not found or not ready for activation yet. The caller is responsible |
| // for calling ActivateReservedHost() or AbandonReservedHost() with the id to |
| // release the reserved host. |
| int ReserveHostToActivate(const GURL& navigation_url, |
| FrameTreeNode& frame_tree_node); |
| |
| // For activators. |
| // Activates the host reserved by ReserveHostToActivate() and returns the |
| // BackForwardCacheImpl::Entry containing the page that was activated on |
| // success, or nullptr on failure. |
| std::unique_ptr<BackForwardCacheImpl::Entry> ActivateReservedHost( |
| int frame_tree_node_id, |
| NavigationRequest& navigation_request); |
| |
| RenderFrameHostImpl* GetRenderFrameHostForReservedHost( |
| int frame_tree_node_id); |
| |
| // For activators. |
| // Abandons the host reserved by ReserveHostToActivate(). |
| void AbandonReservedHost(int frame_tree_node_id); |
| |
| // Returns the non-reserved host with the given id. Returns nullptr if the id |
| // does not match any non-reserved host. |
| PrerenderHost* FindNonReservedHostById(int frame_tree_node_id); |
| |
| // Returns the reserved host with the given id. Returns nullptr if the id |
| // does not match any reserved host. |
| PrerenderHost* FindReservedHostById(int frame_tree_node_id); |
| |
| // Returns the non-reserved host for `prerendering_url`. Returns nullptr if |
| // the URL doesn't match any non-reserved host. |
| PrerenderHost* FindHostByUrlForTesting(const GURL& prerendering_url); |
| |
| private: |
| std::unique_ptr<PrerenderHost> AbandonHostInternal(int frame_tree_node_id); |
| |
| void NotifyTrigger(const GURL& url); |
| |
| // Hosts that are not reserved for activation yet. |
| // TODO(https://crbug.com/1132746): Expire prerendered contents if they are |
| // not used for a while. |
| std::map<int, std::unique_ptr<PrerenderHost>> |
| prerender_host_by_frame_tree_node_id_; |
| std::map<GURL, int> frame_tree_node_id_by_url_; |
| |
| // Hosts that are reserved for activation. |
| std::map<int, std::unique_ptr<PrerenderHost>> |
| reserved_prerender_host_by_frame_tree_node_id_; |
| |
| base::ObserverList<Observer> observers_; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_PRERENDER_PRERENDER_HOST_REGISTRY_H_ |