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

Side by Side Diff: chrome/browser/autocomplete/keyword_provider.cc

Issue 6291003: Revert 71485 - Remove wstring from TemplateURL and friends.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 11 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/autocomplete/keyword_provider.h" 5 #include "chrome/browser/autocomplete/keyword_provider.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "app/l10n_util.h" 10 #include "app/l10n_util.h"
11 #include "base/string16.h" 11 #include "base/string16.h"
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 // Helper functor for Start(), for sorting keyword matches by quality. 84 // Helper functor for Start(), for sorting keyword matches by quality.
85 class CompareQuality { 85 class CompareQuality {
86 public: 86 public:
87 // A keyword is of higher quality when a greater fraction of it has been 87 // A keyword is of higher quality when a greater fraction of it has been
88 // typed, that is, when it is shorter. 88 // typed, that is, when it is shorter.
89 // 89 //
90 // TODO(pkasting): http://b/740691 Most recent and most frequent keywords are 90 // TODO(pkasting): http://b/740691 Most recent and most frequent keywords are
91 // probably better rankings than the fraction of the keyword typed. We should 91 // probably better rankings than the fraction of the keyword typed. We should
92 // always put any exact matches first no matter what, since the code in 92 // always put any exact matches first no matter what, since the code in
93 // Start() assumes this (and it makes sense). 93 // Start() assumes this (and it makes sense).
94 bool operator()(const string16& keyword1, 94 bool operator()(const std::wstring& keyword1,
95 const string16& keyword2) const { 95 const std::wstring& keyword2) const {
96 return keyword1.length() < keyword2.length(); 96 return keyword1.length() < keyword2.length();
97 } 97 }
98 }; 98 };
99 99
100 // We need our input IDs to be unique across all profiles, so we keep a global 100 // We need our input IDs to be unique across all profiles, so we keep a global
101 // UID that each provider uses. 101 // UID that each provider uses.
102 static int global_input_uid_; 102 static int global_input_uid_;
103 103
104 } // namespace 104 } // namespace
105 105
106 // static 106 // static
107 const TemplateURL* KeywordProvider::GetSubstitutingTemplateURLForInput( 107 const TemplateURL* KeywordProvider::GetSubstitutingTemplateURLForInput(
108 Profile* profile, 108 Profile* profile,
109 const AutocompleteInput& input, 109 const AutocompleteInput& input,
110 std::wstring* remaining_input) { 110 std::wstring* remaining_input) {
111 if (!input.allow_exact_keyword_match()) 111 if (!input.allow_exact_keyword_match())
112 return NULL; 112 return NULL;
113 113
114 std::wstring keyword; 114 std::wstring keyword;
115 if (!ExtractKeywordFromInput(input, &keyword, remaining_input)) 115 if (!ExtractKeywordFromInput(input, &keyword, remaining_input))
116 return NULL; 116 return NULL;
117 117
118 // Make sure the model is loaded. This is cheap and quickly bails out if 118 // Make sure the model is loaded. This is cheap and quickly bails out if
119 // the model is already loaded. 119 // the model is already loaded.
120 TemplateURLModel* model = profile->GetTemplateURLModel(); 120 TemplateURLModel* model = profile->GetTemplateURLModel();
121 DCHECK(model); 121 DCHECK(model);
122 model->Load(); 122 model->Load();
123 123
124 const TemplateURL* template_url = 124 const TemplateURL* template_url = model->GetTemplateURLForKeyword(keyword);
125 model->GetTemplateURLForKeyword(WideToUTF16Hack(keyword));
126 return TemplateURL::SupportsReplacement(template_url) ? template_url : NULL; 125 return TemplateURL::SupportsReplacement(template_url) ? template_url : NULL;
127 } 126 }
128 127
129 void KeywordProvider::Start(const AutocompleteInput& input, 128 void KeywordProvider::Start(const AutocompleteInput& input,
130 bool minimal_changes) { 129 bool minimal_changes) {
131 // This object ensures we end keyword mode if we exit the function without 130 // This object ensures we end keyword mode if we exit the function without
132 // toggling keyword mode to on. 131 // toggling keyword mode to on.
133 ScopedEndExtensionKeywordMode keyword_mode_toggle(this); 132 ScopedEndExtensionKeywordMode keyword_mode_toggle(this);
134 133
135 matches_.clear(); 134 matches_.clear();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 // Get the best matches for this keyword. 167 // Get the best matches for this keyword.
169 // 168 //
170 // NOTE: We could cache the previous keywords and reuse them here in the 169 // NOTE: We could cache the previous keywords and reuse them here in the
171 // |minimal_changes| case, but since we'd still have to recalculate their 170 // |minimal_changes| case, but since we'd still have to recalculate their
172 // relevances and we can just recreate the results synchronously anyway, we 171 // relevances and we can just recreate the results synchronously anyway, we
173 // don't bother. 172 // don't bother.
174 // 173 //
175 // TODO(pkasting): http://b/893701 We should remember the user's use of a 174 // TODO(pkasting): http://b/893701 We should remember the user's use of a
176 // search query both from the autocomplete popup and from web pages 175 // search query both from the autocomplete popup and from web pages
177 // themselves. 176 // themselves.
178 std::vector<string16> keyword_matches; 177 std::vector<std::wstring> keyword_matches;
179 model->FindMatchingKeywords(WideToUTF16Hack(keyword), 178 model->FindMatchingKeywords(keyword, !remaining_input.empty(),
180 !remaining_input.empty(),
181 &keyword_matches); 179 &keyword_matches);
182 180
183 // Prune any extension keywords that are disallowed in incognito mode (if 181 // Prune any extension keywords that are disallowed in incognito mode (if
184 // we're incognito), or disabled. 182 // we're incognito), or disabled.
185 for (std::vector<string16>::iterator i(keyword_matches.begin()); 183 for (std::vector<std::wstring>::iterator i(keyword_matches.begin());
186 i != keyword_matches.end(); ) { 184 i != keyword_matches.end(); ) {
187 const TemplateURL* template_url(model->GetTemplateURLForKeyword(*i)); 185 const TemplateURL* template_url(model->GetTemplateURLForKeyword(*i));
188 if (profile_ && 186 if (profile_ &&
189 !input.synchronous_only() && template_url->IsExtensionKeyword()) { 187 !input.synchronous_only() && template_url->IsExtensionKeyword()) {
190 ExtensionService* service = profile_->GetExtensionService(); 188 ExtensionService* service = profile_->GetExtensionService();
191 const Extension* extension = service->GetExtensionById( 189 const Extension* extension = service->GetExtensionById(
192 template_url->GetExtensionId(), false); 190 template_url->GetExtensionId(), false);
193 bool enabled = extension && (!profile_->IsOffTheRecord() || 191 bool enabled = extension && (!profile_->IsOffTheRecord() ||
194 service->IsIncognitoEnabled(extension)); 192 service->IsIncognitoEnabled(extension));
195 if (!enabled) { 193 if (!enabled) {
196 i = keyword_matches.erase(i); 194 i = keyword_matches.erase(i);
197 continue; 195 continue;
198 } 196 }
199 } 197 }
200 ++i; 198 ++i;
201 } 199 }
202 if (keyword_matches.empty()) 200 if (keyword_matches.empty())
203 return; 201 return;
204 std::sort(keyword_matches.begin(), keyword_matches.end(), CompareQuality()); 202 std::sort(keyword_matches.begin(), keyword_matches.end(), CompareQuality());
205 203
206 // Limit to one exact or three inexact matches, and mark them up for display 204 // Limit to one exact or three inexact matches, and mark them up for display
207 // in the autocomplete popup. 205 // in the autocomplete popup.
208 // Any exact match is going to be the highest quality match, and thus at the 206 // Any exact match is going to be the highest quality match, and thus at the
209 // front of our vector. 207 // front of our vector.
210 if (keyword_matches.front() == WideToUTF16Hack(keyword)) { 208 if (keyword_matches.front() == keyword) {
211 const TemplateURL* template_url( 209 const TemplateURL* template_url(model->GetTemplateURLForKeyword(keyword));
212 model->GetTemplateURLForKeyword(WideToUTF16Hack(keyword)));
213 // TODO(pkasting): We should probably check that if the user explicitly 210 // TODO(pkasting): We should probably check that if the user explicitly
214 // typed a scheme, that scheme matches the one in |template_url|. 211 // typed a scheme, that scheme matches the one in |template_url|.
215 matches_.push_back(CreateAutocompleteMatch(model, keyword, input, 212 matches_.push_back(CreateAutocompleteMatch(model, keyword, input,
216 keyword.length(), 213 keyword.length(),
217 remaining_input, -1)); 214 remaining_input, -1));
218 215
219 if (profile_ && 216 if (profile_ &&
220 !input.synchronous_only() && template_url->IsExtensionKeyword()) { 217 !input.synchronous_only() && template_url->IsExtensionKeyword()) {
221 if (template_url->GetExtensionId() != current_keyword_extension_id_) 218 if (template_url->GetExtensionId() != current_keyword_extension_id_)
222 MaybeEndExtensionKeywordMode(); 219 MaybeEndExtensionKeywordMode();
(...skipping 25 matching lines...) Expand all
248 // extensions listening for input changes. 245 // extensions listening for input changes.
249 if (have_listeners) 246 if (have_listeners)
250 done_ = false; 247 done_ = false;
251 } 248 }
252 } 249 }
253 } else { 250 } else {
254 if (keyword_matches.size() > kMaxMatches) { 251 if (keyword_matches.size() > kMaxMatches) {
255 keyword_matches.erase(keyword_matches.begin() + kMaxMatches, 252 keyword_matches.erase(keyword_matches.begin() + kMaxMatches,
256 keyword_matches.end()); 253 keyword_matches.end());
257 } 254 }
258 for (std::vector<string16>::const_iterator i(keyword_matches.begin()); 255 for (std::vector<std::wstring>::const_iterator i(keyword_matches.begin());
259 i != keyword_matches.end(); ++i) { 256 i != keyword_matches.end(); ++i) {
260 matches_.push_back(CreateAutocompleteMatch(model, UTF16ToWideHack(*i), 257 matches_.push_back(CreateAutocompleteMatch(model, *i, input,
261 input, keyword.length(), 258 keyword.length(),
262 remaining_input, -1)); 259 remaining_input, -1));
263 } 260 }
264 } 261 }
265 } 262 }
266 263
267 void KeywordProvider::Stop() { 264 void KeywordProvider::Stop() {
268 done_ = true; 265 done_ = true;
269 MaybeEndExtensionKeywordMode(); 266 MaybeEndExtensionKeywordMode();
270 } 267 }
271 268
272 KeywordProvider::~KeywordProvider() {} 269 KeywordProvider::~KeywordProvider() {}
273 270
274 // static 271 // static
275 bool KeywordProvider::ExtractKeywordFromInput(const AutocompleteInput& input, 272 bool KeywordProvider::ExtractKeywordFromInput(const AutocompleteInput& input,
276 std::wstring* keyword, 273 std::wstring* keyword,
277 std::wstring* remaining_input) { 274 std::wstring* remaining_input) {
278 if ((input.type() == AutocompleteInput::INVALID) || 275 if ((input.type() == AutocompleteInput::INVALID) ||
279 (input.type() == AutocompleteInput::FORCED_QUERY)) 276 (input.type() == AutocompleteInput::FORCED_QUERY))
280 return false; 277 return false;
281 278
282 *keyword = 279 *keyword = TemplateURLModel::CleanUserInputKeyword(
283 UTF16ToWideHack(TemplateURLModel::CleanUserInputKeyword(WideToUTF16Hack( 280 SplitKeywordFromInput(input.text(), true, remaining_input));
284 SplitKeywordFromInput(input.text(), true, remaining_input))));
285 return !keyword->empty(); 281 return !keyword->empty();
286 } 282 }
287 283
288 // static 284 // static
289 std::wstring KeywordProvider::SplitKeywordFromInput( 285 std::wstring KeywordProvider::SplitKeywordFromInput(
290 const std::wstring& input, 286 const std::wstring& input,
291 bool trim_leading_whitespace, 287 bool trim_leading_whitespace,
292 std::wstring* remaining_input) { 288 std::wstring* remaining_input) {
293 // Find end of first token. The AutocompleteController has trimmed leading 289 // Find end of first token. The AutocompleteController has trimmed leading
294 // whitespace, so we need not skip over that. 290 // whitespace, so we need not skip over that.
(...skipping 26 matching lines...) Expand all
321 IDS_EXTENSION_KEYWORD_COMMAND : IDS_KEYWORD_SEARCH; 317 IDS_EXTENSION_KEYWORD_COMMAND : IDS_KEYWORD_SEARCH;
322 if (remaining_input.empty()) { 318 if (remaining_input.empty()) {
323 // Allow extension keyword providers to accept empty string input. This is 319 // Allow extension keyword providers to accept empty string input. This is
324 // useful to allow extensions to do something in the case where no input is 320 // useful to allow extensions to do something in the case where no input is
325 // entered. 321 // entered.
326 if (element->url()->SupportsReplacement() && 322 if (element->url()->SupportsReplacement() &&
327 !element->IsExtensionKeyword()) { 323 !element->IsExtensionKeyword()) {
328 // No query input; return a generic, no-destination placeholder. 324 // No query input; return a generic, no-destination placeholder.
329 match->contents.assign(UTF16ToWideHack( 325 match->contents.assign(UTF16ToWideHack(
330 l10n_util::GetStringFUTF16(message_id, 326 l10n_util::GetStringFUTF16(message_id,
331 element->AdjustedShortNameForLocaleDirection(), 327 WideToUTF16Hack(element->AdjustedShortNameForLocaleDirection()),
332 l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)))); 328 l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE))));
333 match->contents_class.push_back( 329 match->contents_class.push_back(
334 ACMatchClassification(0, ACMatchClassification::DIM)); 330 ACMatchClassification(0, ACMatchClassification::DIM));
335 } else { 331 } else {
336 // Keyword that has no replacement text (aka a shorthand for a URL). 332 // Keyword that has no replacement text (aka a shorthand for a URL).
337 match->destination_url = GURL(element->url()->url()); 333 match->destination_url = GURL(element->url()->url());
338 match->contents.assign(UTF16ToWideHack(element->short_name())); 334 match->contents.assign(element->short_name());
339 AutocompleteMatch::ClassifyLocationInString(0, match->contents.length(), 335 AutocompleteMatch::ClassifyLocationInString(0, match->contents.length(),
340 match->contents.length(), ACMatchClassification::NONE, 336 match->contents.length(), ACMatchClassification::NONE,
341 &match->contents_class); 337 &match->contents_class);
342 } 338 }
343 } else { 339 } else {
344 // Create destination URL by escaping user input and substituting into 340 // Create destination URL by escaping user input and substituting into
345 // keyword template URL. The escaping here handles whitespace in user 341 // keyword template URL. The escaping here handles whitespace in user
346 // input, but we rely on later canonicalization functions to do more 342 // input, but we rely on later canonicalization functions to do more
347 // fixup to make the URL valid if necessary. 343 // fixup to make the URL valid if necessary.
348 DCHECK(element->url()->SupportsReplacement()); 344 DCHECK(element->url()->SupportsReplacement());
349 match->destination_url = GURL(element->url()->ReplaceSearchTerms( 345 match->destination_url = GURL(element->url()->ReplaceSearchTerms(
350 *element, WideToUTF16Hack(remaining_input), 346 *element, remaining_input, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
351 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())); 347 std::wstring()));
352 std::vector<size_t> content_param_offsets; 348 std::vector<size_t> content_param_offsets;
353 match->contents.assign(UTF16ToWideHack( 349 match->contents.assign(UTF16ToWideHack(
354 l10n_util::GetStringFUTF16(message_id, 350 l10n_util::GetStringFUTF16(message_id,
355 element->short_name(), 351 WideToUTF16Hack(element->short_name()),
356 WideToUTF16Hack(remaining_input), 352 WideToUTF16Hack(remaining_input),
357 &content_param_offsets))); 353 &content_param_offsets)));
358 if (content_param_offsets.size() == 2) { 354 if (content_param_offsets.size() == 2) {
359 AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1], 355 AutocompleteMatch::ClassifyLocationInString(content_param_offsets[1],
360 remaining_input.length(), match->contents.length(), 356 remaining_input.length(), match->contents.length(),
361 ACMatchClassification::NONE, &match->contents_class); 357 ACMatchClassification::NONE, &match->contents_class);
362 } else { 358 } else {
363 // See comments on an identical NOTREACHED() in search_provider.cc. 359 // See comments on an identical NOTREACHED() in search_provider.cc.
364 NOTREACHED(); 360 NOTREACHED();
365 } 361 }
(...skipping 16 matching lines...) Expand all
382 378
383 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch( 379 AutocompleteMatch KeywordProvider::CreateAutocompleteMatch(
384 TemplateURLModel* model, 380 TemplateURLModel* model,
385 const std::wstring& keyword, 381 const std::wstring& keyword,
386 const AutocompleteInput& input, 382 const AutocompleteInput& input,
387 size_t prefix_length, 383 size_t prefix_length,
388 const std::wstring& remaining_input, 384 const std::wstring& remaining_input,
389 int relevance) { 385 int relevance) {
390 DCHECK(model); 386 DCHECK(model);
391 // Get keyword data from data store. 387 // Get keyword data from data store.
392 const TemplateURL* element( 388 const TemplateURL* element(model->GetTemplateURLForKeyword(keyword));
393 model->GetTemplateURLForKeyword(WideToUTF16Hack(keyword)));
394 DCHECK(element && element->url()); 389 DCHECK(element && element->url());
395 const bool supports_replacement = element->url()->SupportsReplacement(); 390 const bool supports_replacement = element->url()->SupportsReplacement();
396 391
397 // Create an edit entry of "[keyword] [remaining input]". This is helpful 392 // Create an edit entry of "[keyword] [remaining input]". This is helpful
398 // even when [remaining input] is empty, as the user can select the popup 393 // even when [remaining input] is empty, as the user can select the popup
399 // choice and immediately begin typing in query input. 394 // choice and immediately begin typing in query input.
400 const bool keyword_complete = (prefix_length == keyword.length()); 395 const bool keyword_complete = (prefix_length == keyword.length());
401 if (relevance < 0) { 396 if (relevance < 0) {
402 relevance = 397 relevance =
403 CalculateRelevance(input.type(), keyword_complete, 398 CalculateRelevance(input.type(), keyword_complete,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 return; 455 return;
461 456
462 case NotificationType::EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED: { 457 case NotificationType::EXTENSION_OMNIBOX_DEFAULT_SUGGESTION_CHANGED: {
463 // It's possible to change the default suggestion while not in an editing 458 // It's possible to change the default suggestion while not in an editing
464 // session. 459 // session.
465 std::wstring keyword, remaining_input; 460 std::wstring keyword, remaining_input;
466 if (matches_.empty() || current_keyword_extension_id_.empty() || 461 if (matches_.empty() || current_keyword_extension_id_.empty() ||
467 !ExtractKeywordFromInput(input, &keyword, &remaining_input)) 462 !ExtractKeywordFromInput(input, &keyword, &remaining_input))
468 return; 463 return;
469 464
470 const TemplateURL* template_url( 465 const TemplateURL* template_url(model->GetTemplateURLForKeyword(keyword));
471 model->GetTemplateURLForKeyword(WideToUTF16Hack(keyword)));
472 ApplyDefaultSuggestionForExtensionKeyword(profile_, template_url, 466 ApplyDefaultSuggestionForExtensionKeyword(profile_, template_url,
473 WideToUTF16(remaining_input), 467 WideToUTF16(remaining_input),
474 &matches_[0]); 468 &matches_[0]);
475 listener_->OnProviderUpdate(true); 469 listener_->OnProviderUpdate(true);
476 return; 470 return;
477 } 471 }
478 472
479 case NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY: { 473 case NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY: {
480 const ExtensionOmniboxSuggestions& suggestions = 474 const ExtensionOmniboxSuggestions& suggestions =
481 *Details<ExtensionOmniboxSuggestions>(details).ptr(); 475 *Details<ExtensionOmniboxSuggestions>(details).ptr();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 } 528 }
535 529
536 void KeywordProvider::MaybeEndExtensionKeywordMode() { 530 void KeywordProvider::MaybeEndExtensionKeywordMode() {
537 if (!current_keyword_extension_id_.empty()) { 531 if (!current_keyword_extension_id_.empty()) {
538 ExtensionOmniboxEventRouter::OnInputCancelled( 532 ExtensionOmniboxEventRouter::OnInputCancelled(
539 profile_, current_keyword_extension_id_); 533 profile_, current_keyword_extension_id_);
540 534
541 current_keyword_extension_id_.clear(); 535 current_keyword_extension_id_.clear();
542 } 536 }
543 } 537 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_unittest.cc ('k') | chrome/browser/autocomplete/keyword_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698