blob: acfcbfd3a8eaf4ccd89001606c7566f2dfcf0f96 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/preloading/anchor_element_interaction_host_impl.h"
#include "content/browser/preloading/preloading.h"
#include "content/browser/preloading/preloading_decider.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
#include "third_party/blink/public/common/features.h"
namespace content {
namespace {
bool IsOutermostMainFrame(const RenderFrameHost& render_frame_host) {
return !render_frame_host.GetParentOrOuterDocument();
}
void MaybePrewarmHttpDiskCache(const GURL& url,
RenderFrameHost& render_frame_host) {
static const bool enabled =
base::FeatureList::IsEnabled(blink::features::kHttpDiskCachePrewarming) &&
blink::features::kHttpDiskCachePrewarmingTriggerOnPointerDownOrHover
.Get();
if (!enabled) {
return;
}
if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
return;
}
if (!IsOutermostMainFrame(render_frame_host)) {
return;
}
// Disallow PrewarmHttpDiskCache when there are other windows that
// might script with this frame to mitigate security and privacy
// concerns.
if (render_frame_host.GetSiteInstance()->GetRelatedActiveContentsCount() >
1u) {
return;
}
GetContentClient()->browser()->MaybePrewarmHttpDiskCache(
*render_frame_host.GetBrowserContext(),
render_frame_host.GetLastCommittedOrigin(), url);
}
void MaybeWarmUpServiceWorker(const GURL& url,
RenderFrameHost& render_frame_host) {
if (!IsOutermostMainFrame(render_frame_host)) {
return;
}
// Disallow service worker warm-up when there are other windows that
// might script with this frame to mitigate security and privacy
// concerns.
if (render_frame_host.GetSiteInstance()->GetRelatedActiveContentsCount() >
1u) {
return;
}
content::StoragePartition* storage_partition =
render_frame_host.GetStoragePartition();
if (!storage_partition) {
return;
}
content::ServiceWorkerContext* service_worker_context =
storage_partition->GetServiceWorkerContext();
if (!service_worker_context) {
return;
}
if (!content::OriginCanAccessServiceWorkers(url)) {
return;
}
const blink::StorageKey key =
blink::StorageKey::CreateFirstParty(url::Origin::Create(url));
if (!service_worker_context->MaybeHasRegistrationForStorageKey(key)) {
return;
}
service_worker_context->WarmUpServiceWorker(url, key, base::DoNothing());
}
void MaybeWarmUpServiceWorkerOnPointerDown(const GURL& url,
RenderFrameHost& render_frame_host) {
static const bool enabled =
base::FeatureList::IsEnabled(
blink::features::kSpeculativeServiceWorkerWarmUp) &&
blink::features::kSpeculativeServiceWorkerWarmUpOnPointerdown.Get();
if (enabled) {
MaybeWarmUpServiceWorker(url, render_frame_host);
}
}
void MaybeWarmUpServiceWorkerOnPointerHover(
const GURL& url,
RenderFrameHost& render_frame_host) {
static const bool enabled =
base::FeatureList::IsEnabled(
blink::features::kSpeculativeServiceWorkerWarmUp) &&
blink::features::kSpeculativeServiceWorkerWarmUpOnPointerover.Get();
if (enabled) {
MaybeWarmUpServiceWorker(url, render_frame_host);
}
}
} // namespace
AnchorElementInteractionHostImpl::AnchorElementInteractionHostImpl(
RenderFrameHost& frame_host,
mojo::PendingReceiver<blink::mojom::AnchorElementInteractionHost> receiver)
: DocumentService(frame_host, std::move(receiver)) {}
// static
void AnchorElementInteractionHostImpl::Create(
RenderFrameHost* frame_host,
mojo::PendingReceiver<blink::mojom::AnchorElementInteractionHost>
receiver) {
CHECK(frame_host);
new AnchorElementInteractionHostImpl(*frame_host, std::move(receiver));
}
void AnchorElementInteractionHostImpl::OnPointerDown(const GURL& url) {
auto* preloading_decider =
PreloadingDecider::GetOrCreateForCurrentDocument(&render_frame_host());
preloading_decider->OnPointerDown(url);
MaybePrewarmHttpDiskCache(url, render_frame_host());
MaybeWarmUpServiceWorkerOnPointerDown(url, render_frame_host());
}
void AnchorElementInteractionHostImpl::OnPointerHover(
const GURL& url,
blink::mojom::AnchorElementPointerDataPtr mouse_data) {
auto* preloading_decider =
PreloadingDecider::GetOrCreateForCurrentDocument(&render_frame_host());
preloading_decider->OnPointerHover(url, std::move(mouse_data));
MaybePrewarmHttpDiskCache(url, render_frame_host());
MaybeWarmUpServiceWorkerOnPointerHover(url, render_frame_host());
}
void AnchorElementInteractionHostImpl::OnViewportHeuristicTriggered(
const GURL& url) {
if (!base::FeatureList::IsEnabled(
blink::features::kPreloadingViewportHeuristics)) {
ReportBadMessageAndDeleteThis(
"OnViewportHeuristic should not be called by the renderer without "
"blink::features::kPreloadingViewportHeuristics being enabled");
return;
}
auto* preloading_decider =
PreloadingDecider::GetOrCreateForCurrentDocument(&render_frame_host());
preloading_decider->OnViewportHeuristicTriggered(url);
}
} // namespace content