blob: 7219ba7b91f9bf9aa862c174377410a51ae227a3 [file] [log] [blame]
// Copyright 2023 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_MATCH_RESOLVER_H_
#define CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_MATCH_RESOLVER_H_
#include <map>
#include "base/memory/weak_ptr.h"
#include "content/browser/preloading/prefetch/prefetch_container.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/navigation_handle_user_data.h"
namespace content {
class PrefetchContainer;
// TODO(crbug.com/40274818): Problem: how do we inform this class of prefetches
// being started while we are waiting for existing in-progress prefetches ?
// PrefetchService should probably do it.
class CONTENT_EXPORT PrefetchMatchResolver
: public NavigationHandleUserData<PrefetchMatchResolver> {
public:
PrefetchMatchResolver(const PrefetchMatchResolver&) = delete;
PrefetchMatchResolver& operator=(const PrefetchMatchResolver&) = delete;
~PrefetchMatchResolver() override;
base::WeakPtr<PrefetchMatchResolver> GetWeakPtr();
using OnPrefetchToServeReady =
base::OnceCallback<void(PrefetchContainer::Reader prefetch_to_serve)>;
void SetOnPrefetchToServeReadyCallback(
OnPrefetchToServeReady on_prefetch_to_serve_ready);
// A prefetch can be served, so let the browser know that it can use the
// prefetch for the navigation.
void PrefetchServed(PrefetchContainer::Reader reader);
// The prefetch container / prefetch_url cannot be used. If there are no
// more potential prefetches to wait for, let the browser know to fallback
// to normal navigation.
void PrefetchNotUsable(const PrefetchContainer& prefetch_container);
void PrefetchNotUsable(const GURL& prefetch_url);
// A prefetch is not available so let the browser know to fallback to regular
// navigation instead.
void PrefetchNotAvailable();
// If Cookies have changed, then none of the matched prefetches can be served.
// Remove all of the prefetches from `in_progress_prefetch_matches_` and let
// the browser know to fallback to regular navigation instead.
void FallbackToRegularNavigationWhenMatchedPrefetchCookiesChanged(
PrefetchContainer& prefetch_container);
void WaitForPrefetch(PrefetchContainer& prefetch_container);
void EndWaitForPrefetch(const GURL& prefetch_url);
// Check if we are waiting already for the head of this `prefetch_container`.
bool IsWaitingForPrefetch(const PrefetchContainer& prefetch_container) const;
bool IsWaitingForPrefetch(const GURL& prefetch_url) const;
private:
friend NavigationHandleUserData<PrefetchMatchResolver>;
explicit PrefetchMatchResolver(NavigationHandle& navigation_handle);
void MaybeFallbackToRegularNavigationWhenPrefetchNotUsable();
bool IsWaitingOnPrefetchHead() const;
OnPrefetchToServeReady ReleaseOnPrefetchToServeReadyCallback();
// Once the prefetch (if any) that can be used to serve a navigation to
// |url| is identified, this callback is called with that
// prefetch.
OnPrefetchToServeReady on_prefetch_to_serve_ready_callback_;
// Keep track of all prefetches that we are waiting for head on.
std::map<GURL, base::WeakPtr<PrefetchContainer>>
in_progress_prefetch_matches_;
base::WeakPtrFactory<PrefetchMatchResolver> weak_ptr_factory_{this};
// For debug logs.
CONTENT_EXPORT friend std::ostream& operator<<(
std::ostream& ostream,
const PrefetchMatchResolver& prefetch_match_resolver);
friend NavigationHandleUserData;
NAVIGATION_HANDLE_USER_DATA_KEY_DECL();
};
} // namespace content
#endif // CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_MATCH_RESOLVER_H_