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

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

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