1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
// Copyright 2022 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_DOCUMENT_MANAGER_H_
#define CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_DOCUMENT_MANAGER_H_
#include <map>
#include <memory>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/preloading/prefetch/prefetch_type.h"
#include "content/browser/preloading/speculation_rules/speculation_rules_tags.h"
#include "content/common/content_export.h"
#include "content/common/features.h"
#include "content/public/browser/document_user_data.h"
#include "content/public/browser/prefetch_metrics.h"
#include "content/public/browser/preload_pipeline_info.h"
#include "content/public/browser/preloading.h"
#include "content/public/browser/web_contents_observer.h"
#include "net/http/http_no_vary_search_data.h"
#include "third_party/blink/public/mojom/speculation_rules/speculation_rules.mojom.h"
#include "url/gurl.h"
namespace content {
class PrefetchContainer;
class PrefetchHandle;
class PrefetchService;
class PreloadingPredictor;
// Manages the state of and tracks metrics about prefetches for a single page
// load.
class CONTENT_EXPORT PrefetchDocumentManager
: public DocumentUserData<PrefetchDocumentManager> {
public:
using PrefetchDestructionCallback =
base::RepeatingCallback<void(const GURL&)>;
~PrefetchDocumentManager() override;
PrefetchDocumentManager(const PrefetchDocumentManager&) = delete;
const PrefetchDocumentManager operator=(const PrefetchDocumentManager&) =
delete;
// Returns the `PrefetchDocumentManager` associated with a Document if already
// exists, or `nullptr` otherwise.
static PrefetchDocumentManager* FromDocumentToken(
int process_id,
const blink::DocumentToken& document_token);
// Processes the given speculation candidates to see if they can be
// prefetched. Any candidates that can be prefetched are removed from
// |candidates|, and a prefetch for the URL of the candidate is started.
void ProcessCandidates(
std::vector<blink::mojom::SpeculationCandidatePtr>& candidates);
// Attempts to prefetch the given candidate. Returns true if a new prefetch
// for the candidate's URL is started.
bool MaybePrefetch(blink::mojom::SpeculationCandidatePtr candidate,
const PreloadingPredictor& enacting_predictor);
void PrefetchAheadOfPrerender(
scoped_refptr<PreloadPipelineInfo> preload_pipeline_info,
blink::mojom::SpeculationCandidatePtr candidate,
const PreloadingPredictor& enacting_predictor);
// Starts the process to prefetch |url| with the given |prefetch_type|.
void PrefetchUrl(const GURL& url,
const PrefetchType& prefetch_type,
const PreloadingPredictor& enacting_predictor,
const blink::mojom::Referrer& referrer,
std::optional<SpeculationRulesTags> speculation_rules_tags,
const network::mojom::NoVarySearchPtr& no_vary_search_hint,
scoped_refptr<PreloadPipelineInfo> preload_pipeline_info);
// Checking the canary cache can be a slow and blocking operation (see
// crbug.com/1266018), so we only do this for the first non-decoy prefetch we
// make on the page.
bool HaveCanaryChecksStarted() const { return have_canary_checks_started_; }
void OnCanaryChecksStarted() { have_canary_checks_started_ = true; }
// Returns metrics for prefetches requested by the associated page load.
PrefetchReferringPageMetrics& GetReferringPageMetrics() {
return referring_page_metrics_;
}
// Updates metrics when the eligibility check for a prefetch requested by this
// page load is completed.
void OnEligibilityCheckComplete(bool is_eligible);
// Updates metrics when the response for a prefetch requested by this page
// load is received.
void OnPrefetchSuccessful(PrefetchContainer* prefetch);
// Whether the prefetch attempt for target |url| failed or discarded
bool IsPrefetchAttemptFailedOrDiscarded(const GURL& url);
// Returns a tuple: (can_prefetch_now, prefetch_to_evict). 'can_prefetch_now'
// is true if we can prefetch |next_prefetch| based on the state of the
// document, and the number of existing completed prefetches. The eagerness of
// |next_prefetch| is taken into account when making the decision.
// 'prefetch_to_evict' is set to an existing prefetch if one needs to be
// evicted to make space for the prefetch of |next_prefetch|, or nullptr
// otherwise. 'prefetch_to_evict' will only be non-null if 'can_prefetch_now'
// is true.
std::tuple<bool, base::WeakPtr<PrefetchContainer>> CanPrefetchNow(
PrefetchContainer* next_prefetch);
// See documentation for |prefetch_destruction_callback_|.
void SetPrefetchDestructionCallback(PrefetchDestructionCallback callback);
// Called when a PrefetchContainer started by |this| is being destroyed.
void PrefetchWillBeDestroyed(PrefetchContainer* prefetch);
base::WeakPtr<PrefetchDocumentManager> GetWeakPtr() {
return weak_method_factory_.GetWeakPtr();
}
static void SetPrefetchServiceForTesting(PrefetchService* prefetch_service);
void ResetPrefetchAheadOfPrerenderIfExist(const GURL& url);
private:
explicit PrefetchDocumentManager(RenderFrameHost* rfh);
friend DocumentUserData;
// Helper function to get the |PrefetchService| associated with |this|.
PrefetchService* GetPrefetchService() const;
bool IsPrefetchAttemptFailedOrDiscardedInternal(
const GURL& url,
PreloadingType planned_max_preloading_type);
blink::DocumentToken document_token_;
// This map holds references to all |PrefetchContainer| associated with
// |this|.
//
// Keyed with `(url, planned_max_preloading_type)`.
// `planned_max_preloading_type == kPrerender` indicates it's ahead of
// prerender.
//
// We allow normal prefetch and prefetch ahead of prerender with the same key
// here, to handle and merge them in `PrefetchService`.
std::map<std::pair<GURL, PreloadingType>, std::unique_ptr<PrefetchHandle>>
all_prefetches_;
// Stores whether or not canary checks have been started for this page.
bool have_canary_checks_started_{false};
// A list of eager prefetch requests (from this page) that have completed
// (oldest to newest).
std::vector<base::WeakPtr<PrefetchContainer>> completed_eager_prefetches_;
// A list of non-eager prefetch requests (from this page) that have completed
// (oldest to newest).
std::vector<base::WeakPtr<PrefetchContainer>> completed_non_eager_prefetches_;
// Metrics related to the prefetches requested by this page load.
PrefetchReferringPageMetrics referring_page_metrics_;
// Callback that is run when a prefetch started by |this| is being destroyed.
PrefetchDestructionCallback prefetch_destruction_callback_;
base::WeakPtrFactory<PrefetchDocumentManager> weak_method_factory_{this};
DOCUMENT_USER_DATA_KEY_DECL();
};
} // namespace content
#endif // CONTENT_BROWSER_PRELOADING_PREFETCH_PREFETCH_DOCUMENT_MANAGER_H_
|