history_quick_provider.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/autocomplete/history_quick_provider.h" 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/basictypes.h" 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/i18n/break_iterator.h" 9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/string_util.h" 10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/logging.h" 11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/utf_string_conversions.h" 12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h" 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/history/history.h" 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/prefs/pref_service.h" 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/history/in_memory_url_index.h" 17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/net/url_fixer_upper.h" 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/plugin_service.h" 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/notification_source.h" 20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/notification_type.h" 21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/pref_names.h" 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/url_constants.h" 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "googleurl/src/url_util.h" 24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/escape.h" 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/net_util.h" 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing history::InMemoryURLIndex; 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing history::ScoredHistoryMatch; 29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing history::ScoredHistoryMatches; 30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 31731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickHistoryQuickProvider::HistoryQuickProvider(ACProviderListener* listener, 32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Profile* profile) 33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : HistoryProvider(listener, profile, "HistoryQuickProvider"), 34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick trim_http_(false), 35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)) {} 36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 37731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickHistoryQuickProvider::~HistoryQuickProvider() {} 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid HistoryQuickProvider::Start(const AutocompleteInput& input, 40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool minimal_changes) { 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick matches_.clear(); 42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if ((input.type() == AutocompleteInput::INVALID) || 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (input.type() == AutocompleteInput::FORCED_QUERY)) 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick autocomplete_input_ = input; 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick trim_http_ = !HasHTTPScheme(input.text()); 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Do some fixup on the user input before matching against it, so we provide 51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // good results for local file paths, input with spaces, etc. 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // NOTE: This purposefully doesn't take input.desired_tld() into account; if 53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // it did, then holding "ctrl" would change all the results from the 54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // HistoryQuickProvider provider, not just the What You Typed Result. 55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::wstring fixed_text(FixupUserInput(input)); 56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (fixed_text.empty()) { 57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Conceivably fixup could result in an empty string (although I don't 58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // have cases where this happens offhand). We can't do anything with 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // empty input, so just bail; otherwise we'd crash later. 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick autocomplete_input_.set_text(fixed_text); 63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(pkasting): We should just block here until this loads. Any time 65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // someone unloads the history backend, we'll get inconsistent inline 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // autocomplete behavior here. 67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (GetIndex()) { 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DoAutocomplete(); 69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UpdateStarredStateOfMatches(); 70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// HistoryQuickProvider matches are currently not deletable. 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// TODO(mrossetti): Determine when a match should be deletable. 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid HistoryQuickProvider::DeleteMatch(const AutocompleteMatch& match) {} 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid HistoryQuickProvider::DoAutocomplete() { 78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Get the matching URLs from the DB. 79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick string16 term_string(WideToUTF16(autocomplete_input_.text())); 80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick term_string = UnescapeURLComponent(term_string, 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); 82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick history::InMemoryURLIndex::String16Vector terms( 83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HistoryQuickProvider::WordVectorFromString16(term_string)); 84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ScoredHistoryMatches matches = GetIndex()->HistoryItemsForTerms(terms); 85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t match_num = matches.size() - 1; 87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (ScoredHistoryMatches::const_iterator match_iter = matches.begin(); 88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match_iter != matches.end(); ++match_iter, --match_num) { 89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ScoredHistoryMatch& history_match(*match_iter); 90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteMatch ac_match = 91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick QuickMatchToACMatch(history_match, NORMAL, match_num); 92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick matches_.push_back(ac_match); 93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 96731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickAutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( 97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ScoredHistoryMatch& history_match, 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick MatchType match_type, 99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t match_number) { 100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const history::URLRow& info = history_match.url_info; 101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int score = CalculateRelevance(history_match.raw_score, 102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick autocomplete_input_.type(), 103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match_type, match_number); 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteMatch match(this, score, !!info.visit_count(), 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteMatch::HISTORY_URL); 106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.destination_url = info.url(); 107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(match.destination_url.is_valid()); 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t inline_autocomplete_offset = 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick history_match.input_location + autocomplete_input_.text().length(); 110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ~((trim_http_ && !history_match.match_in_scheme) ? 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 0 : net::kFormatUrlOmitHTTP); 113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string languages = 114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match_type == WHAT_YOU_TYPED ? std::string() : languages_; 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.fill_into_edit = 116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteInput::FormattedStringWithEquivalentMeaning(info.url(), 117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UTF16ToWide(net::FormatUrl(info.url(), languages, format_types, 118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UnescapeRule::SPACES, NULL, NULL, 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &inline_autocomplete_offset))); 120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!autocomplete_input_.prevent_inline_autocomplete()) 121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.inline_autocomplete_offset = inline_autocomplete_offset; 122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK((match.inline_autocomplete_offset == std::wstring::npos) || 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (match.inline_autocomplete_offset <= match.fill_into_edit.length())); 124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t match_start = history_match.input_location; 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.contents = 127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UTF16ToWide(net::FormatUrl(info.url(), languages, format_types, 128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UnescapeRule::SPACES, NULL, NULL, 129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &match_start)); 130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if ((match_start != std::wstring::npos) && 131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (inline_autocomplete_offset != std::wstring::npos) && 132731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (inline_autocomplete_offset != match_start)) { 133731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(inline_autocomplete_offset > match_start); 134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteMatch::ClassifyLocationInString(match_start, 135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick inline_autocomplete_offset - match_start, match.contents.length(), 136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ACMatchClassification::URL, &match.contents_class); 137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } else { 138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteMatch::ClassifyLocationInString(std::wstring::npos, 0, 139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.contents.length(), ACMatchClassification::URL, 140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &match.contents_class); 141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.description = UTF16ToWide(info.title()); 143731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteMatch::ClassifyMatchInString(autocomplete_input_.text(), 144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UTF16ToWide(info.title()), 145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ACMatchClassification::NONE, 146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &match.description_class); 147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return match; 149bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickhistory::InMemoryURLIndex* HistoryQuickProvider::GetIndex() { 152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (index_for_testing_.get()) 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return index_for_testing_.get(); 154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HistoryService* const history_service = 156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!history_service) 158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return NULL; 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return history_service->InMemoryIndex(); 161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid HistoryQuickProvider::SetIndexForTesting( 164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick history::InMemoryURLIndex* index) { 165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(index); 166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick index_for_testing_.reset(index); 167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Utility Functions 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickhistory::InMemoryURLIndex::String16Vector 172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HistoryQuickProvider::WordVectorFromString16(const string16& uni_string) { 173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick history::InMemoryURLIndex::String16Vector words; 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::BreakIterator iter(&uni_string, base::BreakIterator::BREAK_WORD); 175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (iter.Init()) { 176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick while (iter.Advance()) { 177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (iter.IsWord()) 17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen words.push_back(iter.GetString()); 179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return words; 182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint HistoryQuickProvider::CalculateRelevance(int raw_score, 186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteInput::Type input_type, 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick MatchType match_type, 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t match_number) { 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick switch (match_type) { 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case INLINE_AUTOCOMPLETE: 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return 1400; 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case WHAT_YOU_TYPED: 194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return 1200; 195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick default: 197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return 900 + static_cast<int>(match_number); 198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 200