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 "components/suggestions/suggestions_service.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/metrics/sparse_histogram.h" | 12 #include "base/metrics/sparse_histogram.h" |
13 #include "base/single_thread_task_runner.h" | |
13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
15 #include "base/time/time.h" | 16 #include "base/time/time.h" |
16 #include "chrome/browser/search/suggestions/blacklist_store.h" | |
17 #include "chrome/browser/search/suggestions/suggestions_store.h" | |
18 #include "components/pref_registry/pref_registry_syncable.h" | 17 #include "components/pref_registry/pref_registry_syncable.h" |
18 #include "components/suggestions/blacklist_store.h" | |
19 #include "components/suggestions/suggestions_store.h" | |
19 #include "components/variations/variations_associated_data.h" | 20 #include "components/variations/variations_associated_data.h" |
20 #include "components/variations/variations_http_header_provider.h" | 21 #include "components/variations/variations_http_header_provider.h" |
21 #include "content/public/browser/browser_thread.h" | |
22 #include "net/base/escape.h" | 22 #include "net/base/escape.h" |
23 #include "net/base/load_flags.h" | 23 #include "net/base/load_flags.h" |
24 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
25 #include "net/base/url_util.h" | 25 #include "net/base/url_util.h" |
26 #include "net/http/http_response_headers.h" | 26 #include "net/http/http_response_headers.h" |
27 #include "net/http/http_status_code.h" | 27 #include "net/http/http_status_code.h" |
28 #include "net/http/http_util.h" | 28 #include "net/http/http_util.h" |
29 #include "net/url_request/url_fetcher.h" | 29 #include "net/url_request/url_fetcher.h" |
30 #include "net/url_request/url_request_status.h" | 30 #include "net/url_request/url_request_status.h" |
31 #include "url/gurl.h" | 31 #include "url/gurl.h" |
32 | 32 |
33 using base::CancelableClosure; | 33 using base::CancelableClosure; |
34 using content::BrowserThread; | |
35 | 34 |
36 namespace suggestions { | 35 namespace suggestions { |
37 | 36 |
38 namespace { | 37 namespace { |
39 | 38 |
40 // Used to UMA log the state of the last response from the server. | 39 // Used to UMA log the state of the last response from the server. |
41 enum SuggestionsResponseState { | 40 enum SuggestionsResponseState { |
42 RESPONSE_EMPTY, | 41 RESPONSE_EMPTY, |
43 RESPONSE_INVALID, | 42 RESPONSE_INVALID, |
44 RESPONSE_VALID, | 43 RESPONSE_VALID, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 << GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam) << "="; | 112 << GetExperimentParam(kSuggestionsFieldTrialBlacklistUrlParam) << "="; |
114 return blacklist_url_prefix_stream.str(); | 113 return blacklist_url_prefix_stream.str(); |
115 } | 114 } |
116 | 115 |
117 } // namespace | 116 } // namespace |
118 | 117 |
119 SuggestionsService::SuggestionsService( | 118 SuggestionsService::SuggestionsService( |
120 net::URLRequestContextGetter* url_request_context, | 119 net::URLRequestContextGetter* url_request_context, |
121 scoped_ptr<SuggestionsStore> suggestions_store, | 120 scoped_ptr<SuggestionsStore> suggestions_store, |
122 scoped_ptr<ImageManager> thumbnail_manager, | 121 scoped_ptr<ImageManager> thumbnail_manager, |
123 scoped_ptr<BlacklistStore> blacklist_store) | 122 scoped_ptr<BlacklistStore> blacklist_store, |
124 : suggestions_store_(suggestions_store.Pass()), | 123 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) |
blundell
2014/07/24 08:31:45
It looks like this object is created and used enti
| |
124 : ui_task_runner_(ui_task_runner), | |
125 suggestions_store_(suggestions_store.Pass()), | |
125 blacklist_store_(blacklist_store.Pass()), | 126 blacklist_store_(blacklist_store.Pass()), |
126 thumbnail_manager_(thumbnail_manager.Pass()), | 127 thumbnail_manager_(thumbnail_manager.Pass()), |
127 url_request_context_(url_request_context), | 128 url_request_context_(url_request_context), |
128 blacklist_delay_sec_(kBlacklistDefaultDelaySec), | 129 blacklist_delay_sec_(kBlacklistDefaultDelaySec), |
129 weak_ptr_factory_(this), | 130 weak_ptr_factory_(this), |
130 request_timeout_ms_(kDefaultRequestTimeoutMs) { | 131 request_timeout_ms_(kDefaultRequestTimeoutMs) { |
131 // Obtain various parameters from Variations. | 132 // Obtain various parameters from Variations. |
132 suggestions_url_ = | 133 suggestions_url_ = |
133 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + "?" + | 134 GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam) + "?" + |
134 GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam)); | 135 GetExperimentParam(kSuggestionsFieldTrialCommonParamsParam)); |
(...skipping 14 matching lines...) Expand all Loading... | |
149 } | 150 } |
150 | 151 |
151 // static | 152 // static |
152 bool SuggestionsService::IsControlGroup() { | 153 bool SuggestionsService::IsControlGroup() { |
153 return GetExperimentParam(kSuggestionsFieldTrialControlParam) == | 154 return GetExperimentParam(kSuggestionsFieldTrialControlParam) == |
154 kSuggestionsFieldTrialStateEnabled; | 155 kSuggestionsFieldTrialStateEnabled; |
155 } | 156 } |
156 | 157 |
157 void SuggestionsService::FetchSuggestionsData( | 158 void SuggestionsService::FetchSuggestionsData( |
158 SuggestionsService::ResponseCallback callback) { | 159 SuggestionsService::ResponseCallback callback) { |
159 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 160 DCHECK(thread_checker_.CalledOnValidThread()); |
160 | 161 |
161 FetchSuggestionsDataNoTimeout(callback); | 162 FetchSuggestionsDataNoTimeout(callback); |
162 | 163 |
163 // Post a task to serve the cached suggestions if the request hasn't completed | 164 // Post a task to serve the cached suggestions if the request hasn't completed |
164 // after some time. Cancels the previous such task, if one existed. | 165 // after some time. Cancels the previous such task, if one existed. |
165 pending_timeout_closure_.reset(new CancelableClosure(base::Bind( | 166 pending_timeout_closure_.reset(new CancelableClosure(base::Bind( |
166 &SuggestionsService::OnRequestTimeout, weak_ptr_factory_.GetWeakPtr()))); | 167 &SuggestionsService::OnRequestTimeout, weak_ptr_factory_.GetWeakPtr()))); |
167 BrowserThread::PostDelayedTask( | 168 ui_task_runner_->PostDelayedTask( |
168 BrowserThread::UI, FROM_HERE, pending_timeout_closure_->callback(), | 169 FROM_HERE, pending_timeout_closure_->callback(), |
169 base::TimeDelta::FromMilliseconds(request_timeout_ms_)); | 170 base::TimeDelta::FromMilliseconds(request_timeout_ms_)); |
170 } | 171 } |
171 | 172 |
172 void SuggestionsService::FetchSuggestionsDataNoTimeout( | 173 void SuggestionsService::FetchSuggestionsDataNoTimeout( |
173 SuggestionsService::ResponseCallback callback) { | 174 SuggestionsService::ResponseCallback callback) { |
174 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 175 DCHECK(thread_checker_.CalledOnValidThread()); |
175 if (pending_request_.get()) { | 176 if (pending_request_.get()) { |
176 // Request already exists, so just add requestor to queue. | 177 // Request already exists, so just add requestor to queue. |
177 waiting_requestors_.push_back(callback); | 178 waiting_requestors_.push_back(callback); |
178 return; | 179 return; |
179 } | 180 } |
180 | 181 |
181 // Form new request. | 182 // Form new request. |
182 DCHECK(waiting_requestors_.empty()); | 183 DCHECK(waiting_requestors_.empty()); |
183 waiting_requestors_.push_back(callback); | 184 waiting_requestors_.push_back(callback); |
184 IssueRequest(suggestions_url_); | 185 IssueRequest(suggestions_url_); |
185 } | 186 } |
186 | 187 |
187 void SuggestionsService::GetPageThumbnail( | 188 void SuggestionsService::GetPageThumbnail( |
188 const GURL& url, | 189 const GURL& url, |
189 base::Callback<void(const GURL&, const SkBitmap*)> callback) { | 190 base::Callback<void(const GURL&, const SkBitmap*)> callback) { |
190 thumbnail_manager_->GetImageForURL(url, callback); | 191 thumbnail_manager_->GetImageForURL(url, callback); |
191 } | 192 } |
192 | 193 |
193 void SuggestionsService::BlacklistURL( | 194 void SuggestionsService::BlacklistURL( |
194 const GURL& candidate_url, | 195 const GURL& candidate_url, |
195 const SuggestionsService::ResponseCallback& callback) { | 196 const SuggestionsService::ResponseCallback& callback) { |
196 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 197 DCHECK(thread_checker_.CalledOnValidThread()); |
197 waiting_requestors_.push_back(callback); | 198 waiting_requestors_.push_back(callback); |
198 | 199 |
199 // Blacklist locally, for immediate effect. | 200 // Blacklist locally, for immediate effect. |
200 if (!blacklist_store_->BlacklistUrl(candidate_url)) { | 201 if (!blacklist_store_->BlacklistUrl(candidate_url)) { |
201 DVLOG(1) << "Failed blacklisting attempt."; | 202 DVLOG(1) << "Failed blacklisting attempt."; |
202 return; | 203 return; |
203 } | 204 } |
204 | 205 |
205 // If there's an ongoing request, let it complete. | 206 // If there's an ongoing request, let it complete. |
206 if (pending_request_.get()) return; | 207 if (pending_request_.get()) return; |
207 | |
208 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, candidate_url)); | 208 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, candidate_url)); |
209 } | 209 } |
210 | 210 |
211 // static | 211 // static |
212 bool SuggestionsService::GetBlacklistedUrl(const net::URLFetcher& request, | 212 bool SuggestionsService::GetBlacklistedUrl(const net::URLFetcher& request, |
213 GURL* url) { | 213 GURL* url) { |
214 bool is_blacklist_request = StartsWithASCII(request.GetOriginalURL().spec(), | 214 bool is_blacklist_request = StartsWithASCII(request.GetOriginalURL().spec(), |
215 GetBlacklistUrlPrefix(), true); | 215 GetBlacklistUrlPrefix(), true); |
216 if (!is_blacklist_request) return false; | 216 if (!is_blacklist_request) return false; |
217 | 217 |
(...skipping 30 matching lines...) Expand all Loading... | |
248 request->SetRequestContext(url_request_context_); | 248 request->SetRequestContext(url_request_context_); |
249 // Add Chrome experiment state to the request headers. | 249 // Add Chrome experiment state to the request headers. |
250 net::HttpRequestHeaders headers; | 250 net::HttpRequestHeaders headers; |
251 variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( | 251 variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( |
252 request->GetOriginalURL(), false, false, &headers); | 252 request->GetOriginalURL(), false, false, &headers); |
253 request->SetExtraRequestHeaders(headers.ToString()); | 253 request->SetExtraRequestHeaders(headers.ToString()); |
254 return request; | 254 return request; |
255 } | 255 } |
256 | 256 |
257 void SuggestionsService::OnRequestTimeout() { | 257 void SuggestionsService::OnRequestTimeout() { |
258 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 258 DCHECK(thread_checker_.CalledOnValidThread()); |
259 ServeFromCache(); | 259 ServeFromCache(); |
260 } | 260 } |
261 | 261 |
262 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { | 262 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { |
263 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 263 DCHECK(thread_checker_.CalledOnValidThread()); |
264 DCHECK_EQ(pending_request_.get(), source); | 264 DCHECK_EQ(pending_request_.get(), source); |
265 | |
266 // We no longer need the timeout closure. Delete it whether or not it has run. | 265 // We no longer need the timeout closure. Delete it whether or not it has run. |
267 // If it hasn't, this cancels it. | 266 // If it hasn't, this cancels it. |
268 pending_timeout_closure_.reset(); | 267 pending_timeout_closure_.reset(); |
269 | 268 |
270 // The fetcher will be deleted when the request is handled. | 269 // The fetcher will be deleted when the request is handled. |
271 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); | 270 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); |
272 const net::URLRequestStatus& request_status = request->GetStatus(); | 271 const net::URLRequestStatus& request_status = request->GetStatus(); |
273 if (request_status.status() != net::URLRequestStatus::SUCCESS) { | 272 if (request_status.status() != net::URLRequestStatus::SUCCESS) { |
274 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", | 273 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", |
275 -request_status.error()); | 274 -request_status.error()); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 suggestions_store_->LoadSuggestions(&suggestions); | 338 suggestions_store_->LoadSuggestions(&suggestions); |
340 FilterAndServe(&suggestions); | 339 FilterAndServe(&suggestions); |
341 } | 340 } |
342 | 341 |
343 void SuggestionsService::FilterAndServe(SuggestionsProfile* suggestions) { | 342 void SuggestionsService::FilterAndServe(SuggestionsProfile* suggestions) { |
344 blacklist_store_->FilterSuggestions(suggestions); | 343 blacklist_store_->FilterSuggestions(suggestions); |
345 DispatchRequestsAndClear(*suggestions, &waiting_requestors_); | 344 DispatchRequestsAndClear(*suggestions, &waiting_requestors_); |
346 } | 345 } |
347 | 346 |
348 void SuggestionsService::ScheduleBlacklistUpload(bool last_request_successful) { | 347 void SuggestionsService::ScheduleBlacklistUpload(bool last_request_successful) { |
349 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 348 DCHECK(thread_checker_.CalledOnValidThread()); |
350 | 349 |
351 UpdateBlacklistDelay(last_request_successful); | 350 UpdateBlacklistDelay(last_request_successful); |
352 | 351 |
353 // Schedule a blacklist upload task. | 352 // Schedule a blacklist upload task. |
354 GURL blacklist_url; | 353 GURL blacklist_url; |
355 if (blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) { | 354 if (blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) { |
356 base::Closure blacklist_cb = | 355 base::Closure blacklist_cb = |
357 base::Bind(&SuggestionsService::UploadOneFromBlacklist, | 356 base::Bind(&SuggestionsService::UploadOneFromBlacklist, |
358 weak_ptr_factory_.GetWeakPtr()); | 357 weak_ptr_factory_.GetWeakPtr()); |
359 BrowserThread::PostDelayedTask( | 358 ui_task_runner_->PostDelayedTask( |
360 BrowserThread::UI, FROM_HERE, blacklist_cb, | 359 FROM_HERE, blacklist_cb, |
361 base::TimeDelta::FromSeconds(blacklist_delay_sec_)); | 360 base::TimeDelta::FromSeconds(blacklist_delay_sec_)); |
362 } | 361 } |
363 } | 362 } |
364 | 363 |
365 void SuggestionsService::UploadOneFromBlacklist() { | 364 void SuggestionsService::UploadOneFromBlacklist() { |
366 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 365 DCHECK(thread_checker_.CalledOnValidThread()); |
367 | 366 |
368 // If there's an ongoing request, let it complete. | 367 // If there's an ongoing request, let it complete. |
369 if (pending_request_.get()) return; | 368 if (pending_request_.get()) return; |
370 | 369 |
371 GURL blacklist_url; | 370 GURL blacklist_url; |
372 if (!blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) | 371 if (!blacklist_store_->GetFirstUrlFromBlacklist(&blacklist_url)) |
373 return; // Local blacklist is empty. | 372 return; // Local blacklist is empty. |
374 | 373 |
375 // Send blacklisting request. | 374 // Send blacklisting request. |
376 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, blacklist_url)); | 375 IssueRequest(BuildBlacklistRequestURL(blacklist_url_prefix_, blacklist_url)); |
377 } | 376 } |
378 | 377 |
379 void SuggestionsService::UpdateBlacklistDelay(bool last_request_successful) { | 378 void SuggestionsService::UpdateBlacklistDelay(bool last_request_successful) { |
380 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 379 DCHECK(thread_checker_.CalledOnValidThread()); |
381 | 380 |
382 if (last_request_successful) { | 381 if (last_request_successful) { |
383 blacklist_delay_sec_ = kBlacklistDefaultDelaySec; | 382 blacklist_delay_sec_ = kBlacklistDefaultDelaySec; |
384 } else { | 383 } else { |
385 int candidate_delay = blacklist_delay_sec_ * kBlacklistBackoffMultiplier; | 384 int candidate_delay = blacklist_delay_sec_ * kBlacklistBackoffMultiplier; |
386 if (candidate_delay < kBlacklistMaxDelaySec) | 385 if (candidate_delay < kBlacklistMaxDelaySec) |
387 blacklist_delay_sec_ = candidate_delay; | 386 blacklist_delay_sec_ = candidate_delay; |
388 } | 387 } |
389 } | 388 } |
390 | 389 |
391 } // namespace suggestions | 390 } // namespace suggestions |
OLD | NEW |