diff options
author | mrossetti@chromium.org <mrossetti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-11 22:06:00 +0000 |
---|---|---|
committer | mrossetti@chromium.org <mrossetti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-11 22:06:00 +0000 |
commit | f2bfc1ce3ff150af8e375151a106f8cfc5b6fb08 (patch) | |
tree | 7f941e8fa002ce991963663e5a874fc479257d93 /chrome/browser/autocomplete/history_quick_provider.cc | |
parent | cc378a1cc341ecfb60aeaba995ea0b442c9bc83e (diff) | |
download | chromium_src-f2bfc1ce3ff150af8e375151a106f8cfc5b6fb08.zip chromium_src-f2bfc1ce3ff150af8e375151a106f8cfc5b6fb08.tar.gz chromium_src-f2bfc1ce3ff150af8e375151a106f8cfc5b6fb08.tar.bz2 |
Final phase of the URL History Quick autocomplete provider integration. This phase hooks up the InMemoryURLIndex to the HistoryQuickProvider which is itself made active during the autocomplete process. A small amount of refactoring was done to liberate some common functionality from the history_url_provider.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/3375002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62193 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete/history_quick_provider.cc')
-rw-r--r-- | chrome/browser/autocomplete/history_quick_provider.cc | 188 |
1 files changed, 187 insertions, 1 deletions
diff --git a/chrome/browser/autocomplete/history_quick_provider.cc b/chrome/browser/autocomplete/history_quick_provider.cc index 0d4fdda..776c343 100644 --- a/chrome/browser/autocomplete/history_quick_provider.cc +++ b/chrome/browser/autocomplete/history_quick_provider.cc @@ -4,7 +4,193 @@ #include "chrome/browser/autocomplete/history_quick_provider.h" +#include "base/basictypes.h" +#include "base/histogram.h" +#include "base/i18n/word_iterator.h" +#include "base/string_util.h" +#include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/history/history.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/history/in_memory_url_index.h" +#include "chrome/browser/net/url_fixer_upper.h" +#include "chrome/browser/plugin_service.h" +#include "chrome/common/notification_source.h" +#include "chrome/common/notification_type.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "googleurl/src/url_util.h" +#include "net/base/escape.h" +#include "net/base/net_util.h" + +using history::InMemoryURLIndex; +using history::ScoredHistoryMatch; +using history::ScoredHistoryMatches; + +HistoryQuickProvider::HistoryQuickProvider(ACProviderListener* listener, + Profile* profile) + : HistoryProvider(listener, profile, "HistoryQuickProvider"), + trim_http_(false), + languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)) {} + +HistoryQuickProvider::~HistoryQuickProvider() {} + void HistoryQuickProvider::Start(const AutocompleteInput& input, bool minimal_changes) { - // TODO(mrossetti): Implement. + matches_.clear(); + + if ((input.type() == AutocompleteInput::INVALID) || + (input.type() == AutocompleteInput::FORCED_QUERY)) + return; + + autocomplete_input_ = input; + trim_http_ = !HasHTTPScheme(input.text()); + + // Do some fixup on the user input before matching against it, so we provide + // good results for local file paths, input with spaces, etc. + // NOTE: This purposefully doesn't take input.desired_tld() into account; if + // it did, then holding "ctrl" would change all the results from the + // HistoryQuickProvider provider, not just the What You Typed Result. + const std::wstring fixed_text(FixupUserInput(input)); + if (fixed_text.empty()) { + // Conceivably fixup could result in an empty string (although I don't + // have cases where this happens offhand). We can't do anything with + // empty input, so just bail; otherwise we'd crash later. + return; + } + autocomplete_input_.set_text(fixed_text); + + // TODO(pkasting): We should just block here until this loads. Any time + // someone unloads the history backend, we'll get inconsistent inline + // autocomplete behavior here. + if (GetIndex()) { + DoAutocomplete(); + UpdateStarredStateOfMatches(); + } +} + +void HistoryQuickProvider::DoAutocomplete() { + // Get the matching URLs from the DB. + string16 term_string(WideToUTF16(autocomplete_input_.text())); + term_string = UnescapeURLComponent(term_string, + UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); + history::InMemoryURLIndex::String16Vector terms( + HistoryQuickProvider::WordVectorFromString16(term_string)); + ScoredHistoryMatches matches = GetIndex()->HistoryItemsForTerms(terms); + + size_t match_num = matches.size() - 1; + for (ScoredHistoryMatches::const_iterator match_iter = matches.begin(); + match_iter != matches.end(); ++match_iter, --match_num) { + const ScoredHistoryMatch& history_match(*match_iter); + AutocompleteMatch ac_match = + QuickMatchToACMatch(history_match, NORMAL, match_num); + matches_.push_back(ac_match); + } +} + +AutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( + const ScoredHistoryMatch& history_match, + MatchType match_type, + size_t match_number) { + const history::URLRow& info = history_match.url_info; + int score = CalculateRelevance(history_match.raw_score, + autocomplete_input_.type(), + match_type, match_number); + AutocompleteMatch match(this, score, !!info.visit_count(), + AutocompleteMatch::HISTORY_URL); + match.destination_url = info.url(); + DCHECK(match.destination_url.is_valid()); + size_t inline_autocomplete_offset = + history_match.input_location + autocomplete_input_.text().length(); + const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & + ~((trim_http_ && !history_match.match_in_scheme) ? + 0 : net::kFormatUrlOmitHTTP); + std::string languages = + match_type == WHAT_YOU_TYPED ? std::string() : languages_; + match.fill_into_edit = + AutocompleteInput::FormattedStringWithEquivalentMeaning(info.url(), + UTF16ToWide(net::FormatUrl(info.url(), languages, format_types, + UnescapeRule::SPACES, NULL, NULL, + &inline_autocomplete_offset))); + if (!autocomplete_input_.prevent_inline_autocomplete()) + match.inline_autocomplete_offset = inline_autocomplete_offset; + DCHECK((match.inline_autocomplete_offset == std::wstring::npos) || + (match.inline_autocomplete_offset <= match.fill_into_edit.length())); + + size_t match_start = history_match.input_location; + match.contents = + UTF16ToWide(net::FormatUrl(info.url(), languages, format_types, + UnescapeRule::SPACES, NULL, NULL, + &match_start)); + if ((match_start != std::wstring::npos) && + (inline_autocomplete_offset != std::wstring::npos) && + (inline_autocomplete_offset != match_start)) { + DCHECK(inline_autocomplete_offset > match_start); + AutocompleteMatch::ClassifyLocationInString(match_start, + inline_autocomplete_offset - match_start, match.contents.length(), + ACMatchClassification::URL, &match.contents_class); + } else { + AutocompleteMatch::ClassifyLocationInString(std::wstring::npos, 0, + match.contents.length(), ACMatchClassification::URL, + &match.contents_class); + } + match.description = UTF16ToWide(info.title()); + AutocompleteMatch::ClassifyMatchInString(autocomplete_input_.text(), + UTF16ToWide(info.title()), + ACMatchClassification::NONE, + &match.description_class); + + return match; } + +history::InMemoryURLIndex* HistoryQuickProvider::GetIndex() { + if (index_for_testing_.get()) + return index_for_testing_.get(); + + HistoryService* const history_service = + profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (!history_service) + return NULL; + + return history_service->InMemoryIndex(); +} + +void HistoryQuickProvider::SetIndexForTesting( + history::InMemoryURLIndex* index) { + DCHECK(index); + index_for_testing_.reset(index); +} + +// Utility Functions + +history::InMemoryURLIndex::String16Vector + HistoryQuickProvider::WordVectorFromString16(const string16& uni_string) { + history::InMemoryURLIndex::String16Vector words; + WordIterator iter(&uni_string, WordIterator::BREAK_WORD); + if (iter.Init()) { + while (iter.Advance()) { + if (iter.IsWord()) + words.push_back(iter.GetWord()); + } + } + return words; +} + +// static +int HistoryQuickProvider::CalculateRelevance(int raw_score, + AutocompleteInput::Type input_type, + MatchType match_type, + size_t match_number) { + switch (match_type) { + case INLINE_AUTOCOMPLETE: + return 1400; + + case WHAT_YOU_TYPED: + return 1200; + + default: + return 900 + static_cast<int>(match_number); + } +} + |