1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/autocomplete/history_contents_provider.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_utils.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/query_parser.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/url_util.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks;
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Number of days to search for full text results. The longer this is, the more
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// time it will take.
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kDaysToSearch = 30;
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When processing the results from the history query, this structure points to
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a single result. It allows the results to be sorted and processed without
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// modifying the larger and slower results structure.
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct MatchReference {
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MatchReference(const history::URLResult* result, int relevance)
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : result(result),
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        relevance(relevance) {
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const history::URLResult* result;
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int relevance;  // Score of relevance computed by CalculateRelevance.
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is a > operator for MatchReference.
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CompareMatchRelevance(const MatchReference& a, const MatchReference& b) {
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (a.relevance != b.relevance)
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return a.relevance > b.relevance;
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Want results in reverse-chronological order all else being equal.
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return a.result->last_visit() > b.result->last_visit();
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing history::HistoryDatabase;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHistoryContentsProvider::HistoryContentsProvider(ACProviderListener* listener,
553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 Profile* profile)
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : HistoryProvider(listener, profile, "HistoryContents"),
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      star_title_count_(0),
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      star_contents_count_(0),
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      title_count_(0),
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      contents_count_(0),
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      input_type_(AutocompleteInput::INVALID),
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      trim_http_(false),
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      have_results_(false) {
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryContentsProvider::Start(const AutocompleteInput& input,
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    bool minimal_changes) {
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  matches_.clear();
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (input.text().empty() || (input.type() == AutocompleteInput::INVALID) ||
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !profile_ ||
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The history service or bookmark bar model must exist.
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !(profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) ||
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        profile_->GetBookmarkModel())) {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Stop();
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(pkasting): http://b/888148 We disallow URL input and "URL-like" input
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (REQUESTED_URL or UNKNOWN with dots) because we get poor results for it,
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // but we could get better results if we did better tokenizing instead.
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if ((input.type() == AutocompleteInput::URL) ||
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (((input.type() == AutocompleteInput::REQUESTED_URL) ||
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (input.type() == AutocompleteInput::UNKNOWN)) &&
8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen       (input.text().find('.') != string16::npos))) {
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Stop();
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (input.matches_requested() == AutocompleteInput::BEST_MATCH) {
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // None of our results are applicable for best match.
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Stop();
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Change input type so matches will be marked up properly.
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  input_type_ = input.type();
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  trim_http_ = !HasHTTPScheme(input.text());
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Decide what to do about any previous query/results.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!minimal_changes) {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Any in-progress request is irrelevant, cancel it.
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Stop();
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (have_results_) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We finished the previous query and still have its results.  Mark them up
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // again for the new input.
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConvertResults();
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (!done_) {
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We're still running the previous query on the HistoryService.  If we're
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // allowed to keep running it, do so, and when it finishes, its results will
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // get marked up for this new input.  In synchronous_only mode, cancel the
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // history query.
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (input.matches_requested() != AutocompleteInput::ALL_MATCHES) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      done_ = true;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      request_consumer_.CancelAllRequests();
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConvertResults();
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!results_.empty()) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Clear the results. We swap in an empty one as the easy way to clear it.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    history::QueryResults empty_results;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    results_.Swap(&empty_results);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Querying bookmarks is synchronous, so we always do it.
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  QueryBookmarks(input);
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Convert the bookmark results.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ConvertResults();
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (input.matches_requested() == AutocompleteInput::ALL_MATCHES) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HistoryService* history =
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (history) {
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      done_ = false;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      history::QueryOptions options;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      options.SetRecentDayRange(kDaysToSearch);
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      options.max_count = kMaxMatches;
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      history->QueryHistory(input.text(), options,
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &request_consumer_,
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NewCallback(this, &HistoryContentsProvider::QueryComplete));
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryContentsProvider::Stop() {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  done_ = true;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_consumer_.CancelAllRequests();
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Clear the results. We swap in an empty one as the easy way to clear it.
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history::QueryResults empty_results;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  results_.Swap(&empty_results);
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  have_results_ = false;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHistoryContentsProvider::~HistoryContentsProvider() {
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryContentsProvider::QueryComplete(HistoryService::Handle handle,
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            history::QueryResults* results) {
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  results_.AppendResultsBySwapping(results, true);
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  have_results_ = true;
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ConvertResults();
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  done_ = true;
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (listener_)
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    listener_->OnProviderUpdate(!matches_.empty());
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryContentsProvider::ConvertResults() {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reset the relevance counters so that result relevance won't vary on
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // subsequent passes of ConvertResults.
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  star_title_count_ = star_contents_count_ = title_count_ = contents_count_ = 0;
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make the result references and score the results.
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<MatchReference> result_refs;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  result_refs.reserve(results_.size());
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Results are sorted in decreasing order so we run the loop backwards so that
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the relevance increment favors the higher ranked results.
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::vector<history::URLResult*>::const_reverse_iterator i =
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       results_.rbegin(); i != results_.rend(); ++i) {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    history::URLResult* result = *i;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MatchReference ref(result, CalculateRelevance(*result));
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result_refs.push_back(ref);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Get the top matches and add them.
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t max_for_provider = std::min(kMaxMatches, result_refs.size());
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::partial_sort(result_refs.begin(), result_refs.begin() + max_for_provider,
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    result_refs.end(), &CompareMatchRelevance);
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  matches_.clear();
19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < max_for_provider; i++) {
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    matches_.push_back(ResultToMatch(*result_refs[i].result,
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     result_refs[i].relevance));
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool MatchInTitle(const history::URLResult& result) {
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return !result.title_match_positions().empty();
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAutocompleteMatch HistoryContentsProvider::ResultToMatch(
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const history::URLResult& result,
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int score) {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(sky): if matched title highlight matching words in title.
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Also show star in popup.
21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  AutocompleteMatch match(this, score, true, MatchInTitle(result) ?
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AutocompleteMatch::HISTORY_TITLE : AutocompleteMatch::HISTORY_BODY);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match.contents = StringForURLDisplay(result.url(), true, trim_http_);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match.fill_into_edit =
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AutocompleteInput::FormattedStringWithEquivalentMeaning(result.url(),
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                              match.contents);
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match.destination_url = result.url();
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match.contents_class.push_back(
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ACMatchClassification(0, ACMatchClassification::URL));
22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  match.description = result.title();
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  match.starred =
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (profile_->GetBookmarkModel() &&
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       profile_->GetBookmarkModel()->IsBookmarked(result.url()));
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ClassifyDescription(result, &match);
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return match;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryContentsProvider::ClassifyDescription(
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const history::URLResult& result,
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AutocompleteMatch* match) const {
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const Snippet::MatchPositions& title_matches = result.title_match_positions();
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t offset = 0;
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!title_matches.empty()) {
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Classify matches in the title.
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (Snippet::MatchPositions::const_iterator i = title_matches.begin();
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         i != title_matches.end(); ++i) {
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (i->first != offset) {
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        match->description_class.push_back(
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            ACMatchClassification(offset, ACMatchClassification::NONE));
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      match->description_class.push_back(
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            ACMatchClassification(i->first, ACMatchClassification::MATCH));
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      offset = i->second;
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (offset != result.title().size()) {
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    match->description_class.push_back(
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ACMatchClassification(offset, ACMatchClassification::NONE));
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HistoryContentsProvider::CalculateRelevance(
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const history::URLResult& result) {
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const bool in_title = MatchInTitle(result);
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!profile_->GetBookmarkModel() ||
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !profile_->GetBookmarkModel()->IsBookmarked(result.url()))
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return in_title ? (700 + title_count_++) : (500 + contents_count_++);
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return in_title ?
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (1000 + star_title_count_++) : (550 + star_contents_count_++);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryContentsProvider::QueryBookmarks(const AutocompleteInput& input) {
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BookmarkModel* bookmark_model = profile_->GetBookmarkModel();
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bookmark_model)
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(results_.empty());
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start_time = TimeTicks::Now();
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<bookmark_utils::TitleMatch> matches;
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bookmark_model->GetBookmarksWithTitlesMatching(input.text(),
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 kMaxMatches, &matches);
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < matches.size(); ++i)
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AddBookmarkTitleMatchToResults(matches[i]);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UMA_HISTOGRAM_TIMES("Omnibox.QueryBookmarksTime",
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      TimeTicks::Now() - start_time);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryContentsProvider::AddBookmarkTitleMatchToResults(
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const bookmark_utils::TitleMatch& match) {
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history::URLResult url_result(match.node->GetURL(), match.match_positions);
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  url_result.set_title(match.node->GetTitle());
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  results_.AppendURLBySwapping(&url_result);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
288