|  | // Copyright 2012 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_MANAGER_H_ | 
|  | #define COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_MANAGER_H_ | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <memory> | 
|  | #include <set> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/memory/raw_ptr.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/time/clock.h" | 
|  | #include "base/time/time.h" | 
|  | #include "base/timer/timer.h" | 
|  | #include "base/values.h" | 
|  | #include "components/keyed_service/core/keyed_service.h" | 
|  | #include "components/no_state_prefetch/browser/no_state_prefetch_contents.h" | 
|  | #include "components/no_state_prefetch/browser/no_state_prefetch_manager_delegate.h" | 
|  | #include "components/no_state_prefetch/browser/prerender_config.h" | 
|  | #include "components/no_state_prefetch/browser/prerender_histograms.h" | 
|  | #include "components/no_state_prefetch/common/no_state_prefetch_final_status.h" | 
|  | #include "components/no_state_prefetch/common/prerender_origin.h" | 
|  | #include "content/public/browser/preloading_data.h" | 
|  | #include "content/public/browser/render_process_host_observer.h" | 
|  | #include "third_party/abseil-cpp/absl/types/optional.h" | 
|  | #include "third_party/blink/public/mojom/prerender/prerender.mojom.h" | 
|  | #include "url/gurl.h" | 
|  | #include "url/origin.h" | 
|  |  | 
|  | namespace base { | 
|  | class TickClock; | 
|  | }  // namespace base | 
|  |  | 
|  | namespace chrome_browser_net { | 
|  | enum class NetworkPredictionStatus; | 
|  | } | 
|  |  | 
|  | namespace content { | 
|  | class WebContents; | 
|  | class BrowserContext; | 
|  | }  // namespace content | 
|  |  | 
|  | namespace gfx { | 
|  | class Rect; | 
|  | class Size; | 
|  | }  // namespace gfx | 
|  |  | 
|  | namespace prerender { | 
|  |  | 
|  | namespace test_utils { | 
|  | class PrerenderInProcessBrowserTest; | 
|  | } | 
|  |  | 
|  | class NoStatePrefetchHandle; | 
|  | class PrerenderHistory; | 
|  |  | 
|  | // Observer interface for NoStatePrefetchManager events. | 
|  | class NoStatePrefetchManagerObserver { | 
|  | public: | 
|  | virtual ~NoStatePrefetchManagerObserver(); | 
|  |  | 
|  | // Called from the UI thread. | 
|  | virtual void OnFirstContentfulPaint() = 0; | 
|  | }; | 
|  |  | 
|  | // NoStatePrefetchManager is responsible for initiating and keeping prerendered | 
|  | // views of web pages. All methods must be called on the UI thread unless | 
|  | // indicated otherwise. | 
|  | class NoStatePrefetchManager : public content::RenderProcessHostObserver, | 
|  | public KeyedService { | 
|  | public: | 
|  | // One or more of these flags must be passed to ClearData() to specify just | 
|  | // what data to clear.  See function declaration for more information. | 
|  | enum ClearFlags { | 
|  | CLEAR_PRERENDER_CONTENTS = 0x1 << 0, | 
|  | CLEAR_PRERENDER_HISTORY = 0x1 << 1, | 
|  | CLEAR_MAX = 0x1 << 2 | 
|  | }; | 
|  |  | 
|  | // Owned by a BrowserContext object for the lifetime of the browser_context. | 
|  | NoStatePrefetchManager( | 
|  | content::BrowserContext* browser_context, | 
|  | std::unique_ptr<NoStatePrefetchManagerDelegate> delegate); | 
|  |  | 
|  | NoStatePrefetchManager(const NoStatePrefetchManager&) = delete; | 
|  | NoStatePrefetchManager& operator=(const NoStatePrefetchManager&) = delete; | 
|  |  | 
|  | ~NoStatePrefetchManager() override; | 
|  |  | 
|  | // From KeyedService: | 
|  | void Shutdown() override; | 
|  |  | 
|  | // Entry points for adding prerenders. | 
|  |  | 
|  | // Starts a prefetch for |url| if valid. |process_id| and |route_id| identify | 
|  | // the RenderView that the prefetch request came from. If |size| is empty, a | 
|  | // default from the PrerenderConfig is used. Returns a NoStatePrefetchHandle | 
|  | // if the URL was added, NULL if it was not. If the launching RenderView is | 
|  | // itself prefetching, the prefetch is added as a pending prefetch. | 
|  | std::unique_ptr<NoStatePrefetchHandle> StartPrefetchingFromLinkRelPrerender( | 
|  | int process_id, | 
|  | int route_id, | 
|  | const GURL& url, | 
|  | blink::mojom::PrerenderTriggerType trigger_type, | 
|  | const content::Referrer& referrer, | 
|  | const url::Origin& initiator_origin, | 
|  | const gfx::Size& size); | 
|  |  | 
|  | // Starts a prefetch for |url| if valid. As the prefetch request is coming | 
|  | // from a source without a RenderFrameHost (i.e., the omnibox) we don't have a | 
|  | // child or route id, or a referrer. This method uses sensible values for | 
|  | // those. The |session_storage_namespace| matches the namespace of the active | 
|  | // tab at the time the prefetch is started from the omnibox. Returns a | 
|  | // NoStatePrefetchHandle or NULL. If the prefetch fails, the prefetch manager | 
|  | // may fallback and initiate a preconnect to |url|. PreloadingAttempt | 
|  | // represents the attempt corresponding to this prerender to log the necessary | 
|  | // metrics. | 
|  | std::unique_ptr<NoStatePrefetchHandle> StartPrefetchingFromOmnibox( | 
|  | const GURL& url, | 
|  | content::SessionStorageNamespace* session_storage_namespace, | 
|  | const gfx::Size& size, | 
|  | content::PreloadingAttempt* attempt); | 
|  |  | 
|  | // Adds a prerender for the prefetch url from IsolatedPrerender on | 
|  | // page load, if NoStatePrefetch and prefetch_after_preconnect are true. | 
|  | // Uses the NavigationPredictor's browser context and the default | 
|  | // SessionStorageNamespace. Returns a NoStatePrefetchHandle or nullptr. Does | 
|  | // not fallback to preconnecting if the prerender isn't triggered. | 
|  | std::unique_ptr<NoStatePrefetchHandle> AddIsolatedPrerender( | 
|  | const GURL& url, | 
|  | content::SessionStorageNamespace* session_storage_namespace, | 
|  | const gfx::Size& size); | 
|  |  | 
|  | // Adds a NoStatePrefetch that only allows for same origin requests (i.e., | 
|  | // requests that only redirect to the same origin). | 
|  | std::unique_ptr<NoStatePrefetchHandle> AddSameOriginSpeculation( | 
|  | const GURL& url, | 
|  | content::SessionStorageNamespace* session_storage_namespace, | 
|  | const gfx::Size& size, | 
|  | const url::Origin& initiator_origin); | 
|  |  | 
|  | std::unique_ptr<NoStatePrefetchHandle> StartPrefetchingFromExternalRequest( | 
|  | const GURL& url, | 
|  | const content::Referrer& referrer, | 
|  | content::SessionStorageNamespace* session_storage_namespace, | 
|  | const gfx::Rect& bounds); | 
|  |  | 
|  | // Adds a prerender from an external request that will prerender even on | 
|  | // cellular networks as long as the user setting for prerendering is ON. | 
|  | std::unique_ptr<NoStatePrefetchHandle> AddForcedPrerenderFromExternalRequest( | 
|  | const GURL& url, | 
|  | const content::Referrer& referrer, | 
|  | content::SessionStorageNamespace* session_storage_namespace, | 
|  | const gfx::Rect& bounds); | 
|  |  | 
|  | // Cancels all active prerenders. | 
|  | void CancelAllPrerenders(); | 
|  |  | 
|  | // Destroys all pending prerenders using FinalStatus.  Also deletes them as | 
|  | // well as any swapped out WebContents queued for destruction. | 
|  | // Used both on destruction, and when clearing the browsing history. | 
|  | void DestroyAllContents(FinalStatus final_status); | 
|  |  | 
|  | // Moves a NoStatePrefetchContents to the pending delete list from the list of | 
|  | // active prerenders when prerendering should be cancelled. | 
|  | virtual void MoveEntryToPendingDelete(NoStatePrefetchContents* entry, | 
|  | FinalStatus final_status); | 
|  |  | 
|  | // Query the list of current prefetches to see if the given web contents is | 
|  | // prefetching a page. | 
|  | bool IsWebContentsPrefetching(const content::WebContents* web_contents) const; | 
|  |  | 
|  | // Returns the NoStatePrefetchContents object for the given web_contents, | 
|  | // otherwise returns NULL. Note that the NoStatePrefetchContents may have been | 
|  | // Destroy()ed, but not yet deleted. | 
|  | NoStatePrefetchContents* GetNoStatePrefetchContents( | 
|  | const content::WebContents* web_contents) const; | 
|  |  | 
|  | // Returns the NoStatePrefetchContents object for a given child_id, route_id | 
|  | // pair, otherwise returns NULL. Note that the NoStatePrefetchContents may | 
|  | // have been Destroy()ed, but not yet deleted. | 
|  | virtual NoStatePrefetchContents* GetNoStatePrefetchContentsForRoute( | 
|  | int child_id, | 
|  | int route_id) const; | 
|  |  | 
|  | // Returns a list of all WebContents being NoStatePrefetched. | 
|  | std::vector<content::WebContents*> | 
|  | GetAllNoStatePrefetchingContentsForTesting() const; | 
|  |  | 
|  | // Checks whether |url| has been recently navigated to. | 
|  | bool HasRecentlyBeenNavigatedTo(Origin origin, const GURL& url); | 
|  |  | 
|  | // Returns a `base::Value::Dict` object containing the active pages being | 
|  | // prerendered, and a history of pages which were prerendered. | 
|  | base::Value::Dict CopyAsDict() const; | 
|  |  | 
|  | // Clears the data indicated by which bits of clear_flags are set. | 
|  | // | 
|  | // If the CLEAR_PRERENDER_CONTENTS bit is set, all active prerenders are | 
|  | // cancelled and then deleted, and any WebContents queued for destruction are | 
|  | // destroyed as well. | 
|  | // | 
|  | // If the CLEAR_PRERENDER_HISTORY bit is set, the prerender history is | 
|  | // cleared, including any entries newly created by destroying them in | 
|  | // response to the CLEAR_PRERENDER_CONTENTS flag. | 
|  | // | 
|  | // Intended to be used when clearing the cache or history. | 
|  | void ClearData(int clear_flags); | 
|  |  | 
|  | // Record a final status of a prerendered page in a histogram. | 
|  | void RecordFinalStatus(Origin origin, FinalStatus final_status) const; | 
|  |  | 
|  | const Config& config() const { return config_; } | 
|  | Config& mutable_config() { return config_; } | 
|  |  | 
|  | // Records that some visible tab navigated (or was redirected) to the | 
|  | // provided URL. | 
|  | void RecordNavigation(const GURL& url); | 
|  |  | 
|  | // Return current time and ticks with ability to mock the clock out for | 
|  | // testing. | 
|  | base::Time GetCurrentTime() const; | 
|  | base::TimeTicks GetCurrentTimeTicks() const; | 
|  | void SetTickClockForTesting(const base::TickClock* tick_clock); | 
|  |  | 
|  | void AddObserver(std::unique_ptr<NoStatePrefetchManagerObserver> observer); | 
|  |  | 
|  | // Notification that a prerender has completed and its bytes should be | 
|  | // recorded. | 
|  | void RecordNetworkBytesConsumed(Origin origin, int64_t prerender_bytes); | 
|  |  | 
|  | // Registers a new ProcessHost performing a prerender. Called by | 
|  | // NoStatePrefetchContents. | 
|  | void AddPrerenderProcessHost(content::RenderProcessHost* process_host); | 
|  |  | 
|  | // Returns whether or not |process_host| may be reused for new navigations | 
|  | // from a prerendering perspective. Currently, if Prerender Cookie Stores are | 
|  | // enabled, prerenders must be in their own processes that may not be shared. | 
|  | bool MayReuseProcessHost(content::RenderProcessHost* process_host); | 
|  |  | 
|  | // content::RenderProcessHostObserver implementation. | 
|  | void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; | 
|  |  | 
|  | // Cleans up the expired prefetches and then returns true if |url| was | 
|  | // no-state prefetched recently. If so, |prefetch_age|, |final_status| and | 
|  | // |origin| are set based on the no-state prefetch information if they are | 
|  | // non-null. | 
|  | bool GetPrefetchInformation(const GURL& url, | 
|  | base::TimeDelta* prefetch_age, | 
|  | FinalStatus* final_status, | 
|  | Origin* origin); | 
|  |  | 
|  | void SetNoStatePrefetchContentsFactoryForTest( | 
|  | NoStatePrefetchContents::Factory* no_state_prefetch_contents_factory); | 
|  |  | 
|  | base::WeakPtr<NoStatePrefetchManager> AsWeakPtr(); | 
|  |  | 
|  | // Clears the list of recently prefetched URLs. Allows, for example, to reuse | 
|  | // the same URL in tests, without running into FINAL_STATUS_DUPLICATE. | 
|  | void ClearPrefetchInformationForTesting(); | 
|  |  | 
|  | // Returns true iff the |url| is found in the list of recent prefetches. | 
|  | bool HasRecentlyPrefetchedUrlForTesting(const GURL& url); | 
|  |  | 
|  | // Starts a prefetch for |url| from |initiator_origin|. The |origin| specifies | 
|  | // how the prefetch was started. Returns a NoStatePrefetchHandle or nullptr. | 
|  | // Only for testing. | 
|  | std::unique_ptr<NoStatePrefetchHandle> | 
|  | StartPrefetchingWithPreconnectFallbackForTesting( | 
|  | Origin origin, | 
|  | const GURL& url, | 
|  | const absl::optional<url::Origin>& initiator_origin); | 
|  |  | 
|  | protected: | 
|  | class NoStatePrefetchData | 
|  | : public base::SupportsWeakPtr<NoStatePrefetchData> { | 
|  | public: | 
|  | struct OrderByExpiryTime; | 
|  |  | 
|  | NoStatePrefetchData(NoStatePrefetchManager* manager, | 
|  | std::unique_ptr<NoStatePrefetchContents> contents, | 
|  | base::TimeTicks expiry_time); | 
|  |  | 
|  | NoStatePrefetchData(const NoStatePrefetchData&) = delete; | 
|  | NoStatePrefetchData& operator=(const NoStatePrefetchData&) = delete; | 
|  |  | 
|  | ~NoStatePrefetchData(); | 
|  |  | 
|  | // A new NoStatePrefetchHandle has been created for this | 
|  | // NoStatePrefetchData. | 
|  | void OnHandleCreated(NoStatePrefetchHandle* handle); | 
|  |  | 
|  | // The launcher associated with a handle is navigating away from the context | 
|  | // that launched this prefetch. If the prerender is active, it may stay | 
|  | // alive briefly though, in case we we going through a redirect chain that | 
|  | // will eventually land at it. | 
|  | void OnHandleNavigatedAway(NoStatePrefetchHandle* handle); | 
|  |  | 
|  | // The launcher associated with a handle has taken explicit action to cancel | 
|  | // this prefetch. We may well destroy the prerender in this case if no other | 
|  | // handles continue to track it. | 
|  | void OnHandleCanceled(NoStatePrefetchHandle* handle); | 
|  |  | 
|  | NoStatePrefetchContents* contents() { return contents_.get(); } | 
|  |  | 
|  | std::unique_ptr<NoStatePrefetchContents> ReleaseContents(); | 
|  |  | 
|  | int handle_count() const { return handle_count_; } | 
|  |  | 
|  | base::TimeTicks abandon_time() const { return abandon_time_; } | 
|  |  | 
|  | base::TimeTicks expiry_time() const { return expiry_time_; } | 
|  | void set_expiry_time(base::TimeTicks expiry_time) { | 
|  | expiry_time_ = expiry_time; | 
|  | } | 
|  |  | 
|  | private: | 
|  | const raw_ptr<NoStatePrefetchManager> manager_; | 
|  | std::unique_ptr<NoStatePrefetchContents> contents_; | 
|  |  | 
|  | // The number of distinct NoStatePrefetchHandles created for |this|, | 
|  | // including ones that have called | 
|  | // NoStatePrefetchData::OnHandleNavigatedAway(), but not counting the ones | 
|  | // that have called NoStatePrefetchData::OnHandleCanceled(). For pending | 
|  | // prefetches, this will always be 1, since the NoStatePrefetchManager only | 
|  | // merges handles of running prefetches. | 
|  | int handle_count_ = 0; | 
|  |  | 
|  | // The time when OnHandleNavigatedAway was called. | 
|  | base::TimeTicks abandon_time_; | 
|  |  | 
|  | // After this time, this prefetch is no longer fresh, and should be removed. | 
|  | base::TimeTicks expiry_time_; | 
|  | }; | 
|  |  | 
|  | // Called by a NoStatePrefetchData to signal that the launcher has navigated | 
|  | // away from the context that launched the prefetch. A user may have clicked | 
|  | // a link in a page containing a <link rel=prerender> element, or the user | 
|  | // might have committed an omnibox navigation. This is used to possibly | 
|  | // shorten the TTL of the page for NoStatePrefetch. | 
|  | void SourceNavigatedAway(NoStatePrefetchData* prefetch_data); | 
|  |  | 
|  | // Same as base::SysInfo::IsLowEndDevice(), overridden in tests. | 
|  | virtual bool IsLowEndDevice() const; | 
|  |  | 
|  | // Whether network prediction is enabled for prefetch origin, |origin|. | 
|  | bool IsPredictionEnabled(Origin origin); | 
|  |  | 
|  | private: | 
|  | friend class test_utils::PrerenderInProcessBrowserTest; | 
|  | friend class NoStatePrefetchContents; | 
|  | friend class NoStatePrefetchHandle; | 
|  | friend class UnitTestNoStatePrefetchManager; | 
|  |  | 
|  | class OnCloseWebContentsDeleter; | 
|  | struct NavigationRecord; | 
|  | using NoStatePrefetchDataVector = | 
|  | std::vector<std::unique_ptr<NoStatePrefetchData>>; | 
|  |  | 
|  | // Time interval before a new prefetch is allowed. | 
|  | static const int kMinTimeBetweenPrefetchesMs = 500; | 
|  |  | 
|  | // Time window for which we record old navigations, in milliseconds. | 
|  | static const int kNavigationRecordWindowMs = 5000; | 
|  |  | 
|  | // Starts a prefetch for |url| from |referrer|. The |origin| specifies how the | 
|  | // prefetch was started. If |bounds| is empty, then | 
|  | // NoStatePrefetchContents::StartPrerendering will instead use a default from | 
|  | // PrerenderConfig. Returns a NoStatePrefetchHandle or NULL. | 
|  | // PreloadingAttempt helps us to log various metrics associated with | 
|  | // particular NoStatePrefetch attempt. | 
|  | // TODO(crbug.com/1363358): Remove nullptr as default parameter once NSP is | 
|  | // integrated with all different predictors. | 
|  | std::unique_ptr<NoStatePrefetchHandle> StartPrefetchingWithPreconnectFallback( | 
|  | Origin origin, | 
|  | const GURL& url, | 
|  | const content::Referrer& referrer, | 
|  | const absl::optional<url::Origin>& initiator_origin, | 
|  | const gfx::Rect& bounds, | 
|  | content::SessionStorageNamespace* session_storage_namespace, | 
|  | base::WeakPtr<content::PreloadingAttempt> attempt = nullptr); | 
|  |  | 
|  | void StartSchedulingPeriodicCleanups(); | 
|  | void StopSchedulingPeriodicCleanups(); | 
|  |  | 
|  | // Deletes stale and cancelled prerendered NoStatePrefetchContents, as well as | 
|  | // WebContents that have been replaced by prerendered WebContents. | 
|  | // Also identifies and kills NoStatePrefetchContents that use too much | 
|  | // resources. | 
|  | void PeriodicCleanup(); | 
|  |  | 
|  | // Posts a task to call PeriodicCleanup.  Results in quicker destruction of | 
|  | // objects.  If |this| is deleted before the task is run, the task will | 
|  | // automatically be cancelled. | 
|  | void PostCleanupTask(); | 
|  |  | 
|  | base::TimeTicks GetExpiryTimeForNewPrerender(Origin origin) const; | 
|  | base::TimeTicks GetExpiryTimeForNavigatedAwayPrerender() const; | 
|  |  | 
|  | void DeleteOldEntries(); | 
|  |  | 
|  | void DeleteToDeletePrerenders(); | 
|  |  | 
|  | // Virtual so unit tests can override this. | 
|  | virtual std::unique_ptr<NoStatePrefetchContents> | 
|  | CreateNoStatePrefetchContents( | 
|  | const GURL& url, | 
|  | const content::Referrer& referrer, | 
|  | const absl::optional<url::Origin>& initiator_origin, | 
|  | Origin origin); | 
|  |  | 
|  | // Insures the |active_prefetches_| are sorted by increasing expiry time. Call | 
|  | // after every mutation of |active_prefetches_| that can possibly make it | 
|  | // unsorted (e.g. an insert, or changing an expiry time). | 
|  | void SortActivePrefetches(); | 
|  |  | 
|  | // Finds the active NoStatePrefetchData object for a running prefetch matching | 
|  | // |url| and |session_storage_namespace|. | 
|  | NoStatePrefetchData* FindNoStatePrefetchData( | 
|  | const GURL& url, | 
|  | content::SessionStorageNamespace* session_storage_namespace); | 
|  |  | 
|  | // Given the |no_state_prefetch_contents|, find the iterator in | 
|  | // |active_prefetches_| corresponding to the given prefetch. | 
|  | NoStatePrefetchDataVector::iterator FindIteratorForNoStatePrefetchContents( | 
|  | NoStatePrefetchContents* no_state_prefetch_contents); | 
|  |  | 
|  | bool DoesRateLimitAllowPrefetch(Origin origin) const; | 
|  |  | 
|  | // Deletes old WebContents that have been replaced by prerendered ones.  This | 
|  | // is needed because they're replaced in a callback from the old WebContents, | 
|  | // so cannot immediately be deleted. | 
|  | void DeleteOldWebContents(); | 
|  |  | 
|  | // Called when NoStatePrefetchContents gets destroyed. Attaches the | 
|  | // |final_status| to the most recent prefetch matching the |url|. | 
|  | void SetPrefetchFinalStatusForUrl(const GURL& url, FinalStatus final_status); | 
|  |  | 
|  | // Called when a prefetch has been used. Prefetches avoid cache revalidation | 
|  | // only once. | 
|  | void OnPrefetchUsed(const GURL& url); | 
|  |  | 
|  | // Cleans up old NavigationRecord's. | 
|  | void CleanUpOldNavigations(std::vector<NavigationRecord>* navigations, | 
|  | base::TimeDelta max_age); | 
|  |  | 
|  | // Arrange for the given WebContents to be deleted asap. Delete |deleter| as | 
|  | // well. | 
|  | void ScheduleDeleteOldWebContents(std::unique_ptr<content::WebContents> tab, | 
|  | OnCloseWebContentsDeleter* deleter); | 
|  |  | 
|  | // Adds to the history list. | 
|  | void AddToHistory(NoStatePrefetchContents* contents); | 
|  |  | 
|  | // Returns a new `base::Value::List` representing the pages currently being | 
|  | // prerendered. | 
|  | base::Value::List GetActivePrerenders() const; | 
|  |  | 
|  | // Records the final status a prerender in the case that a | 
|  | // NoStatePrefetchContents was never created, adds a PrerenderHistory entry, | 
|  | // and may also initiate a preconnect to |url|. | 
|  | void SkipNoStatePrefetchContentsAndMaybePreconnect( | 
|  | const GURL& url, | 
|  | Origin origin, | 
|  | FinalStatus final_status) const; | 
|  |  | 
|  | // May initiate a preconnect to |url_arg| based on |origin|. | 
|  | void MaybePreconnect(Origin origin, const GURL& url_arg) const; | 
|  |  | 
|  | // The configuration. | 
|  | Config config_; | 
|  |  | 
|  | // The browser_context that owns this NoStatePrefetchManager. | 
|  | raw_ptr<content::BrowserContext> browser_context_; | 
|  |  | 
|  | // The delegate that allows content embedder to override the logic in this | 
|  | // class. | 
|  | std::unique_ptr<NoStatePrefetchManagerDelegate> delegate_; | 
|  |  | 
|  | // All running prefetches. Sorted by expiry time, in ascending order. | 
|  | NoStatePrefetchDataVector active_prefetches_; | 
|  |  | 
|  | // Prefetches awaiting deletion. | 
|  | NoStatePrefetchDataVector to_delete_prefetches_; | 
|  |  | 
|  | // List of recent navigations in this browser_context, sorted by ascending | 
|  | // |navigate_time_|. | 
|  | std::vector<NavigationRecord> navigations_; | 
|  |  | 
|  | // List of recent prefetches, sorted by ascending navigate time. | 
|  | std::vector<NavigationRecord> prefetches_; | 
|  |  | 
|  | std::unique_ptr<NoStatePrefetchContents::Factory> | 
|  | no_state_prefetch_contents_factory_; | 
|  |  | 
|  | // RepeatingTimer to perform periodic cleanups of pending prerendered | 
|  | // pages. | 
|  | base::RepeatingTimer repeating_timer_; | 
|  |  | 
|  | // Track time of last prefetch to limit prefetch spam. | 
|  | base::TimeTicks last_prefetch_start_time_; | 
|  |  | 
|  | std::vector<std::unique_ptr<content::WebContents>> old_web_contents_list_; | 
|  |  | 
|  | std::vector<std::unique_ptr<OnCloseWebContentsDeleter>> | 
|  | on_close_web_contents_deleters_; | 
|  |  | 
|  | const std::unique_ptr<PrerenderHistory> prerender_history_; | 
|  |  | 
|  | const std::unique_ptr<PrerenderHistograms> histograms_; | 
|  |  | 
|  | // The number of bytes transferred over the network for the browser_context | 
|  | // this NoStatePrefetchManager is attached to. | 
|  | int64_t browser_context_network_bytes_ = 0; | 
|  |  | 
|  | // The value of browser_context_network_bytes_ that was last recorded. | 
|  | int64_t last_recorded_browser_context_network_bytes_ = 0; | 
|  |  | 
|  | // Set of process hosts being prerendered. | 
|  | using PrerenderProcessSet = std::set<content::RenderProcessHost*>; | 
|  | PrerenderProcessSet prerender_process_hosts_; | 
|  |  | 
|  | raw_ptr<const base::TickClock> tick_clock_; | 
|  |  | 
|  | std::vector<std::unique_ptr<NoStatePrefetchManagerObserver>> observers_; | 
|  |  | 
|  | base::WeakPtrFactory<NoStatePrefetchManager> weak_factory_{this}; | 
|  | }; | 
|  |  | 
|  | }  // namespace prerender | 
|  |  | 
|  | #endif  // COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_MANAGER_H_ |