910e62b5创建于 1月15日历史提交
// Copyright 2021 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_PRERENDER_PRERENDER_METRICS_H_
#define CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_METRICS_H_

#include <cstdint>
#include <string>
#include <variant>

#include "base/time/time.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/preloading/prerender/prerender_host.h"
#include "content/common/content_export.h"
#include "content/public/browser/preloading_trigger_type.h"
#include "services/metrics/public/cpp/ukm_source_id.h"

namespace content {

struct CONTENT_EXPORT PrerenderMismatchedHeaders {
 public:
  PrerenderMismatchedHeaders(const std::string& header_name,
                             std::optional<std::string> initial_value,
                             std::optional<std::string> activation_value);

  ~PrerenderMismatchedHeaders();

  PrerenderMismatchedHeaders(const PrerenderMismatchedHeaders& other);
  PrerenderMismatchedHeaders(PrerenderMismatchedHeaders&& other);

  PrerenderMismatchedHeaders& operator=(
      const PrerenderMismatchedHeaders& other);
  PrerenderMismatchedHeaders& operator=(PrerenderMismatchedHeaders&& other);

  std::string header_name;
  std::optional<std::string> initial_value;
  std::optional<std::string> activation_value;
};

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// Note: Please update GetCancelledInterfaceType() in the corresponding .cc file
// and the enum of PrerenderCancelledUnknownInterface in
// tools/metrics/histograms/enums.xml if you add a new item.
enum class PrerenderCancelledInterface {
  kUnknown = 0,  // For kCancel interfaces added by embedders or tests.
  kGamepadHapticsManager = 1,
  kGamepadMonitor = 2,
  // kNotificationService = 3,   Deprecated.
  kTrustedVaultEncryptionKeys = 4,
  kMaxValue = kTrustedVaultEncryptionKeys
};

// Used by PrerenderNavigationThrottle, to track the cross-origin cancellation
// reason, and break it down into more cases.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class PrerenderCrossOriginRedirectionMismatch {
  kShouldNotBeReported = 0,
  kPortMismatch = 1,
  kHostMismatch = 2,
  kHostPortMismatch = 3,
  kSchemeMismatch = 4,
  kSchemePortMismatch = 5,
  kSchemeHostMismatch = 6,
  kSchemeHostPortMismatch = 7,
  kMaxValue = kSchemeHostPortMismatch
};

// Assembles PrerenderHostFinalStatus with a detailed explanation if applicable.
// Some FinalStatus enums cover multiple sub cases. To explain them in detail,
// some explanations can be attached to the status.
class CONTENT_EXPORT PrerenderCancellationReason {
 public:
  // Tagged by `final_status_`. See `BuildFor*` and `ToDevtoolReasonString`.
  using DetailedReasonVariant =
      std::variant<std::monostate,
                   int32_t,
                   uint64_t,
                   std::string,
                   std::vector<PrerenderMismatchedHeaders>>;

  explicit PrerenderCancellationReason(PrerenderFinalStatus final_status);
  ~PrerenderCancellationReason();

  static PrerenderCancellationReason BuildForDisallowActivationState(
      uint64_t disallow_activation_reason);

  static PrerenderCancellationReason BuildForMojoBinderPolicy(
      const std::string& interface_name);

  static PrerenderCancellationReason BuildForLoadingError(int32_t error_code);

  static PrerenderCancellationReason
  CreateCandidateReasonForActivationParameterMismatch();

  PrerenderCancellationReason(PrerenderCancellationReason&& reason);

  // Reports UMA and UKM metrics.
  void ReportMetrics(const std::string& histogram_suffix) const;

  PrerenderFinalStatus final_status() const { return final_status_; }

  // Returns disallowed Mojo interface name iff final status is
  // `kMojoBinderPolicy`.
  std::optional<std::string> DisallowedMojoInterface() const;

  // Returns the pointer of the vector of PrerenderMismatchedHeaders iff
  // header mismatch occurred.
  const std::vector<PrerenderMismatchedHeaders>* GetPrerenderMismatchedHeaders()
      const;

  void SetPrerenderMismatchedHeaders(
      std::unique_ptr<std::vector<PrerenderMismatchedHeaders>>
          mismatched_headers);

 private:
  PrerenderCancellationReason(PrerenderFinalStatus final_status,
                              DetailedReasonVariant explanation);

  const PrerenderFinalStatus final_status_;

  DetailedReasonVariant explanation_;
};

// Used by PrerenderNavigationThrottle. This is a breakdown enum for
// PrerenderCrossOriginRedirectionMismatch.kSchemePortMismatch.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class PrerenderCrossOriginRedirectionProtocolChange {
  kHttpProtocolUpgrade = 0,
  kHttpProtocolDowngrade = 1,
  kMaxValue = kHttpProtocolDowngrade
};

std::string GeneratePrerenderHistogramSuffix(
    PreloadingTriggerType trigger_type,
    const std::string& embedder_suffix);

void RecordPrerenderTriggered(ukm::SourceId ukm_id);

void RecordPrerenderActivationTime(
    base::TimeDelta delta,
    PreloadingTriggerType trigger_type,
    const std::string& embedder_histogram_suffix);

// Used by failing prerender attempts. Records the status to UMA and UKM, and
// reports the failing reason to devtools. In the attributes, `initiator_ukm_id`
// represents the page that starts prerendering.
void RecordFailedPrerenderFinalStatus(
    const PrerenderCancellationReason& cancellation_reason,
    const PrerenderAttributes& attributes);

// Records a success activation to UMA and UKM.
// `prerendered_ukm_id` is the UKM ID of the activated page.
void ReportSuccessActivation(const PrerenderAttributes& attributes,
                             ukm::SourceId prerendered_ukm_id);

// Records which navigation parameters are different between activation and
// initial prerender navigation when activation fails.
void RecordPrerenderActivationNavigationParamsMatch(
    PrerenderHost::ActivationNavigationParamsMatch result,
    const std::string& histogram_suffix);

// Records the detailed types of the cross-origin redirection, e.g., changes to
// scheme, host name etc.
void RecordPrerenderRedirectionMismatchType(
    PrerenderCrossOriginRedirectionMismatch case_type,
    const std::string& histogram_suffix);

// Records whether the redirection was caused by HTTP protocol upgrade.
void RecordPrerenderRedirectionProtocolChange(
    PrerenderCrossOriginRedirectionProtocolChange change_type,
    const std::string& histogram_suffix);

// Records ui::PageTransition of prerender activation navigation when transition
// mismatch happens on prerender activation.
void RecordPrerenderActivationTransition(
    int32_t potential_activation_transition,
    const std::string& histogram_suffix);

// If you change this, please follow the process in
// go/preloading-dashboard-updates to update the mapping reflected in dashboard,
// or if you are not a Googler, please file an FYI bug on https://crbug.new with
// component Internals>Preload.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// These are also mapped onto the second content internal range of
// `PreloadingEligibility`.
//
// LINT.IfChange
enum class PrerenderBackNavigationEligibility {
  kEligible = 0,

  kNoBackEntry = 1,
  kTargetIsSameDocument = 2,
  kMethodNotGet = 3,
  kTargetIsFailedNavigation = 4,
  kBfcacheEntryExists = 5,
  kTargetIsSameSite = 6,
  kNoHttpCacheEntry = 7,
  kTargetingOtherWindow = 8,
  kTargetIsNonHttp = 9,
  kRelatedActiveContents = 10,

  kMaxValue = kRelatedActiveContents,
};
// LINT.ThenChange()

// Maps `eligibility` onto a content internal range of PreloadingEligibility.
CONTENT_EXPORT PreloadingEligibility
ToPreloadingEligibility(PrerenderBackNavigationEligibility eligibility);

void RecordPrerenderBackNavigationEligibility(
    PreloadingPredictor predictor,
    PrerenderBackNavigationEligibility eligibility,
    PreloadingAttempt* preloading_attempt);

void RecordPrerenderActivationCommitDeferTime(
    base::TimeDelta time_delta,
    PreloadingTriggerType trigger_type,
    const std::string& embedder_histogram_suffix);

void RecordReceivedPrerendersPerPrimaryPageChangedCount(
    int number,
    PreloadingTriggerType trigger_type,
    const std::string& eagerness_category);

}  // namespace content

#endif  // CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_METRICS_H_