blob: d05bfb04f5a456953ae5be81650ff784e6c58cfd [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/optional.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/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/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 NavigationController;
class PrerenderHostRegistry;
class RenderFrameHostImpl;
class WebContentsImpl;
// Prerender2:
// PrerenderHost creates a new WebContents and starts prerendering with that.
// Then navigation code is expected to find this host from PrerenderHostRegistry
// and activate the prerendered WebContents 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.
//
// TODO(https://crbug.com/1132746): This class has two different ways of
// prerendering the page: a dedicated WebContents instance or using a separate
// FrameTree instance (MPArch). You can choose one or the other via the feature
// parameter "implementation". The MPArch code is still in its very early stages
// but will eventually completely replace the WebContents approach.
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,
kMaxValue = kMainFrameNavigation
};
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;
void StartPrerendering();
// WebContentsObserver implementation:
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
// Activates the prerendered contents. This must be called after this host
// gets ready for activation. `old_render_frame_host` is the RenderFrameHost
// that will be swapped out and destroyed by the activation. For MPArch
// implementation, returns the activating page prepared for cross-FrameTree
// transfer. For multiple WebContents implementation, always returns nullptr.
//
// TODO(https://crbug.com/1154501): WebContents implementation will need to be
// removed.
//
// TODO(https://crbug.com/1170277): Potentially update implementation so that
// the |old_render_frame_host| parameter is not required.
//
// 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> ActivatePrerenderedContents(
RenderFrameHostImpl& old_render_frame_host,
NavigationRequest& navigation_request);
// Returns the main RenderFrameHost of the prerendered page.
// This must be called after StartPrerendering() and before
// ActivatePrerenderedContents().
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);
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:
// There are two implementations of this interface. One holds the page in a
// WebContents, and one holds it in a FrameTree (for MPArch).
// TODO(https://crbug.com/1170277): Remove once MPArch is the only
// implementation.
class PageHolderInterface;
class MPArchPageHolder;
class WebContentsPageHolder;
void RecordFinalStatus(FinalStatus status);
// Returns the frame tree associated with |prerendered_contents_|;
FrameTree* GetPrerenderedFrameTree();
void CreatePageHolder(WebContentsImpl& web_contents);
NavigationController& GetNavigationController();
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;
base::Optional<FinalStatus> final_status_;
std::unique_ptr<PageHolderInterface> page_holder_;
base::ObserverList<Observer> observers_;
};
} // namespace content
#endif // CONTENT_BROWSER_PRERENDER_PRERENDER_HOST_H_