diff options
author | mrossetti@chromium.org <mrossetti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-12 17:31:23 +0000 |
---|---|---|
committer | mrossetti@chromium.org <mrossetti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-12 17:31:23 +0000 |
commit | 497606bc48a31173166147910fdd225533aeca60 (patch) | |
tree | 543f2a9c9a918f7330588c27afe8fec263706113 /chrome/browser/autocomplete/history_quick_provider.cc | |
parent | b6842d34c371f7ff7d8e6d033524903ea7f64dc8 (diff) | |
download | chromium_src-497606bc48a31173166147910fdd225533aeca60.zip chromium_src-497606bc48a31173166147910fdd225533aeca60.tar.gz chromium_src-497606bc48a31173166147910fdd225533aeca60.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.
Previous CL: http://codereview.chromium.org/3375002
BUG=23654,19736
TEST=Green bots. Start typing text which occurs in URLs which are in the history. Verify that those history items appear if they have been manually typed more than once or the have been visited more than three time or they have been visited within the last three days.
Review URL: http://codereview.chromium.org/3713003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62298 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); + } +} + |