| 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 |