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

#include <optional>
#include <ostream>

#include "content/common/content_export.h"

namespace content {

enum class PrefetchContainerLoadState;
enum class PrefetchPotentialCandidateServingResult;

// TODO(crbug.com/372186548): Revisit the shape of `PrefetchServableState`.
//
// See also https://crrev.com/c/5831122
enum class PrefetchServableState {
  // `PrefetchService` is checking eligibility of the prefetch or waiting load
  // start after eligibility check.
  //
  // Prefetch matching process should block until eligibility is got (and load
  // start) not to fall back normal navigation without waiting prefetch ahead of
  // prerender and send a duplicated fetch request.
  //
  // This state occurs only if `kPrerender2FallbackPrefetchSpecRules` is
  // enabled. Otherwise, `kNotServable` is returned for this period.
  kShouldBlockUntilEligibilityGot,

  // The load is started but non redirect header is not received yet.
  //
  // Prefetch matching process should block until the head of this is received
  // on a navigation to a matching URL, as a server can send a response header
  // including NoVarySearch header that contradicts NoVarySearch hint.
  kShouldBlockUntilHeadReceived,

  // This received non redirect header and is not expired.
  //
  // Note that it needs more checks to serve, e.g. cookie check. See also e.g.
  // `PrefetchMatchResolver::OnDeterminedHead()`.
  kServable,

  // Not other states.
  kNotServable,
};

CONTENT_EXPORT std::ostream& operator<<(std::ostream& ostream,
                                        PrefetchServableState servable_state);

// Action for wait loop of prefetch matching
//
// This represents an action of `PrefetchMatchResolver` for `PrefetchContainer`.
//
// Currently, this is an intermediate data and converted to
// `PrefetchServableState`.
//
// Mid-term plan:
// https://docs.google.com/document/d/1yRYq7GekwIjvvF5XRjDa6bGoba3HQKrlcw8vZIjTIo0
class CONTENT_EXPORT PrefetchMatchResolverAction {
 public:
  enum class ActionKind {
    // The `PrefetchContainer` is not available now. Please drop and don't wait.
    kDrop,
    // The `PrefetchContainer` will be loaded. Please wait further events.
    kWait,
    // The `PrefetchContainer` is likely servebale. Please check further
    // conditions e.g. `IsCandidateAvailable()` in prefetch_match_resolver.h,
    // and try to start serving it.
    kMaybeServe,
  };

  // `is_expired` must be non null iff `kind == ActionKind::kMaybeServe`.
  PrefetchMatchResolverAction(ActionKind kind,
                              PrefetchContainerLoadState reason,
                              std::optional<bool> is_expired);
  ~PrefetchMatchResolverAction();

  // Movable but not copyable.
  PrefetchMatchResolverAction(PrefetchMatchResolverAction&& other) = default;
  PrefetchMatchResolverAction& operator=(PrefetchMatchResolverAction&& other) =
      default;
  PrefetchMatchResolverAction(const PrefetchMatchResolverAction&) = delete;
  PrefetchMatchResolverAction& operator=(const PrefetchMatchResolverAction&) =
      delete;

  PrefetchServableState ToServableState() const;

  ActionKind kind() const { return kind_; }
  PrefetchContainerLoadState prefetch_container_load_state() const {
    return prefetch_container_load_state_;
  }
  std::optional<bool> is_expired() const { return is_expired_; }

 private:
  ActionKind kind_;
  PrefetchContainerLoadState prefetch_container_load_state_;
  std::optional<bool> is_expired_;
};

// Encodes servable state and matcher action to int for debug
//
// Cardinality for `base::UmaHistogramSparse()`:
//
// ```
//    cardinality
// <= #PrefetchServableState * #PrefetchMatchResolverAction * 2
// =  3 * 8 * 2
// =  48
// ```
//
// For more details, see the implementation of
// `PrefetchContainer::GetMatchResolverAction()`. (Each `case` has at most two
// possible return values.)
//
// We expect `PrefetchServableState` derived from `PrefetchMatchResolverAction`
// coicides with `GetPrefetchServableState()`, and actual cardinality is at
// most 16.
int GetCodeOfPrefetchServableStateAndPrefetchMatchResolverActionForDebug(
    PrefetchServableState servable_state,
    const PrefetchMatchResolverAction& match_resolver_action);

// Encodes serving result, servable state and matcher action to int for debug.
//
// See the comment of
// `GetCodeOfPrefetchServableStateAndPrefetchMatchResolverActionForDebug()` for
// cardinality.
int GetCodeOfPotentialCandidateServingResultAndServableStateAndMatcherAction(
    content::PrefetchPotentialCandidateServingResult serving_result,
    PrefetchServableState servable_state,
    const PrefetchMatchResolverAction& match_resolver_action);
}  // namespace content

#endif  // CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_SERVABLE_STATE_H_