1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
// 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_ATTEMPT_IMPL_H_
#define CONTENT_BROWSER_PRELOADING_PRELOADING_ATTEMPT_IMPL_H_
#include <optional>
#include <vector>
#include "base/timer/elapsed_timer.h"
#include "content/public/browser/preloading.h"
#include "content/public/browser/preloading_data.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom-shared.h"
#include "url/gurl.h"
namespace content {
namespace test {
class PreloadingAttemptAccessor;
}
class CONTENT_EXPORT PreloadingAttemptImpl : public PreloadingAttempt {
public:
~PreloadingAttemptImpl() override;
// PreloadingAttempt implementation:
void SetEligibility(PreloadingEligibility eligibility) override;
void SetHoldbackStatus(PreloadingHoldbackStatus holdback_status) override;
bool ShouldHoldback() override;
void SetTriggeringOutcome(
PreloadingTriggeringOutcome triggering_outcome) override;
void SetFailureReason(PreloadingFailureReason reason) override;
base::WeakPtr<PreloadingAttempt> GetWeakPtr() override;
// Records UKMs for both Preloading_Attempt and
// Preloading_Attempt_PreviousPrimaryPage. Metrics for both these are same.
// Only difference is that the Preloading_Attempt_PreviousPrimaryPage UKM is
// associated with the WebContents primary page that triggered the preloading
// attempt. This is done to easily analyze the impact of the preloading
// attempt on the primary visible page. Here `navigated_page` represent the
// ukm::SourceId of the navigated page. If the navigation doesn't happen this
// could be invalid. This must be called after the page load ends and we know
// if the attempt was accurate.
void RecordPreloadingAttemptMetrics(ukm::SourceId navigated_page);
void SetNoVarySearchMatchPredicate(
PreloadingURLMatchCallback no_vary_search_match_predicate);
// Sets `is_accurate_triggering_` to true if `navigated_url` matches the
// predicate URL logic. It also records `time_to_next_navigation_`.
void SetIsAccurateTriggering(const GURL& navigated_url);
bool IsAccurateTriggering() const { return is_accurate_triggering_; }
PreloadingAttemptImpl(
const PreloadingPredictor& creating_predictor,
const PreloadingPredictor& enacting_predictor,
PreloadingType preloading_type,
ukm::SourceId triggered_primary_page_source_id,
PreloadingURLMatchCallback url_match_predicate,
uint32_t sampling_seed);
std::vector<PreloadingPredictor> GetPredictors() const;
PreloadingType preloading_type() const { return preloading_type_; }
void SetSpeculationEagerness(blink::mojom::SpeculationEagerness eagerness);
// Describes what type of checks we had to do to identify if the attempt's
// URL is or is not under a Service Worker.
enum class ServiceWorkerRegisteredCheck {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// The origin doesn't have any Service Workers registered.
kOriginOnly = 0,
// The origin has at least one Service Worker registered and we had to
// perform a path test to identify if the attempt's URL is under a
// registered Service Worker.
kPath = 1,
kMaxValue = kPath
};
static constexpr double kServiceWorkerRegisteredCheckDurationBucketSpacing =
1.15;
void SetServiceWorkerRegisteredCheck(ServiceWorkerRegisteredCheck check);
void SetServiceWorkerRegisteredCheckDuration(base::TimeDelta duration);
private:
friend class test::PreloadingAttemptAccessor;
void RecordPreloadingAttemptUMA();
// Reason why the preloading attempt failed, this is similar to specific
// preloading logging reason. Zero as a failure reason signifies no reason is
// specified. This value is casted from preloading specific enum to int64_t
// instead of having an enum declaration for each case.
PreloadingFailureReason failure_reason_ =
PreloadingFailureReason::kUnspecified;
// Specifies the eligibility status for this PreloadingAttempt.
PreloadingEligibility eligibility_ = PreloadingEligibility::kUnspecified;
PreloadingHoldbackStatus holdback_status_ =
PreloadingHoldbackStatus::kUnspecified;
// Specifies the triggering outcome for this PreloadingAttempt.
PreloadingTriggeringOutcome triggering_outcome_ =
PreloadingTriggeringOutcome::kUnspecified;
// Preloading predictor of this PreloadingAttempt.
const PreloadingPredictor creating_predictor_;
const PreloadingPredictor enacting_predictor_;
// PreloadingType this attempt is associated with.
const PreloadingType preloading_type_;
// Holds the ukm::SourceId of the triggered primary page of this preloading
// attempt.
const ukm::SourceId triggered_primary_page_source_id_;
// Triggers can specify their own predicate for judging whether two URLs are
// considered as pointing to the same destination.
const PreloadingURLMatchCallback url_match_predicate_;
// Set when a predicted page provides No-Vary-Search header.
PreloadingURLMatchCallback no_vary_search_match_predicate_;
// Set to true if this PreloadingAttempt was used for the next navigation.
bool is_accurate_triggering_ = false;
// Records when the preloading attempt began, for computing times.
const base::ElapsedTimer elapsed_timer_;
// The time between the creation of the attempt and the start of the next
// navigation, whether accurate or not. The latency is reported as standard
// buckets, of 1.15 spacing.
std::optional<base::TimeDelta> time_to_next_navigation_;
// Represents the duration between the attempt creation and its
// `triggering_outcome_` becoming `kReady`. The latency is reported as
// standard buckets, of 1.15 spacing.
std::optional<base::TimeDelta> ready_time_;
// The random seed used to determine if a preloading attempt should be sampled
// in UKM logs. We use a different random seed for each session (that is the
// source of randomness for sampling) and then hash that seed with the UKM
// source ID so that all attempts for a given source ID use the same random
// value to determine sampling. This allows all PreloadingAttempt for a given
// (preloading_type, predictor) in a page load to be sampled in or out
// together.
uint32_t sampling_seed_;
// Eagerness of this preloading attempt (specified by a speculation rule).
// This is only set for attempts that are triggered by speculation rules.
std::optional<blink::mojom::SpeculationEagerness> eagerness_ = std::nullopt;
// Describes the type of check we did for to find out if the attempt's URL
// is under a Service Worker's path. The simplest check is: does the URL's
// origin have any registered service workers or not, the more complicated
// check is: given the URL's origin has service workers registered, is the
// URL under one of these Service Workers.
// This is only set for prefetch attempts that are triggered by speculation
// rules.
std::optional<ServiceWorkerRegisteredCheck> service_worker_registered_check_ =
std::nullopt;
std::optional<base::TimeDelta> service_worker_registered_check_duration_ =
std::nullopt;
base::WeakPtrFactory<PreloadingAttemptImpl> weak_factory_{this};
};
// Used when DCHECK_STATE_TRANSITION triggers.
CONTENT_EXPORT std::ostream& operator<<(std::ostream& o,
const PreloadingTriggeringOutcome& s);
} // namespace content
#endif // CONTENT_BROWSER_PRELOADING_PRELOADING_ATTEMPT_IMPL_H_
|