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

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

Issue 6306011: Remove wstring from autocomplete. (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) 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 std::wstring& input_text, 66 void SearchProvider::FinalizeInstantQuery(const string16& input_text,
67 const std::wstring& suggest_text) { 67 const string16& 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 std::wstring adjusted_input_text(input_text); 83 string16 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 std::wstring text = adjusted_input_text + suggest_text; 87 const string16 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(UTF16ToWideHack( 183 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE));
184 l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)));
185 match.contents_class.push_back( 184 match.contents_class.push_back(
186 ACMatchClassification(0, ACMatchClassification::NONE)); 185 ACMatchClassification(0, ACMatchClassification::NONE));
187 matches_.push_back(match); 186 matches_.push_back(match);
188 UpdateFirstSearchMatchDescription(); 187 UpdateFirstSearchMatchDescription();
189 } 188 }
190 Stop(); 189 Stop();
191 return; 190 return;
192 } 191 }
193 192
194 input_ = input; 193 input_ = input;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 DCHECK_GE(suggest_results_pending_, 0); // Should never go negative. 236 DCHECK_GE(suggest_results_pending_, 0); // Should never go negative.
238 const net::HttpResponseHeaders* const response_headers = 237 const net::HttpResponseHeaders* const response_headers =
239 source->response_headers(); 238 source->response_headers();
240 std::string json_data(data); 239 std::string json_data(data);
241 // JSON is supposed to be UTF-8, but some suggest service providers send JSON 240 // JSON is supposed to be UTF-8, but some suggest service providers send JSON
242 // files in non-UTF-8 encodings. The actual encoding is usually specified in 241 // files in non-UTF-8 encodings. The actual encoding is usually specified in
243 // the Content-Type header field. 242 // the Content-Type header field.
244 if (response_headers) { 243 if (response_headers) {
245 std::string charset; 244 std::string charset;
246 if (response_headers->GetCharset(&charset)) { 245 if (response_headers->GetCharset(&charset)) {
247 std::wstring wide_data; 246 string16 data_16;
248 // TODO(jungshik): Switch to CodePageToUTF8 after it's added. 247 // TODO(jungshik): Switch to CodePageToUTF8 after it's added.
249 if (base::CodepageToWide(data, charset.c_str(), 248 if (base::CodepageToUTF16(data, charset.c_str(),
250 base::OnStringConversionError::FAIL, 249 base::OnStringConversionError::FAIL,
251 &wide_data)) 250 &data_16))
252 json_data = WideToUTF8(wide_data); 251 json_data = UTF16ToUTF8(data_16);
253 } 252 }
254 } 253 }
255 254
256 bool is_keyword_results = (source == keyword_fetcher_.get()); 255 bool is_keyword_results = (source == keyword_fetcher_.get());
257 SuggestResults* suggest_results = is_keyword_results ? 256 SuggestResults* suggest_results = is_keyword_results ?
258 &keyword_suggest_results_ : &default_suggest_results_; 257 &keyword_suggest_results_ : &default_suggest_results_;
259 258
260 if (status.is_success() && response_code == 200) { 259 if (status.is_success() && response_code == 200) {
261 JSONStringValueSerializer deserializer(json_data); 260 JSONStringValueSerializer deserializer(json_data);
262 deserializer.set_allow_trailing_comma(true); 261 deserializer.set_allow_trailing_comma(true);
263 scoped_ptr<Value> root_val(deserializer.Deserialize(NULL, NULL)); 262 scoped_ptr<Value> root_val(deserializer.Deserialize(NULL, NULL));
264 const std::wstring& input_text = 263 const string16& input_text =
265 is_keyword_results ? keyword_input_text_ : input_.text(); 264 is_keyword_results ? keyword_input_text_ : input_.text();
266 have_suggest_results_ = 265 have_suggest_results_ =
267 root_val.get() && 266 root_val.get() &&
268 ParseSuggestResults(root_val.get(), is_keyword_results, input_text, 267 ParseSuggestResults(root_val.get(), is_keyword_results, input_text,
269 suggest_results); 268 suggest_results);
270 } 269 }
271 270
272 ConvertResultsToAutocompleteMatches(); 271 ConvertResultsToAutocompleteMatches();
273 listener_->OnProviderUpdate(!suggest_results->empty()); 272 listener_->OnProviderUpdate(!suggest_results->empty());
274 } 273 }
(...skipping 14 matching lines...) Expand all
289 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 288 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
290 history::URLDatabase* url_db = history_service ? 289 history::URLDatabase* url_db = history_service ?
291 history_service->InMemoryDatabase() : NULL; 290 history_service->InMemoryDatabase() : NULL;
292 if (!url_db) 291 if (!url_db)
293 return; 292 return;
294 293
295 // Request history for both the keyword and default provider. 294 // Request history for both the keyword and default provider.
296 if (providers_.valid_keyword_provider()) { 295 if (providers_.valid_keyword_provider()) {
297 url_db->GetMostRecentKeywordSearchTerms( 296 url_db->GetMostRecentKeywordSearchTerms(
298 providers_.keyword_provider().id(), 297 providers_.keyword_provider().id(),
299 WideToUTF16(keyword_input_text_), 298 keyword_input_text_,
300 static_cast<int>(kMaxMatches), 299 static_cast<int>(kMaxMatches),
301 &keyword_history_results_); 300 &keyword_history_results_);
302 } 301 }
303 if (providers_.valid_default_provider()) { 302 if (providers_.valid_default_provider()) {
304 url_db->GetMostRecentKeywordSearchTerms( 303 url_db->GetMostRecentKeywordSearchTerms(
305 providers_.default_provider().id(), 304 providers_.default_provider().id(),
306 WideToUTF16(input_.text()), 305 input_.text(),
307 static_cast<int>(kMaxMatches), 306 static_cast<int>(kMaxMatches),
308 &default_history_results_); 307 &default_history_results_);
309 } 308 }
310 } 309 }
311 310
312 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { 311 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) {
313 // Don't send any queries to the server until some time has elapsed after 312 // Don't send any queries to the server until some time has elapsed after
314 // the last keypress, to avoid flooding the server with requests we are 313 // the last keypress, to avoid flooding the server with requests we are
315 // likely to end up throwing away anyway. 314 // likely to end up throwing away anyway.
316 static const int kQueryDelayMs = 200; 315 static const int kQueryDelayMs = 200;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 // Next we check the scheme. If this is UNKNOWN/REQUESTED_URL/URL with a 365 // Next we check the scheme. If this is UNKNOWN/REQUESTED_URL/URL with a
367 // scheme that isn't http/https/ftp, we shouldn't send it. Sending things 366 // scheme that isn't http/https/ftp, we shouldn't send it. Sending things
368 // like file: and data: is both a waste of time and a disclosure of 367 // like file: and data: is both a waste of time and a disclosure of
369 // potentially private, local data. Other "schemes" may actually be 368 // potentially private, local data. Other "schemes" may actually be
370 // usernames, and we don't want to send passwords. If the scheme is OK, we 369 // usernames, and we don't want to send passwords. If the scheme is OK, we
371 // still need to check other cases below. If this is QUERY, then the presence 370 // still need to check other cases below. If this is QUERY, then the presence
372 // of these schemes means the user explicitly typed one, and thus this is 371 // of these schemes means the user explicitly typed one, and thus this is
373 // probably a URL that's being entered and happens to currently be invalid -- 372 // probably a URL that's being entered and happens to currently be invalid --
374 // in which case we again want to run our checks below. Other QUERY cases are 373 // in which case we again want to run our checks below. Other QUERY cases are
375 // less likely to be URLs and thus we assume we're OK. 374 // less likely to be URLs and thus we assume we're OK.
376 if ((input_.scheme() != L"http") && (input_.scheme() != L"https") && 375 if (!LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpScheme) &&
377 (input_.scheme() != L"ftp")) 376 !LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpsScheme) &&
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 ((input_.scheme() == L"https") && parts.path.is_nonempty()) 394 if (LowerCaseEqualsASCII(input_.scheme(), chrome::kHttpsScheme) &&
395 parts.path.is_nonempty())
395 return false; 396 return false;
396 397
397 return true; 398 return true;
398 } 399 }
399 400
400 void SearchProvider::StopSuggest() { 401 void SearchProvider::StopSuggest() {
401 suggest_results_pending_ = 0; 402 suggest_results_pending_ = 0;
402 timer_.Stop(); 403 timer_.Stop();
403 // Stop any in-progress URL fetches. 404 // Stop any in-progress URL fetches.
404 keyword_fetcher_.reset(); 405 keyword_fetcher_.reset();
405 default_fetcher_.reset(); 406 default_fetcher_.reset();
406 keyword_suggest_results_.clear(); 407 keyword_suggest_results_.clear();
407 default_suggest_results_.clear(); 408 default_suggest_results_.clear();
408 keyword_navigation_results_.clear(); 409 keyword_navigation_results_.clear();
409 default_navigation_results_.clear(); 410 default_navigation_results_.clear();
410 have_suggest_results_ = false; 411 have_suggest_results_ = false;
411 } 412 }
412 413
413 URLFetcher* SearchProvider::CreateSuggestFetcher(int id, 414 URLFetcher* SearchProvider::CreateSuggestFetcher(int id,
414 const TemplateURL& provider, 415 const TemplateURL& provider,
415 const std::wstring& text) { 416 const string16& text) {
416 const TemplateURLRef* const suggestions_url = provider.suggestions_url(); 417 const TemplateURLRef* const suggestions_url = provider.suggestions_url();
417 DCHECK(suggestions_url->SupportsReplacement()); 418 DCHECK(suggestions_url->SupportsReplacement());
418 URLFetcher* fetcher = URLFetcher::Create(id, 419 URLFetcher* fetcher = URLFetcher::Create(id,
419 GURL(suggestions_url->ReplaceSearchTerms( 420 GURL(suggestions_url->ReplaceSearchTerms(
420 provider, WideToUTF16Hack(text), 421 provider, text,
421 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())), 422 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())),
422 URLFetcher::GET, this); 423 URLFetcher::GET, this);
423 fetcher->set_request_context(profile_->GetRequestContext()); 424 fetcher->set_request_context(profile_->GetRequestContext());
424 fetcher->Start(); 425 fetcher->Start();
425 return fetcher; 426 return fetcher;
426 } 427 }
427 428
428 bool SearchProvider::ParseSuggestResults(Value* root_val, 429 bool SearchProvider::ParseSuggestResults(Value* root_val,
429 bool is_keyword, 430 bool is_keyword,
430 const std::wstring& input_text, 431 const string16& input_text,
431 SuggestResults* suggest_results) { 432 SuggestResults* suggest_results) {
432 if (!root_val->IsType(Value::TYPE_LIST)) 433 if (!root_val->IsType(Value::TYPE_LIST))
433 return false; 434 return false;
434 ListValue* root_list = static_cast<ListValue*>(root_val); 435 ListValue* root_list = static_cast<ListValue*>(root_val);
435 436
436 Value* query_val; 437 Value* query_val;
437 string16 query_str; 438 string16 query_str;
438 Value* result_val; 439 Value* result_val;
439 if ((root_list->GetSize() < 2) || !root_list->Get(0, &query_val) || 440 if ((root_list->GetSize() < 2) || !root_list->Get(0, &query_val) ||
440 !query_val->GetAsString(&query_str) || 441 !query_val->GetAsString(&query_str) ||
441 (query_str != WideToUTF16Hack(input_text)) || 442 (query_str != input_text) ||
442 !root_list->Get(1, &result_val) || !result_val->IsType(Value::TYPE_LIST)) 443 !root_list->Get(1, &result_val) || !result_val->IsType(Value::TYPE_LIST))
443 return false; 444 return false;
444 445
445 ListValue* description_list = NULL; 446 ListValue* description_list = NULL;
446 if (root_list->GetSize() > 2) { 447 if (root_list->GetSize() > 2) {
447 // 3rd element: Description list. 448 // 3rd element: Description list.
448 Value* description_val; 449 Value* description_val;
449 if (root_list->Get(2, &description_val) && 450 if (root_list->Get(2, &description_val) &&
450 description_val->IsType(Value::TYPE_LIST)) 451 description_val->IsType(Value::TYPE_LIST))
451 description_list = static_cast<ListValue*>(description_val); 452 description_list = static_cast<ListValue*>(description_val);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 is_keyword ? keyword_navigation_results_ : 497 is_keyword ? keyword_navigation_results_ :
497 default_navigation_results_; 498 default_navigation_results_;
498 if ((navigation_results.size() < kMaxMatches) && 499 if ((navigation_results.size() < kMaxMatches) &&
499 description_list && description_list->Get(i, &site_val) && 500 description_list && description_list->Get(i, &site_val) &&
500 site_val->IsType(Value::TYPE_STRING) && 501 site_val->IsType(Value::TYPE_STRING) &&
501 site_val->GetAsString(&site_name)) { 502 site_val->GetAsString(&site_name)) {
502 // We can't blindly trust the URL coming from the server to be valid. 503 // We can't blindly trust the URL coming from the server to be valid.
503 GURL result_url(URLFixerUpper::FixupURL(UTF16ToUTF8(suggestion_str), 504 GURL result_url(URLFixerUpper::FixupURL(UTF16ToUTF8(suggestion_str),
504 std::string())); 505 std::string()));
505 if (result_url.is_valid()) { 506 if (result_url.is_valid()) {
506 navigation_results.push_back(NavigationResult(result_url, 507 navigation_results.push_back(NavigationResult(result_url, site_name));
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(UTF16ToWideHack(suggestion_str)); 514 suggest_results->push_back(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(UTF16ToWide(i->term), 615 AddMatchToMap(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 std::wstring& query_string, 720 void SearchProvider::AddMatchToMap(const string16& query_string,
721 const std::wstring& input_text, 721 const string16& 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 == std::wstring::npos) { 738 if (input_position == string16::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(L"?"); 777 match.fill_into_edit.assign(ASCIIToUTF16("?"));
778 ++search_start; 778 ++search_start;
779 } 779 }
780 if (is_keyword) { 780 if (is_keyword) {
781 match.fill_into_edit.append(UTF16ToWideHack( 781 match.fill_into_edit.append(
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 WideToUTF16Hack(query_string), 796 query_string,
797 accepted_suggestion, 797 accepted_suggestion,
798 WideToUTF16Hack(input_text))); 798 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<std::wstring, AutocompleteMatch>( 808 std::pair<string16, AutocompleteMatch>(
809 UTF16ToWide(l10n_util::ToLower(WideToUTF16(query_string))), match)); 809 l10n_util::ToLower(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 std::wstring& input_text = 826 const string16& 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(L"?"); 846 match.fill_into_edit.assign(ASCIIToUTF16("?"));
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( 873 match.description.assign(l10n_util::GetStringFUTF16(
874 UTF16ToWideHack(l10n_util::GetStringFUTF16( 874 IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION,
875 IDS_AUTOCOMPLETE_SEARCH_DESCRIPTION, 875 providers_.default_provider().
876 providers_.default_provider(). 876 AdjustedShortNameForLocaleDirection()));
877 AdjustedShortNameForLocaleDirection())));
878 match.description_class.push_back( 877 match.description_class.push_back(
879 ACMatchClassification(0, ACMatchClassification::DIM)); 878 ACMatchClassification(0, ACMatchClassification::DIM));
880 // Only the first search match gets a description. 879 // Only the first search match gets a description.
881 return; 880 return;
882 881
883 default: 882 default:
884 break; 883 break;
885 } 884 }
886 } 885 }
887 } 886 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698