blob: e0bb908ecf3fca00b895846190bfb1509e23f578 [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.
#ifndef CONTENT_BROWSER_PRELOADING_PRELOADING_PREDICTION_H_
#define CONTENT_BROWSER_PRELOADING_PRELOADING_PREDICTION_H_
#include "content/public/browser/preloading_data.h"
#include "base/timer/elapsed_timer.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace content {
// PreloadingPrediction keeps track of every preloading prediction associated
// with various predictors as defined in content/public/preloading.h
// (please see for more details); whether the prediction is accurate or not;
// whether the prediction is confident enough or not.
class PreloadingPrediction {
public:
~PreloadingPrediction();
// Disallow copy and assign.
PreloadingPrediction(const PreloadingPrediction& other) = delete;
PreloadingPrediction& operator=(const PreloadingPrediction& other) = delete;
// Records both UKMs Preloading_Prediction and
// Preloading_Prediction_PreviousPrimaryPage. Metrics for both these are same.
// Only difference is that the Preloading_Prediction_PreviousPrimaryPage UKM
// is associated with the WebContents primary page that triggered the
// preloading prediction. This is done to easily analyze the impact of the
// preloading prediction on the primary visible page.
void RecordPreloadingPredictionUKMs(ukm::SourceId navigated_page_source_id);
// Sets `is_accurate_prediction_` to true if `navigated_url` matches the URL
// predicate. It also records `time_to_next_navigation_`.
void SetIsAccuratePrediction(const GURL& navigated_url);
bool IsAccuratePrediction() const { return is_accurate_prediction_; }
PreloadingPrediction(
PreloadingPredictor predictor,
double confidence,
ukm::SourceId triggered_primary_page_source_id,
base::RepeatingCallback<bool(const GURL&)> url_match_predicate);
// Called by the `PreloadingDataImpl` that owns this prediction, to check the
// validity of `predictor_type_`.
PreloadingPredictor predictor_type() const { return predictor_type_; }
private:
// Preloading predictor of this preloading prediction.
const PreloadingPredictor predictor_type_;
// Confidence percentage of predictor's preloading prediction. This value
// should be between 0 - 100.
const int64_t confidence_;
// Holds the triggered primary page of preloading operation ukm::SourceId.
const ukm::SourceId triggered_primary_page_source_id_;
// Triggers can specify their own predicate to judge whether two URLs are
// considered as pointing to the same destination as this varies for different
// predictors.
const PreloadingURLMatchCallback url_match_predicate_;
// Set to true when preloading prediction was correct i.e., when the
// navigation happens to the same predicted URL.
bool is_accurate_prediction_ = false;
// Records when the preloading prediction was first recorded.
const base::ElapsedTimer elapsed_timer_;
// The time between the creation of the prediction and the start of the next
// navigation, whether accurate or not. The latency is reported as standard
// buckets, of 1.15 spacing.
absl::optional<base::TimeDelta> time_to_next_navigation_;
};
// The output of many predictors is a logit/probability score. To use this score
// for binary classification, we compare it to a threshold. If the score is
// above the threshold, we classify the instance as positive; otherwise, we
// classify it as negative. Threshold choice affects classifier precision and
// recall. There is a trade-off between precision and recall. If we set the
// threshold too low, we will have high precision but low recall. If we set the
// threshold too high, we will have high recall but low precision. To choose the
// best threshold, we can use ROC curves, precision-recall curves, or
// logit-precision and logit-recall curves. `ExperimentalPreloadingPrediction`
// helps us collect the UMA data required to achieve this.
class ExperimentalPreloadingPrediction {
public:
ExperimentalPreloadingPrediction() = delete;
ExperimentalPreloadingPrediction(
base::StringPiece name,
PreloadingURLMatchCallback url_match_predicate,
float score,
float min_score,
float max_score,
size_t buckets);
~ExperimentalPreloadingPrediction();
base::StringPiece PredictorName() const { return name_; }
bool IsAccuratePrediction() const { return is_accurate_prediction_; }
float Score() const { return score_; }
void SetIsAccuratePrediction(const GURL& navigated_url);
void RecordToUMA() const;
private:
// Experimental predictor's name
base::StringPiece name_;
// Set to true when preloading prediction was correct i.e., when the
// navigation happens to the same predicted URL.
bool is_accurate_prediction_ = false;
// The logit or probability score output of the predictor model.
float score_;
// The minimum value that the `score` can have
float min_score_;
// The maximum value that the `score` can have
float max_score_;
// The number of buckets that will be used for UMA aggregation. It must be
// less than 101.
size_t buckets_;
// The callback to verify that the navigated URL is a match.
PreloadingURLMatchCallback url_match_predicate_;
};
} // namespace content
#endif // CONTENT_BROWSER_PRELOADING_PRELOADING_PREDICTION_H_