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