OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 { | |
219 const std::string kHttps("https"); | |
Peter Kasting
2012/06/22 21:48:31
Nit: Use chrome::kHttpsScheme from chrome/common/u
Bart N
2012/06/22 22:42:02
Done.
| |
220 if (!search_terms_args.assisted_query_stats.empty() && | |
221 // Either search or autocomplete base URL must be using HTTPS | |
Peter Kasting
2012/06/22 21:48:31
This code isn't actually sufficient.
First, someo
msw
2012/06/22 22:28:21
See candidates at chrome/browser/google/google_uti
Bart N
2012/06/22 22:42:02
Yes, that's a good point. I fixed it according to
| |
222 // in order to prevent from man-in-the-middle attacks. | |
223 (StartsWithASCII(search_terms_data.GoogleBaseURLValue(), kHttps, | |
224 false) || | |
225 StartsWithASCII(search_terms_data.GoogleBaseSuggestURLValue(), | |
226 kHttps, false))) { | |
227 url.insert(i->index, | |
228 "aqs=" + search_terms_args.assisted_query_stats + "&"); | |
229 } | |
230 } | |
231 break; | |
232 | |
210 case GOOGLE_ACCEPTED_SUGGESTION: | 233 case GOOGLE_ACCEPTED_SUGGESTION: |
211 if (accepted_suggestion == NO_SUGGESTION_CHOSEN) | 234 if (search_terms_args.accepted_suggestion == NO_SUGGESTION_CHOSEN) { |
212 url.insert(i->index, "aq=f&"); | 235 url.insert(i->index, "aq=f&"); |
213 else if (accepted_suggestion != NO_SUGGESTIONS_AVAILABLE) | 236 } else if (search_terms_args.accepted_suggestion != |
237 NO_SUGGESTIONS_AVAILABLE) { | |
214 url.insert(i->index, | 238 url.insert(i->index, |
215 base::StringPrintf("aq=%d&", accepted_suggestion)); | 239 base::StringPrintf("aq=%d&", |
240 search_terms_args.accepted_suggestion)); | |
241 } | |
216 break; | 242 break; |
217 | 243 |
218 case GOOGLE_BASE_URL: | 244 case GOOGLE_BASE_URL: |
219 url.insert(i->index, search_terms_data.GoogleBaseURLValue()); | 245 url.insert(i->index, search_terms_data.GoogleBaseURLValue()); |
220 break; | 246 break; |
221 | 247 |
222 case GOOGLE_BASE_SUGGEST_URL: | 248 case GOOGLE_BASE_SUGGEST_URL: |
223 url.insert(i->index, search_terms_data.GoogleBaseSuggestURLValue()); | 249 url.insert(i->index, search_terms_data.GoogleBaseSuggestURLValue()); |
224 break; | 250 break; |
225 | 251 |
226 case GOOGLE_INSTANT_ENABLED: | 252 case GOOGLE_INSTANT_ENABLED: |
227 url.insert(i->index, search_terms_data.InstantEnabledParam()); | 253 url.insert(i->index, search_terms_data.InstantEnabledParam()); |
228 break; | 254 break; |
229 | 255 |
230 case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION: | 256 case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION: |
231 if (accepted_suggestion >= 0) | 257 if (search_terms_args.accepted_suggestion >= 0 || |
258 !search_terms_args.assisted_query_stats.empty()) { | |
232 url.insert(i->index, "oq=" + UTF16ToUTF8(encoded_original_query) + | 259 url.insert(i->index, "oq=" + UTF16ToUTF8(encoded_original_query) + |
233 "&"); | 260 "&"); |
261 } | |
234 break; | 262 break; |
235 | 263 |
236 case GOOGLE_RLZ: { | 264 case GOOGLE_RLZ: { |
237 // On platforms that don't have RLZ, we still want this branch | 265 // On platforms that don't have RLZ, we still want this branch |
238 // to happen so that we replace the RLZ template with the | 266 // to happen so that we replace the RLZ template with the |
239 // empty string. (If we don't handle this case, we hit a | 267 // empty string. (If we don't handle this case, we hit a |
240 // NOTREACHED below.) | 268 // NOTREACHED below.) |
241 #if defined(ENABLE_RLZ) | 269 #if defined(ENABLE_RLZ) |
242 string16 rlz_string = search_terms_data.GetRlzParameterValue(); | 270 string16 rlz_string = search_terms_data.GetRlzParameterValue(); |
243 if (!rlz_string.empty()) { | 271 if (!rlz_string.empty()) { |
244 url.insert(i->index, "rlz=" + UTF16ToUTF8(rlz_string) + "&"); | 272 url.insert(i->index, "rlz=" + UTF16ToUTF8(rlz_string) + "&"); |
245 } | 273 } |
246 #endif | 274 #endif |
247 break; | 275 break; |
248 } | 276 } |
249 | 277 |
250 case GOOGLE_SEARCH_FIELDTRIAL_GROUP: | 278 case GOOGLE_SEARCH_FIELDTRIAL_GROUP: |
251 if (AutocompleteFieldTrial::InSuggestFieldTrial()) { | 279 if (AutocompleteFieldTrial::InSuggestFieldTrial()) { |
252 // Add something like sugexp=chrome,mod=5 to the URL request. | 280 // Add something like sugexp=chrome,mod=5 to the URL request. |
253 url.insert(i->index, "sugexp=chrome,mod=" + | 281 url.insert(i->index, "sugexp=chrome,mod=" + |
254 AutocompleteFieldTrial::GetSuggestGroupName() + "&"); | 282 AutocompleteFieldTrial::GetSuggestGroupName() + "&"); |
255 } | 283 } |
256 break; | 284 break; |
257 | 285 |
258 case GOOGLE_UNESCAPED_SEARCH_TERMS: { | 286 case GOOGLE_UNESCAPED_SEARCH_TERMS: { |
259 std::string unescaped_terms; | 287 std::string unescaped_terms; |
260 base::UTF16ToCodepage(terms, input_encoding.c_str(), | 288 base::UTF16ToCodepage(search_terms_args.search_terms, |
289 input_encoding.c_str(), | |
261 base::OnStringConversionError::SKIP, | 290 base::OnStringConversionError::SKIP, |
262 &unescaped_terms); | 291 &unescaped_terms); |
263 url.insert(i->index, std::string(unescaped_terms.begin(), | 292 url.insert(i->index, std::string(unescaped_terms.begin(), |
264 unescaped_terms.end())); | 293 unescaped_terms.end())); |
265 break; | 294 break; |
266 } | 295 } |
267 | 296 |
268 case LANGUAGE: | 297 case LANGUAGE: |
269 url.insert(i->index, search_terms_data.GetApplicationLocale()); | 298 url.insert(i->index, search_terms_data.GetApplicationLocale()); |
270 break; | 299 break; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 url->insert(start, "1"); | 439 url->insert(start, "1"); |
411 } else if (parameter == kLanguageParameter) { | 440 } else if (parameter == kLanguageParameter) { |
412 replacements->push_back(Replacement(LANGUAGE, start)); | 441 replacements->push_back(Replacement(LANGUAGE, start)); |
413 } else if (parameter == kInputEncodingParameter) { | 442 } else if (parameter == kInputEncodingParameter) { |
414 replacements->push_back(Replacement(ENCODING, start)); | 443 replacements->push_back(Replacement(ENCODING, start)); |
415 } else if (parameter == kOutputEncodingParameter) { | 444 } else if (parameter == kOutputEncodingParameter) { |
416 if (!optional) | 445 if (!optional) |
417 url->insert(start, kOutputEncodingType); | 446 url->insert(start, kOutputEncodingType); |
418 } else if (parameter == kGoogleAcceptedSuggestionParameter) { | 447 } else if (parameter == kGoogleAcceptedSuggestionParameter) { |
419 replacements->push_back(Replacement(GOOGLE_ACCEPTED_SUGGESTION, start)); | 448 replacements->push_back(Replacement(GOOGLE_ACCEPTED_SUGGESTION, start)); |
449 } else if (parameter == kGoogleAssistedQueryStatsParameter) { | |
450 replacements->push_back(Replacement(GOOGLE_ASSISTED_QUERY_STATS, start)); | |
420 } else if (parameter == kGoogleBaseURLParameter) { | 451 } else if (parameter == kGoogleBaseURLParameter) { |
421 replacements->push_back(Replacement(GOOGLE_BASE_URL, start)); | 452 replacements->push_back(Replacement(GOOGLE_BASE_URL, start)); |
422 } else if (parameter == kGoogleBaseSuggestURLParameter) { | 453 } else if (parameter == kGoogleBaseSuggestURLParameter) { |
423 replacements->push_back(Replacement(GOOGLE_BASE_SUGGEST_URL, start)); | 454 replacements->push_back(Replacement(GOOGLE_BASE_SUGGEST_URL, start)); |
424 } else if (parameter == kGoogleInstantEnabledParameter) { | 455 } else if (parameter == kGoogleInstantEnabledParameter) { |
425 replacements->push_back(Replacement(GOOGLE_INSTANT_ENABLED, start)); | 456 replacements->push_back(Replacement(GOOGLE_INSTANT_ENABLED, start)); |
426 } else if (parameter == kGoogleOriginalQueryForSuggestionParameter) { | 457 } else if (parameter == kGoogleOriginalQueryForSuggestionParameter) { |
427 replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION, | 458 replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION, |
428 start)); | 459 start)); |
429 } else if (parameter == kGoogleRLZParameter) { | 460 } else if (parameter == kGoogleRLZParameter) { |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
679 } | 710 } |
680 | 711 |
681 void TemplateURL::ResetKeywordIfNecessary(bool force) { | 712 void TemplateURL::ResetKeywordIfNecessary(bool force) { |
682 if (IsGoogleSearchURLWithReplaceableKeyword() || force) { | 713 if (IsGoogleSearchURLWithReplaceableKeyword() || force) { |
683 DCHECK(!IsExtensionKeyword()); | 714 DCHECK(!IsExtensionKeyword()); |
684 GURL url(TemplateURLService::GenerateSearchURL(this)); | 715 GURL url(TemplateURLService::GenerateSearchURL(this)); |
685 if (url.is_valid()) | 716 if (url.is_valid()) |
686 data_.SetKeyword(TemplateURLService::GenerateKeyword(url)); | 717 data_.SetKeyword(TemplateURLService::GenerateKeyword(url)); |
687 } | 718 } |
688 } | 719 } |
OLD | NEW |