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

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

Issue 6256010: Revert 72380 - Remove wstring from autocomplete.... (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) 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/search_provider.h" 5 #include "chrome/browser/autocomplete/search_provider.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 cached_keyword_provider_ = *keyword_provider; 56 cached_keyword_provider_ = *keyword_provider;
57 } 57 }
58 58
59 SearchProvider::SearchProvider(ACProviderListener* listener, Profile* profile) 59 SearchProvider::SearchProvider(ACProviderListener* listener, Profile* profile)
60 : AutocompleteProvider(listener, profile, "Search"), 60 : AutocompleteProvider(listener, profile, "Search"),
61 suggest_results_pending_(0), 61 suggest_results_pending_(0),
62 have_suggest_results_(false), 62 have_suggest_results_(false),
63 instant_finalized_(false) { 63 instant_finalized_(false) {
64 } 64 }
65 65
66 void SearchProvider::FinalizeInstantQuery(const string16& input_text, 66 void SearchProvider::FinalizeInstantQuery(const std::wstring& input_text,
67 const string16& suggest_text) { 67 const std::wstring& suggest_text) {
68 if (done_ || instant_finalized_) 68 if (done_ || instant_finalized_)
69 return; 69 return;
70 70
71 instant_finalized_ = true; 71 instant_finalized_ = true;
72 UpdateDone(); 72 UpdateDone();
73 73
74 if (input_text.empty()) { 74 if (input_text.empty()) {
75 // We only need to update the listener if we're actually done. 75 // We only need to update the listener if we're actually done.
76 if (done_) 76 if (done_)
77 listener_->OnProviderUpdate(false); 77 listener_->OnProviderUpdate(false);
78 return; 78 return;
79 } 79 }
80 80
81 default_provider_suggest_text_ = suggest_text; 81 default_provider_suggest_text_ = suggest_text;
82 82
83 string16 adjusted_input_text(input_text); 83 std::wstring adjusted_input_text(input_text);
84 AutocompleteInput::RemoveForcedQueryStringIfNecessary(input_.type(), 84 AutocompleteInput::RemoveForcedQueryStringIfNecessary(input_.type(),
85 &adjusted_input_text); 85 &adjusted_input_text);
86 86
87 const string16 text = adjusted_input_text + suggest_text; 87 const std::wstring text = adjusted_input_text + suggest_text;
88 // Remove any matches that are identical to |text|. We don't use the 88 // Remove any matches that are identical to |text|. We don't use the
89 // destination_url for comparison as it varies depending upon the index passed 89 // destination_url for comparison as it varies depending upon the index passed
90 // to TemplateURL::ReplaceSearchTerms. 90 // to TemplateURL::ReplaceSearchTerms.
91 for (ACMatches::iterator i = matches_.begin(); i != matches_.end();) { 91 for (ACMatches::iterator i = matches_.begin(); i != matches_.end();) {
92 // Reset the description/description_class of all searches. We'll set the 92 // Reset the description/description_class of all searches. We'll set the
93 // description of the new first match in the call to 93 // description of the new first match in the call to
94 // UpdateFirstSearchMatchDescription() below. 94 // UpdateFirstSearchMatchDescription() below.
95 if ((i->type == AutocompleteMatch::SEARCH_HISTORY) || 95 if ((i->type == AutocompleteMatch::SEARCH_HISTORY) ||
96 (i->type == AutocompleteMatch::SEARCH_SUGGEST) || 96 (i->type == AutocompleteMatch::SEARCH_SUGGEST) ||
97 (i->type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED)) { 97 (i->type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED)) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 } 173 }
174 174
175 providers_.Set(default_provider, keyword_provider); 175 providers_.Set(default_provider, keyword_provider);
176 176
177 if (input.text().empty()) { 177 if (input.text().empty()) {
178 // User typed "?" alone. Give them a placeholder result indicating what 178 // User typed "?" alone. Give them a placeholder result indicating what
179 // this syntax does. 179 // this syntax does.
180 if (default_provider) { 180 if (default_provider) {
181 AutocompleteMatch match; 181 AutocompleteMatch match;
182 match.provider = this; 182 match.provider = this;
183 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)); 183 match.contents.assign(UTF16ToWideHack(
184 l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)));
184 match.contents_class.push_back( 185 match.contents_class.push_back(
185 ACMatchClassification(0, ACMatchClassification::NONE)); 186 ACMatchClassification(0, ACMatchClassification::NONE));
186 matches_.push_back(match); 187 matches_.push_back(match);
187 UpdateFirstSearchMatchDescription(); 188 UpdateFirstSearchMatchDescription();
188 } 189 }
189 Stop(); 190 Stop();
190 return; 191 return;
191 } 192 }
192 193
193 input_ = input; 194 input_ = input;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 DCHECK_GE(suggest_results_pending_, 0); // Should never go negative. 237 DCHECK_GE(suggest_results_pending_, 0); // Should never go negative.
237 const net::HttpResponseHeaders* const response_headers = 238 const net::HttpResponseHeaders* const response_headers =
238 source->response_headers(); 239 source->response_headers();
239 std::string json_data(data); 240 std::string json_data(data);
240 // JSON is supposed to be UTF-8, but some suggest service providers send JSON 241 // JSON is supposed to be UTF-8, but some suggest service providers send JSON
241 // files in non-UTF-8 encodings. The actual encoding is usually specified in 242 // files in non-UTF-8 encodings. The actual encoding is usually specified in
242 // the Content-Type header field. 243 // the Content-Type header field.
243 if (response_headers) { 244 if (response_headers) {
244 std::string charset; 245 std::string charset;
245 if (response_headers->GetCharset(&charset)) { 246 if (response_headers->GetCharset(&charset)) {
246 string16 data_16; 247 std::wstring wide_data;
247 // TODO(jungshik): Switch to CodePageToUTF8 after it's added. 248 // TODO(jungshik): Switch to CodePageToUTF8 after it's added.
248 if (base::CodepageToUTF16(data, charset.c_str(), 249 if (base::CodepageToWide(data, charset.c_str(),
249 base::OnStringConversionError::FAIL, 250 base::OnStringConversionError::FAIL,
250 &data_16)) 251 &wide_data))
251 json_data = UTF16ToUTF8(data_16); 252 json_data = WideToUTF8(wide_data);
252 } 253 }
253 } 254 }
254 255
255 bool is_keyword_results = (source == keyword_fetcher_.get()); 256 bool is_keyword_results = (source == keyword_fetcher_.get());
256 SuggestResults* suggest_results = is_keyword_results ? 257 SuggestResults* suggest_results = is_keyword_results ?
257 &keyword_suggest_results_ : &default_suggest_results_; 258 &keyword_suggest_results_ : &default_suggest_results_;
258 259
259 if (status.is_success() && response_code == 200) { 260 if (status.is_success() && response_code == 200) {
260 JSONStringValueSerializer deserializer(json_data); 261 JSONStringValueSerializer deserializer(json_data);
261 deserializer.set_allow_trailing_comma(true); 262 deserializer.set_allow_trailing_comma(true);
262 scoped_ptr<Value> root_val(deserializer.Deserialize(NULL, NULL)); 263 scoped_ptr<Value> root_val(deserializer.Deserialize(NULL, NULL));
263 const string16& input_text = 264 const std::wstring& input_text =
264 is_keyword_results ? keyword_input_text_ : input_.text(); 265 is_keyword_results ? keyword_input_text_ : input_.text();
265 have_suggest_results_ = 266 have_suggest_results_ =
266 root_val.get() && 267 root_val.get() &&
267 ParseSuggestResults(root_val.get(), is_keyword_results, input_text, 268 ParseSuggestResults(root_val.get(), is_keyword_results, input_text,
268 suggest_results); 269 suggest_results);
269 } 270 }
270 271
271 ConvertResultsToAutocompleteMatches(); 272 ConvertResultsToAutocompleteMatches();
272 listener_->OnProviderUpdate(!suggest_results->empty()); 273 listener_->OnProviderUpdate(!suggest_results->empty());
273 } 274 }
(...skipping 14 matching lines...) Expand all
288 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 289 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
289 history::URLDatabase* url_db = history_service ? 290 history::URLDatabase* url_db = history_service ?
290 history_service->InMemoryDatabase() : NULL; 291 history_service->InMemoryDatabase() : NULL;
291 if (!url_db) 292 if (!url_db)
292 return; 293 return;
293 294
294 // Request history for both the keyword and default provider. 295 // Request history for both the keyword and default provider.
295 if (providers_.valid_keyword_provider()) { 296 if (providers_.valid_keyword_provider()) {
296 url_db->GetMostRecentKeywordSearchTerms( 297 url_db->GetMostRecentKeywordSearchTerms(
297 providers_.keyword_provider().id(), 298 providers_.keyword_provider().id(),
298 keyword_input_text_, 299 WideToUTF16(keyword_input_text_),
299 static_cast<int>(kMaxMatches), 300 static_cast<int>(kMaxMatches),
300 &keyword_history_results_); 301 &keyword_history_results_);
301 } 302 }
302 if (providers_.valid_default_provider()) { 303 if (providers_.valid_default_provider()) {
303 url_db->GetMostRecentKeywordSearchTerms( 304 url_db->GetMostRecentKeywordSearchTerms(
304 providers_.default_provider().id(), 305 providers_.default_provider().id(),
305 input_.text(), 306 WideToUTF16(input_.text()),
306 static_cast<int>(kMaxMatches), 307 static_cast<int>(kMaxMatches),
307 &default_history_results_); 308 &default_history_results_);
308 } 309 }
309 } 310 }
310 311
311 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { 312 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) {
312 // Don't send any queries to the server until some time has elapsed after 313 // Don't send any queries to the server until some time has elapsed after
313 // the last keypress, to avoid flooding the server with requests we are 314 // the last keypress, to avoid flooding the server with requests we are
314 // likely to end up throwing away anyway. 315 // likely to end up throwing away anyway.
315 static const int kQueryDelayMs = 200; 316 static const int kQueryDelayMs = 200;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 // Next we check the scheme. If this is UNKNOWN/REQUESTED_URL/URL with a 366 // Next we check the scheme. If this is UNKNOWN/REQUESTED_URL/URL with a
366 // scheme that isn't http/https/ftp, we shouldn't send it. Sending things 367 // scheme that isn't http/https/ftp, we shouldn't send it. Sending things
367 // like file: and data: is both a waste of time and a disclosure of 368 // like file: and data: is both a waste of time and a disclosure of
368 // potentially private, local data. Other "schemes" may actually be 369 // potentially private, local data. Other "schemes" may actually be
369 // usernames, and we don't want to send passwords. If the scheme is OK, we 370 // usernames, and we don't want to send passwords. If the scheme is OK, we
370 // still need to check other cases below. If this is QUERY, then the presence 371 // still need to check other cases below. If this is QUERY, then the presence
371 // of these schemes means the user explicitly typed one, and thus this is 372 // of these schemes means the user explicitly typed one, and thus this is
372 // probably a URL that's being entered and happens to currently be invalid -- 373 // probably a URL that's being entered and happens to currently be invalid --
373 // in which case we again want to run our checks below. Other QUERY cases are 374 // in which case we again want to run our checks below. Other QUERY cases are
374 // less likely to be URLs and thus we assume we're OK. 375 // less likely to be URLs and thus we assume we're OK.
375 if (!LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpScheme) && 376 if ((input_.scheme() != L"http") && (input_.scheme() != L"https") &&
376 !LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpsScheme) && 377 (input_.scheme() != L"ftp"))
377 !LowerCaseEqualsASCII(input_.scheme(), chrome::kFtpScheme))
378 return (input_.type() == AutocompleteInput::QUERY); 378 return (input_.type() == AutocompleteInput::QUERY);
379 379
380 // Don't send URLs with usernames, queries or refs. Some of these are 380 // Don't send URLs with usernames, queries or refs. Some of these are
381 // private, and the Suggest server is unlikely to have any useful results 381 // private, and the Suggest server is unlikely to have any useful results
382 // for any of them. Also don't send URLs with ports, as we may initially 382 // for any of them. Also don't send URLs with ports, as we may initially
383 // think that a username + password is a host + port (and we don't want to 383 // think that a username + password is a host + port (and we don't want to
384 // send usernames/passwords), and even if the port really is a port, the 384 // send usernames/passwords), and even if the port really is a port, the
385 // server is once again unlikely to have and useful results. 385 // server is once again unlikely to have and useful results.
386 const url_parse::Parsed& parts = input_.parts(); 386 const url_parse::Parsed& parts = input_.parts();
387 if (parts.username.is_nonempty() || parts.port.is_nonempty() || 387 if (parts.username.is_nonempty() || parts.port.is_nonempty() ||
388 parts.query.is_nonempty() || parts.ref.is_nonempty()) 388 parts.query.is_nonempty() || parts.ref.is_nonempty())
389 return false; 389 return false;
390 390
391 // Don't send anything for https except the hostname. Hostnames are OK 391 // Don't send anything for https except the hostname. Hostnames are OK
392 // because they are visible when the TCP connection is established, but the 392 // because they are visible when the TCP connection is established, but the
393 // specific path may reveal private information. 393 // specific path may reveal private information.
394 if (LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpsScheme) && 394 if ((input_.scheme() == L"https") && parts.path.is_nonempty())
395 parts.path.is_nonempty())
396 return false; 395 return false;
397 396
398 return true; 397 return true;
399 } 398 }
400 399
401 void SearchProvider::StopSuggest() { 400 void SearchProvider::StopSuggest() {
402 suggest_results_pending_ = 0; 401 suggest_results_pending_ = 0;
403 timer_.Stop(); 402 timer_.Stop();
404 // Stop any in-progress URL fetches. 403 // Stop any in-progress URL fetches.
405 keyword_fetcher_.reset(); 404 keyword_fetcher_.reset();
406 default_fetcher_.reset(); 405 default_fetcher_.reset();
407 keyword_suggest_results_.clear(); 406 keyword_suggest_results_.clear();
408 default_suggest_results_.clear(); 407 default_suggest_results_.clear();
409 keyword_navigation_results_.clear(); 408 keyword_navigation_results_.clear();
410 default_navigation_results_.clear(); 409 default_navigation_results_.clear();
411 have_suggest_results_ = false; 410 have_suggest_results_ = false;
412 } 411 }
413 412
414 URLFetcher* SearchProvider::CreateSuggestFetcher(int id, 413 URLFetcher* SearchProvider::CreateSuggestFetcher(int id,
415 const TemplateURL& provider, 414 const TemplateURL& provider,
416 const string16& text) { 415 const std::wstring& text) {
417 const TemplateURLRef* const suggestions_url = provider.suggestions_url(); 416 const TemplateURLRef* const suggestions_url = provider.suggestions_url();
418 DCHECK(suggestions_url->SupportsReplacement()); 417 DCHECK(suggestions_url->SupportsReplacement());
419 URLFetcher* fetcher = URLFetcher::Create(id, 418 URLFetcher* fetcher = URLFetcher::Create(id,
420 GURL(suggestions_url->ReplaceSearchTerms( 419 GURL(suggestions_url->ReplaceSearchTerms(
421 provider, text, 420 provider, WideToUTF16Hack(text),
422 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())), 421 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())),
423 URLFetcher::GET, this); 422 URLFetcher::GET, this);
424 fetcher->set_request_context(profile_->GetRequestContext()); 423 fetcher->set_request_context(profile_->GetRequestContext());
425 fetcher->Start(); 424 fetcher->Start();
426 return fetcher; 425 return fetcher;
427 } 426 }
428 427
429 bool SearchProvider::ParseSuggestResults(Value* root_val, 428 bool SearchProvider::ParseSuggestResults(Value* root_val,
430 bool is_keyword, 429 bool is_keyword,
431 const string16& input_text, 430 const std::wstring& input_text,
432 SuggestResults* suggest_results) { 431 SuggestResults* suggest_results) {
433 if (!root_val->IsType(Value::TYPE_LIST)) 432 if (!root_val->IsType(Value::TYPE_LIST))
434 return false; 433 return false;
435 ListValue* root_list = static_cast<ListValue*>(root_val); 434 ListValue* root_list = static_cast<ListValue*>(root_val);
436 435
437 Value* query_val; 436 Value* query_val;
438 string16 query_str; 437 string16 query_str;
439 Value* result_val; 438 Value* result_val;
440 if ((root_list->GetSize() < 2) || !root_list->Get(0, &query_val) || 439 if ((root_list->GetSize() < 2) || !root_list->Get(0, &query_val) ||
441 !query_val->GetAsString(&query_str) || 440 !query_val->GetAsString(&query_str) ||
442 (query_str != input_text) || 441 (query_str != WideToUTF16Hack(input_text)) ||
443 !root_list->Get(1, &result_val) || !result_val->IsType(Value::TYPE_LIST)) 442 !root_list->Get(1, &result_val) || !result_val->IsType(Value::TYPE_LIST))
444 return false; 443 return false;
445 444
446 ListValue* description_list = NULL; 445 ListValue* description_list = NULL;
447 if (root_list->GetSize() > 2) { 446 if (root_list->GetSize() > 2) {
448 // 3rd element: Description list. 447 // 3rd element: Description list.
449 Value* description_val; 448 Value* description_val;
450 if (root_list->Get(2, &description_val) && 449 if (root_list->Get(2, &description_val) &&
451 description_val->IsType(Value::TYPE_LIST)) 450 description_val->IsType(Value::TYPE_LIST))
452 description_list = static_cast<ListValue*>(description_val); 451 description_list = static_cast<ListValue*>(description_val);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 is_keyword ? keyword_navigation_results_ : 496 is_keyword ? keyword_navigation_results_ :
498 default_navigation_results_; 497 default_navigation_results_;
499 if ((navigation_results.size() < kMaxMatches) && 498 if ((navigation_results.size() < kMaxMatches) &&
500 description_list && description_list->Get(i, &site_val) && 499 description_list && description_list->Get(i, &site_val) &&
501 site_val->IsType(Value::TYPE_STRING) && 500 site_val->IsType(Value::TYPE_STRING) &&
502 site_val->GetAsString(&site_name)) { 501 site_val->GetAsString(&site_name)) {
503 // We can't blindly trust the URL coming from the server to be valid. 502 // We can't blindly trust the URL coming from the server to be valid.
504 GURL result_url(URLFixerUpper::FixupURL(UTF16ToUTF8(suggestion_str), 503 GURL result_url(URLFixerUpper::FixupURL(UTF16ToUTF8(suggestion_str),
505 std::string())); 504 std::string()));
506 if (result_url.is_valid()) { 505 if (result_url.is_valid()) {
507 navigation_results.push_back(NavigationResult(result_url, site_name)); 506 navigation_results.push_back(NavigationResult(result_url,
507 UTF16ToWideHack(site_name)));
508 } 508 }
509 } 509 }
510 } else { 510 } else {
511 // TODO(kochi): Currently we treat a calculator result as a query, but it 511 // TODO(kochi): Currently we treat a calculator result as a query, but it
512 // is better to have better presentation for caluculator results. 512 // is better to have better presentation for caluculator results.
513 if (suggest_results->size() < kMaxMatches) 513 if (suggest_results->size() < kMaxMatches)
514 suggest_results->push_back(suggestion_str); 514 suggest_results->push_back(UTF16ToWideHack(suggestion_str));
515 } 515 }
516 } 516 }
517 517
518 return true; 518 return true;
519 } 519 }
520 520
521 void SearchProvider::ConvertResultsToAutocompleteMatches() { 521 void SearchProvider::ConvertResultsToAutocompleteMatches() {
522 // Convert all the results to matches and add them to a map, so we can keep 522 // Convert all the results to matches and add them to a map, so we can keep
523 // the most relevant match for each result. 523 // the most relevant match for each result.
524 MatchMap map; 524 MatchMap map;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 // match having a relevance greater than the previous, but they might be 605 // match having a relevance greater than the previous, but they might be
606 // equal. If we didn't force the relevance to decrease and we ended up in a 606 // equal. If we didn't force the relevance to decrease and we ended up in a
607 // situation where the relevance was equal, then which was shown first would 607 // situation where the relevance was equal, then which was shown first would
608 // be random. 608 // be random.
609 // This uses >= to handle the case where 3 or more results have the same 609 // This uses >= to handle the case where 3 or more results have the same
610 // relevance. 610 // relevance.
611 int relevance = CalculateRelevanceForHistory(i->time, is_keyword); 611 int relevance = CalculateRelevanceForHistory(i->time, is_keyword);
612 if (i != results.begin() && relevance >= last_relevance) 612 if (i != results.begin() && relevance >= last_relevance)
613 relevance = last_relevance - 1; 613 relevance = last_relevance - 1;
614 last_relevance = relevance; 614 last_relevance = relevance;
615 AddMatchToMap(i->term, 615 AddMatchToMap(UTF16ToWide(i->term),
616 is_keyword ? keyword_input_text_ : input_.text(), 616 is_keyword ? keyword_input_text_ : input_.text(),
617 relevance, 617 relevance,
618 AutocompleteMatch::SEARCH_HISTORY, did_not_accept_suggestion, 618 AutocompleteMatch::SEARCH_HISTORY, did_not_accept_suggestion,
619 is_keyword, input_.initial_prevent_inline_autocomplete(), 619 is_keyword, input_.initial_prevent_inline_autocomplete(),
620 map); 620 map);
621 } 621 }
622 } 622 }
623 623
624 void SearchProvider::AddSuggestResultsToMap( 624 void SearchProvider::AddSuggestResultsToMap(
625 const SuggestResults& suggest_results, 625 const SuggestResults& suggest_results,
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 int SearchProvider::CalculateRelevanceForNavigation(size_t num_results, 710 int SearchProvider::CalculateRelevanceForNavigation(size_t num_results,
711 size_t result_number, 711 size_t result_number,
712 bool is_keyword) const { 712 bool is_keyword) const {
713 DCHECK(result_number < num_results); 713 DCHECK(result_number < num_results);
714 // TODO(kochi): http://b/784900 Use relevance score from the NavSuggest 714 // TODO(kochi): http://b/784900 Use relevance score from the NavSuggest
715 // server if possible. 715 // server if possible.
716 return (providers_.is_primary_provider(is_keyword) ? 800 : 150) + 716 return (providers_.is_primary_provider(is_keyword) ? 800 : 150) +
717 static_cast<int>(num_results - 1 - result_number); 717 static_cast<int>(num_results - 1 - result_number);
718 } 718 }
719 719
720 void SearchProvider::AddMatchToMap(const string16& query_string, 720 void SearchProvider::AddMatchToMap(const std::wstring& query_string,
721 const string16& input_text, 721 const std::wstring& input_text,
722 int relevance, 722 int relevance,
723 AutocompleteMatch::Type type, 723 AutocompleteMatch::Type type,
724 int accepted_suggestion, 724 int accepted_suggestion,
725 bool is_keyword, 725 bool is_keyword,
726 bool prevent_inline_autocomplete, 726 bool prevent_inline_autocomplete,
727 MatchMap* map) { 727 MatchMap* map) {
728 AutocompleteMatch match(this, relevance, false, type); 728 AutocompleteMatch match(this, relevance, false, type);
729 std::vector<size_t> content_param_offsets; 729 std::vector<size_t> content_param_offsets;
730 const TemplateURL& provider = is_keyword ? providers_.keyword_provider() : 730 const TemplateURL& provider = is_keyword ? providers_.keyword_provider() :
731 providers_.default_provider(); 731 providers_.default_provider();
732 match.contents.assign(query_string); 732 match.contents.assign(query_string);
733 // We do intra-string highlighting for suggestions - the suggested segment 733 // We do intra-string highlighting for suggestions - the suggested segment
734 // will be highlighted, e.g. for input_text = "you" the suggestion may be 734 // will be highlighted, e.g. for input_text = "you" the suggestion may be
735 // "youtube", so we'll bold the "tube" section: you*tube*. 735 // "youtube", so we'll bold the "tube" section: you*tube*.
736 if (input_text != query_string) { 736 if (input_text != query_string) {
737 size_t input_position = match.contents.find(input_text); 737 size_t input_position = match.contents.find(input_text);
738 if (input_position == string16::npos) { 738 if (input_position == std::wstring::npos) {
739 // The input text is not a substring of the query string, e.g. input 739 // The input text is not a substring of the query string, e.g. input
740 // text is "slasdot" and the query string is "slashdot", so we bold the 740 // text is "slasdot" and the query string is "slashdot", so we bold the
741 // whole thing. 741 // whole thing.
742 match.contents_class.push_back( 742 match.contents_class.push_back(
743 ACMatchClassification(0, ACMatchClassification::MATCH)); 743 ACMatchClassification(0, ACMatchClassification::MATCH));
744 } else { 744 } else {
745 // TODO(beng): ACMatchClassification::MATCH now seems to just mean 745 // TODO(beng): ACMatchClassification::MATCH now seems to just mean
746 // "bold" this. Consider modifying the terminology. 746 // "bold" this. Consider modifying the terminology.
747 // We don't iterate over the string here annotating all matches because 747 // We don't iterate over the string here annotating all matches because
748 // it looks odd to have every occurrence of a substring that may be as 748 // it looks odd to have every occurrence of a substring that may be as
(...skipping 18 matching lines...) Expand all
767 // completion. 767 // completion.
768 match.contents_class.push_back( 768 match.contents_class.push_back(
769 ACMatchClassification(0, ACMatchClassification::NONE)); 769 ACMatchClassification(0, ACMatchClassification::NONE));
770 } 770 }
771 771
772 // When the user forced a query, we need to make sure all the fill_into_edit 772 // When the user forced a query, we need to make sure all the fill_into_edit
773 // values preserve that property. Otherwise, if the user starts editing a 773 // values preserve that property. Otherwise, if the user starts editing a
774 // suggestion, non-Search results will suddenly appear. 774 // suggestion, non-Search results will suddenly appear.
775 size_t search_start = 0; 775 size_t search_start = 0;
776 if (input_.type() == AutocompleteInput::FORCED_QUERY) { 776 if (input_.type() == AutocompleteInput::FORCED_QUERY) {
777 match.fill_into_edit.assign(ASCIIToUTF16("?")); 777 match.fill_into_edit.assign(L"?");
778 ++search_start; 778 ++search_start;
779 } 779 }
780 if (is_keyword) { 780 if (is_keyword) {
781 match.fill_into_edit.append( 781 match.fill_into_edit.append(UTF16ToWideHack(
782 providers_.keyword_provider().keyword() + char16(' ')); 782 providers_.keyword_provider().keyword() + char16(' ')));
783 match.template_url = &providers_.keyword_provider(); 783 match.template_url = &providers_.keyword_provider();
784 } 784 }
785 match.fill_into_edit.append(query_string); 785 match.fill_into_edit.append(query_string);
786 // Not all suggestions start with the original input. 786 // Not all suggestions start with the original input.
787 if (!prevent_inline_autocomplete && 787 if (!prevent_inline_autocomplete &&
788 !match.fill_into_edit.compare(search_start, input_text.length(), 788 !match.fill_into_edit.compare(search_start, input_text.length(),
789 input_text)) 789 input_text))
790 match.inline_autocomplete_offset = search_start + input_text.length(); 790 match.inline_autocomplete_offset = search_start + input_text.length();
791 791
792 const TemplateURLRef* const search_url = provider.url(); 792 const TemplateURLRef* const search_url = provider.url();
793 DCHECK(search_url->SupportsReplacement()); 793 DCHECK(search_url->SupportsReplacement());
794 match.destination_url = 794 match.destination_url =
795 GURL(search_url->ReplaceSearchTerms(provider, 795 GURL(search_url->ReplaceSearchTerms(provider,
796 query_string, 796 WideToUTF16Hack(query_string),
797 accepted_suggestion, 797 accepted_suggestion,
798 input_text)); 798 WideToUTF16Hack(input_text)));
799 799
800 // Search results don't look like URLs. 800 // Search results don't look like URLs.
801 match.transition = 801 match.transition =
802 is_keyword ? PageTransition::KEYWORD : PageTransition::GENERATED; 802 is_keyword ? PageTransition::KEYWORD : PageTransition::GENERATED;
803 803
804 // Try to add |match| to |map|. If a match for |query_string| is already in 804 // Try to add |match| to |map|. If a match for |query_string| is already in
805 // |map|, replace it if |match| is more relevant. 805 // |map|, replace it if |match| is more relevant.
806 // NOTE: Keep this ToLower() call in sync with url_database.cc. 806 // NOTE: Keep this ToLower() call in sync with url_database.cc.
807 const std::pair<MatchMap::iterator, bool> i = map->insert( 807 const std::pair<MatchMap::iterator, bool> i = map->insert(
808 std::pair<string16, AutocompleteMatch>( 808 std::pair<std::wstring, AutocompleteMatch>(
809 l10n_util::ToLower(query_string), match)); 809 UTF16ToWide(l10n_util::ToLower(WideToUTF16(query_string))), match));
810 // NOTE: We purposefully do a direct relevance comparison here instead of 810 // NOTE: We purposefully do a direct relevance comparison here instead of
811 // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added 811 // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added
812 // first" rather than "items alphabetically first" when the scores are equal. 812 // first" rather than "items alphabetically first" when the scores are equal.
813 // The only case this matters is when a user has results with the same score 813 // The only case this matters is when a user has results with the same score
814 // that differ only by capitalization; because the history system returns 814 // that differ only by capitalization; because the history system returns
815 // results sorted by recency, this means we'll pick the most recent such 815 // results sorted by recency, this means we'll pick the most recent such
816 // result even if the precision of our relevance score is too low to 816 // result even if the precision of our relevance score is too low to
817 // distinguish the two. 817 // distinguish the two.
818 if (!i.second && (match.relevance > i.first->second.relevance)) 818 if (!i.second && (match.relevance > i.first->second.relevance))
819 i.first->second = match; 819 i.first->second = match;
820 } 820 }
821 821
822 AutocompleteMatch SearchProvider::NavigationToMatch( 822 AutocompleteMatch SearchProvider::NavigationToMatch(
823 const NavigationResult& navigation, 823 const NavigationResult& navigation,
824 int relevance, 824 int relevance,
825 bool is_keyword) { 825 bool is_keyword) {
826 const string16& input_text = 826 const std::wstring& input_text =
827 is_keyword ? keyword_input_text_ : input_.text(); 827 is_keyword ? keyword_input_text_ : input_.text();
828 AutocompleteMatch match(this, relevance, false, 828 AutocompleteMatch match(this, relevance, false,
829 AutocompleteMatch::NAVSUGGEST); 829 AutocompleteMatch::NAVSUGGEST);
830 match.destination_url = navigation.url; 830 match.destination_url = navigation.url;
831 match.contents = 831 match.contents =
832 StringForURLDisplay(navigation.url, true, !HasHTTPScheme(input_text)); 832 StringForURLDisplay(navigation.url, true, !HasHTTPScheme(input_text));
833 AutocompleteMatch::ClassifyMatchInString(input_text, match.contents, 833 AutocompleteMatch::ClassifyMatchInString(input_text, match.contents,
834 ACMatchClassification::URL, 834 ACMatchClassification::URL,
835 &match.contents_class); 835 &match.contents_class);
836 836
837 match.description = navigation.site_name; 837 match.description = navigation.site_name;
838 AutocompleteMatch::ClassifyMatchInString(input_text, navigation.site_name, 838 AutocompleteMatch::ClassifyMatchInString(input_text, navigation.site_name,
839 ACMatchClassification::NONE, 839 ACMatchClassification::NONE,
840 &match.description_class); 840 &match.description_class);
841 841
842 // When the user forced a query, we need to make sure all the fill_into_edit 842 // When the user forced a query, we need to make sure all the fill_into_edit
843 // values preserve that property. Otherwise, if the user starts editing a 843 // values preserve that property. Otherwise, if the user starts editing a
844 // suggestion, non-Search results will suddenly appear. 844 // suggestion, non-Search results will suddenly appear.
845 if (input_.type() == AutocompleteInput::FORCED_QUERY) 845 if (input_.type() == AutocompleteInput::FORCED_QUERY)
846 match.fill_into_edit.assign(ASCIIToUTF16("?")); 846 match.fill_into_edit.assign(L"?");
847 match.fill_into_edit.append( 847 match.fill_into_edit.append(
848 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url, 848 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url,
849 match.contents)); 849 match.contents));
850 // TODO(pkasting): http://b/1112879 These should perhaps be 850 // TODO(pkasting): http://b/1112879 These should perhaps be
851 // inline-autocompletable? 851 // inline-autocompletable?
852 852
853 return match; 853 return match;
854 } 854 }
855 855
856 void SearchProvider::UpdateDone() { 856 void SearchProvider::UpdateDone() {
857 // We're done when there are no more suggest queries pending (this is set to 1 857 // We're done when there are no more suggest queries pending (this is set to 1
858 // when the timer is started) and we're not waiting on instant. 858 // when the timer is started) and we're not waiting on instant.
859 done_ = ((suggest_results_pending_ == 0) && 859 done_ = ((suggest_results_pending_ == 0) &&
860 (instant_finalized_ || !InstantController::IsEnabled(profile_))); 860 (instant_finalized_ || !InstantController::IsEnabled(profile_)));
861 } 861 }
862 862
863 void SearchProvider::UpdateFirstSearchMatchDescription() { 863 void SearchProvider::UpdateFirstSearchMatchDescription() {
864 if (!providers_.valid_default_provider() || matches_.empty()) 864 if (!providers_.valid_default_provider() || matches_.empty())
865 return; 865 return;
866 866
867 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) { 867 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) {
868 AutocompleteMatch& match = *i; 868 AutocompleteMatch& match = *i;
869 switch (match.type) { 869 switch (match.type) {
870 case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: 870 case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED:
871 case AutocompleteMatch::SEARCH_HISTORY: 871 case AutocompleteMatch::SEARCH_HISTORY:
872 case AutocompleteMatch::SEARCH_SUGGEST: 872 case AutocompleteMatch::SEARCH_SUGGEST:
873 match.description.assign(l10n_util::GetStringFUTF16( 873 match.description.assign(
874 IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION, 874 UTF16ToWideHack(l10n_util::GetStringFUTF16(
875 providers_.default_provider(). 875 IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION,
876 AdjustedShortNameForLocaleDirection())); 876 providers_.default_provider().
877 AdjustedShortNameForLocaleDirection())));
877 match.description_class.push_back( 878 match.description_class.push_back(
878 ACMatchClassification(0, ACMatchClassification::DIM)); 879 ACMatchClassification(0, ACMatchClassification::DIM));
879 // Only the first search match gets a description. 880 // Only the first search match gets a description.
880 return; 881 return;
881 882
882 default: 883 default:
883 break; 884 break;
884 } 885 }
885 } 886 }
886 } 887 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/search_provider.h ('k') | chrome/browser/autocomplete/search_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698