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_SERVING_HANDLE_H_
#define CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_SERVING_HANDLE_H_

#include "base/memory/weak_ptr.h"
#include "content/browser/preloading/prefetch/prefetch_streaming_url_loader_common_types.h"
#include "content/common/content_export.h"

class GURL;

namespace content {

class PrefetchContainer;
class PrefetchNetworkContext;
class PrefetchResponseReader;
class PrefetchSingleRedirectHop;
class ServiceWorkerClient;
enum class PrefetchProbeResult;
enum class PrefetchServableState;
enum class PrefetchStatus;

// A `PrefetchServingHandle` represents the current state of serving
// for a `PrefetchContainer`. The `PrefetchServingHandle` methods all
// operate on the currently *serving* `PrefetchSingleRedirectHop`,
// which is the element in |PrefetchContainer::redirect_chain()| at index
// |index_redirect_chain_to_serve_|.
//
// This works like `base::WeakPtr<PrefetchContainer>` plus additional states,
// so check that the reader is valid (e.g. `if (reader)`) before calling other
// methods (except for `Clone()`).
class CONTENT_EXPORT PrefetchServingHandle final {
 public:
  PrefetchServingHandle();

  PrefetchServingHandle(base::WeakPtr<PrefetchContainer> prefetch_container,
                        size_t index_redirect_chain_to_serve);

  PrefetchServingHandle(const PrefetchServingHandle&) = delete;
  PrefetchServingHandle& operator=(const PrefetchServingHandle&) = delete;

  PrefetchServingHandle(PrefetchServingHandle&&);
  PrefetchServingHandle& operator=(PrefetchServingHandle&&);

  ~PrefetchServingHandle();

  PrefetchContainer* GetPrefetchContainer() const {
    return prefetch_container_.get();
  }
  PrefetchServingHandle Clone() const;

  // Returns true if `this` is valid.
  // Do not call methods below if false.
  explicit operator bool() const { return GetPrefetchContainer(); }

  // Methods redirecting to `GetPrefetchContainer()`.
  PrefetchServableState GetServableState(
      base::TimeDelta cacheable_duration) const;
  bool HasPrefetchStatus() const;
  PrefetchStatus GetPrefetchStatus() const;

  // Returns whether `this` reached the end. If true, the methods below
  // shouldn't be called, because the current `SingleRedirectHop` doesn't exist.
  bool IsEnd() const;

  // Whether or not an isolated network context is required to serve.
  bool IsIsolatedNetworkContextRequiredToServe() const;

  PrefetchNetworkContext* GetCurrentNetworkContextToServe() const;

  bool HaveDefaultContextCookiesChanged() const;

  // Before a prefetch can be served, any cookies added to the isolated
  // network context must be copied over to the default network context. These
  // functions are used to check and update the status of this process, as
  // well as record metrics about how long this process takes.
  bool HasIsolatedCookieCopyStarted() const;
  bool IsIsolatedCookieCopyInProgress() const;
  void OnIsolatedCookieCopyStart() const;
  void OnIsolatedCookiesReadCompleteAndWriteStart() const;
  void OnIsolatedCookieCopyComplete() const;
  void OnInterceptorCheckCookieCopy() const;
  void SetOnCookieCopyCompleteCallback(base::OnceClosure callback) const;

  // Called with the result of the probe. If the probing feature is enabled,
  // then a probe must complete successfully before the prefetch can be
  // served.
  void OnPrefetchProbeResult(PrefetchProbeResult probe_result) const;

  // Checks if the given URL matches the the URL that can be served next.
  bool DoesCurrentURLToServeMatch(const GURL& url) const;

  // Returns the URL that can be served next.
  const GURL& GetCurrentURLToServe() const;

  // Gets the current PrefetchResponseReader.
  base::WeakPtr<PrefetchResponseReader>
  GetCurrentResponseReaderToServeForTesting();

  // Called when one element of |redirect_chain_| is served and the next
  // element can now be served.
  void AdvanceCurrentURLToServe() { index_redirect_chain_to_serve_++; }

  // See the comment for `PrefetchResponseReader::CreateRequestHandler()`.
  std::pair<PrefetchRequestHandler, base::WeakPtr<ServiceWorkerClient>>
  CreateRequestHandler();

  // See the corresponding functions on `PrefetchResponseReader`.
  // These apply to the current `SingleRedirectHop` (and so, may change as the
  // prefetch advances through a redirect change).
  bool VariesOnCookieIndices() const;
  bool MatchesCookieIndices(
      base::span<const std::pair<std::string, std::string>> cookies) const;

 private:
  const std::vector<std::unique_ptr<PrefetchSingleRedirectHop>>&
  redirect_chain() const;

  // Returns the `SingleRedirectHop` to be served next.
  const PrefetchSingleRedirectHop& GetCurrentSingleRedirectHopToServe() const;

  base::WeakPtr<PrefetchContainer> prefetch_container_;

  // The index of the element in |GetPrefetchContainer()->redirect_chain()| that
  // can be served.
  size_t index_redirect_chain_to_serve_ = 0;
};

}  // namespace content

#endif  // CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_SERVING_HANDLE_H_