1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_SERVICE_H_ 6 #define CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_SERVICE_H_ 7 8 #include <map> 9 10 #include "base/callback.h" 11 #include "base/optional.h" 12 #include "base/scoped_observation.h" 13 #include "base/strings/string16.h" 14 #include "base/timer/timer.h" 15 #include "components/keyed_service/core/keyed_service.h" 16 #include "components/search_engines/template_url_data.h" 17 #include "components/search_engines/template_url_service.h" 18 #include "components/search_engines/template_url_service_observer.h" 19 #include "services/network/public/cpp/simple_url_loader.h" 20 #include "url/gurl.h" 21 22 class Profile; 23 class GURL; 24 class PrefetchedResponseContainer; 25 26 class AutocompleteController; 27 28 enum class SearchPrefetchStatus { 29 // The request is on the network and may move to any other state. 30 kInFlight = 1, 31 // The request received all the data and is ready to serve. 32 kSuccessfullyCompleted = 2, 33 // The request hit an error and cannot be served. 34 kRequestFailed = 3, 35 // The request was cancelled before completion. 36 kRequestCancelled = 4, 37 }; 38 39 class SearchPrefetchService : public KeyedService, 40 public TemplateURLServiceObserver { 41 public: 42 explicit SearchPrefetchService(Profile* profile); 43 ~SearchPrefetchService() override; 44 45 SearchPrefetchService(const SearchPrefetchService&) = delete; 46 SearchPrefetchService& operator=(const SearchPrefetchService&) = delete; 47 48 // KeyedService: 49 void Shutdown() override; 50 51 // TemplateURLServiceObserver: 52 // Monitors changes to DSE. If a change occurs, clears prefetches. 53 void OnTemplateURLServiceChanged() override; 54 55 // Called when |controller| has updated information. 56 void OnResultChanged(AutocompleteController* controller); 57 58 // Returns whether the prefetch started or not. 59 bool MaybePrefetchURL(const GURL& url); 60 61 // Clear all prefetches from the service. 62 void ClearPrefetches(); 63 64 // Takes the response from this object if |url| matches a prefetched URL. 65 std::unique_ptr<PrefetchedResponseContainer> TakePrefetchResponse( 66 const GURL& url); 67 68 // Reports the status of a prefetch for a given search term. 69 base::Optional<SearchPrefetchStatus> GetSearchPrefetchStatusForTesting( 70 base::string16 search_terms); 71 72 private: 73 // Removes the prefetch and prefetch timers associated with |search_terms|. 74 void DeletePrefetch(base::string16 search_terms); 75 76 // Records the current time to prevent prefetches for a set duration. 77 void ReportError(); 78 79 // Internal class to represent an ongoing or completed prefetch. 80 class PrefetchRequest { 81 public: 82 // |service| must outlive this class and be able to manage this class's 83 // lifetime. 84 PrefetchRequest(const GURL& prefetch_url, 85 base::OnceClosure report_error_callback); 86 ~PrefetchRequest(); 87 88 PrefetchRequest(const PrefetchRequest&) = delete; 89 PrefetchRequest& operator=(const PrefetchRequest&) = delete; 90 91 // Starts the network request to prefetch |prefetch_url_|. 92 void StartPrefetchRequest(Profile* profile); 93 94 // Cancels the on-going prefetch and marks the status appropriately. 95 void CancelPrefetch(); 96 current_status()97 SearchPrefetchStatus current_status() const { return current_status_; } 98 prefetch_url()99 const GURL& prefetch_url() const { return prefetch_url_; } 100 101 // Takes ownership of the prefetched data. 102 std::unique_ptr<PrefetchedResponseContainer> TakePrefetchResponse(); 103 104 private: 105 // Called as a callback when the prefetch request is complete. Stores the 106 // response and other metadata in |prefetch_response_container_|. 107 void LoadDone(std::unique_ptr<std::string> response_body); 108 109 SearchPrefetchStatus current_status_ = SearchPrefetchStatus::kInFlight; 110 111 // The URL to prefetch the search terms from. 112 const GURL prefetch_url_; 113 114 // The ongoing prefetch request. Null before and after the fetch. 115 std::unique_ptr<network::SimpleURLLoader> simple_loader_; 116 117 // Once a prefetch is completed successfully, the associated prefetch data 118 // and metadata about the request. 119 std::unique_ptr<PrefetchedResponseContainer> prefetch_response_container_; 120 121 // Called when there is a network/server error on the prefetch request. 122 base::OnceClosure report_error_callback_; 123 }; 124 125 // Prefetches that are started are stored using search terms as a key. Only 126 // one prefetch should be started for a given search term until the old 127 // prefetch expires. 128 std::map<base::string16, std::unique_ptr<PrefetchRequest>> prefetches_; 129 130 // A group of timers to expire |prefetches_| based on the same key. 131 std::map<base::string16, std::unique_ptr<base::OneShotTimer>> 132 prefetch_expiry_timers_; 133 134 // The time of the last prefetch network/server error. 135 base::TimeTicks last_error_time_ticks_; 136 137 // The current state of the DSE. 138 base::Optional<TemplateURLData> template_url_service_data_; 139 140 base::ScopedObservation<TemplateURLService, TemplateURLServiceObserver> 141 observer_{this}; 142 143 Profile* profile_; 144 }; 145 146 #endif // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_SEARCH_PREFETCH_SERVICE_H_ 147