Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: chrome/browser/search_engines/template_url.cc

Issue 10537154: A working implementation of AQS (Assisted Query Stats). (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Addressed comments. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_engines/template_url.h" 5 #include "chrome/browser/search_engines/template_url.h"
6 6
7 #include "base/guid.h" 7 #include "base/guid.h"
8 #include "base/i18n/case_conversion.h" 8 #include "base/i18n/case_conversion.h"
9 #include "base/i18n/icu_string_conversions.h" 9 #include "base/i18n/icu_string_conversions.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/field_trial.h" 12 #include "base/metrics/field_trial.h"
13 #include "base/string_number_conversions.h" 13 #include "base/string_number_conversions.h"
14 #include "base/string_util.h"
14 #include "base/stringprintf.h" 15 #include "base/stringprintf.h"
15 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
16 #include "chrome/browser/autocomplete/autocomplete_field_trial.h" 17 #include "chrome/browser/autocomplete/autocomplete_field_trial.h"
17 #include "chrome/browser/google/google_util.h" 18 #include "chrome/browser/google/google_util.h"
18 #include "chrome/browser/search_engines/search_terms_data.h" 19 #include "chrome/browser/search_engines/search_terms_data.h"
19 #include "chrome/browser/search_engines/template_url_service.h" 20 #include "chrome/browser/search_engines/template_url_service.h"
20 #include "chrome/common/url_constants.h" 21 #include "chrome/common/url_constants.h"
21 #include "net/base/escape.h" 22 #include "net/base/escape.h"
22 #include "ui/base/l10n/l10n_util.h" 23 #include "ui/base/l10n/l10n_util.h"
23 24
(...skipping 11 matching lines...) Expand all
35 const char kSearchTermsParameter[] = "searchTerms"; 36 const char kSearchTermsParameter[] = "searchTerms";
36 const char kSearchTermsParameterFull[] = "{searchTerms}"; 37 const char kSearchTermsParameterFull[] = "{searchTerms}";
37 const char kCountParameter[] = "count"; 38 const char kCountParameter[] = "count";
38 const char kStartIndexParameter[] = "startIndex"; 39 const char kStartIndexParameter[] = "startIndex";
39 const char kStartPageParameter[] = "startPage"; 40 const char kStartPageParameter[] = "startPage";
40 const char kLanguageParameter[] = "language"; 41 const char kLanguageParameter[] = "language";
41 const char kInputEncodingParameter[] = "inputEncoding"; 42 const char kInputEncodingParameter[] = "inputEncoding";
42 const char kOutputEncodingParameter[] = "outputEncoding"; 43 const char kOutputEncodingParameter[] = "outputEncoding";
43 44
44 const char kGoogleAcceptedSuggestionParameter[] = "google:acceptedSuggestion"; 45 const char kGoogleAcceptedSuggestionParameter[] = "google:acceptedSuggestion";
46 const char kGoogleAssistedQueryStatsParameter[] = "google:assistedQueryStats";
45 // Host/Domain Google searches are relative to. 47 // Host/Domain Google searches are relative to.
46 const char kGoogleBaseURLParameter[] = "google:baseURL"; 48 const char kGoogleBaseURLParameter[] = "google:baseURL";
47 const char kGoogleBaseURLParameterFull[] = "{google:baseURL}"; 49 const char kGoogleBaseURLParameterFull[] = "{google:baseURL}";
48 // Like google:baseURL, but for the Search Suggest capability. 50 // Like google:baseURL, but for the Search Suggest capability.
49 const char kGoogleBaseSuggestURLParameter[] = "google:baseSuggestURL"; 51 const char kGoogleBaseSuggestURLParameter[] = "google:baseSuggestURL";
50 const char kGoogleBaseSuggestURLParameterFull[] = "{google:baseSuggestURL}"; 52 const char kGoogleBaseSuggestURLParameterFull[] = "{google:baseSuggestURL}";
51 const char kGoogleInstantEnabledParameter[] = "google:instantEnabledParameter"; 53 const char kGoogleInstantEnabledParameter[] = "google:instantEnabledParameter";
52 const char kGoogleOriginalQueryForSuggestionParameter[] = 54 const char kGoogleOriginalQueryForSuggestionParameter[] =
53 "google:originalQueryForSuggestion"; 55 "google:originalQueryForSuggestion";
54 const char kGoogleRLZParameter[] = "google:RLZ"; 56 const char kGoogleRLZParameter[] = "google:RLZ";
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 base::OnStringConversionError::SKIP, &encoded_original_query)) 101 base::OnStringConversionError::SKIP, &encoded_original_query))
100 return false; 102 return false;
101 *escaped_original_query = 103 *escaped_original_query =
102 UTF8ToUTF16(net::EscapeQueryParamValue(encoded_original_query, true)); 104 UTF8ToUTF16(net::EscapeQueryParamValue(encoded_original_query, true));
103 return true; 105 return true;
104 } 106 }
105 107
106 } // namespace 108 } // namespace
107 109
108 110
111 // TemplateURLRef::SearchTermsArgs --------------------------------------------
112
113 TemplateURLRef::SearchTermsArgs::SearchTermsArgs(const string16& search_terms)
114 : search_terms(search_terms),
115 accepted_suggestion(NO_SUGGESTIONS_AVAILABLE) {
116 }
117
118
109 // TemplateURLRef ------------------------------------------------------------- 119 // TemplateURLRef -------------------------------------------------------------
110 120
111 TemplateURLRef::TemplateURLRef(TemplateURL* owner, Type type) 121 TemplateURLRef::TemplateURLRef(TemplateURL* owner, Type type)
112 : owner_(owner), 122 : owner_(owner),
113 type_(type), 123 type_(type),
114 parsed_(false), 124 parsed_(false),
115 valid_(false), 125 valid_(false),
116 supports_replacements_(false), 126 supports_replacements_(false),
117 prepopulated_(false) { 127 prepopulated_(false) {
118 DCHECK(owner_); 128 DCHECK(owner_);
(...skipping 16 matching lines...) Expand all
135 return SupportsReplacementUsingTermsData(search_terms_data); 145 return SupportsReplacementUsingTermsData(search_terms_data);
136 } 146 }
137 147
138 bool TemplateURLRef::SupportsReplacementUsingTermsData( 148 bool TemplateURLRef::SupportsReplacementUsingTermsData(
139 const SearchTermsData& search_terms_data) const { 149 const SearchTermsData& search_terms_data) const {
140 ParseIfNecessaryUsingTermsData(search_terms_data); 150 ParseIfNecessaryUsingTermsData(search_terms_data);
141 return valid_ && supports_replacements_; 151 return valid_ && supports_replacements_;
142 } 152 }
143 153
144 std::string TemplateURLRef::ReplaceSearchTerms( 154 std::string TemplateURLRef::ReplaceSearchTerms(
145 const string16& terms, 155 const SearchTermsArgs& search_terms_args) const {
146 int accepted_suggestion,
147 const string16& original_query_for_suggestion) const {
148 UIThreadSearchTermsData search_terms_data(owner_->profile()); 156 UIThreadSearchTermsData search_terms_data(owner_->profile());
149 return ReplaceSearchTermsUsingTermsData(terms, accepted_suggestion, 157 return ReplaceSearchTermsUsingTermsData(search_terms_args, search_terms_data);
150 original_query_for_suggestion, search_terms_data);
151 } 158 }
152 159
153 std::string TemplateURLRef::ReplaceSearchTermsUsingTermsData( 160 std::string TemplateURLRef::ReplaceSearchTermsUsingTermsData(
154 const string16& terms, 161 const SearchTermsArgs& search_terms_args,
155 int accepted_suggestion,
156 const string16& original_query_for_suggestion,
157 const SearchTermsData& search_terms_data) const { 162 const SearchTermsData& search_terms_data) const {
158 ParseIfNecessaryUsingTermsData(search_terms_data); 163 ParseIfNecessaryUsingTermsData(search_terms_data);
159 if (!valid_) 164 if (!valid_)
160 return std::string(); 165 return std::string();
161 166
162 if (replacements_.empty()) 167 if (replacements_.empty())
163 return parsed_url_; 168 return parsed_url_;
164 169
165 // Determine if the search terms are in the query or before. We're escaping 170 // Determine if the search terms are in the query or before. We're escaping
166 // space as '+' in the former case and as '%20' in the latter case. 171 // space as '+' in the former case and as '%20' in the latter case.
167 bool is_in_query = true; 172 bool is_in_query = true;
168 for (Replacements::iterator i = replacements_.begin(); 173 for (Replacements::iterator i = replacements_.begin();
169 i != replacements_.end(); ++i) { 174 i != replacements_.end(); ++i) {
170 if (i->type == SEARCH_TERMS) { 175 if (i->type == SEARCH_TERMS) {
171 string16::size_type query_start = parsed_url_.find('?'); 176 string16::size_type query_start = parsed_url_.find('?');
172 is_in_query = query_start != string16::npos && 177 is_in_query = query_start != string16::npos &&
173 (static_cast<string16::size_type>(i->index) > query_start); 178 (static_cast<string16::size_type>(i->index) > query_start);
174 break; 179 break;
175 } 180 }
176 } 181 }
177 182
178 string16 encoded_terms; 183 string16 encoded_terms;
179 string16 encoded_original_query; 184 string16 encoded_original_query;
180 std::string input_encoding; 185 std::string input_encoding;
181 // Encode the search terms so that we know the encoding. 186 // Encode the search terms so that we know the encoding.
182 for (std::vector<std::string>::const_iterator i( 187 for (std::vector<std::string>::const_iterator i(
183 owner_->input_encodings().begin()); 188 owner_->input_encodings().begin());
184 i != owner_->input_encodings().end(); ++i) { 189 i != owner_->input_encodings().end(); ++i) {
185 if (TryEncoding(terms, original_query_for_suggestion, i->c_str(), 190 if (TryEncoding(search_terms_args.search_terms,
191 search_terms_args.original_query, i->c_str(),
186 is_in_query, &encoded_terms, &encoded_original_query)) { 192 is_in_query, &encoded_terms, &encoded_original_query)) {
187 input_encoding = *i; 193 input_encoding = *i;
188 break; 194 break;
189 } 195 }
190 } 196 }
191 if (input_encoding.empty()) { 197 if (input_encoding.empty()) {
192 input_encoding = "UTF-8"; 198 input_encoding = "UTF-8";
193 if (!TryEncoding(terms, original_query_for_suggestion, 199 if (!TryEncoding(search_terms_args.search_terms,
200 search_terms_args.original_query,
194 input_encoding.c_str(), is_in_query, &encoded_terms, 201 input_encoding.c_str(), is_in_query, &encoded_terms,
195 &encoded_original_query)) 202 &encoded_original_query))
196 NOTREACHED(); 203 NOTREACHED();
197 } 204 }
198 205
199 std::string url = parsed_url_; 206 std::string url = parsed_url_;
200 207
201 // replacements_ is ordered in ascending order, as such we need to iterate 208 // replacements_ is ordered in ascending order, as such we need to iterate
202 // from the back. 209 // from the back.
203 for (Replacements::reverse_iterator i = replacements_.rbegin(); 210 for (Replacements::reverse_iterator i = replacements_.rbegin();
204 i != replacements_.rend(); ++i) { 211 i != replacements_.rend(); ++i) {
205 switch (i->type) { 212 switch (i->type) {
206 case ENCODING: 213 case ENCODING:
207 url.insert(i->index, input_encoding); 214 url.insert(i->index, input_encoding);
208 break; 215 break;
209 216
217 case GOOGLE_ASSISTED_QUERY_STATS:
218 if (!search_terms_args.assisted_query_stats.empty()) {
219 // Get the base URL without substituting AQS to avoid infinite
220 // recursion. We need the URL to find out if it meets all
221 // AQS requirements.
222 SearchTermsArgs search_terms_args_without_aqs(search_terms_args);
223 search_terms_args_without_aqs.assisted_query_stats.clear();
224 const std::string& base_url = ReplaceSearchTermsUsingTermsData(
225 search_terms_args_without_aqs,
226 search_terms_data);
227 // We support sending AQS to any search provider supporting HTTPS.
228 if (StartsWithASCII(base_url, chrome::kHttpsScheme, false)) {
Peter Kasting 2012/06/22 23:18:11 Nit: Safer: GURL base_url(ReplaceSearch
Bart N 2012/06/23 01:06:30 Done.
229 url.insert(i->index,
230 "aqs=" + search_terms_args.assisted_query_stats + "&");
231 }
232 }
233 break;
234
210 case GOOGLE_ACCEPTED_SUGGESTION: 235 case GOOGLE_ACCEPTED_SUGGESTION:
211 if (accepted_suggestion == NO_SUGGESTION_CHOSEN) 236 if (search_terms_args.accepted_suggestion == NO_SUGGESTION_CHOSEN) {
212 url.insert(i->index, "aq=f&"); 237 url.insert(i->index, "aq=f&");
213 else if (accepted_suggestion != NO_SUGGESTIONS_AVAILABLE) 238 } else if (search_terms_args.accepted_suggestion !=
239 NO_SUGGESTIONS_AVAILABLE) {
214 url.insert(i->index, 240 url.insert(i->index,
215 base::StringPrintf("aq=%d&", accepted_suggestion)); 241 base::StringPrintf("aq=%d&",
242 search_terms_args.accepted_suggestion));
243 }
216 break; 244 break;
217 245
218 case GOOGLE_BASE_URL: 246 case GOOGLE_BASE_URL:
219 url.insert(i->index, search_terms_data.GoogleBaseURLValue()); 247 url.insert(i->index, search_terms_data.GoogleBaseURLValue());
220 break; 248 break;
221 249
222 case GOOGLE_BASE_SUGGEST_URL: 250 case GOOGLE_BASE_SUGGEST_URL:
223 url.insert(i->index, search_terms_data.GoogleBaseSuggestURLValue()); 251 url.insert(i->index, search_terms_data.GoogleBaseSuggestURLValue());
224 break; 252 break;
225 253
226 case GOOGLE_INSTANT_ENABLED: 254 case GOOGLE_INSTANT_ENABLED:
227 url.insert(i->index, search_terms_data.InstantEnabledParam()); 255 url.insert(i->index, search_terms_data.InstantEnabledParam());
228 break; 256 break;
229 257
230 case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION: 258 case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION:
231 if (accepted_suggestion >= 0) 259 if (search_terms_args.accepted_suggestion >= 0 ||
260 !search_terms_args.assisted_query_stats.empty()) {
232 url.insert(i->index, "oq=" + UTF16ToUTF8(encoded_original_query) + 261 url.insert(i->index, "oq=" + UTF16ToUTF8(encoded_original_query) +
233 "&"); 262 "&");
263 }
234 break; 264 break;
235 265
236 case GOOGLE_RLZ: { 266 case GOOGLE_RLZ: {
237 // On platforms that don't have RLZ, we still want this branch 267 // On platforms that don't have RLZ, we still want this branch
238 // to happen so that we replace the RLZ template with the 268 // to happen so that we replace the RLZ template with the
239 // empty string. (If we don't handle this case, we hit a 269 // empty string. (If we don't handle this case, we hit a
240 // NOTREACHED below.) 270 // NOTREACHED below.)
241 #if defined(ENABLE_RLZ) 271 #if defined(ENABLE_RLZ)
242 string16 rlz_string = search_terms_data.GetRlzParameterValue(); 272 string16 rlz_string = search_terms_data.GetRlzParameterValue();
243 if (!rlz_string.empty()) { 273 if (!rlz_string.empty()) {
244 url.insert(i->index, "rlz=" + UTF16ToUTF8(rlz_string) + "&"); 274 url.insert(i->index, "rlz=" + UTF16ToUTF8(rlz_string) + "&");
245 } 275 }
246 #endif 276 #endif
247 break; 277 break;
248 } 278 }
249 279
250 case GOOGLE_SEARCH_FIELDTRIAL_GROUP: 280 case GOOGLE_SEARCH_FIELDTRIAL_GROUP:
251 if (AutocompleteFieldTrial::InSuggestFieldTrial()) { 281 if (AutocompleteFieldTrial::InSuggestFieldTrial()) {
252 // Add something like sugexp=chrome,mod=5 to the URL request. 282 // Add something like sugexp=chrome,mod=5 to the URL request.
253 url.insert(i->index, "sugexp=chrome,mod=" + 283 url.insert(i->index, "sugexp=chrome,mod=" +
254 AutocompleteFieldTrial::GetSuggestGroupName() + "&"); 284 AutocompleteFieldTrial::GetSuggestGroupName() + "&");
255 } 285 }
256 break; 286 break;
257 287
258 case GOOGLE_UNESCAPED_SEARCH_TERMS: { 288 case GOOGLE_UNESCAPED_SEARCH_TERMS: {
259 std::string unescaped_terms; 289 std::string unescaped_terms;
260 base::UTF16ToCodepage(terms, input_encoding.c_str(), 290 base::UTF16ToCodepage(search_terms_args.search_terms,
291 input_encoding.c_str(),
261 base::OnStringConversionError::SKIP, 292 base::OnStringConversionError::SKIP,
262 &unescaped_terms); 293 &unescaped_terms);
263 url.insert(i->index, std::string(unescaped_terms.begin(), 294 url.insert(i->index, std::string(unescaped_terms.begin(),
264 unescaped_terms.end())); 295 unescaped_terms.end()));
265 break; 296 break;
266 } 297 }
267 298
268 case LANGUAGE: 299 case LANGUAGE:
269 url.insert(i->index, search_terms_data.GetApplicationLocale()); 300 url.insert(i->index, search_terms_data.GetApplicationLocale());
270 break; 301 break;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 url->insert(start, "1"); 441 url->insert(start, "1");
411 } else if (parameter == kLanguageParameter) { 442 } else if (parameter == kLanguageParameter) {
412 replacements->push_back(Replacement(LANGUAGE, start)); 443 replacements->push_back(Replacement(LANGUAGE, start));
413 } else if (parameter == kInputEncodingParameter) { 444 } else if (parameter == kInputEncodingParameter) {
414 replacements->push_back(Replacement(ENCODING, start)); 445 replacements->push_back(Replacement(ENCODING, start));
415 } else if (parameter == kOutputEncodingParameter) { 446 } else if (parameter == kOutputEncodingParameter) {
416 if (!optional) 447 if (!optional)
417 url->insert(start, kOutputEncodingType); 448 url->insert(start, kOutputEncodingType);
418 } else if (parameter == kGoogleAcceptedSuggestionParameter) { 449 } else if (parameter == kGoogleAcceptedSuggestionParameter) {
419 replacements->push_back(Replacement(GOOGLE_ACCEPTED_SUGGESTION, start)); 450 replacements->push_back(Replacement(GOOGLE_ACCEPTED_SUGGESTION, start));
451 } else if (parameter == kGoogleAssistedQueryStatsParameter) {
452 replacements->push_back(Replacement(GOOGLE_ASSISTED_QUERY_STATS, start));
420 } else if (parameter == kGoogleBaseURLParameter) { 453 } else if (parameter == kGoogleBaseURLParameter) {
421 replacements->push_back(Replacement(GOOGLE_BASE_URL, start)); 454 replacements->push_back(Replacement(GOOGLE_BASE_URL, start));
422 } else if (parameter == kGoogleBaseSuggestURLParameter) { 455 } else if (parameter == kGoogleBaseSuggestURLParameter) {
423 replacements->push_back(Replacement(GOOGLE_BASE_SUGGEST_URL, start)); 456 replacements->push_back(Replacement(GOOGLE_BASE_SUGGEST_URL, start));
424 } else if (parameter == kGoogleInstantEnabledParameter) { 457 } else if (parameter == kGoogleInstantEnabledParameter) {
425 replacements->push_back(Replacement(GOOGLE_INSTANT_ENABLED, start)); 458 replacements->push_back(Replacement(GOOGLE_INSTANT_ENABLED, start));
426 } else if (parameter == kGoogleOriginalQueryForSuggestionParameter) { 459 } else if (parameter == kGoogleOriginalQueryForSuggestionParameter) {
427 replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION, 460 replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
428 start)); 461 start));
429 } else if (parameter == kGoogleRLZParameter) { 462 } else if (parameter == kGoogleRLZParameter) {
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 } 712 }
680 713
681 void TemplateURL::ResetKeywordIfNecessary(bool force) { 714 void TemplateURL::ResetKeywordIfNecessary(bool force) {
682 if (IsGoogleSearchURLWithReplaceableKeyword() || force) { 715 if (IsGoogleSearchURLWithReplaceableKeyword() || force) {
683 DCHECK(!IsExtensionKeyword()); 716 DCHECK(!IsExtensionKeyword());
684 GURL url(TemplateURLService::GenerateSearchURL(this)); 717 GURL url(TemplateURLService::GenerateSearchURL(this));
685 if (url.is_valid()) 718 if (url.is_valid())
686 data_.SetKeyword(TemplateURLService::GenerateKeyword(url)); 719 data_.SetKeyword(TemplateURLService::GenerateKeyword(url));
687 } 720 }
688 } 721 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698