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

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: Base version 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 <string>
8
7 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
8 #include "base/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
9 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
10 #include "base/metrics/sparse_histogram.h" 12 #include "base/metrics/sparse_histogram.h"
11 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
12 #include "base/time/time.h" 14 #include "base/time/time.h"
13 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/history/history_types.h" 16 #include "chrome/browser/history/history_types.h"
15 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" 17 #include "chrome/browser/metrics/variations/variations_http_header_provider.h"
16 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/search/suggestions/blacklist_store.h"
17 #include "chrome/browser/search/suggestions/suggestions_store.h" 20 #include "chrome/browser/search/suggestions/suggestions_store.h"
18 #include "components/pref_registry/pref_registry_syncable.h" 21 #include "components/pref_registry/pref_registry_syncable.h"
19 #include "components/variations/variations_associated_data.h" 22 #include "components/variations/variations_associated_data.h"
20 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
21 #include "net/base/escape.h" 24 #include "net/base/escape.h"
22 #include "net/base/load_flags.h" 25 #include "net/base/load_flags.h"
23 #include "net/base/net_errors.h" 26 #include "net/base/net_errors.h"
27 #include "net/base/url_util.h"
24 #include "net/http/http_response_headers.h" 28 #include "net/http/http_response_headers.h"
25 #include "net/http/http_status_code.h" 29 #include "net/http/http_status_code.h"
26 #include "net/http/http_util.h" 30 #include "net/http/http_util.h"
27 #include "net/url_request/url_fetcher.h" 31 #include "net/url_request/url_fetcher.h"
28 #include "net/url_request/url_request_status.h" 32 #include "net/url_request/url_request_status.h"
29 #include "url/gurl.h" 33 #include "url/gurl.h"
30 34
31 using base::CancelableClosure; 35 using base::CancelableClosure;
32 using content::BrowserThread; 36 using content::BrowserThread;
33 37
(...skipping 21 matching lines...) Expand all
55 key); 59 key);
56 } 60 }
57 61
58 // Runs each callback in |requestors| on |suggestions|, then deallocates 62 // Runs each callback in |requestors| on |suggestions|, then deallocates
59 // |requestors|. 63 // |requestors|.
60 void DispatchRequestsAndClear( 64 void DispatchRequestsAndClear(
61 const SuggestionsProfile& suggestions, 65 const SuggestionsProfile& suggestions,
62 std::vector<SuggestionsService::ResponseCallback>* requestors) { 66 std::vector<SuggestionsService::ResponseCallback>* requestors) {
63 std::vector<SuggestionsService::ResponseCallback>::iterator it; 67 std::vector<SuggestionsService::ResponseCallback>::iterator it;
64 for (it = requestors->begin(); it != requestors->end(); ++it) { 68 for (it = requestors->begin(); it != requestors->end(); ++it) {
65 it->Run(suggestions); 69 if (!it->is_null()) it->Run(suggestions);
66 } 70 }
67 std::vector<SuggestionsService::ResponseCallback>().swap(*requestors); 71 std::vector<SuggestionsService::ResponseCallback>().swap(*requestors);
68 } 72 }
69 73
70 // Timeout before serving requestors after a fetch suggestions request has been 74 // Timeout before serving requestors after a fetch suggestions request has been
71 // issued. 75 // issued.
72 // TODO(manzagop): make this a Variations parameter to enable tweaking. 76 // TODO(manzagop): make this a Variations parameter to enable tweaking.
73 const unsigned int kRequestTimeoutMs = 200; 77 const unsigned int kRequestTimeoutMs = 200;
74 78
79 // Initial delay used when scheduling a blacklist request.
Mathieu 2014/06/17 14:51:15 nit: Initial -> Default? Also remove Initial from
manzagop (departed) 2014/06/17 15:42:23 Done.
80 const unsigned int kBlacklistInitialDelaySec = 1;
81
82 // Multiplier on the delay used when scheduling a blacklist request, in case the
83 // last observed request was unsuccessful.
84 const unsigned int kBlacklistBackoffMultiplier = 2;
85
86 // Maximum valid delay for scheduling a request. Candidate delays larger than
87 // this are rejected. This means the maximum backoff is at least 5400 / 2, ie
Mathieu 2014/06/17 14:51:15 *i.e.
manzagop (departed) 2014/06/17 15:42:23 Done.
88 // 45 minutes.
89 const unsigned int kBacklistMaxDelaySec = 5400;
Mathieu 2014/06/17 14:51:14 *Blacklist
Mathieu 2014/06/17 14:51:15 How do you pick this value? I think it should be m
manzagop (departed) 2014/06/17 15:42:23 Can this keep the phone awake and nuke the battery
manzagop (departed) 2014/06/17 15:42:23 Done.
Mathieu 2014/06/17 19:54:36 I don't think so, because this will not run if Chr
90
75 } // namespace 91 } // namespace
76 92
77 const char kSuggestionsFieldTrialName[] = "ChromeSuggestions"; 93 const char kSuggestionsFieldTrialName[] = "ChromeSuggestions";
78 const char kSuggestionsFieldTrialURLParam[] = "url"; 94 const char kSuggestionsFieldTrialURLParam[] = "url";
79 const char kSuggestionsFieldTrialSuggestionsSuffixParam[] = 95 const char kSuggestionsFieldTrialSuggestionsSuffixParam[] =
80 "suggestions_suffix"; 96 "suggestions_suffix";
81 const char kSuggestionsFieldTrialBlacklistSuffixParam[] = "blacklist_suffix"; 97 const char kSuggestionsFieldTrialBlacklistSuffixParam[] = "blacklist_suffix";
82 const char kSuggestionsFieldTrialStateParam[] = "state"; 98 const char kSuggestionsFieldTrialStateParam[] = "state";
83 const char kSuggestionsFieldTrialStateEnabled[] = "enabled"; 99 const char kSuggestionsFieldTrialStateEnabled[] = "enabled";
84 100
85 SuggestionsService::SuggestionsService( 101 SuggestionsService::SuggestionsService(
Mathieu 2014/06/17 14:51:14 I think somewhere in the construction path (or som
manzagop (departed) 2014/06/17 15:42:23 An upload will happen after the first attempt to g
Mathieu 2014/06/17 19:54:36 No, but we should make sure that the blacklist doe
86 Profile* profile, scoped_ptr<SuggestionsStore> suggestions_store) 102 Profile* profile, scoped_ptr<SuggestionsStore> suggestions_store,
103 scoped_ptr<BlacklistStore> blacklist_store)
87 : suggestions_store_(suggestions_store.Pass()), 104 : suggestions_store_(suggestions_store.Pass()),
105 blacklist_store_(blacklist_store.Pass()),
88 thumbnail_manager_(new ThumbnailManager(profile)), 106 thumbnail_manager_(new ThumbnailManager(profile)),
89 profile_(profile), 107 profile_(profile),
108 blacklist_delay_sec_(kBlacklistInitialDelaySec),
90 weak_ptr_factory_(this) { 109 weak_ptr_factory_(this) {
91 // Obtain the URL to use to fetch suggestions data from the Variations param. 110 // Obtain the URL to use to fetch suggestions data from the Variations param.
92 suggestions_url_ = 111 suggestions_url_ =
93 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + 112 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) +
94 GetExperimentParam(kSuggestionsFieldTrialSuggestionsSuffixParam)); 113 GetExperimentParam(kSuggestionsFieldTrialSuggestionsSuffixParam));
95 blacklist_url_prefix_ = 114 blacklist_url_prefix_ =
96 GetExperimentParam(kSuggestionsFieldTrialURLParam) + 115 GetExperimentParam(kSuggestionsFieldTrialURLParam) +
97 GetExperimentParam(kSuggestionsFieldTrialBlacklistSuffixParam); 116 GetExperimentParam(kSuggestionsFieldTrialBlacklistSuffixParam);
98 } 117 }
99 118
(...skipping 25 matching lines...) Expand all
125 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 144 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
126 if (pending_request_.get()) { 145 if (pending_request_.get()) {
127 // Request already exists, so just add requestor to queue. 146 // Request already exists, so just add requestor to queue.
128 waiting_requestors_.push_back(callback); 147 waiting_requestors_.push_back(callback);
129 return; 148 return;
130 } 149 }
131 150
132 // Form new request. 151 // Form new request.
133 DCHECK(waiting_requestors_.empty()); 152 DCHECK(waiting_requestors_.empty());
134 waiting_requestors_.push_back(callback); 153 waiting_requestors_.push_back(callback);
135 154 IssueRequest(suggestions_url_);
136 pending_request_.reset(CreateSuggestionsRequest(suggestions_url_));
137 pending_request_->Start();
138 last_request_started_time_ = base::TimeTicks::Now();
139 } 155 }
140 156
141 void SuggestionsService::GetPageThumbnail( 157 void SuggestionsService::GetPageThumbnail(
142 const GURL& url, 158 const GURL& url,
143 base::Callback<void(const GURL&, const SkBitmap*)> callback) { 159 base::Callback<void(const GURL&, const SkBitmap*)> callback) {
144 thumbnail_manager_->GetPageThumbnail(url, callback); 160 thumbnail_manager_->GetPageThumbnail(url, callback);
145 } 161 }
146 162
147 void SuggestionsService::BlacklistURL( 163 void SuggestionsService::BlacklistURL(
148 const GURL& candidate_url, SuggestionsService::ResponseCallback callback) { 164 const GURL& candidate_url,
165 const SuggestionsService::ResponseCallback& callback) {
149 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 166 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
150 waiting_requestors_.push_back(callback); 167 waiting_requestors_.push_back(callback);
151 168
152 if (pending_request_.get()) { 169 // Blacklist locally, for immediate effect.
153 if (IsBlacklistRequest(pending_request_.get())) { 170 if (!blacklist_store_->BlacklistUrl(candidate_url))
154 // Pending request is a blacklist request. Silently drop the new blacklist 171 DVLOG(1) << "Failed blacklisting attempt.";
155 // request. TODO - handle this case. 172
156 return; 173 // If there's an ongoing request, let it complete.
157 } else { 174 if (pending_request_.get()) return;
158 // Pending request is not a blacklist request - cancel it and go on to
159 // issuing a blacklist request. Also ensure the timeout closure does not
160 // run; instead we'll wait for the updated suggestions before servicing
161 // requestors.
162 pending_request_.reset(NULL);
163 pending_timeout_closure_.reset(NULL);
164 }
165 }
166 175
167 // Send blacklisting request. 176 // Send blacklisting request.
168 // TODO(manzagop): make this a PUT request instead of a GET request.
169 GURL url(blacklist_url_prefix_ + 177 GURL url(blacklist_url_prefix_ +
170 net::EscapeQueryParamValue(candidate_url.spec(), true)); 178 net::EscapeQueryParamValue(candidate_url.spec(), true));
171 pending_request_.reset(CreateSuggestionsRequest(url)); 179 IssueRequest(url);
172 pending_request_->Start(); 180 }
173 last_request_started_time_ = base::TimeTicks::Now(); 181
182 void SuggestionsService::UploadBlacklist() {
183 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
184
185 // If there's an ongoing request, let it complete.
186 if (pending_request_.get()) return;
187
188 GURL blacklist_url;
189 if (!blacklist_store_->GetSomeBlacklistedUrl(&blacklist_url))
190 return; // Local blacklist is empty.
191
192 // Send blacklisting request.
193 GURL url(blacklist_url_prefix_ +
194 net::EscapeQueryParamValue(blacklist_url.spec(), true));
195 IssueRequest(url);
196 }
197
198 // static
199 bool SuggestionsService::IsBlacklistRequest(const net::URLFetcher& request) {
200 std::string blacklist_url_prefix =
201 GetExperimentParam(kSuggestionsFieldTrialURLParam) +
202 GetExperimentParam(kSuggestionsFieldTrialBlacklistSuffixParam);
203 return StartsWithASCII(request.GetOriginalURL().spec(), blacklist_url_prefix,
204 true);
205 }
206
207 // static
208 bool SuggestionsService::GetBlacklistedUrl(const net::URLFetcher& request,
209 GURL* url) {
210 if (!IsBlacklistRequest(request)) return false;
211
212 std::string blacklisted;
213 // TODO(manzagop): don't hardcode the parameter name. DONOTSUBMIT!
214 if (!net::GetValueForKeyInQuery(request.GetOriginalURL(), std::string("url"),
215 &blacklisted))
216 return false;
217
218 GURL blacklisted_url(blacklisted);
219 blacklisted_url.Swap(url);
220 return true;
174 } 221 }
175 222
176 // static 223 // static
177 void SuggestionsService::RegisterProfilePrefs( 224 void SuggestionsService::RegisterProfilePrefs(
178 user_prefs::PrefRegistrySyncable* registry) { 225 user_prefs::PrefRegistrySyncable* registry) {
179 SuggestionsStore::RegisterProfilePrefs(registry); 226 SuggestionsStore::RegisterProfilePrefs(registry);
227 BlacklistStore::RegisterProfilePrefs(registry);
180 } 228 }
181 229
182 void SuggestionsService::OnRequestTimeout() { 230 void SuggestionsService::OnRequestTimeout() {
183 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 231 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
184 ServeFromCache(); 232 ServeFromCache();
185 } 233 }
186 234
187 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { 235 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) {
188 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 236 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
189 DCHECK_EQ(pending_request_.get(), source); 237 DCHECK_EQ(pending_request_.get(), source);
190 238
191 // We no longer need the timeout closure. Delete it whether or not it has run 239 // We no longer need the timeout closure. Delete it whether or not it has run.
192 // (if it hasn't, this cancels it). 240 // If it hasn't, this cancels it.
193 pending_timeout_closure_.reset(); 241 pending_timeout_closure_.reset();
194 242
195 // The fetcher will be deleted when the request is handled. 243 // The fetcher will be deleted when the request is handled.
196 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); 244 scoped_ptr<const net::URLFetcher> request(pending_request_.release());
197 const net::URLRequestStatus& request_status = request->GetStatus(); 245 const net::URLRequestStatus& request_status = request->GetStatus();
198 if (request_status.status() != net::URLRequestStatus::SUCCESS) { 246 if (request_status.status() != net::URLRequestStatus::SUCCESS) {
199 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", 247 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode",
200 -request_status.error()); 248 -request_status.error());
201 DVLOG(1) << "Suggestions server request failed with error: " 249 DVLOG(1) << "Suggestions server request failed with error: "
202 << request_status.error() << ": " 250 << request_status.error() << ": "
203 << net::ErrorToString(request_status.error()); 251 << net::ErrorToString(request_status.error());
204 // Dispatch the cached profile on error. 252 // Dispatch the cached profile on error.
205 ServeFromCache(); 253 ServeFromCache();
254 ScheduleBlacklistUpload(false);
206 return; 255 return;
207 } 256 }
208 257
209 // Log the response code. 258 // Log the response code.
210 const int response_code = request->GetResponseCode(); 259 const int response_code = request->GetResponseCode();
211 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code); 260 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FetchResponseCode", response_code);
212 if (response_code != net::HTTP_OK) { 261 if (response_code != net::HTTP_OK) {
213 // Aggressively clear the store. 262 // Aggressively clear the store.
214 suggestions_store_->ClearSuggestions(); 263 suggestions_store_->ClearSuggestions();
215 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); 264 SuggestionsProfile suggestions;
265 FilterAndServe(&suggestions);
Mathieu 2014/06/17 14:51:14 If it's an empty profile, why not keep DispatchReq
manzagop (departed) 2014/06/17 15:42:23 Done.
266 ScheduleBlacklistUpload(false);
216 return; 267 return;
217 } 268 }
218 269
219 const base::TimeDelta latency = 270 const base::TimeDelta latency =
220 base::TimeTicks::Now() - last_request_started_time_; 271 base::TimeTicks::Now() - last_request_started_time_;
221 UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency); 272 UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency);
222 273
274 // Handle a successful blacklisting.
275 GURL blacklisted_url;
276 if (GetBlacklistedUrl(*source, &blacklisted_url)) {
277 blacklist_store_->RemoveUrl(blacklisted_url);
278 }
279
223 std::string suggestions_data; 280 std::string suggestions_data;
224 bool success = request->GetResponseAsString(&suggestions_data); 281 bool success = request->GetResponseAsString(&suggestions_data);
225 DCHECK(success); 282 DCHECK(success);
226 283
227 // Compute suggestions, and dispatch then to requestors. On error still 284 // Compute suggestions, and dispatch then to requestors. On error still
228 // dispatch empty suggestions. 285 // dispatch empty suggestions.
229 SuggestionsProfile suggestions; 286 SuggestionsProfile suggestions;
230 if (suggestions_data.empty()) { 287 if (suggestions_data.empty()) {
231 LogResponseState(RESPONSE_EMPTY); 288 LogResponseState(RESPONSE_EMPTY);
232 suggestions_store_->ClearSuggestions(); 289 suggestions_store_->ClearSuggestions();
233 } else if (suggestions.ParseFromString(suggestions_data)) { 290 } else if (suggestions.ParseFromString(suggestions_data)) {
234 LogResponseState(RESPONSE_VALID); 291 LogResponseState(RESPONSE_VALID);
235 thumbnail_manager_->InitializeThumbnailMap(suggestions); 292 thumbnail_manager_->InitializeThumbnailMap(suggestions);
236 suggestions_store_->StoreSuggestions(suggestions); 293 suggestions_store_->StoreSuggestions(suggestions);
237 } else { 294 } else {
238 LogResponseState(RESPONSE_INVALID); 295 LogResponseState(RESPONSE_INVALID);
239 suggestions_store_->LoadSuggestions(&suggestions); 296 suggestions_store_->LoadSuggestions(&suggestions);
240 } 297 }
241 298
242 DispatchRequestsAndClear(suggestions, &waiting_requestors_); 299 FilterAndServe(&suggestions);
300 ScheduleBlacklistUpload(true);
243 } 301 }
244 302
245 void SuggestionsService::Shutdown() { 303 void SuggestionsService::Shutdown() {
246 // Cancel pending request and timeout closure, then serve existing requestors 304 // Cancel pending request and timeout closure, then serve existing requestors
247 // from cache. 305 // from cache.
248 pending_request_.reset(NULL); 306 pending_request_.reset(NULL);
249 pending_timeout_closure_.reset(NULL); 307 pending_timeout_closure_.reset(NULL);
250 ServeFromCache(); 308 ServeFromCache();
251 } 309 }
252 310
253 bool SuggestionsService::IsBlacklistRequest(net::URLFetcher* request) const {
254 DCHECK(request);
255 return StartsWithASCII(request->GetOriginalURL().spec(),
256 blacklist_url_prefix_, true);
257 }
258
259 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) { 311 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) {
260 net::URLFetcher* request = 312 net::URLFetcher* request =
261 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this); 313 net::URLFetcher::Create(0, url, net::URLFetcher::GET, this);
262 request->SetLoadFlags(net::LOAD_DISABLE_CACHE); 314 request->SetLoadFlags(net::LOAD_DISABLE_CACHE);
263 request->SetRequestContext(profile_->GetRequestContext()); 315 request->SetRequestContext(profile_->GetRequestContext());
264 // Add Chrome experiment state to the request headers. 316 // Add Chrome experiment state to the request headers.
265 net::HttpRequestHeaders headers; 317 net::HttpRequestHeaders headers;
266 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( 318 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
267 request->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); 319 request->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers);
268 request->SetExtraRequestHeaders(headers.ToString()); 320 request->SetExtraRequestHeaders(headers.ToString());
269 return request; 321 return request;
270 } 322 }
271 323
324 void SuggestionsService::IssueRequest(const GURL& url) {
Mathieu 2014/06/17 14:51:14 very nit: I would have this before OnURLFetchCompl
manzagop (departed) 2014/06/17 15:42:24 Done.
325 pending_request_.reset(CreateSuggestionsRequest(url));
326 pending_request_->Start();
327 last_request_started_time_ = base::TimeTicks::Now();
328 }
329
272 void SuggestionsService::ServeFromCache() { 330 void SuggestionsService::ServeFromCache() {
273 SuggestionsProfile suggestions; 331 SuggestionsProfile suggestions;
274 suggestions_store_->LoadSuggestions(&suggestions); 332 suggestions_store_->LoadSuggestions(&suggestions);
275 DispatchRequestsAndClear(suggestions, &waiting_requestors_); 333 FilterAndServe(&suggestions);
334 }
335
336 void SuggestionsService::FilterAndServe(SuggestionsProfile* suggestions) {
337 blacklist_store_->FilterSuggestions(suggestions);
338 DispatchRequestsAndClear(*suggestions, &waiting_requestors_);
339 }
340
341 void SuggestionsService::ScheduleBlacklistUpload(bool last_request_successful) {
342 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
343
344 // Update the scheduling delay.
345 if (last_request_successful) {
346 blacklist_delay_sec_ = kBlacklistInitialDelaySec;
347 } else {
348 unsigned int candidate_delay =
349 blacklist_delay_sec_ * kBlacklistBackoffMultiplier;
350 if (candidate_delay < kBacklistMaxDelaySec)
351 blacklist_delay_sec_ = candidate_delay;
352 }
353
354 // Schedule a blacklist upload task.
355 GURL blacklist_url;
356 if (blacklist_store_->GetSomeBlacklistedUrl(&blacklist_url)) {
Mathieu 2014/06/17 14:51:14 Again "Some" seems random.
manzagop (departed) 2014/06/17 15:42:23 Done.
357 base::Closure blacklist_cb = base::Bind(
358 &SuggestionsService::UploadBlacklist, weak_ptr_factory_.GetWeakPtr());
359 BrowserThread::PostDelayedTask(
360 BrowserThread::UI, FROM_HERE, blacklist_cb,
361 base::TimeDelta::FromSeconds(blacklist_delay_sec_));
362 }
276 } 363 }
277 364
278 } // namespace suggestions 365 } // namespace suggestions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698