OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |