 Chromium Code Reviews
 Chromium Code Reviews Issue 410673002:
  [Suggestions] Moving suggestions code to a new component  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 410673002:
  [Suggestions] Moving suggestions code to a new component  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| 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 |