1 // Copyright 2014 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 COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_ 6 #define COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/callback.h" 13 #include "base/cancelable_callback.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/threading/thread_checker.h" 18 #include "base/time/time.h" 19 #include "components/keyed_service/core/keyed_service.h" 20 #include "components/suggestions/image_manager.h" 21 #include "components/suggestions/proto/suggestions.pb.h" 22 #include "components/suggestions/suggestions_utils.h" 23 #include "net/url_request/url_fetcher_delegate.h" 24 #include "ui/gfx/image/image_skia.h" 25 #include "url/gurl.h" 26 27 namespace net { 28 class URLRequestContextGetter; 29 } // namespace net 30 31 namespace user_prefs { 32 class PrefRegistrySyncable; 33 } // namespace user_prefs 34 35 namespace suggestions { 36 37 class BlacklistStore; 38 class SuggestionsStore; 39 40 extern const char kSuggestionsFieldTrialName[]; 41 extern const char kSuggestionsFieldTrialURLParam[]; 42 extern const char kSuggestionsFieldTrialCommonParamsParam[]; 43 extern const char kSuggestionsFieldTrialBlacklistPathParam[]; 44 extern const char kSuggestionsFieldTrialBlacklistUrlParam[]; 45 extern const char kSuggestionsFieldTrialStateParam[]; 46 extern const char kSuggestionsFieldTrialControlParam[]; 47 extern const char kSuggestionsFieldTrialStateEnabled[]; 48 extern const int64 kDefaultExpiryUsec; 49 50 // An interface to fetch server suggestions asynchronously. 51 class SuggestionsService : public KeyedService, public net::URLFetcherDelegate { 52 public: 53 typedef base::Callback<void(const SuggestionsProfile&)> ResponseCallback; 54 55 SuggestionsService( 56 net::URLRequestContextGetter* url_request_context, 57 scoped_ptr<SuggestionsStore> suggestions_store, 58 scoped_ptr<ImageManager> thumbnail_manager, 59 scoped_ptr<BlacklistStore> blacklist_store); 60 virtual ~SuggestionsService(); 61 62 // Whether this service is enabled. 63 static bool IsEnabled(); 64 65 // Whether the user is part of a control group. 66 static bool IsControlGroup(); 67 68 // Request suggestions data, which will be passed to |callback|. |sync_state| 69 // will influence the behavior of this function (see SyncState definition). 70 // 71 // |sync_state| must be specified based on the current state of the system 72 // (see suggestions::GetSyncState). Callers should call this function again if 73 // sync state changes. 74 // 75 // If state allows for a network request, it is initiated unless a pending one 76 // exists. To prevent multiple requests, all |callback|s are placed in a queue 77 // and are updated simultaneously when the fetch completes. Also posts a task 78 // to execute OnRequestTimeout if the request hasn't completed in a given 79 // amount of time. 80 void FetchSuggestionsData(SyncState sync_state, 81 ResponseCallback callback); 82 83 // Retrieves stored thumbnail for website |url| asynchronously. Calls 84 // |callback| with Bitmap pointer if found, and NULL otherwise. 85 void GetPageThumbnail( 86 const GURL& url, 87 base::Callback<void(const GURL&, const SkBitmap*)> callback); 88 89 // Issue a blacklist request. If there is already a blacklist request 90 // in flight, the new blacklist request is ignored. 91 void BlacklistURL(const GURL& candidate_url, 92 const ResponseCallback& callback); 93 94 // Determines which URL a blacklist request was for, irrespective of the 95 // request's status. Returns false if |request| is not a blacklist request. 96 static bool GetBlacklistedUrl(const net::URLFetcher& request, GURL* url); 97 98 // Register SuggestionsService related prefs in the Profile prefs. 99 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); 100 101 // Sets default timestamp for suggestions which do not have expiry timestamp. 102 void SetDefaultExpiryTimestamp(SuggestionsProfile* suggestions, 103 int64 timestamp_usec); 104 private: 105 friend class SuggestionsServiceTest; 106 FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, BlacklistURLFails); 107 FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, FetchSuggestionsData); 108 FRIEND_TEST_ALL_PREFIXES(SuggestionsServiceTest, UpdateBlacklistDelay); 109 110 // Similar to FetchSuggestionsData but doesn't post a task to execute 111 // OnDelaySinceFetch. 112 void FetchSuggestionsDataNoTimeout(ResponseCallback callback); 113 114 // Issue a request. 115 void IssueRequest(const GURL& url); 116 117 // Creates a request to the suggestions service, properly setting headers. 118 net::URLFetcher* CreateSuggestionsRequest(const GURL& url); 119 120 // Called to service the requestors if the issued suggestions request has 121 // not completed in a given amount of time. 122 virtual void OnRequestTimeout(); 123 124 // net::URLFetcherDelegate implementation. 125 // Called when fetch request completes. Parses the received suggestions data, 126 // and dispatches them to callbacks stored in queue. 127 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 128 129 // KeyedService implementation. 130 virtual void Shutdown() OVERRIDE; 131 132 // Load the cached suggestions and service the requestors with them. 133 void ServeFromCache(); 134 135 // Apply the local blacklist to |suggestions|, then serve the requestors. 136 void FilterAndServe(SuggestionsProfile* suggestions); 137 138 // Schedule a blacklisting request if the local blacklist isn't empty. 139 // |last_request_successful| is used for exponentially backing off when 140 // requests fail. 141 void ScheduleBlacklistUpload(bool last_request_successful); 142 143 // If the local blacklist isn't empty, pick a URL from it and issue a 144 // blacklist request for it. 145 void UploadOneFromBlacklist(); 146 147 // Updates |blacklist_delay_sec_| based on the success of the last request. 148 void UpdateBlacklistDelay(bool last_request_successful); 149 150 // Test seams. 151 int blacklist_delay() const { return blacklist_delay_sec_; } 152 void set_blacklist_delay(int delay) { blacklist_delay_sec_ = delay; } 153 154 base::ThreadChecker thread_checker_; 155 156 // The cache for the suggestions. 157 scoped_ptr<SuggestionsStore> suggestions_store_; 158 159 // The local cache for temporary blacklist, until uploaded to the server. 160 scoped_ptr<BlacklistStore> blacklist_store_; 161 162 // Contains the current suggestions fetch request. Will only have a value 163 // while a request is pending, and will be reset by |OnURLFetchComplete|. 164 scoped_ptr<net::URLFetcher> pending_request_; 165 166 // A closure that is run on a timeout from issuing the suggestions fetch 167 // request, if the request hasn't completed. 168 scoped_ptr<base::CancelableClosure> pending_timeout_closure_; 169 170 // The start time of the previous suggestions request. This is used to measure 171 // the latency of requests. Initially zero. 172 base::TimeTicks last_request_started_time_; 173 174 // The URL to fetch suggestions data from. 175 GURL suggestions_url_; 176 177 // Prefix for building the blacklisting URL. 178 std::string blacklist_url_prefix_; 179 180 // Queue of callbacks. These are flushed when fetch request completes. 181 std::vector<ResponseCallback> waiting_requestors_; 182 183 // Used to obtain server thumbnails, if available. 184 scoped_ptr<ImageManager> thumbnail_manager_; 185 186 net::URLRequestContextGetter* url_request_context_; 187 188 // Delay used when scheduling a blacklisting task. 189 int blacklist_delay_sec_; 190 191 // Timeout (in ms) before serving requestors after a fetch suggestions request 192 // has been issued. 193 int request_timeout_ms_; 194 195 // For callbacks may be run after destruction. 196 base::WeakPtrFactory<SuggestionsService> weak_ptr_factory_; 197 198 DISALLOW_COPY_AND_ASSIGN(SuggestionsService); 199 }; 200 201 } // namespace suggestions 202 203 #endif // COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_ 204