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 : thumbnail_manager_(new ThumbnailManager(profile)), | 75 : thumbnail_manager_(new ThumbnailManager(profile)), |
72 profile_(profile) { | 76 profile_(profile) { |
73 // Obtain the URL to use to fetch suggestions data from the Variations param. | 77 // Obtain the URL to use to fetch suggestions data from the Variations param. |
74 suggestions_url_ = GURL(GetExperimentParam(kSuggestionsFieldTrialURLParam)); | 78 suggestions_url_ = GURL( |
| 79 GetExperimentParam(kSuggestionsFieldTrialURLParam) + |
| 80 GetExperimentParam(kSuggestionsFieldTrialSuggestionsSuffixParam)); |
| 81 blacklist_url_prefix_ = GetExperimentParam(kSuggestionsFieldTrialURLParam) + |
| 82 GetExperimentParam(kSuggestionsFieldTrialBlacklistSuffixParam); |
75 } | 83 } |
76 | 84 |
77 SuggestionsService::~SuggestionsService() { | 85 SuggestionsService::~SuggestionsService() { |
78 } | 86 } |
79 | 87 |
80 // static | 88 // static |
81 bool SuggestionsService::IsEnabled() { | 89 bool SuggestionsService::IsEnabled() { |
82 return GetExperimentParam(kSuggestionsFieldTrialStateParam) == | 90 return GetExperimentParam(kSuggestionsFieldTrialStateParam) == |
83 kSuggestionsFieldTrialStateEnabled; | 91 kSuggestionsFieldTrialStateEnabled; |
84 } | 92 } |
85 | 93 |
86 void SuggestionsService::FetchSuggestionsData( | 94 void SuggestionsService::FetchSuggestionsData( |
87 SuggestionsService::ResponseCallback callback) { | 95 SuggestionsService::ResponseCallback callback) { |
88 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 96 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
89 | 97 |
90 if (pending_request_.get()) { | 98 if (pending_request_.get()) { |
91 // Request already exists, so just add requestor to queue. | 99 // Request already exists, so just add requestor to queue. |
92 waiting_requestors_.push_back(callback); | 100 waiting_requestors_.push_back(callback); |
93 return; | 101 return; |
94 } | 102 } |
95 | 103 |
96 // Form new request. | 104 // Form new request. |
97 DCHECK(waiting_requestors_.empty()); | 105 DCHECK(waiting_requestors_.empty()); |
98 waiting_requestors_.push_back(callback); | 106 waiting_requestors_.push_back(callback); |
99 | 107 |
100 pending_request_.reset(net::URLFetcher::Create( | 108 pending_request_.reset(CreateSuggestionsRequest(suggestions_url_)); |
101 0, suggestions_url_, net::URLFetcher::GET, this)); | |
102 pending_request_->SetLoadFlags(net::LOAD_DISABLE_CACHE); | |
103 pending_request_->SetRequestContext(profile_->GetRequestContext()); | |
104 // Add Chrome experiment state to the request headers. | |
105 net::HttpRequestHeaders headers; | |
106 chrome_variations::VariationsHttpHeaderProvider::GetInstance()-> | |
107 AppendHeaders(pending_request_->GetOriginalURL(), | |
108 profile_->IsOffTheRecord(), false, &headers); | |
109 pending_request_->SetExtraRequestHeaders(headers.ToString()); | |
110 pending_request_->Start(); | 109 pending_request_->Start(); |
111 | 110 |
112 last_request_started_time_ = base::TimeTicks::Now(); | 111 last_request_started_time_ = base::TimeTicks::Now(); |
113 } | 112 } |
114 | 113 |
115 void SuggestionsService::GetPageThumbnail( | 114 void SuggestionsService::GetPageThumbnail( |
116 const GURL& url, | 115 const GURL& url, |
117 base::Callback<void(const GURL&, const SkBitmap*)> callback) { | 116 base::Callback<void(const GURL&, const SkBitmap*)> callback) { |
118 thumbnail_manager_->GetPageThumbnail(url, callback); | 117 thumbnail_manager_->GetPageThumbnail(url, callback); |
119 } | 118 } |
120 | 119 |
| 120 void SuggestionsService::AddBlacklistedURL( |
| 121 const GURL& candidate_url, |
| 122 SuggestionsService::ResponseCallback callback) { |
| 123 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 124 waiting_requestors_.push_back(callback); |
| 125 |
| 126 if (pending_request_.get()) { |
| 127 if (IsBlacklistRequest(pending_request_.get())) { |
| 128 // Pending request is a blacklist request. Silently drop the new blacklist |
| 129 // request. TODO - handle this case. |
| 130 return; |
| 131 } else { |
| 132 // Pending request is not a blacklist request - cancel it and go on to |
| 133 // issuing a blacklist request. |
| 134 pending_request_.reset(); |
| 135 } |
| 136 } |
| 137 |
| 138 // Send blacklisting request. |
| 139 // TODO(manzagop): make this a PUT request instead of a GET request. |
| 140 GURL url(blacklist_url_prefix_ + |
| 141 net::EscapeQueryParamValue(candidate_url.spec(), true)); |
| 142 pending_request_.reset(CreateSuggestionsRequest(url)); |
| 143 pending_request_->Start(); |
| 144 last_request_started_time_ = base::TimeTicks::Now(); |
| 145 } |
| 146 |
121 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { | 147 void SuggestionsService::OnURLFetchComplete(const net::URLFetcher* source) { |
122 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 148 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
123 DCHECK_EQ(pending_request_.get(), source); | 149 DCHECK_EQ(pending_request_.get(), source); |
124 | 150 |
125 // The fetcher will be deleted when the request is handled. | 151 // The fetcher will be deleted when the request is handled. |
126 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); | 152 scoped_ptr<const net::URLFetcher> request(pending_request_.release()); |
127 const net::URLRequestStatus& request_status = request->GetStatus(); | 153 const net::URLRequestStatus& request_status = request->GetStatus(); |
128 if (request_status.status() != net::URLRequestStatus::SUCCESS) { | 154 if (request_status.status() != net::URLRequestStatus::SUCCESS) { |
129 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", | 155 UMA_HISTOGRAM_SPARSE_SLOWLY("Suggestions.FailedRequestErrorCode", |
130 -request_status.error()); | 156 -request_status.error()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 196 } |
171 | 197 |
172 void SuggestionsService::Shutdown() { | 198 void SuggestionsService::Shutdown() { |
173 // Cancel pending request. | 199 // Cancel pending request. |
174 pending_request_.reset(NULL); | 200 pending_request_.reset(NULL); |
175 | 201 |
176 // Dispatch empty suggestions to requestors. | 202 // Dispatch empty suggestions to requestors. |
177 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); | 203 DispatchRequestsAndClear(SuggestionsProfile(), &waiting_requestors_); |
178 } | 204 } |
179 | 205 |
| 206 bool SuggestionsService::IsBlacklistRequest(net::URLFetcher* request) const { |
| 207 DCHECK(request); |
| 208 return StartsWithASCII(request->GetOriginalURL().spec(), |
| 209 blacklist_url_prefix_, |
| 210 true); |
| 211 } |
| 212 |
| 213 net::URLFetcher* SuggestionsService::CreateSuggestionsRequest(const GURL& url) { |
| 214 net::URLFetcher* request = net::URLFetcher::Create( |
| 215 0, url, net::URLFetcher::GET, this); |
| 216 request->SetLoadFlags(net::LOAD_DISABLE_CACHE); |
| 217 request->SetRequestContext(profile_->GetRequestContext()); |
| 218 // Add Chrome experiment state to the request headers. |
| 219 net::HttpRequestHeaders headers; |
| 220 chrome_variations::VariationsHttpHeaderProvider::GetInstance()-> |
| 221 AppendHeaders(request->GetOriginalURL(), profile_->IsOffTheRecord(), |
| 222 false, &headers); |
| 223 request->SetExtraRequestHeaders(headers.ToString()); |
| 224 return request; |
| 225 } |
| 226 |
180 } // namespace suggestions | 227 } // namespace suggestions |
OLD | NEW |