blob: c985d7c0c23d8f561c40b609f5e1ed48fa1de8cf [file] [log] [blame]
// Copyright 2021 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.
#include "chrome/browser/prefetch/speculation_host_impl.h"
#include "chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "third_party/blink/public/common/features.h"
#include "url/origin.h"
// static
void SpeculationHostImpl::Bind(
content::RenderFrameHost* frame_host,
mojo::PendingReceiver<blink::mojom::SpeculationHost> receiver) {
// Note: Currently SpeculationHostImpl doesn't trigger prerendering.
// TODO(crbug.com/1197133): Support prerendering after moving to content/.
if (!base::FeatureList::IsEnabled(
blink::features::kSpeculationRulesPrefetchProxy) &&
!blink::features::IsPrerender2Enabled()) {
mojo::ReportBadMessage(
"Speculation rules must be enabled to bind to "
"blink.mojom.SpeculationHost in the browser.");
return;
}
// FrameServiceBase will destroy this on pipe closure or frame destruction.
new SpeculationHostImpl(frame_host, std::move(receiver));
}
SpeculationHostImpl::SpeculationHostImpl(
content::RenderFrameHost* frame_host,
mojo::PendingReceiver<blink::mojom::SpeculationHost> receiver)
: FrameServiceBase(frame_host, std::move(receiver)),
document_url_(frame_host->GetLastCommittedURL()) {}
SpeculationHostImpl::~SpeculationHostImpl() = default;
void SpeculationHostImpl::UpdateSpeculationCandidates(
std::vector<blink::mojom::SpeculationCandidatePtr> candidates) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Only one update per document is allowed for now.
// TODO(ryansturm): Add support for updates. https://crbug.com/1190338
if (received_update_)
return;
received_update_ = true;
// Only handle main frame current frame messages.
if (!render_frame_host()->IsCurrent())
return;
if (render_frame_host()->GetParent())
return;
// TODO(ryansturm): Handle non-private speculations.
// https://crbug.com/1190331
std::vector<GURL> private_prefetches_with_subresources;
std::vector<GURL> private_prefetches;
for (auto& candidate : candidates) {
if (candidate->url.HostIsIPAddress())
continue;
if (!candidate->url.SchemeIsHTTPOrHTTPS()) {
continue;
}
if (candidate->requires_anonymous_client_ip_when_cross_origin &&
url::Origin::Create(candidate->url) != origin()) {
if (candidate->action ==
blink::mojom::SpeculationAction::kPrefetchWithSubresources) {
private_prefetches_with_subresources.push_back(candidate->url);
} else if (candidate->action ==
blink::mojom::SpeculationAction::kPrefetch) {
private_prefetches.push_back(candidate->url);
}
}
}
if (private_prefetches.size() == 0 &&
private_prefetches_with_subresources.size() == 0)
return;
auto* prefetch_proxy_tab_helper = PrefetchProxyTabHelper::FromWebContents(
content::WebContents::FromRenderFrameHost(render_frame_host()));
if (!prefetch_proxy_tab_helper)
return;
// TODO(ryansturm): Handle CSP prefetch-src. https://crbug.com/1192857
prefetch_proxy_tab_helper->PrefetchSpeculationCandidates(
private_prefetches_with_subresources, private_prefetches, document_url_);
}