blob: ab8152caa265d97093b0260191315a0bb7efe112 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// 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/callback.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
#include "url/gurl.h"
class PrerenderManager;
class Profile;
class SearchPrefetchURLLoader;
class StreamingSearchPrefetchURLLoader;
// 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.
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|. It may also move to |kCanBeServedAndUserClicked| when the user
// navigates to the result in omnibox or |kRequestCancelled| if the user
// closes omnibox.
kCanBeServed = 2,
// The request can be served to the navigation stack, and is marked as being
// clicked by the user. At this point, it may move to |kComplete| or
// |kRequestFailed|.
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,
// The request was cancelled before completion. This is a terminal state.
kRequestCancelled = 6,
// The request was served to the navigation stack. This is a terminal state.
kPrefetchServedForRealNavigation = 7,
// The request was served to the prerender navigation stack. It may move to
// |kPrerenderedAndClicked| when the user navigates to the result in omnibox
// or |kRequestCancelled| if the user closes omnibox.
kPrerendered = 8,
// Similar to |kCanBeServedAndUserClicked|, the request was served to the
// prerender navigation stack, and is marked as being
// clicked by the user. It is expected to move to |kPrerenderActivated| after
// the corresponding prerender is fully activated by the user.
kPrerenderedAndClicked = 9,
// The request was served to the prerender navigation stack, and the prerender
// page is fully activated by the user. This is a terminal state.
kPrerenderActivated = 10,
kMaxValue = kPrerenderActivated,
};
// 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 terms.
// - 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 std::u16string& prefetch_search_terms,
const GURL& prefetch_url,
bool navigation_prefetch,
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 and calls |StartPrefetchRequestInternal()|. Returns
// |false| if the request is not started (i.e., it would be deferred by
// throttles).
bool StartPrefetchRequest(Profile* profile);
// Returns true if this request should be canceled when the Autocomplete
// suggestion no longer lists this search prefetch.
bool ShouldBeCancelledOnResultChanges() const;
// Marks a prefetch as canceled and stops any ongoing fetch.
void CancelPrefetch();
// 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);
// 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 serveable.
void MarkPrefetchAsServable();
// Update the status when the request is complete.
void MarkPrefetchAsComplete();
// Update the status when the relevant search item is clicked in omnibox.
void MarkPrefetchAsClicked();
// Update the status when the request is actually served to the navigation
// stack of a real navigation request.
void MarkPrefetchAsServed();
// Updates the status when the request is served to a prerendering navigation
// stack. Note that after this point, this request cannot be served to a real
// navigation anymore.
void MarkPrefetchAsPrerendered();
// Updates the status when the prerendering page it is serving was activated.
void MarkPrefetchAsPrerenderActivated();
// 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.
std::unique_ptr<SearchPrefetchURLLoader> TakeSearchPrefetchURLLoader();
// 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_; }
private:
// Starts and begins processing |resource_request|.
void StartPrefetchRequestInternal(
Profile* profile,
std::unique_ptr<network::ResourceRequest> resource_request,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
base::OnceCallback<void(bool)> report_error_callback);
// Stops the on-going prefetch and should mark |current_status_|
// appropriately.
void StopPrefetch();
// Cancels ongoing and pending prerender.
void StopPrerender();
// 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 search terms that this request is prefetching.
const std::u16string prefetch_search_terms_;
// 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_;
std::unique_ptr<net::NetworkTrafficAnnotationTag> network_traffic_annotation_;
// The ongoing prefetch request. Null before and after the fetch.
std::unique_ptr<StreamingSearchPrefetchURLLoader> streaming_url_loader_;
// Called when there is a network/server error on the prefetch request.
base::OnceCallback<void(bool)> report_error_callback_;
// 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_;
base::raw_ptr<Profile> profile_;
};
#endif // CHROME_BROWSER_PRELOADING_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_REQUEST_H_