blob: 56db477d35e65658f8bd05c5b2db72d227602c4a [file] [log] [blame]
// Copyright 2022 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 "content/browser/preloading_data_impl.h"
#include "content/browser/preloading_attempt_impl.h"
#include "content/browser/preloading_prediction.h"
#include "content/public/browser/page.h"
#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/ukm_builders.h"
namespace content {
// static
PreloadingData* PreloadingData::GetOrCreateForWebContents(
WebContents* web_contents) {
return PreloadingDataImpl::GetOrCreateForWebContents(web_contents);
}
// static
PreloadingDataImpl* PreloadingDataImpl::GetOrCreateForWebContents(
WebContents* web_contents) {
auto* preloading_impl = PreloadingDataImpl::FromWebContents(web_contents);
if (!preloading_impl)
PreloadingDataImpl::CreateForWebContents(web_contents);
return PreloadingDataImpl::FromWebContents(web_contents);
}
PreloadingAttempt* PreloadingDataImpl::AddPreloadingAttempt(
PreloadingPredictor predictor,
PreloadingType preloading_type,
PreloadingURLMatchCallback url_match_predicate) {
// We want to log the metrics for user visible primary pages to measure the
// impact of PreloadingAttempt on the page user is viewing.
// TODO(crbug.com/1330783): Extend this for non-primary page and inner
// WebContents preloading attempts.
ukm::SourceId triggered_primary_page_source_id =
web_contents()->GetPrimaryMainFrame()->GetPageUkmSourceId();
auto attempt = std::make_unique<PreloadingAttemptImpl>(
predictor, preloading_type, triggered_primary_page_source_id,
std::move(url_match_predicate));
preloading_attempts_.push_back(std::move(attempt));
return preloading_attempts_.back().get();
}
void PreloadingDataImpl::AddPreloadingPrediction(
PreloadingPredictor predictor,
int64_t confidence,
PreloadingURLMatchCallback url_match_predicate) {
// Cross-check that we set confidence percentage in the limits.
DCHECK(confidence >= 0 && confidence <= 100);
// We want to log the metrics for user visible primary pages to measure the
// impact of PreloadingPredictions on the page user is viewing.
// TODO(crbug.com/1330783): Extend this for non-primary page and inner
// WebContents preloading predictions.
ukm::SourceId triggered_primary_page_source_id =
web_contents()->GetPrimaryMainFrame()->GetPageUkmSourceId();
auto prediction = std::make_unique<PreloadingPrediction>(
predictor, confidence, triggered_primary_page_source_id,
std::move(url_match_predicate));
preloading_predictions_.push_back(std::move(prediction));
}
PreloadingDataImpl::PreloadingDataImpl(WebContents* web_contents)
: WebContentsUserData<PreloadingDataImpl>(*web_contents),
WebContentsObserver(web_contents) {}
PreloadingDataImpl::~PreloadingDataImpl() = default;
void PreloadingDataImpl::PrimaryPageChanged(Page& page) {
ukm::SourceId navigated_page_source_id =
page.GetMainDocument().GetPageUkmSourceId();
GURL navigated_url = page.GetMainDocument().GetLastCommittedURL();
// Log the UKMs also on navigation when the user ends up navigating. Please
// note that we currently log the metrics on the primary page to analyze
// preloading impact on user-visible primary pages.
RecordUKMForPreloadingAttempts(navigated_page_source_id, navigated_url);
RecordUKMForPreloadingPredictions(navigated_page_source_id, navigated_url);
// Delete the user data after logging.
web_contents()->RemoveUserData(UserDataKey());
}
void PreloadingDataImpl::WebContentsDestroyed() {
// Log the UKMs also on WebContentsDestroyed event to avoid losing the data
// in case the user doesn't end up navigating. When the WebContents is
// destroyed before navigation, we pass ukm::kInvalidSourceId and empty URL to
// avoid the UKM associated to wrong page.
RecordUKMForPreloadingAttempts(ukm::kInvalidSourceId, GURL());
RecordUKMForPreloadingPredictions(ukm::kInvalidSourceId, GURL());
// Delete the user data after logging.
web_contents()->RemoveUserData(UserDataKey());
}
void PreloadingDataImpl::RecordUKMForPreloadingAttempts(
ukm::SourceId navigated_page_source_id,
const GURL& navigated_url) {
for (auto& attempt : preloading_attempts_) {
attempt->RecordPreloadingAttemptUKMs(navigated_page_source_id,
navigated_url);
}
// Clear all records once we record the UKMs.
preloading_attempts_.clear();
}
void PreloadingDataImpl::RecordUKMForPreloadingPredictions(
ukm::SourceId navigated_page_source_id,
const GURL& navigated_url) {
for (auto& prediction : preloading_predictions_) {
prediction->RecordPreloadingPredictionUKMs(navigated_page_source_id,
navigated_url);
}
// Clear all records once we record the UKMs.
preloading_predictions_.clear();
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(PreloadingDataImpl);
} // namespace content