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 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
|
// 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_PRELOADING_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_REQUEST_H_
#define CHROME_BROWSER_PRELOADING_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_REQUEST_H_
#include <memory>
#include "base/functional/callback.h"
#include "chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_url_loader.h"
#include "services/network/public/cpp/resource_request.h"
#include "url/gurl.h"
class PrerenderManager;
class Profile;
class StreamingSearchPrefetchURLLoader;
namespace content {
class PreloadingAttempt;
enum class PreloadingTriggeringOutcome;
enum class PreloadingFailureReason;
} // namespace content
namespace net {
struct NetworkTrafficAnnotationTag;
} // namespace net
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// Any updates to this class need to be propagated to enums.xml.
enum class SearchPrefetchStatus {
// The request has not started yet. This status should ideally never be
// recorded as Start() should be called on the same stack as creating the
// fetcher (as of now).
kNotStarted = 0,
// The request is on the network and may move to any other state. Removed
// after https://crbug.com/40217275 is implemented.
// kInFlight = 1,
// The request can be served to the navigation stack, but may still encounter
// errors and move to |kRequestFailed| or it may complete and move to
// |kComplete|.
kCanBeServed = 2,
// Obsolete: After updating the cancellation logic, we no longer need this
// status to prevent a clicked prefetch from being deleted.
// kCanBeServedAndUserClicked = 3,
// The request can be served to the navigation stack, and has fully streamed
// the response with no errors.
kComplete = 4,
// The request hit an error and cannot be served.
kRequestFailed = 5,
// Obsolete: After updating the cancellation logic, we no longer cancel
// in-flight prefetch requests on autocomplete result changed.
// kRequestCancelled = 6,
kPrefetchServedForRealNavigation = 7,
// Obsolete: Now search prefetch requests are reusable, i.e., can be served to
// both real navigation and prerender navigation, so we no longer track these
// statuses.
// kPrerendered = 8,
// kPrerenderedAndClicked = 9,
// kPrerenderActivated = 10,
kMaxValue = kPrefetchServedForRealNavigation,
};
// A class representing a prefetch used by the Search Prefetch Service.
// It plays the following roles to support search preloading.
// - Preparing a resource request to prefetch a search page.
// - Starting prerendering upon the request succeeding to upgrade prefetch to
// prerender after the Search Prefetch Service tells it that the prefetched
// term is prerenderable.
// - A container for a StreamingSearchPrefetchURLLoader, to support
// |TakeSearchPrefetchURLLoader()|
// more easily.
class SearchPrefetchRequest {
public:
SearchPrefetchRequest(const GURL& canonical_search_url,
const GURL& prefetch_url,
bool navigation_prefetch,
content::PreloadingAttempt* prefetch_preloading_attempt,
base::OnceCallback<void(bool)> report_error_callback);
~SearchPrefetchRequest();
SearchPrefetchRequest(const SearchPrefetchRequest&) = delete;
SearchPrefetchRequest& operator=(const SearchPrefetchRequest&) = delete;
// The NTA for any search prefetch request.
static net::NetworkTrafficAnnotationTag NetworkAnnotationForPrefetch();
// Starts the network request to prefetch `prefetch_url_`. Sets various fields
// on a resource request. Returns `false` if the request is not started (i.e.,
// it would be deferred by throttles).
bool StartPrefetchRequest(Profile* profile);
// Called when SearchPrefetchService receives the hint that this prefetch
// request can be upgraded to a prerender attempt.
void MaybeStartPrerenderSearchResult(PrerenderManager& prerender_manager,
const GURL& prerender_url,
content::PreloadingAttempt& attempt);
// Called when the prefetch encounters an error.
void ErrorEncountered();
// Called on the URL loader receives servable response.
void OnServableResponseCodeReceived();
// Update the status when the request is complete.
void MarkPrefetchAsComplete();
// Update the status when the request is actually served to the navigation
// stack of a real navigation request.
void MarkPrefetchAsServed();
// Called when AutocompleteMatches changes. It resets PrerenderUpgrader.
// And if the AutocompleteMatches suggests to prerender a search result,
// `MaybeStartPrerenderSearchResult` will be called soon.
void ResetPrerenderUpgrader();
// Record the time at which the user clicked a suggestion matching this
// prefetch.
void RecordClickTime();
// Takes ownership of underlying data/objects needed to serve the response.
scoped_refptr<StreamingSearchPrefetchURLLoader> TakeSearchPrefetchURLLoader();
// Instead of completely letting a navigation stack own the prefetch loader,
// creates a copy of the prefetched response so that it can be shared among
// different clients.
// Note: This method should be called after the response reader received
// response headers.
SearchPrefetchURLLoader::RequestHandler CreateResponseReader();
// Whether the request was started as a navigation prefetch (as opposed to a
// suggestion prefetch).
bool navigation_prefetch() const { return navigation_prefetch_; }
SearchPrefetchStatus current_status() const { return current_status_; }
const GURL& prefetch_url() const { return prefetch_url_; }
// Sets `prefetch_preloading_attempt_` PreloadingFailureReason to `reason` if
// exists.
void SetPrefetchAttemptFailureReason(content::PreloadingFailureReason reason);
// Tells StreamingSearchPrefetchURLLoader to run the callback upon
// destruction.
void SetLoaderDestructionCallbackForTesting(
base::OnceClosure streaming_url_loader_destruction_callback);
private:
// Stops the on-going prefetch and should mark |current_status_|
// appropriately.
void StopPrefetch();
// Cancels ongoing and pending prerender.
void StopPrerender();
// Updates the `current_status_` to status.
void SetSearchPrefetchStatus(SearchPrefetchStatus status);
// Sets the PreloadingTriggeringOutcome for `prefetch_preloading_attempt_` to
// `outcome`.
void SetPrefetchAttemptTriggeringOutcome(
content::PreloadingTriggeringOutcome outcome);
// Whether the request has received a servable response. See
// `CanServePrefetchRequest` in ./streaming_search_prefetch_url_loader.cc for
// the definition of servable response.
bool servable_response_code_received_ = false;
SearchPrefetchStatus current_status_ = SearchPrefetchStatus::kNotStarted;
// The canonical representation of the search suggestion including query,
// intent, and extra parameters that can alter the Search page.
const GURL canonical_search_url_;
// The URL to prefetch the search terms from.
GURL prefetch_url_;
// The URL to prerender the search terms from.
// `prerender_url_` can be different from `prefetch_url_`. The latter is used
// to send network requests, so it may contain a special parameter for the
// server to recognize that it is a prefetch request, but the former does not
// send network requests, i.e. this parameter is not required.
GURL prerender_url_;
// Whether this is for a navigation-time prefetch.
bool navigation_prefetch_;
// The ongoing prefetch request. Null before and after the fetch.
scoped_refptr<StreamingSearchPrefetchURLLoader> streaming_url_loader_;
// Once set, this is used to log the metrics corresponding to the prefetch
// attempt. Please note this is different from `prerender_preloading_attempt_`
// which is for corresponding prerender attempt. We store the WeakPtr because
// it is possible that the PreloadingAttempt can be deleted (on navigation) or
// not created (when no WebContents is present) before search prefetch uses
// it.
base::WeakPtr<content::PreloadingAttempt> prefetch_preloading_attempt_;
// Called when there is a network/server error on the prefetch request.
base::OnceCallback<void(bool)> report_error_callback_;
base::TimeTicks time_start_prefetch_request_;
// The time at which the prefetched URL was clicked in the Omnibox.
base::TimeTicks time_clicked_;
// Once set, this request will trigger search prerender upon receiving success
// response.
base::WeakPtr<PrerenderManager> prerender_manager_;
// Once set, this PreloadingAttempt corresponding to prerender attempt will be
// passed to log various metrics. We store WeakPtr as prerender can be deleted
// before we receive a prefetch response or the prerender is not created.
base::WeakPtr<content::PreloadingAttempt> prerender_preloading_attempt_;
};
// Used when DCHECK_STATE_TRANSITION triggers.
std::ostream& operator<<(std::ostream& o, const SearchPrefetchStatus& s);
#endif // CHROME_BROWSER_PRELOADING_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_REQUEST_H_
|