blob: 00f84d944a4620977b085591db293bc0ec7eeaea [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_H_
#define CONTENT_BROWSER_PRERENDER_PRERENDER_HOST_H_
#include <memory>
#include "base/observer_list_types.h"
#include "base/types/pass_key.h"
#include "content/browser/renderer_host/back_forward_cache_impl.h"
#include "content/common/content_export.h"
#include "content/common/navigation_params.mojom.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
#include "url/gurl.h"
namespace content {
class FrameTree;
class PrerenderHostRegistry;
class RenderFrameHostImpl;
class WebContentsImpl;
// Prerender2:
// PrerenderHost creates a new FrameTree in WebContents associated with the page
// that triggered prerendering and starts prerendering. Then NavigationRequest
// is expected to find this host from PrerenderHostRegistry and activate the
// prerendered page upon navigation. This is created per request from a renderer
// process via PrerenderProcessor or will directly be created for
// browser-initiated prerendering (this code path is not implemented yet). This
// is owned by PrerenderHostRegistry.
class CONTENT_EXPORT PrerenderHost : public WebContentsObserver {
public:
class Observer : public base::CheckedObserver {
public:
// Called on the page activation.
virtual void OnActivated() {}
// Called from the PrerenderHost's destructor. The observer should drop any
// reference to the host.
virtual void OnHostDestroyed() {}
};
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class FinalStatus {
kActivated = 0,
kDestroyed = 1,
kLowEndDevice = 2,
kCrossOriginRedirect = 3,
kCrossOriginNavigation = 4,
kInvalidSchemeRedirect = 5,
kInvalidSchemeNavigation = 6,
kInProgressNavigation = 7,
kNavigationRequestFailure = 8,
kNavigationRequestBlockedByCsp = 9,
kMainFrameNavigation = 10,
kMojoBinderPolicy = 11,
kPlugin = 12,
kRendererProcessCrashed = 13,
kRendererProcessKilled = 14,
kDownload = 15,
kTriggerDestroyed = 16,
kNavigationNotCommitted = 17,
kMaxValue = kNavigationNotCommitted,
};
PrerenderHost(blink::mojom::PrerenderAttributesPtr attributes,
RenderFrameHostImpl& initiator_render_frame_host);
~PrerenderHost() override;
PrerenderHost(const PrerenderHost&) = delete;
PrerenderHost& operator=(const PrerenderHost&) = delete;
PrerenderHost(PrerenderHost&&) = delete;
PrerenderHost& operator=(PrerenderHost&&) = delete;
// Returns false if prerendering hasn't been started.
bool StartPrerendering();
// WebContentsObserver implementation:
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
// Activates the prerendered page and returns BackForwardCacheImpl::Entry
// containing the page. This must be called after this host gets ready for
// activation.
//
// TODO(https://crbug.com/1181263): Refactor BackForwardCacheImpl::Entry into
// a generic "page" object to make clear that the same logic is also used for
// prerendering.
std::unique_ptr<BackForwardCacheImpl::Entry> Activate(
NavigationRequest& navigation_request);
// Returns true if the navigation params that were used in the initial
// prerender navigation (i.e., in StartPrerendering()) match the navigation
// params in `navigation_request`. This function can be used to determine
// whether `navigation_request` may be eligible to activate this
// PrerenderHost.
bool AreInitialPrerenderNavigationParamsCompatibleWithNavigation(
NavigationRequest& navigation_request);
// Returns the main RenderFrameHost of the prerendered page.
// This must be called after StartPrerendering() and before Activate().
RenderFrameHostImpl* GetPrerenderedMainFrameHost();
// Tells the reason of the destruction of this host. PrerenderHostRegistry
// uses this before abandoning the host.
void RecordFinalStatus(base::PassKey<PrerenderHostRegistry>,
FinalStatus status);
// Waits until the page load finishes.
void WaitForLoadStopForTesting();
const GURL& GetInitialUrl() const;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// The initial navigation id is set by the PrerenderNavigationThrottle
// when the PrerenderHost is first navigated, which happens immediately
// after creation.
absl::optional<int64_t> GetInitialNavigationId() const;
void SetInitialNavigationId(int64_t navigation_id);
url::Origin initiator_origin() const { return initiator_origin_; }
int frame_tree_node_id() const { return frame_tree_node_id_; }
bool is_ready_for_activation() const { return is_ready_for_activation_; }
private:
class PageHolder;
void RecordFinalStatus(FinalStatus status);
void CreatePageHolder(WebContentsImpl& web_contents);
// Asks the registry to cancel prerendering.
void Cancel(FinalStatus status);
// TODO(https://crbug.com/1217045): Flatten the params and do not rely on
// PrerenderAttributesPtr.
const blink::mojom::PrerenderAttributesPtr attributes_;
const url::Origin initiator_origin_;
const int initiator_process_id_;
const blink::LocalFrameToken initiator_frame_token_;
// Indicates if `page_holder_` is ready for activation.
bool is_ready_for_activation_ = false;
// The ID of the root node of the frame tree for the prerendered page `this`
// is hosting. Since PrerenderHost has 1:1 correspondence with FrameTree,
// this is also used for the ID of this PrerenderHost.
int frame_tree_node_id_ = RenderFrameHost::kNoFrameTreeNodeId;
absl::optional<FinalStatus> final_status_;
std::unique_ptr<PageHolder> page_holder_;
base::ObserverList<Observer> observers_;
// Navigation parameters for the navigation which loaded the main document of
// the prerendered page, copied immediately after BeginNavigation. They will
// be compared with the navigation parameters of the potential activation when
// attempting to reserve the prerender host for a navigation.
mojom::BeginNavigationParamsPtr begin_params_;
mojom::CommonNavigationParamsPtr common_params_;
// Holds the navigation ID for the main frame initial navigation.
absl::optional<int64_t> initial_navigation_id_;
};
} // namespace content
#endif // CONTENT_BROWSER_PRERENDER_PRERENDER_HOST_H_