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

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: Final merge. 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;
Alexei Svitkine (slow) 2014/06/20 14:41:41 Nit: Generally, we use size_t for unsigned ints in
manzagop (departed) 2014/06/20 15:13:53 Done.
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 kSuggestionsFieldTrialControlParam[] = "control"; 105 const char kSuggestionsFieldTrialControlParam[] = "control";
83 const char kSuggestionsFieldTrialStateEnabled[] = "enabled"; 106 const char kSuggestionsFieldTrialStateEnabled[] = "enabled";
84 const char kSuggestionsFieldTrialTimeoutMs[] = "timeout_ms"; 107 const char kSuggestionsFieldTrialTimeoutMs[] = "timeout_ms";
85 108
109 namespace {
110
111 std::string GetBlacklistUrlPrefix() {
112 std::stringstream blacklist_url_prefix_stream;
113 blacklist_url_prefix_stream
114 << GetExperimentParam(kSuggestionsFieldTrialURLParam)
115 << GetExperimentParam(kSuggestionsFieldTrialBlacklistPathParam) << "?"
116 << GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam) << "&"
117 << GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam) << "=";
118 return blacklist_url_prefix_stream.str();
119 }
120
121 } // namespace
122
86 SuggestionsService::SuggestionsService( 123 SuggestionsService::SuggestionsService(
87 Profile* profile, scoped_ptr<SuggestionsStore> suggestions_store) 124 Profile* profile, scoped_ptr<SuggestionsStore> suggestions_store,
125 scoped_ptr<BlacklistStore> blacklist_store)
88 : suggestions_store_(suggestions_store.Pass()), 126 : suggestions_store_(suggestions_store.Pass()),
127 blacklist_store_(blacklist_store.Pass()),
89 thumbnail_manager_(new ThumbnailManager(profile)), 128 thumbnail_manager_(new ThumbnailManager(profile)),
90 profile_(profile), 129 profile_(profile),
130 blacklist_delay_sec_(kBlacklistDefaultDelaySec),
91 weak_ptr_factory_(this), 131 weak_ptr_factory_(this),
92 request_timeout_ms_(kDefaultRequestTimeoutMs) { 132 request_timeout_ms_(kDefaultRequestTimeoutMs) {
93 // Obtain various parameters from Variations. 133 // Obtain various parameters from Variations.
94 suggestions_url_ = 134 suggestions_url_ =
95 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + 135 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + "?" +
96 GetExperimentParam(kSuggestionsFieldTrialSuggestionsSuffixParam)); 136 GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam));
97 blacklist_url_prefix_ = 137 blacklist_url_prefix_ = GetBlacklistUrlPrefix();
98 GetExperimentParam(kSuggestionsFieldTrialURLParam) +
99 GetExperimentParam(kSuggestionsFieldTrialBlacklistSuffixParam);
100 std::string timeout = GetExperimentParam(kSuggestionsFieldTrialTimeoutMs); 138 std::string timeout = GetExperimentParam(kSuggestionsFieldTrialTimeoutMs);
101 int temp_timeout; 139 int temp_timeout;
102 if (!timeout.empty() && base::StringToInt(timeout, &temp_timeout)) { 140 if (!timeout.empty() && base::StringToInt(timeout, &temp_timeout)) {
103 request_timeout_ms_ = temp_timeout; 141 request_timeout_ms_ = temp_timeout;
104 } 142 }
105 } 143 }
106 144
107 SuggestionsService::~SuggestionsService() {} 145 SuggestionsService::~SuggestionsService() {}
108 146
109 // static 147 // static
(...skipping 28 matching lines...) Expand all
138 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 176 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
139 if (pending_request_.get()) { 177 if (pending_request_.get()) {
140 // Request already exists, so just add requestor to queue. 178 // Request already exists, so just add requestor to queue.
141 waiting_requestors_.push_back(callback); 179 waiting_requestors_.push_back(callback);
142 return; 180 return;
143 } 181 }
144 182
145 // Form new request. 183 // Form new request.
146 DCHECK(waiting_requestors_.empty()); 184 DCHECK(waiting_requestors_.empty());
147 waiting_requestors_.push_back(callback); 185 waiting_requestors_.push_back(callback);
148 186 IssueRequest(suggestions_url_);
149 pending_request_.reset(CreateSuggestionsRequest(suggestions_url_));
150 pending_request_->Start();
151 last_request_started_time_ = base::TimeTicks::Now();
152 } 187 }
153 188
154 void SuggestionsService::GetPageThumbnail( 189 void SuggestionsService::GetPageThumbnail(
155 const GURL& url, 190 const GURL& url,
156 base::Callback<void(const GURL&, const SkBitmap*)> callback) { 191 base::Callback<void(const GURL&, const SkBitmap*)> callback) {
157 thumbnail_manager_->GetPageThumbnail(url, callback); 192 thumbnail_manager_->GetPageThumbnail(url, callback);
158 } 193 }
159 194
160 void SuggestionsService::BlacklistURL( 195 void SuggestionsService::BlacklistURL(
161 const GURL& candidate_url, SuggestionsService::ResponseCallback callback) { 196 const GURL& candidate_url,
197 const SuggestionsService::ResponseCallback& callback) {
162 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 198 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
163 waiting_requestors_.push_back(callback); 199 waiting_requestors_.push_back(callback);
164 200
165 if (pending_request_.get()) { 201 // Blacklist locally, for immediate effect.
166 if (IsBlacklistRequest(pending_request_.get())) { 202 if (!blacklist_store_->BlacklistUrl(candidate_url)) {
167 // Pending request is a blacklist request. Silently drop the new blacklist 203 DVLOG(1) << "Failed blacklisting attempt.";
168 // request. TODO - handle this case. 204 return;
169 return;
170 } else {
171 // Pending request is not a blacklist request - cancel it and go on to
172 // issuing a blacklist request. Also ensure the timeout closure does not
173 // run; instead we'll wait for the updated suggestions before servicing
174 // requestors.
175 pending_request_.reset(NULL);
176 pending_timeout_closure_.reset(NULL);
177 }
178 } 205 }
179 206
180 // Send blacklisting request. 207 // If there's an ongoing request, let it complete.
181 // TODO(manzagop): make this a PUT request instead of a GET request. 208 if (pending_request_.get()) return;
182 GURL url(blacklist_url_prefix_ + 209
183 net::EscapeQueryParamValue(candidate_url.spec(), true)); 210 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, candidate_url));
184 pending_request_.reset(CreateSuggestionsRequest(url)); 211 }
185 pending_request_->Start(); 212
186 last_request_started_time_ = base::TimeTicks::Now(); 213 // static
214 bool SuggestionsService::GetBlacklistedUrl(const net::URLFetcher& request,
215 GURL* url) {
216 bool is_blacklist_request = StartsWithASCII(request.GetOriginalURL().spec(),
217 GetBlacklistUrlPrefix(), true);
218 if (!is_blacklist_request) return false;
219
220 // Extract the blacklisted URL from the blacklist request.
221 std::string blacklisted;
222 if (!net::GetValueForKeyInQuery(
223 request.GetOriginalURL(),
224 GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam),
225 &blacklisted))
226 return false;
227
228 GURL blacklisted_url(blacklisted);
229 blacklisted_url.Swap(url);
230 return true;
187 } 231 }
188 232
189 // static 233 // static
190 void SuggestionsService::RegisterProfilePrefs( 234 void SuggestionsService::RegisterProfilePrefs(
191 user_prefs::PrefRegistrySyncable* registry) { 235 user_prefs::PrefRegistrySyncable* registry) {
192 SuggestionsStore::RegisterProfilePrefs(registry); 236 SuggestionsStore::RegisterProfilePrefs(registry);
237 BlacklistStore::RegisterProfilePrefs(registry);
238 }
239
240 void SuggestionsService::IssueRequest(const GURL& url) {
241 pending_request_.reset(CreateSuggestionsRequest(url));
242 pending_request_->Start();
243 last_request_started_time_ = base::TimeTicks::Now();
244 }
245
246 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) {
247 net::URLFetcher* request =
248 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this);
249 request->SetLoadFlags(net::LOAD_DISABLE_CACHE);
250 request->SetRequestContext(profile_->GetRequestContext());
251 // Add Chrome experiment state to the request headers.
252 net::HttpRequestHeaders headers;
253 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
254 request->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers);
255 request->SetExtraRequestHeaders(headers.ToString());
256 return request;
193 } 257 }
194 258
195 void SuggestionsService::OnRequestTimeout() { 259 void SuggestionsService::OnRequestTimeout() {
196 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 260 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
197 ServeFromCache(); 261 ServeFromCache();
198 } 262 }
199 263
200 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { 264 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) {
201 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 265 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
202 DCHECK_EQ(pending_request_.get(), source); 266 DCHECK_EQ(pending_request_.get(), source);
203 267
204 // We no longer need the timeout closure. Delete it whether or not it has run 268 // We no longer need the timeout closure. Delete it whether or not it has run.
205 // (if it hasn't, this cancels it). 269 // If it hasn't, this cancels it.
206 pending_timeout_closure_.reset(); 270 pending_timeout_closure_.reset();
207 271
208 // The fetcher will be deleted when the request is handled. 272 // The fetcher will be deleted when the request is handled.
209 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); 273 scoped_ptr<const net::URLFetcher> request(pending_request_.release());
210 const net::URLRequestStatus& request_status = request->GetStatus(); 274 const net::URLRequestStatus& request_status = request->GetStatus();
211 if (request_status.status() != net::URLRequestStatus::SUCCESS) { 275 if (request_status.status() != net::URLRequestStatus::SUCCESS) {
212 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", 276 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode",
213 -request_status.error()); 277 -request_status.error());
214 DVLOG(1) << "Suggestions server request failed with error: " 278 DVLOG(1) << "Suggestions server request failed with error: "
215 << request_status.error() << ": " 279 << request_status.error() << ": "
216 << net::ErrorToString(request_status.error()); 280 << net::ErrorToString(request_status.error());
217 // Dispatch the cached profile on error. 281 // Dispatch the cached profile on error.
218 ServeFromCache(); 282 ServeFromCache();
283 ScheduleBlacklistUpload(false);
219 return; 284 return;
220 } 285 }
221 286
222 // Log the response code. 287 // Log the response code.
223 const int response_code = request->GetResponseCode(); 288 const int response_code = request->GetResponseCode();
224 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code); 289 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code);
225 if (response_code != net::HTTP_OK) { 290 if (response_code != net::HTTP_OK) {
226 // Aggressively clear the store. 291 // Aggressively clear the store.
227 suggestions_store_->ClearSuggestions(); 292 suggestions_store_->ClearSuggestions();
228 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); 293 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_);
294 ScheduleBlacklistUpload(false);
229 return; 295 return;
230 } 296 }
231 297
232 const base::TimeDelta latency = 298 const base::TimeDelta latency =
233 base::TimeTicks::Now() - last_request_started_time_; 299 base::TimeTicks::Now() - last_request_started_time_;
234 UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency); 300 UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency);
235 301
302 // Handle a successful blacklisting.
303 GURL blacklisted_url;
304 if (GetBlacklistedUrl(*source, &blacklisted_url)) {
305 blacklist_store_->RemoveUrl(blacklisted_url);
306 }
307
236 std::string suggestions_data; 308 std::string suggestions_data;
237 bool success = request->GetResponseAsString(&suggestions_data); 309 bool success = request->GetResponseAsString(&suggestions_data);
238 DCHECK(success); 310 DCHECK(success);
239 311
240 // Compute suggestions, and dispatch then to requestors. On error still 312 // Compute suggestions, and dispatch then to requestors. On error still
241 // dispatch empty suggestions. 313 // dispatch empty suggestions.
242 SuggestionsProfile suggestions; 314 SuggestionsProfile suggestions;
243 if (suggestions_data.empty()) { 315 if (suggestions_data.empty()) {
244 LogResponseState(RESPONSE_EMPTY); 316 LogResponseState(RESPONSE_EMPTY);
245 suggestions_store_->ClearSuggestions(); 317 suggestions_store_->ClearSuggestions();
246 } else if (suggestions.ParseFromString(suggestions_data)) { 318 } else if (suggestions.ParseFromString(suggestions_data)) {
247 LogResponseState(RESPONSE_VALID); 319 LogResponseState(RESPONSE_VALID);
248 thumbnail_manager_->InitializeThumbnailMap(suggestions); 320 thumbnail_manager_->InitializeThumbnailMap(suggestions);
249 suggestions_store_->StoreSuggestions(suggestions); 321 suggestions_store_->StoreSuggestions(suggestions);
250 } else { 322 } else {
251 LogResponseState(RESPONSE_INVALID); 323 LogResponseState(RESPONSE_INVALID);
252 suggestions_store_->LoadSuggestions(&suggestions); 324 suggestions_store_->LoadSuggestions(&suggestions);
253 } 325 }
254 326
255 DispatchRequestsAndClear(suggestions, &waiting_requestors_); 327 FilterAndServe(&suggestions);
328 ScheduleBlacklistUpload(true);
256 } 329 }
257 330
258 void SuggestionsService::Shutdown() { 331 void SuggestionsService::Shutdown() {
259 // Cancel pending request and timeout closure, then serve existing requestors 332 // Cancel pending request and timeout closure, then serve existing requestors
260 // from cache. 333 // from cache.
261 pending_request_.reset(NULL); 334 pending_request_.reset(NULL);
262 pending_timeout_closure_.reset(NULL); 335 pending_timeout_closure_.reset(NULL);
263 ServeFromCache(); 336 ServeFromCache();
264 } 337 }
265 338
266 bool SuggestionsService::IsBlacklistRequest(net::URLFetcher* request) const {
267 DCHECK(request);
268 return StartsWithASCII(request->GetOriginalURL().spec(),
269 blacklist_url_prefix_, true);
270 }
271
272 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) {
273 net::URLFetcher* request =
274 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this);
275 request->SetLoadFlags(net::LOAD_DISABLE_CACHE);
276 request->SetRequestContext(profile_->GetRequestContext());
277 // Add Chrome experiment state to the request headers.
278 net::HttpRequestHeaders headers;
279 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
280 request->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers);
281 request->SetExtraRequestHeaders(headers.ToString());
282 return request;
283 }
284
285 void SuggestionsService::ServeFromCache() { 339 void SuggestionsService::ServeFromCache() {
286 SuggestionsProfile suggestions; 340 SuggestionsProfile suggestions;
287 suggestions_store_->LoadSuggestions(&suggestions); 341 suggestions_store_->LoadSuggestions(&suggestions);
288 DispatchRequestsAndClear(suggestions, &waiting_requestors_); 342 FilterAndServe(&suggestions);
343 }
344
345 void SuggestionsService::FilterAndServe(SuggestionsProfile* suggestions) {
346 blacklist_store_->FilterSuggestions(suggestions);
347 DispatchRequestsAndClear(*suggestions, &waiting_requestors_);
348 }
349
350 void SuggestionsService::ScheduleBlacklistUpload(bool last_request_successful) {
351 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
352
353 UpdateBlacklistDelay(last_request_successful);
354
355 // Schedule a blacklist upload task.
356 GURL blacklist_url;
357 if (blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) {
358 base::Closure blacklist_cb =
359 base::Bind(&SuggestionsService::UploadOneFromBlacklist,
360 weak_ptr_factory_.GetWeakPtr());
361 BrowserThread::PostDelayedTask(
362 BrowserThread::UI, FROM_HERE, blacklist_cb,
363 base::TimeDelta::FromSeconds(blacklist_delay_sec_));
364 }
365 }
366
367 void SuggestionsService::UploadOneFromBlacklist() {
368 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
369
370 // If there's an ongoing request, let it complete.
371 if (pending_request_.get()) return;
372
373 GURL blacklist_url;
374 if (!blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url))
375 return; // Local blacklist is empty.
376
377 // Send blacklisting request.
378 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, blacklist_url));
379 }
380
381 void SuggestionsService::UpdateBlacklistDelay(bool last_request_successful) {
382 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
383
384 if (last_request_successful) {
385 blacklist_delay_sec_ = kBlacklistDefaultDelaySec;
386 } else {
387 unsigned int candidate_delay =
388 blacklist_delay_sec_ * kBlacklistBackoffMultiplier;
389 if (candidate_delay < kBlacklistMaxDelaySec)
390 blacklist_delay_sec_ = candidate_delay;
391 }
289 } 392 }
290 393
291 } // namespace suggestions 394 } // namespace suggestions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698