blob: d79c67fbbd725580af430039c3bb52a5f4fef210 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANDROID_WEBVIEW_BROWSER_PREFETCH_AW_PREFETCH_MANAGER_DATA_H_
#define ANDROID_WEBVIEW_BROWSER_PREFETCH_AW_PREFETCH_MANAGER_DATA_H_
#include "android_webview/browser/prefetch/aw_prefetch_handle_wrapper.h"
#include "net/http/http_no_vary_search_data.h"
#include "url/gurl.h"
namespace android_webview {
using AwPrefetchKey = int;
// The default TTL value in `//content` is 10 minutes which is too long for most
// of WebView cases. This value here can change in the future and that shouldn't
// affect the `//content` TTL default value.
inline constexpr int kDefaultTtlInSec = 60;
// The MaxPrefetches number is not present in the `//content` layer, so it is
// specific to WebView.
inline constexpr size_t kDefaultMaxPrefetches = 10;
// This is the source of truth for the absolute maximum number of prefetches
// that can ever be cached in WebView. It can override the number set by the
// AndroidX API.
inline constexpr size_t kAbsoluteMaxPrefetches = 20;
// Returned from `AwPrefetchManager::StartPrefetchRequest` if the prefetch
// request was unsuccessful (i.e. there is no key for the prefetch).
inline constexpr AwPrefetchKey NO_PREFETCH_KEY = -1;
// An `AwPrefetchManager`-specific store that manages its mutable state, which
// can be modified by this public methods.
//
// Thread mode:
//
// This class is designed to be thread-safe.
//
// This should be created/owned/destructed by `AwPrefetchManager` on the UI
// thread.
//
// When `kWebViewPrefetchOffTheMainThread` feature is enabled:
// - All public methods acquire `lock_` before accessing member variables.
// And thus public methods shouldn't call other public methods, as annotated
// by LOCKS_EXCLUDED(lock_).
// - Private methods (`*Locked()`) must be called after acquiring `lock_`, as
// annotated by `EXCLUSIVE_LOCKS_REQUIRED(lock_)`.
// - To avoid unexpected reentrancy/deadlocks, any method shouldn't trigger any
// complex logic, external delegates/callbacks etc. `lock_` is not needed to
// be instantiated, and thus ignored by `AutoLockMaybe`.
//
// When `kWebViewPrefetchOffTheMainThread` feature is disabled, this class
// should only be accessed from the UI thread.
class AwPrefetchManagerData {
public:
AwPrefetchManagerData();
~AwPrefetchManagerData();
// Returns true if the prefetch with URL and NVS hint is considered a
// duplicate of existing `all_prefetches_map_`.
// Used only when `kWebViewPrefetchOffTheMainThread` is enabled.
bool IsPrefetchDuplicate(const GURL& url,
const std::optional<net::HttpNoVarySearchData>&
expected_no_vary_search) const
LOCKS_EXCLUDED(lock_);
// Evicts the oldest prefetch from `all_prefetches_map_` to guarantee
// there is space for one new request when `max_prefetches_` is reached.
void MayEvictOldestPrefetchHandleForANewRequest() LOCKS_EXCLUDED(lock_);
// Stores the wrapper and returns its tracking key.
//
// Currently callers are expected to ensure there is available capacity and
// no deduplication before insertion, by calling
// `MayEvictOldestPrefetchHandleForANewRequest()` and `IsPrefetchDuplicate()`.
// For the latter, see `MayEvictOldestPrefetchHandleForANewRequest()`'s inner
// comment for more context.
// TODO(crbug.com/452406598): This procedure causes a potential race condition
// if enabled, since the look up and update for `all_prefetches_map_` is not
// an atomic operation. See crrev.com/c/7666497/comment/074daee9_6ca0a982/ for
// more details.
AwPrefetchKey AddNewPrefetchHandleWrapper(
std::unique_ptr<AwPrefetchHandleWrapper> prefetch_handle_wrapper)
LOCKS_EXCLUDED(lock_);
void CancelPrefetch(AwPrefetchKey prefetch_key) LOCKS_EXCLUDED(lock_);
size_t GetMaxPrefetches() const LOCKS_EXCLUDED(lock_);
void SetTtlInSec(int ttl_in_sec) LOCKS_EXCLUDED(lock_);
int GetTtlInSec() const LOCKS_EXCLUDED(lock_);
void SetMaxPrefetches(size_t max_prefetches) LOCKS_EXCLUDED(lock_);
// Testing utilities.
std::vector<AwPrefetchKey> GetAllPrefetchKeysForTesting() const
LOCKS_EXCLUDED(lock_);
AwPrefetchKey GetLastPrefetchKeyForTesting() const LOCKS_EXCLUDED(lock_);
bool GetIsPrefetchInCacheForTesting(AwPrefetchKey prefetch_key) const
LOCKS_EXCLUDED(lock_);
private:
// Utility functions that assume the lock is already held.
AwPrefetchKey GetNextPrefetchKeyLocked() const
EXCLUSIVE_LOCKS_REQUIRED(lock_);
void UpdateLastPrefetchKeyLocked(AwPrefetchKey new_key)
EXCLUSIVE_LOCKS_REQUIRED(lock_);
// Guards the below non-const members. Allocated only when the
// `WebViewPrefetchOffTheMainThread` feature is enabled. Should be used with
// `base::AutoLockMaybe` to avoid lock overhead when the feature is
// disabled.
const std::unique_ptr<base::Lock> lock_;
int ttl_in_sec_ GUARDED_BY(lock_) = kDefaultTtlInSec;
size_t max_prefetches_ GUARDED_BY(lock_) = kDefaultMaxPrefetches;
std::map<AwPrefetchKey, std::unique_ptr<AwPrefetchHandleWrapper>>
all_prefetches_map_ GUARDED_BY(lock_);
// Should only be incremented. Acts as an "order added" mechanism
// inside of `all_prefetches_map_` since `std::map` stores keys
// in a sorted order.
AwPrefetchKey last_prefetch_key_ GUARDED_BY(lock_) = -1;
};
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_PREFETCH_AW_PREFETCH_MANAGER_DATA_H_