blob: dfec0043d25fc686b3ffde3f0459c3b686beaab2 [file] [log] [blame]
// 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_