blob: 7182f5fc2e0d2dc836eb57c64686371587aa3d3a [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PREDICTORS_PREFETCH_MANAGER_H_
#define CHROME_BROWSER_PREDICTORS_PREFETCH_MANAGER_H_
#include <list>
#include <map>
#include <memory>
#include <optional>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/predictors/resource_prefetch_predictor.h"
#include "net/base/network_anonymization_key.h"
#include "services/network/public/mojom/fetch_api.mojom-forward.h"
#include "services/network/public/mojom/url_loader.mojom-forward.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-forward.h"
#include "url/gurl.h"
class Profile;
namespace blink {
class ThrottlingURLLoader;
}
namespace network {
namespace mojom {
class URLLoaderClient;
}
class SharedURLLoaderFactory;
struct URLLoaderCompletionStatus;
}
namespace predictors {
struct PrefetchRequest;
struct PrefetchInfo;
struct PrefetchJob;
inline constexpr size_t kMaxInflightPrefetches = 3;
struct PrefetchStats {
explicit PrefetchStats(const GURL& url);
~PrefetchStats();
PrefetchStats(const PrefetchStats&) = delete;
PrefetchStats& operator=(const PrefetchStats&) = delete;
GURL url;
base::TimeTicks start_time;
// TODO(falken): Add stats about what was requested to measure
// the accuracy.
};
// PrefetchManager prefetches input lists of URLs.
// - The input list of URLs is associated with a main frame url that can be
// used for cancelling.
// - Limits the total number of prefetches in flight.
// - All methods of the class must be called on the UI thread.
//
// This class is very similar to PreconnectManager, which does
// preresolve/preconnect instead of prefetching. It is only
// usable when LoadingPredictorPrefetch is enabled.
class PrefetchManager {
public:
// Delegate methods are not called when the
// kPrefetchManagerUseNetworkContextPrefetch feature is enabled, as this class
// does not track progress in that case.
class Delegate {
public:
virtual ~Delegate() = default;
// Called when a prefetch is initiated. |prefetch_url| is the subresource
// being prefetched, and |url| is the main frame of the navigation.
virtual void PrefetchInitiated(const GURL& url,
const GURL& prefetch_url) = 0;
// Called when all prefetch jobs for the |stats->url| are finished.
// Called on the UI thread.
virtual void PrefetchFinished(std::unique_ptr<PrefetchStats> stats) = 0;
};
// For testing. Observer methods will not be called when the
// kPrefetchManagerUseNetworkContextPrefetch feature is enabled.
class Observer {
public:
virtual ~Observer() = default;
virtual void OnPrefetchFinished(
const GURL& url,
const GURL& prefetch_url,
const network::URLLoaderCompletionStatus& status) {}
virtual void OnAllPrefetchesFinished(const GURL& url) {}
};
PrefetchManager(base::WeakPtr<Delegate> delegate, Profile* profile);
~PrefetchManager();
PrefetchManager(const PrefetchManager&) = delete;
PrefetchManager& operator=(const PrefetchManager&) = delete;
static bool IsAvailableForPrefetch(
network::mojom::RequestDestination destination);
// Starts prefetch jobs keyed by |url|.
void Start(const GURL& url, std::vector<PrefetchRequest> requests);
// Stops further prefetch jobs keyed by |url|. Queued jobs will never start;
// started jobs will continue to completion.
void Stop(const GURL& url);
base::WeakPtr<PrefetchManager> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
// Called by PrefetchInfo.
void AllPrefetchJobsForUrlFinished(PrefetchInfo& info);
void set_observer_for_testing(Observer* observer) {
observer_for_testing_ = observer;
}
private:
friend class PrefetchManagerTest;
void PrefetchUrl(std::unique_ptr<PrefetchJob> job,
scoped_refptr<network::SharedURLLoaderFactory> factory);
void OnPrefetchFinished(
std::unique_ptr<PrefetchJob> job,
std::unique_ptr<blink::ThrottlingURLLoader> loader,
std::unique_ptr<network::mojom::URLLoaderClient> client,
const network::URLLoaderCompletionStatus& status);
void TryToLaunchPrefetchJobs();
base::WeakPtr<Delegate> delegate_;
const raw_ptr<Profile, DanglingUntriaged> profile_;
// All the jobs that haven't yet started. A job is removed once it starts.
// Inflight jobs destruct once finished.
std::list<std::unique_ptr<PrefetchJob>> queued_jobs_;
std::map<GURL, std::unique_ptr<PrefetchInfo>> prefetch_info_;
// The total number of prefetches that have started and not yet finished,
// across all main frame URLs.
size_t inflight_jobs_count_ = 0;
raw_ptr<Observer, DanglingUntriaged> observer_for_testing_ = nullptr;
// True if the feature "PrefetchManagerUseNetworkContextPrefetch" is in use,
// in which case this class just fires off prefetches but does not track their
// completion.
const bool use_network_context_prefetch_;
base::WeakPtrFactory<PrefetchManager> weak_factory_{this};
};
// Returns a relevant ResourceType for the given RequestDestination if it's
// supported by prefetch. Otherwise, returns nullopt.
std::optional<blink::mojom::ResourceType> GetResourceTypeForPrefetch(
network::mojom::RequestDestination destination);
} // namespace predictors
#endif // CHROME_BROWSER_PREDICTORS_PREFETCH_MANAGER_H_