#include "content/browser/preloading/prerender/prerender_new_tab_handle.h"
#include "base/check_op.h"
#include "base/notreached.h"
#include "content/browser/preloading/preloading_attempt_impl.h"
#include "content/browser/preloading/preloading_data_impl.h"
#include "content/browser/preloading/prerender/prerender_host.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame.mojom.h"
#include "content/public/browser/web_contents_delegate.h"
namespace content {
PrerenderNewTabHandle::PrerenderNewTabHandle(
const PrerenderAttributes& attributes,
BrowserContext& browser_context)
: attributes_(attributes), web_contents_create_params_(&browser_context) {
CHECK(!attributes.IsBrowserInitiated());
auto* initiator_render_frame_host = RenderFrameHostImpl::FromFrameToken(
attributes_.initiator_process_id,
attributes_.initiator_frame_token.value());
web_contents_create_params_.opener_render_process_id =
initiator_render_frame_host->GetProcess()->GetDeprecatedID();
web_contents_create_params_.opener_render_frame_id =
initiator_render_frame_host->GetRoutingID();
web_contents_create_params_.opener_suppressed = true;
web_contents_create_params_.initially_hidden = true;
web_contents_ = base::WrapUnique(static_cast<WebContentsImpl*>(
WebContents::Create(web_contents_create_params_).release()));
web_contents_delegate_ =
GetContentClient()->browser()->CreatePrerenderWebContentsDelegate();
web_contents_delegate_->PrerenderWebContentsCreated(web_contents_.get());
web_contents_->SetDelegate(web_contents_delegate_.get());
CHECK_EQ(web_contents_->GetVisibility(), Visibility::HIDDEN);
CHECK(web_contents_->GetPrimaryMainFrame());
CHECK(web_contents_->GetPrimaryMainFrame()->is_initial_empty_document());
}
PrerenderNewTabHandle::~PrerenderNewTabHandle() {
if (web_contents_)
web_contents_->SetDelegate(nullptr);
}
FrameTreeNodeId PrerenderNewTabHandle::StartPrerendering(
const PreloadingPredictor& creating_predictor,
const PreloadingPredictor& enacting_predictor,
PreloadingConfidence confidence) {
CHECK(web_contents_);
CHECK(attributes_.initiator_web_contents);
auto* preloading_data =
PreloadingDataImpl::GetOrCreateForWebContents(web_contents_.get());
PreloadingURLMatchCallback same_url_matcher =
PreloadingData::GetSameURLMatcher(attributes_.prerendering_url);
ukm::SourceId triggered_primary_page_source_id =
attributes_.initiator_web_contents->GetPrimaryMainFrame()
->GetPageUkmSourceId();
auto* preloading_attempt =
static_cast<PreloadingAttemptImpl*>(preloading_data->AddPreloadingAttempt(
creating_predictor, enacting_predictor, PreloadingType::kPrerender,
std::move(same_url_matcher),
triggered_primary_page_source_id));
preloading_data->AddPreloadingPrediction(
enacting_predictor, confidence,
PreloadingData::GetSameURLMatcher(attributes_.prerendering_url),
triggered_primary_page_source_id);
preloading_data->CopyPredictorDomains(
*PreloadingDataImpl::GetOrCreateForWebContents(
attributes_.initiator_web_contents.get()),
{creating_predictor, enacting_predictor});
CHECK(eagerness().has_value());
preloading_attempt->SetSpeculationEagerness(eagerness().value());
prerender_host_id_ = GetPrerenderHostRegistry().CreateAndStartHost(
attributes_, preloading_attempt);
return prerender_host_id_;
}
void PrerenderNewTabHandle::CancelPrerendering(
const PrerenderCancellationReason& reason) {
GetPrerenderHostRegistry().CancelHost(prerender_host_id_, reason);
}
std::unique_ptr<WebContentsImpl>
PrerenderNewTabHandle::TakeWebContentsIfAvailable(
const mojom::CreateNewWindowParams& create_new_window_params,
const WebContents::CreateParams& web_contents_create_params) {
PrerenderHost* host =
GetPrerenderHostRegistry().FindNonReservedHostById(prerender_host_id_);
if (!host) {
return nullptr;
}
if (host->GetInitialUrl() != create_new_window_params.target_url) {
return nullptr;
}
if (web_contents_create_params_.opener_render_process_id !=
web_contents_create_params.opener_render_process_id) {
return nullptr;
}
if (web_contents_create_params_.opener_render_frame_id !=
web_contents_create_params.opener_render_frame_id) {
return nullptr;
}
CHECK(web_contents_create_params_.main_frame_name.empty());
if (web_contents_create_params_.main_frame_name !=
web_contents_create_params.main_frame_name) {
return nullptr;
}
CHECK(web_contents_);
web_contents_->SetDelegate(nullptr);
return std::move(web_contents_);
}
PrerenderHostRegistry& PrerenderNewTabHandle::GetPrerenderHostRegistry() {
CHECK(web_contents_);
return *web_contents_->GetPrerenderHostRegistry();
}
}