#ifndef ANDROID_WEBVIEW_BROWSER_PREFETCH_AW_PREFETCH_MANAGER_H_
#define ANDROID_WEBVIEW_BROWSER_PREFETCH_AW_PREFETCH_MANAGER_H_
#include "base/containers/circular_deque.h"
#include "base/memory/raw_ref.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/prefetch_handle.h"
#include "content/public/browser/prefetch_request_status_listener.h"
#include "net/http/http_no_vary_search_data.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/cpp/resource_request.h"
#include "url/gurl.h"
namespace android_webview {
inline constexpr int DEFAULT_TTL_IN_SEC = 60;
inline constexpr size_t DEFAULT_MAX_PREFETCHES = 10;
inline constexpr int32_t ABSOLUTE_MAX_PREFETCHES = 20;
inline constexpr int NO_PREFETCH_KEY = -1;
inline constexpr char AW_PREFETCH_METRICS_SUFFIX[] = "WebView";
class AwPrefetchManager {
public:
explicit AwPrefetchManager(content::BrowserContext* browser_context);
AwPrefetchManager(const AwPrefetchManager&) = delete;
AwPrefetchManager& operator=(const AwPrefetchManager&) = delete;
~AwPrefetchManager();
static bool IsPrefetchRequest(
const network::ResourceRequest& resource_request);
static bool IsPrerenderRequest(
const network::ResourceRequest& resource_request);
static bool IsSecPurposeForPrefetch(
std::optional<std::string> sec_purpose_header_value);
int StartPrefetchRequest(
JNIEnv* env,
const std::string& url,
const base::android::JavaParamRef<jobject>& prefetch_params,
const base::android::JavaParamRef<jobject>& callback,
const base::android::JavaParamRef<jobject>& callback_executor);
void CancelPrefetch(JNIEnv* env, jint prefetch_key);
bool GetIsPrefetchInCacheForTesting(JNIEnv* env, jint prefetch_key);
void SetTtlInSec(JNIEnv* env, jint ttl_in_sec) { ttl_in_sec_ = ttl_in_sec; }
void SetMaxPrefetches(JNIEnv* env, jint max_prefetches) {
max_prefetches_ = std::min(max_prefetches, ABSOLUTE_MAX_PREFETCHES);
}
jint GetTtlInSec(JNIEnv* env) const { return ttl_in_sec_; }
jint GetMaxPrefetches(JNIEnv* env) const { return max_prefetches_; }
int AddPrefetchHandle(
std::unique_ptr<content::PrefetchHandle> prefetch_handle) {
CHECK(prefetch_handle);
CHECK(max_prefetches_ > 0u);
CHECK(all_prefetches_map_.size() < max_prefetches_);
const int32_t new_prefetch_key = GetNextPrefetchKey();
all_prefetches_map_[new_prefetch_key] = std::move(prefetch_handle);
UpdateLastPrefetchKey(new_prefetch_key);
return new_prefetch_key;
}
std::vector<int32_t> GetAllPrefetchKeysForTesting() const {
std::vector<int32_t> prefetch_keys;
prefetch_keys.reserve(all_prefetches_map_.size());
for (const auto& prefetch_pair : all_prefetches_map_) {
prefetch_keys.push_back(prefetch_pair.first);
}
return prefetch_keys;
}
int GetLastPrefetchKeyForTesting() const { return last_prefetch_key_; }
base::android::ScopedJavaLocalRef<jobject> GetJavaPrefetchManager();
private:
raw_ref<content::BrowserContext> browser_context_;
int ttl_in_sec_ = DEFAULT_TTL_IN_SEC;
size_t max_prefetches_ = DEFAULT_MAX_PREFETCHES;
std::map<int32_t, std::unique_ptr<content::PrefetchHandle>>
all_prefetches_map_;
base::android::ScopedJavaGlobalRef<jobject> java_obj_;
int32_t last_prefetch_key_ = -1;
int32_t GetNextPrefetchKey() const { return last_prefetch_key_ + 1; }
void UpdateLastPrefetchKey(int new_key) {
CHECK(new_key > last_prefetch_key_);
last_prefetch_key_ = new_key;
}
};
}
#endif