OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autocomplete/history_url_provider.h" | 5 #include "chrome/browser/autocomplete/history_url_provider.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 cull_redirects_( | 365 cull_redirects_( |
366 !OmniboxFieldTrial::InHUPCullRedirectsFieldTrial() || | 366 !OmniboxFieldTrial::InHUPCullRedirectsFieldTrial() || |
367 !OmniboxFieldTrial::InHUPCullRedirectsFieldTrialExperimentGroup()), | 367 !OmniboxFieldTrial::InHUPCullRedirectsFieldTrialExperimentGroup()), |
368 create_shorter_match_( | 368 create_shorter_match_( |
369 !OmniboxFieldTrial::InHUPCreateShorterMatchFieldTrial() || | 369 !OmniboxFieldTrial::InHUPCreateShorterMatchFieldTrial() || |
370 !OmniboxFieldTrial:: | 370 !OmniboxFieldTrial:: |
371 InHUPCreateShorterMatchFieldTrialExperimentGroup()), | 371 InHUPCreateShorterMatchFieldTrialExperimentGroup()), |
372 search_url_database_(true) { | 372 search_url_database_(true) { |
373 } | 373 } |
374 | 374 |
375 // static | 375 void HistoryURLProvider::Start(const AutocompleteInput& input, |
| 376 bool minimal_changes) { |
| 377 // NOTE: We could try hard to do less work in the |minimal_changes| case |
| 378 // here; some clever caching would let us reuse the raw matches from the |
| 379 // history DB without re-querying. However, we'd still have to go back to |
| 380 // the history thread to mark these up properly, and if pass 2 is currently |
| 381 // running, we'd need to wait for it to return to the main thread before |
| 382 // doing this (we can't just write new data for it to read due to thread |
| 383 // safety issues). At that point it's just as fast, and easier, to simply |
| 384 // re-run the query from scratch and ignore |minimal_changes|. |
| 385 |
| 386 // Cancel any in-progress query. |
| 387 Stop(false); |
| 388 |
| 389 RunAutocompletePasses(input, true); |
| 390 } |
| 391 |
| 392 void HistoryURLProvider::Stop(bool clear_cached_results) { |
| 393 done_ = true; |
| 394 |
| 395 if (params_) |
| 396 params_->cancel_flag.Set(); |
| 397 } |
| 398 |
376 AutocompleteMatch HistoryURLProvider::SuggestExactInput( | 399 AutocompleteMatch HistoryURLProvider::SuggestExactInput( |
377 AutocompleteProvider* provider, | 400 const string16& text, |
378 const AutocompleteInput& input, | 401 const GURL& destination_url, |
379 bool trim_http) { | 402 bool trim_http) { |
380 AutocompleteMatch match(provider, 0, false, | 403 AutocompleteMatch match(this, 0, false, |
381 AutocompleteMatchType::URL_WHAT_YOU_TYPED); | 404 AutocompleteMatchType::URL_WHAT_YOU_TYPED); |
382 | 405 |
383 const GURL& url = input.canonicalized_url(); | 406 if (destination_url.is_valid()) { |
384 if (url.is_valid()) { | 407 match.destination_url = destination_url; |
385 match.destination_url = url; | |
386 | 408 |
387 // Trim off "http://" if the user didn't type it. | 409 // Trim off "http://" if the user didn't type it. |
388 // NOTE: We use TrimHttpPrefix() here rather than StringForURLDisplay() to | 410 // NOTE: We use TrimHttpPrefix() here rather than StringForURLDisplay() to |
389 // strip the scheme as we need to know the offset so we can adjust the | 411 // strip the scheme as we need to know the offset so we can adjust the |
390 // |match_location| below. StringForURLDisplay() and TrimHttpPrefix() have | 412 // |match_location| below. StringForURLDisplay() and TrimHttpPrefix() have |
391 // slightly different behavior as well (the latter will strip even without | 413 // slightly different behavior as well (the latter will strip even without |
392 // two slashes after the scheme). | 414 // two slashes after the scheme). |
393 DCHECK(!trim_http || !HasHTTPScheme(input.text())); | 415 DCHECK(!trim_http || !HasHTTPScheme(text)); |
394 string16 display_string(provider->StringForURLDisplay(url, false, false)); | 416 string16 display_string(StringForURLDisplay(destination_url, false, false)); |
395 const size_t offset = trim_http ? TrimHttpPrefix(&display_string) : 0; | 417 const size_t offset = trim_http ? TrimHttpPrefix(&display_string) : 0; |
396 match.fill_into_edit = | 418 match.fill_into_edit = |
397 AutocompleteInput::FormattedStringWithEquivalentMeaning(url, | 419 AutocompleteInput::FormattedStringWithEquivalentMeaning(destination_url, |
398 display_string); | 420 display_string); |
399 match.allowed_to_be_default_match = true; | 421 match.allowed_to_be_default_match = true; |
400 // NOTE: Don't set match.inline_autocompletion to something non-empty here; | 422 // NOTE: Don't set match.inline_autocompletion to something non-empty here; |
401 // it's surprising and annoying. | 423 // it's surprising and annoying. |
402 | 424 |
403 // Try to highlight "innermost" match location. If we fix up "w" into | 425 // Try to highlight "innermost" match location. If we fix up "w" into |
404 // "www.w.com", we want to highlight the fifth character, not the first. | 426 // "www.w.com", we want to highlight the fifth character, not the first. |
405 // This relies on match.destination_url being the non-prefix-trimmed version | 427 // This relies on match.destination_url being the non-prefix-trimmed version |
406 // of match.contents. | 428 // of match.contents. |
407 match.contents = display_string; | 429 match.contents = display_string; |
408 const URLPrefix* best_prefix = URLPrefix::BestURLPrefix( | 430 const URLPrefix* best_prefix = |
409 UTF8ToUTF16(match.destination_url.spec()), input.text()); | 431 URLPrefix::BestURLPrefix(UTF8ToUTF16(destination_url.spec()), text); |
410 // It's possible for match.destination_url to not contain the user's input | 432 // It's possible for match.destination_url to not contain the user's input |
411 // at all (so |best_prefix| is NULL), for example if the input is | 433 // at all (so |best_prefix| is NULL), for example if the input is |
412 // "view-source:x" and |destination_url| has an inserted "http://" in the | 434 // "view-source:x" and |destination_url| has an inserted "http://" in the |
413 // middle. | 435 // middle. |
414 if (best_prefix == NULL) { | 436 if (best_prefix == NULL) { |
415 AutocompleteMatch::ClassifyMatchInString(input.text(), match.contents, | 437 AutocompleteMatch::ClassifyMatchInString(text, match.contents, |
416 ACMatchClassification::URL, | 438 ACMatchClassification::URL, |
417 &match.contents_class); | 439 &match.contents_class); |
418 } else { | 440 } else { |
419 AutocompleteMatch::ClassifyLocationInString( | 441 AutocompleteMatch::ClassifyLocationInString( |
420 best_prefix->prefix.length() - offset, input.text().length(), | 442 best_prefix->prefix.length() - offset, text.length(), |
421 match.contents.length(), ACMatchClassification::URL, | 443 match.contents.length(), ACMatchClassification::URL, |
422 &match.contents_class); | 444 &match.contents_class); |
423 } | 445 } |
424 | 446 |
425 match.is_history_what_you_typed_match = true; | 447 match.is_history_what_you_typed_match = true; |
426 } | 448 } |
427 | 449 |
428 return match; | 450 return match; |
429 } | 451 } |
430 | 452 |
431 void HistoryURLProvider::Start(const AutocompleteInput& input, | |
432 bool minimal_changes) { | |
433 // NOTE: We could try hard to do less work in the |minimal_changes| case | |
434 // here; some clever caching would let us reuse the raw matches from the | |
435 // history DB without re-querying. However, we'd still have to go back to | |
436 // the history thread to mark these up properly, and if pass 2 is currently | |
437 // running, we'd need to wait for it to return to the main thread before | |
438 // doing this (we can't just write new data for it to read due to thread | |
439 // safety issues). At that point it's just as fast, and easier, to simply | |
440 // re-run the query from scratch and ignore |minimal_changes|. | |
441 | |
442 // Cancel any in-progress query. | |
443 Stop(false); | |
444 | |
445 RunAutocompletePasses(input, true); | |
446 } | |
447 | |
448 void HistoryURLProvider::Stop(bool clear_cached_results) { | |
449 done_ = true; | |
450 | |
451 if (params_) | |
452 params_->cancel_flag.Set(); | |
453 } | |
454 | |
455 // Called on the history thread. | 453 // Called on the history thread. |
456 void HistoryURLProvider::ExecuteWithDB(history::HistoryBackend* backend, | 454 void HistoryURLProvider::ExecuteWithDB(history::HistoryBackend* backend, |
457 history::URLDatabase* db, | 455 history::URLDatabase* db, |
458 HistoryURLProviderParams* params) { | 456 HistoryURLProviderParams* params) { |
459 // We may get called with a NULL database if it couldn't be properly | 457 // We may get called with a NULL database if it couldn't be properly |
460 // initialized. | 458 // initialized. |
461 if (!db) { | 459 if (!db) { |
462 params->failed = true; | 460 params->failed = true; |
463 } else if (!params->cancel_flag.IsSet()) { | 461 } else if (!params->cancel_flag.IsSet()) { |
464 base::TimeTicks beginning_time = base::TimeTicks::Now(); | 462 base::TimeTicks beginning_time = base::TimeTicks::Now(); |
(...skipping 25 matching lines...) Expand all Loading... |
490 // that is when their input can be opened as a URL. | 488 // that is when their input can be opened as a URL. |
491 // Otherwise, this is just low-quality noise. In the cases where we've parsed | 489 // Otherwise, this is just low-quality noise. In the cases where we've parsed |
492 // as UNKNOWN, we'll still show an accidental search infobar if need be. | 490 // as UNKNOWN, we'll still show an accidental search infobar if need be. |
493 bool have_what_you_typed_match = | 491 bool have_what_you_typed_match = |
494 params->input.canonicalized_url().is_valid() && | 492 params->input.canonicalized_url().is_valid() && |
495 (params->input.type() != AutocompleteInput::QUERY) && | 493 (params->input.type() != AutocompleteInput::QUERY) && |
496 ((params->input.type() != AutocompleteInput::UNKNOWN) || | 494 ((params->input.type() != AutocompleteInput::UNKNOWN) || |
497 (classifier.type() == VisitClassifier::UNVISITED_INTRANET) || | 495 (classifier.type() == VisitClassifier::UNVISITED_INTRANET) || |
498 !params->trim_http || | 496 !params->trim_http || |
499 (AutocompleteInput::NumNonHostComponents(params->input.parts()) > 0)); | 497 (AutocompleteInput::NumNonHostComponents(params->input.parts()) > 0)); |
500 AutocompleteMatch what_you_typed_match( | 498 AutocompleteMatch what_you_typed_match(SuggestExactInput( |
501 SuggestExactInput(this, params->input, params->trim_http)); | 499 params->input.text(), params->input.canonicalized_url(), |
| 500 params->trim_http)); |
502 what_you_typed_match.relevance = CalculateRelevance(WHAT_YOU_TYPED, 0); | 501 what_you_typed_match.relevance = CalculateRelevance(WHAT_YOU_TYPED, 0); |
503 | 502 |
504 // Get the matching URLs from the DB | 503 // Get the matching URLs from the DB |
505 history::URLRows url_matches; | 504 history::URLRows url_matches; |
506 history::HistoryMatches history_matches; | 505 history::HistoryMatches history_matches; |
507 | 506 |
508 if (search_url_database_) { | 507 if (search_url_database_) { |
509 const URLPrefixes& prefixes = URLPrefix::GetURLPrefixes(); | 508 const URLPrefixes& prefixes = URLPrefix::GetURLPrefixes(); |
510 for (URLPrefixes::const_iterator i(prefixes.begin()); i != prefixes.end(); | 509 for (URLPrefixes::const_iterator i(prefixes.begin()); i != prefixes.end(); |
511 ++i) { | 510 ++i) { |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 return; | 670 return; |
672 | 671 |
673 // Create a match for exactly what the user typed. This will only be used as | 672 // Create a match for exactly what the user typed. This will only be used as |
674 // a fallback in case we can't get the history service or URL DB; otherwise, | 673 // a fallback in case we can't get the history service or URL DB; otherwise, |
675 // we'll run this again in DoAutocomplete() and use that result instead. | 674 // we'll run this again in DoAutocomplete() and use that result instead. |
676 const bool trim_http = !HasHTTPScheme(input.text()); | 675 const bool trim_http = !HasHTTPScheme(input.text()); |
677 // Don't do this for queries -- while we can sometimes mark up a match for | 676 // Don't do this for queries -- while we can sometimes mark up a match for |
678 // this, it's not what the user wants, and just adds noise. | 677 // this, it's not what the user wants, and just adds noise. |
679 if ((input.type() != AutocompleteInput::QUERY) && | 678 if ((input.type() != AutocompleteInput::QUERY) && |
680 input.canonicalized_url().is_valid()) { | 679 input.canonicalized_url().is_valid()) { |
681 AutocompleteMatch what_you_typed(SuggestExactInput(this, input, trim_http)); | 680 AutocompleteMatch what_you_typed(SuggestExactInput( |
| 681 input.text(), input.canonicalized_url(), trim_http)); |
682 what_you_typed.relevance = CalculateRelevance(WHAT_YOU_TYPED, 0); | 682 what_you_typed.relevance = CalculateRelevance(WHAT_YOU_TYPED, 0); |
683 matches_.push_back(what_you_typed); | 683 matches_.push_back(what_you_typed); |
684 } | 684 } |
685 | 685 |
686 // We'll need the history service to run both passes, so try to obtain it. | 686 // We'll need the history service to run both passes, so try to obtain it. |
687 if (!profile_) | 687 if (!profile_) |
688 return; | 688 return; |
689 HistoryService* const history_service = | 689 HistoryService* const history_service = |
690 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); | 690 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
691 if (!history_service) | 691 if (!history_service) |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 &match.contents_class); | 1087 &match.contents_class); |
1088 } | 1088 } |
1089 match.description = info.title(); | 1089 match.description = info.title(); |
1090 AutocompleteMatch::ClassifyMatchInString(params.input.text(), | 1090 AutocompleteMatch::ClassifyMatchInString(params.input.text(), |
1091 info.title(), | 1091 info.title(), |
1092 ACMatchClassification::NONE, | 1092 ACMatchClassification::NONE, |
1093 &match.description_class); | 1093 &match.description_class); |
1094 RecordAdditionalInfoFromUrlRow(info, &match); | 1094 RecordAdditionalInfoFromUrlRow(info, &match); |
1095 return match; | 1095 return match; |
1096 } | 1096 } |
OLD | NEW |