Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: chrome/browser/search/suggestions/suggestions_service.cc

Issue 330473003: Offline blacklisting for SuggestionsService. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address second round of comments. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/search/suggestions/suggestions_service.h" 5 #include "chrome/browser/search/suggestions/suggestions_service.h"
6 6
7 #include <sstream>
8 #include <string>
9
7 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
8 #include "base/metrics/field_trial.h" 11 #include "base/metrics/field_trial.h"
9 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
10 #include "base/metrics/sparse_histogram.h" 13 #include "base/metrics/sparse_histogram.h"
11 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
13 #include "base/time/time.h" 16 #include "base/time/time.h"
14 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/history/history_types.h" 18 #include "chrome/browser/history/history_types.h"
16 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" 19 #include "chrome/browser/metrics/variations/variations_http_header_provider.h"
17 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/search/suggestions/blacklist_store.h"
18 #include "chrome/browser/search/suggestions/suggestions_store.h" 22 #include "chrome/browser/search/suggestions/suggestions_store.h"
19 #include "components/pref_registry/pref_registry_syncable.h" 23 #include "components/pref_registry/pref_registry_syncable.h"
20 #include "components/variations/variations_associated_data.h" 24 #include "components/variations/variations_associated_data.h"
21 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/browser_thread.h"
22 #include "net/base/escape.h" 26 #include "net/base/escape.h"
23 #include "net/base/load_flags.h" 27 #include "net/base/load_flags.h"
24 #include "net/base/net_errors.h" 28 #include "net/base/net_errors.h"
29 #include "net/base/url_util.h"
25 #include "net/http/http_response_headers.h" 30 #include "net/http/http_response_headers.h"
26 #include "net/http/http_status_code.h" 31 #include "net/http/http_status_code.h"
27 #include "net/http/http_util.h" 32 #include "net/http/http_util.h"
28 #include "net/url_request/url_fetcher.h" 33 #include "net/url_request/url_fetcher.h"
29 #include "net/url_request/url_request_status.h" 34 #include "net/url_request/url_request_status.h"
30 #include "url/gurl.h" 35 #include "url/gurl.h"
31 36
32 using base::CancelableClosure; 37 using base::CancelableClosure;
33 using content::BrowserThread; 38 using content::BrowserThread;
34 39
(...skipping 15 matching lines...) Expand all
50 RESPONSE_STATE_SIZE); 55 RESPONSE_STATE_SIZE);
51 } 56 }
52 57
53 // Obtains the experiment parameter under the supplied |key|, or empty string 58 // Obtains the experiment parameter under the supplied |key|, or empty string
54 // if the parameter does not exist. 59 // if the parameter does not exist.
55 std::string GetExperimentParam(const std::string& key) { 60 std::string GetExperimentParam(const std::string& key) {
56 return chrome_variations::GetVariationParamValue(kSuggestionsFieldTrialName, 61 return chrome_variations::GetVariationParamValue(kSuggestionsFieldTrialName,
57 key); 62 key);
58 } 63 }
59 64
65 GURL BuildBlacklistRequestURL(const std::string& blacklist_url_prefix,
66 const GURL& candidate_url) {
67 return GURL(blacklist_url_prefix +
68 net::EscapeQueryParamValue(candidate_url.spec(), true));
69 }
70
60 // Runs each callback in |requestors| on |suggestions|, then deallocates 71 // Runs each callback in |requestors| on |suggestions|, then deallocates
61 // |requestors|. 72 // |requestors|.
62 void DispatchRequestsAndClear( 73 void DispatchRequestsAndClear(
63 const SuggestionsProfile& suggestions, 74 const SuggestionsProfile& suggestions,
64 std::vector<SuggestionsService::ResponseCallback>* requestors) { 75 std::vector<SuggestionsService::ResponseCallback>* requestors) {
65 std::vector<SuggestionsService::ResponseCallback>::iterator it; 76 std::vector<SuggestionsService::ResponseCallback>::iterator it;
66 for (it = requestors->begin(); it != requestors->end(); ++it) { 77 for (it = requestors->begin(); it != requestors->end(); ++it) {
67 it->Run(suggestions); 78 if (!it->is_null()) it->Run(suggestions);
68 } 79 }
69 std::vector<SuggestionsService::ResponseCallback>().swap(*requestors); 80 std::vector<SuggestionsService::ResponseCallback>().swap(*requestors);
70 } 81 }
71 82
72 const int kDefaultRequestTimeoutMs = 200; 83 const int kDefaultRequestTimeoutMs = 200;
73 84
85 // Default delay used when scheduling a blacklist request.
86 const unsigned int kBlacklistDefaultDelaySec = 1;
87
88 // Multiplier on the delay used when scheduling a blacklist request, in case the
89 // last observed request was unsuccessful.
90 const unsigned int kBlacklistBackoffMultiplier = 2;
91
92 // Maximum valid delay for scheduling a request. Candidate delays larger than
93 // this are rejected. This means the maximum backoff is at least 300 / 2, i.e.
94 // 2.5 minutes.
95 const unsigned int kBlacklistMaxDelaySec = 300; // 5 minutes
96
74 } // namespace 97 } // namespace
75 98
76 const char kSuggestionsFieldTrialName[] = "ChromeSuggestions"; 99 const char kSuggestionsFieldTrialName[] = "ChromeSuggestions";
77 const char kSuggestionsFieldTrialURLParam[] = "url"; 100 const char kSuggestionsFieldTrialURLParam[] = "url";
78 const char kSuggestionsFieldTrialSuggestionsSuffixParam[] = 101 const char kSuggestionsFieldTrialCommonParamsParam[] = "common_params";
79 "suggestions_suffix"; 102 const char kSuggestionsFieldTrialBlacklistPathParam[] = "blacklist_path";
80 const char kSuggestionsFieldTrialBlacklistSuffixParam[] = "blacklist_suffix"; 103 const char kSuggestionsFieldTrialBlacklistUrlParam[] = "blacklist_url_param";
81 const char kSuggestionsFieldTrialStateParam[] = "state"; 104 const char kSuggestionsFieldTrialStateParam[] = "state";
82 const char kSuggestionsFieldTrialStateEnabled[] = "enabled"; 105 const char kSuggestionsFieldTrialStateEnabled[] = "enabled";
83 const char kSuggestionsFieldTrialTimeoutMs[] = "timeout_ms"; 106 const char kSuggestionsFieldTrialTimeoutMs[] = "timeout_ms";
84 107
108 namespace {
109
110 std::string GetBlacklistUrlPrefix() {
111 std::stringstream blacklist_url_prefix_stream;
112 blacklist_url_prefix_stream
113 << GetExperimentParam(kSuggestionsFieldTrialURLParam)
114 << GetExperimentParam(kSuggestionsFieldTrialBlacklistPathParam) << "?"
115 << GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam) << "&"
116 << GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam) << "=";
117 return blacklist_url_prefix_stream.str();
118 }
119
120 } // namespace
121
85 SuggestionsService::SuggestionsService( 122 SuggestionsService::SuggestionsService(
86 Profile* profile, scoped_ptr<SuggestionsStore> suggestions_store) 123 Profile* profile, scoped_ptr<SuggestionsStore> suggestions_store,
124 scoped_ptr<BlacklistStore> blacklist_store)
87 : suggestions_store_(suggestions_store.Pass()), 125 : suggestions_store_(suggestions_store.Pass()),
126 blacklist_store_(blacklist_store.Pass()),
88 thumbnail_manager_(new ThumbnailManager(profile)), 127 thumbnail_manager_(new ThumbnailManager(profile)),
89 profile_(profile), 128 profile_(profile),
129
Mathieu 2014/06/18 19:04:53 extra line?
manzagop (departed) 2014/06/19 14:36:55 Done. Funny, clang-format was happy with it.
130 blacklist_delay_sec_(kBlacklistDefaultDelaySec),
90 weak_ptr_factory_(this), 131 weak_ptr_factory_(this),
91 request_timeout_ms_(kDefaultRequestTimeoutMs) { 132 request_timeout_ms_(kDefaultRequestTimeoutMs) {
92 // Obtain various parameters from Variations. 133 // Obtain various parameters from Variations.
93 suggestions_url_ = 134 suggestions_url_ =
94 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + 135 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + "?" +
95 GetExperimentParam(kSuggestionsFieldTrialSuggestionsSuffixParam)); 136 GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam));
96 blacklist_url_prefix_ = 137 blacklist_url_prefix_ = GetBlacklistUrlPrefix();
97 GetExperimentParam(kSuggestionsFieldTrialURLParam) +
98 GetExperimentParam(kSuggestionsFieldTrialBlacklistSuffixParam);
99 std::string timeout = GetExperimentParam(kSuggestionsFieldTrialTimeoutMs); 138 std::string timeout = GetExperimentParam(kSuggestionsFieldTrialTimeoutMs);
100 int temp_timeout; 139 int temp_timeout;
101 if (!timeout.empty() && base::StringToInt(timeout, &temp_timeout)) { 140 if (!timeout.empty() && base::StringToInt(timeout, &temp_timeout)) {
102 request_timeout_ms_ = temp_timeout; 141 request_timeout_ms_ = temp_timeout;
103 } 142 }
104 } 143 }
105 144
106 SuggestionsService::~SuggestionsService() {} 145 SuggestionsService::~SuggestionsService() {}
107 146
108 // static 147 // static
(...skipping 22 matching lines...) Expand all
131 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 170 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
132 if (pending_request_.get()) { 171 if (pending_request_.get()) {
133 // Request already exists, so just add requestor to queue. 172 // Request already exists, so just add requestor to queue.
134 waiting_requestors_.push_back(callback); 173 waiting_requestors_.push_back(callback);
135 return; 174 return;
136 } 175 }
137 176
138 // Form new request. 177 // Form new request.
139 DCHECK(waiting_requestors_.empty()); 178 DCHECK(waiting_requestors_.empty());
140 waiting_requestors_.push_back(callback); 179 waiting_requestors_.push_back(callback);
141 180 IssueRequest(suggestions_url_);
142 pending_request_.reset(CreateSuggestionsRequest(suggestions_url_));
143 pending_request_->Start();
144 last_request_started_time_ = base::TimeTicks::Now();
145 } 181 }
146 182
147 void SuggestionsService::GetPageThumbnail( 183 void SuggestionsService::GetPageThumbnail(
148 const GURL& url, 184 const GURL& url,
149 base::Callback<void(const GURL&, const SkBitmap*)> callback) { 185 base::Callback<void(const GURL&, const SkBitmap*)> callback) {
150 thumbnail_manager_->GetPageThumbnail(url, callback); 186 thumbnail_manager_->GetPageThumbnail(url, callback);
151 } 187 }
152 188
153 void SuggestionsService::BlacklistURL( 189 void SuggestionsService::BlacklistURL(
154 const GURL& candidate_url, SuggestionsService::ResponseCallback callback) { 190 const GURL& candidate_url,
191 const SuggestionsService::ResponseCallback& callback) {
155 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 192 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
156 waiting_requestors_.push_back(callback); 193 waiting_requestors_.push_back(callback);
157 194
158 if (pending_request_.get()) { 195 // Blacklist locally, for immediate effect.
159 if (IsBlacklistRequest(pending_request_.get())) { 196 if (!blacklist_store_->BlacklistUrl(candidate_url)) {
160 // Pending request is a blacklist request. Silently drop the new blacklist 197 DVLOG(1) << "Failed blacklisting attempt.";
161 // request. TODO - handle this case. 198 return;
162 return;
163 } else {
164 // Pending request is not a blacklist request - cancel it and go on to
165 // issuing a blacklist request. Also ensure the timeout closure does not
166 // run; instead we'll wait for the updated suggestions before servicing
167 // requestors.
168 pending_request_.reset(NULL);
169 pending_timeout_closure_.reset(NULL);
170 }
171 } 199 }
172 200
173 // Send blacklisting request. 201 // If there's an ongoing request, let it complete.
174 // TODO(manzagop): make this a PUT request instead of a GET request. 202 if (pending_request_.get()) return;
175 GURL url(blacklist_url_prefix_ + 203
176 net::EscapeQueryParamValue(candidate_url.spec(), true)); 204 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, candidate_url));
177 pending_request_.reset(CreateSuggestionsRequest(url)); 205 }
178 pending_request_->Start(); 206
179 last_request_started_time_ = base::TimeTicks::Now(); 207 // static
208 bool SuggestionsService::GetBlacklistedUrl(const net::URLFetcher& request,
209 GURL* url) {
210 bool is_blacklist_request = StartsWithASCII(request.GetOriginalURL().spec(),
211 GetBlacklistUrlPrefix(), true);
212 if (!is_blacklist_request) return false;
213
214 // Extract the blacklisted url from the blacklist request.
Mathieu 2014/06/18 19:04:53 *URL
manzagop (departed) 2014/06/19 14:36:56 Done. Arg! Sorry, I know I keep writing it lowerca
215 std::string blacklisted;
216 if (!net::GetValueForKeyInQuery(
217 request.GetOriginalURL(),
218 GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam),
219 &blacklisted))
220 return false;
221
222 GURL blacklisted_url(blacklisted);
223 blacklisted_url.Swap(url);
224 return true;
180 } 225 }
181 226
182 // static 227 // static
183 void SuggestionsService::RegisterProfilePrefs( 228 void SuggestionsService::RegisterProfilePrefs(
184 user_prefs::PrefRegistrySyncable* registry) { 229 user_prefs::PrefRegistrySyncable* registry) {
185 SuggestionsStore::RegisterProfilePrefs(registry); 230 SuggestionsStore::RegisterProfilePrefs(registry);
231 BlacklistStore::RegisterProfilePrefs(registry);
232 }
233
234 void SuggestionsService::IssueRequest(const GURL& url) {
235 pending_request_.reset(CreateSuggestionsRequest(url));
236 pending_request_->Start();
237 last_request_started_time_ = base::TimeTicks::Now();
238 }
239
240 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) {
241 net::URLFetcher* request =
242 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this);
243 request->SetLoadFlags(net::LOAD_DISABLE_CACHE);
244 request->SetRequestContext(profile_->GetRequestContext());
245 // Add Chrome experiment state to the request headers.
246 net::HttpRequestHeaders headers;
247 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
248 request->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers);
249 request->SetExtraRequestHeaders(headers.ToString());
250 return request;
186 } 251 }
187 252
188 void SuggestionsService::OnRequestTimeout() { 253 void SuggestionsService::OnRequestTimeout() {
189 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 254 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
190 ServeFromCache(); 255 ServeFromCache();
191 } 256 }
192 257
193 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { 258 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) {
194 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 259 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
195 DCHECK_EQ(pending_request_.get(), source); 260 DCHECK_EQ(pending_request_.get(), source);
196 261
197 // We no longer need the timeout closure. Delete it whether or not it has run 262 // We no longer need the timeout closure. Delete it whether or not it has run.
198 // (if it hasn't, this cancels it). 263 // If it hasn't, this cancels it.
199 pending_timeout_closure_.reset(); 264 pending_timeout_closure_.reset();
200 265
201 // The fetcher will be deleted when the request is handled. 266 // The fetcher will be deleted when the request is handled.
202 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); 267 scoped_ptr<const net::URLFetcher> request(pending_request_.release());
203 const net::URLRequestStatus& request_status = request->GetStatus(); 268 const net::URLRequestStatus& request_status = request->GetStatus();
204 if (request_status.status() != net::URLRequestStatus::SUCCESS) { 269 if (request_status.status() != net::URLRequestStatus::SUCCESS) {
205 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", 270 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode",
206 -request_status.error()); 271 -request_status.error());
207 DVLOG(1) << "Suggestions server request failed with error: " 272 DVLOG(1) << "Suggestions server request failed with error: "
208 << request_status.error() << ": " 273 << request_status.error() << ": "
209 << net::ErrorToString(request_status.error()); 274 << net::ErrorToString(request_status.error());
210 // Dispatch the cached profile on error. 275 // Dispatch the cached profile on error.
211 ServeFromCache(); 276 ServeFromCache();
277 ScheduleBlacklistUpload(false);
212 return; 278 return;
213 } 279 }
214 280
215 // Log the response code. 281 // Log the response code.
216 const int response_code = request->GetResponseCode(); 282 const int response_code = request->GetResponseCode();
217 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code); 283 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code);
218 if (response_code != net::HTTP_OK) { 284 if (response_code != net::HTTP_OK) {
219 // Aggressively clear the store. 285 // Aggressively clear the store.
220 suggestions_store_->ClearSuggestions(); 286 suggestions_store_->ClearSuggestions();
221 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); 287 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_);
288 ScheduleBlacklistUpload(false);
222 return; 289 return;
223 } 290 }
224 291
225 const base::TimeDelta latency = 292 const base::TimeDelta latency =
226 base::TimeTicks::Now() - last_request_started_time_; 293 base::TimeTicks::Now() - last_request_started_time_;
227 UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency); 294 UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency);
228 295
296 // Handle a successful blacklisting.
297 GURL blacklisted_url;
298 if (GetBlacklistedUrl(*source, &blacklisted_url)) {
299 blacklist_store_->RemoveUrl(blacklisted_url);
300 }
301
229 std::string suggestions_data; 302 std::string suggestions_data;
230 bool success = request->GetResponseAsString(&suggestions_data); 303 bool success = request->GetResponseAsString(&suggestions_data);
231 DCHECK(success); 304 DCHECK(success);
232 305
233 // Compute suggestions, and dispatch then to requestors. On error still 306 // Compute suggestions, and dispatch then to requestors. On error still
234 // dispatch empty suggestions. 307 // dispatch empty suggestions.
235 SuggestionsProfile suggestions; 308 SuggestionsProfile suggestions;
236 if (suggestions_data.empty()) { 309 if (suggestions_data.empty()) {
237 LogResponseState(RESPONSE_EMPTY); 310 LogResponseState(RESPONSE_EMPTY);
238 suggestions_store_->ClearSuggestions(); 311 suggestions_store_->ClearSuggestions();
239 } else if (suggestions.ParseFromString(suggestions_data)) { 312 } else if (suggestions.ParseFromString(suggestions_data)) {
240 LogResponseState(RESPONSE_VALID); 313 LogResponseState(RESPONSE_VALID);
241 thumbnail_manager_->InitializeThumbnailMap(suggestions); 314 thumbnail_manager_->InitializeThumbnailMap(suggestions);
242 suggestions_store_->StoreSuggestions(suggestions); 315 suggestions_store_->StoreSuggestions(suggestions);
243 } else { 316 } else {
244 LogResponseState(RESPONSE_INVALID); 317 LogResponseState(RESPONSE_INVALID);
245 suggestions_store_->LoadSuggestions(&suggestions); 318 suggestions_store_->LoadSuggestions(&suggestions);
246 } 319 }
247 320
248 DispatchRequestsAndClear(suggestions, &waiting_requestors_); 321 FilterAndServe(&suggestions);
322 ScheduleBlacklistUpload(true);
249 } 323 }
250 324
251 void SuggestionsService::Shutdown() { 325 void SuggestionsService::Shutdown() {
252 // Cancel pending request and timeout closure, then serve existing requestors 326 // Cancel pending request and timeout closure, then serve existing requestors
253 // from cache. 327 // from cache.
254 pending_request_.reset(NULL); 328 pending_request_.reset(NULL);
255 pending_timeout_closure_.reset(NULL); 329 pending_timeout_closure_.reset(NULL);
256 ServeFromCache(); 330 ServeFromCache();
257 } 331 }
258 332
259 bool SuggestionsService::IsBlacklistRequest(net::URLFetcher* request) const {
260 DCHECK(request);
261 return StartsWithASCII(request->GetOriginalURL().spec(),
262 blacklist_url_prefix_, true);
263 }
264
265 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) {
266 net::URLFetcher* request =
267 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this);
268 request->SetLoadFlags(net::LOAD_DISABLE_CACHE);
269 request->SetRequestContext(profile_->GetRequestContext());
270 // Add Chrome experiment state to the request headers.
271 net::HttpRequestHeaders headers;
272 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
273 request->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers);
274 request->SetExtraRequestHeaders(headers.ToString());
275 return request;
276 }
277
278 void SuggestionsService::ServeFromCache() { 333 void SuggestionsService::ServeFromCache() {
279 SuggestionsProfile suggestions; 334 SuggestionsProfile suggestions;
280 suggestions_store_->LoadSuggestions(&suggestions); 335 suggestions_store_->LoadSuggestions(&suggestions);
281 DispatchRequestsAndClear(suggestions, &waiting_requestors_); 336 FilterAndServe(&suggestions);
337 }
338
339 void SuggestionsService::FilterAndServe(SuggestionsProfile* suggestions) {
340 blacklist_store_->FilterSuggestions(suggestions);
341 DispatchRequestsAndClear(*suggestions, &waiting_requestors_);
342 }
343
344 void SuggestionsService::ScheduleBlacklistUpload(bool last_request_successful) {
345 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
346
347 UpdateBlacklistDelay(last_request_successful);
348
349 // Schedule a blacklist upload task.
350 GURL blacklist_url;
351 if (blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) {
352 base::Closure blacklist_cb =
353 base::Bind(&SuggestionsService::UploadOneFromBlacklist,
354 weak_ptr_factory_.GetWeakPtr());
355 BrowserThread::PostDelayedTask(
356 BrowserThread::UI, FROM_HERE, blacklist_cb,
357 base::TimeDelta::FromSeconds(blacklist_delay_sec_));
358 }
359 }
360
361 void SuggestionsService::UploadOneFromBlacklist() {
362 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
363
364 // If there's an ongoing request, let it complete.
365 if (pending_request_.get()) return;
366
367 GURL blacklist_url;
368 if (!blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url))
369 return; // Local blacklist is empty.
370
371 // Send blacklisting request.
372 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, blacklist_url));
373 }
374
375 void SuggestionsService::UpdateBlacklistDelay(bool last_request_successful) {
376 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
377
378 if (last_request_successful) {
379 blacklist_delay_sec_ = kBlacklistDefaultDelaySec;
380 } else {
381 unsigned int candidate_delay =
382 blacklist_delay_sec_ * kBlacklistBackoffMultiplier;
383 if (candidate_delay < kBlacklistMaxDelaySec)
384 blacklist_delay_sec_ = candidate_delay;
385 }
282 } 386 }
283 387
284 } // namespace suggestions 388 } // namespace suggestions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698