Chromium Code Reviews| 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 "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/metrics/sparse_histogram.h" | 10 #include "base/metrics/sparse_histogram.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
| 13 #include "chrome/browser/history/history_types.h" | 13 #include "chrome/browser/history/history_types.h" |
| 14 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" | 14 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "components/variations/variations_associated_data.h" | 16 #include "components/variations/variations_associated_data.h" |
| 17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 18 #include "net/base/escape.h" | |
| 18 #include "net/base/load_flags.h" | 19 #include "net/base/load_flags.h" |
| 19 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 20 #include "net/http/http_response_headers.h" | 21 #include "net/http/http_response_headers.h" |
| 21 #include "net/http/http_status_code.h" | 22 #include "net/http/http_status_code.h" |
| 22 #include "net/http/http_util.h" | 23 #include "net/http/http_util.h" |
| 23 #include "net/url_request/url_fetcher.h" | 24 #include "net/url_request/url_fetcher.h" |
| 24 #include "net/url_request/url_request_status.h" | 25 #include "net/url_request/url_request_status.h" |
| 25 #include "url/gurl.h" | 26 #include "url/gurl.h" |
| 26 | 27 |
| 27 namespace suggestions { | 28 namespace suggestions { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 57 for (it = requestors->begin(); it != requestors->end(); ++it) { | 58 for (it = requestors->begin(); it != requestors->end(); ++it) { |
| 58 it->Run(suggestions); | 59 it->Run(suggestions); |
| 59 } | 60 } |
| 60 std::vector<SuggestionsService::ResponseCallback>().swap(*requestors); | 61 std::vector<SuggestionsService::ResponseCallback>().swap(*requestors); |
| 61 } | 62 } |
| 62 | 63 |
| 63 } // namespace | 64 } // namespace |
| 64 | 65 |
| 65 const char kSuggestionsFieldTrialName[] = "ChromeSuggestions"; | 66 const char kSuggestionsFieldTrialName[] = "ChromeSuggestions"; |
| 66 const char kSuggestionsFieldTrialURLParam[] = "url"; | 67 const char kSuggestionsFieldTrialURLParam[] = "url"; |
| 68 const char kSuggestionsFieldTrialSuggestionsSuffixParam[] = | |
| 69 "suggestions_suffix"; | |
| 70 const char kSuggestionsFieldTrialBlacklistSuffixParam[] = "blacklist_suffix"; | |
| 67 const char kSuggestionsFieldTrialStateParam[] = "state"; | 71 const char kSuggestionsFieldTrialStateParam[] = "state"; |
| 68 const char kSuggestionsFieldTrialStateEnabled[] = "enabled"; | 72 const char kSuggestionsFieldTrialStateEnabled[] = "enabled"; |
| 69 | 73 |
| 70 SuggestionsService::SuggestionsService(Profile* profile) | 74 SuggestionsService::SuggestionsService(Profile* profile) |
| 71 : profile_(profile) { | 75 : profile_(profile) { |
| 72 // Obtain the URL to use to fetch suggestions data from the Variations param. | 76 // Obtain the URL to use to fetch suggestions data from the Variations param. |
| 73 suggestions_url_ = GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam)); | 77 suggestions_url_ = GURL( |
| 78 GetExperimentParam(kSuggestionsFieldTrialURLParam) + | |
| 79 GetExperimentParam(kSuggestionsFieldTrialSuggestionsSuffixParam)); | |
| 80 blacklist_url_prefix_ = GetExperimentParam(kSuggestionsFieldTrialURLParam) + | |
| 81 GetExperimentParam(kSuggestionsFieldTrialBlacklistSuffixParam); | |
| 74 } | 82 } |
| 75 | 83 |
| 76 SuggestionsService::~SuggestionsService() { | 84 SuggestionsService::~SuggestionsService() { |
| 77 } | 85 } |
| 78 | 86 |
| 79 // static | 87 // static |
| 80 bool SuggestionsService::IsEnabled() { | 88 bool SuggestionsService::IsEnabled() { |
| 81 return GetExperimentParam(kSuggestionsFieldTrialStateParam) == | 89 return GetExperimentParam(kSuggestionsFieldTrialStateParam) == |
| 82 kSuggestionsFieldTrialStateEnabled; | 90 kSuggestionsFieldTrialStateEnabled; |
| 83 } | 91 } |
| 84 | 92 |
| 85 void SuggestionsService::FetchSuggestionsData( | 93 void SuggestionsService::FetchSuggestionsData( |
| 86 SuggestionsService::ResponseCallback callback) { | 94 SuggestionsService::ResponseCallback callback) { |
| 87 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 95 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 88 | 96 |
| 89 if (pending_request_.get()) { | 97 if (pending_request_.get()) { |
|
Jered
2014/05/27 22:33:17
What if the pending request is a blacklist request
manzagop (departed)
2014/05/29 21:40:31
That's fine as the blacklist request returns updat
| |
| 90 // Request already exists, so just add requestor to queue. | 98 // Request already exists, so just add requestor to queue. |
| 91 waiting_requestors_.push_back(callback); | 99 waiting_requestors_.push_back(callback); |
| 92 return; | 100 return; |
| 93 } | 101 } |
| 94 | 102 |
| 95 // Form new request. | 103 // Form new request. |
| 96 DCHECK(waiting_requestors_.empty()); | 104 DCHECK(waiting_requestors_.empty()); |
| 97 waiting_requestors_.push_back(callback); | 105 waiting_requestors_.push_back(callback); |
| 98 | 106 |
| 99 pending_request_.reset(net::URLFetcher::Create( | 107 pending_request_.reset(CreateSuggestionsRequest(suggestions_url_)); |
| 100 0, suggestions_url_, net::URLFetcher::GET, this)); | |
| 101 pending_request_->SetLoadFlags(net::LOAD_DISABLE_CACHE); | |
| 102 pending_request_->SetRequestContext(profile_->GetRequestContext()); | |
| 103 // Add Chrome experiment state to the request headers. | |
| 104 net::HttpRequestHeaders headers; | |
| 105 chrome_variations::VariationsHttpHeaderProvider::GetInstance()-> | |
| 106 AppendHeaders(pending_request_->GetOriginalURL(), | |
| 107 profile_->IsOffTheRecord(), false, &headers); | |
| 108 pending_request_->SetExtraRequestHeaders(headers.ToString()); | |
| 109 pending_request_->Start(); | 108 pending_request_->Start(); |
| 110 | 109 |
| 111 last_request_started_time_ = base::TimeTicks::Now(); | 110 last_request_started_time_ = base::TimeTicks::Now(); |
| 112 } | 111 } |
| 113 | 112 |
| 113 void SuggestionsService::AddBlacklistedURL( | |
| 114 const GURL& candidate_url, | |
| 115 SuggestionsService::ResponseCallback callback) { | |
| 116 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 117 waiting_requestors_.push_back(callback); | |
| 118 | |
| 119 if (pending_request_.get()) { | |
| 120 if (IsBlacklistRequest(pending_request_.get())) { | |
| 121 // Pending request is a blacklist request. Silently drop the new blacklist | |
| 122 // request. TODO - handle this case. | |
| 123 return; | |
| 124 } else { | |
| 125 // Pending request is not a blacklist request - cancel it and go on to | |
| 126 // issuing a blacklist request. | |
| 127 pending_request_.reset(); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 // Send blacklisting request. | |
| 132 GURL url(blacklist_url_prefix_ + | |
| 133 net::EscapeQueryParamValue(candidate_url.spec(), true)); | |
| 134 pending_request_.reset(CreateSuggestionsRequest(url)); | |
|
Jered
2014/05/27 22:33:17
nit: To me this makes more sense as a PUT request
manzagop (departed)
2014/05/29 21:40:31
You're quite right: this is a request with server-
| |
| 135 pending_request_->Start(); | |
| 136 last_request_started_time_ = base::TimeTicks::Now(); | |
| 137 } | |
| 138 | |
| 114 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { | 139 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { |
| 115 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 140 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 116 DCHECK_EQ(pending_request_.get(), source); | 141 DCHECK_EQ(pending_request_.get(), source); |
| 117 | 142 |
| 118 // The fetcher will be deleted when the request is handled. | 143 // The fetcher will be deleted when the request is handled. |
| 119 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); | 144 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); |
| 120 const net::URLRequestStatus& request_status = request->GetStatus(); | 145 const net::URLRequestStatus& request_status = request->GetStatus(); |
| 121 if (request_status.status() != net::URLRequestStatus::SUCCESS) { | 146 if (request_status.status() != net::URLRequestStatus::SUCCESS) { |
| 122 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", | 147 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", |
| 123 -request_status.error()); | 148 -request_status.error()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 } | 187 } |
| 163 | 188 |
| 164 void SuggestionsService::Shutdown() { | 189 void SuggestionsService::Shutdown() { |
| 165 // Cancel pending request. | 190 // Cancel pending request. |
| 166 pending_request_.reset(NULL); | 191 pending_request_.reset(NULL); |
| 167 | 192 |
| 168 // Dispatch empty suggestions to requestors. | 193 // Dispatch empty suggestions to requestors. |
| 169 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); | 194 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); |
| 170 } | 195 } |
| 171 | 196 |
| 197 bool SuggestionsService::IsBlacklistRequest(net::URLFetcher* request) const { | |
| 198 DCHECK(request); | |
| 199 return StartsWithASCII(request->GetOriginalURL().spec(), | |
| 200 blacklist_url_prefix_, | |
| 201 true); | |
| 202 } | |
| 203 | |
| 204 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) { | |
| 205 net::URLFetcher* request = net::URLFetcher::Create( | |
| 206 0, url, net::URLFetcher::GET, this); | |
| 207 request->SetLoadFlags(net::LOAD_DISABLE_CACHE); | |
| 208 request->SetRequestContext(profile_->GetRequestContext()); | |
| 209 // Add Chrome experiment state to the request headers. | |
| 210 net::HttpRequestHeaders headers; | |
| 211 chrome_variations::VariationsHttpHeaderProvider::GetInstance()-> | |
| 212 AppendHeaders(request->GetOriginalURL(), profile_->IsOffTheRecord(), | |
| 213 false, &headers); | |
| 214 request->SetExtraRequestHeaders(headers.ToString()); | |
| 215 return request; | |
| 216 } | |
| 217 | |
| 172 } // namespace suggestions | 218 } // namespace suggestions |
| OLD | NEW |