1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <vector> 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/basictypes.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/i18n/break_iterator.h" 11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/logging.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/metrics/histogram.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_number_conversions.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/time.h" 16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/utf_string_conversions.h" 17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/history/history.h" 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/history/in_memory_url_index.h" 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/net/url_fixer_upper.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/pref_service.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h" 22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/pref_names.h" 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/common/url_constants.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "googleurl/src/url_parse.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h" 27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "googleurl/src/url_util.h" 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/escape.h" 29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/base/net_util.h" 30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 31731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing history::InMemoryURLIndex; 32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing history::ScoredHistoryMatch; 33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing history::ScoredHistoryMatches; 34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 35731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickHistoryQuickProvider::HistoryQuickProvider(ACProviderListener* listener, 36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick Profile* profile) 37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : HistoryProvider(listener, profile, "HistoryQuickProvider"), 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)) {} 39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 40731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickHistoryQuickProvider::~HistoryQuickProvider() {} 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid HistoryQuickProvider::Start(const AutocompleteInput& input, 43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool minimal_changes) { 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick matches_.clear(); 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if ((input.type() == AutocompleteInput::INVALID) || 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (input.type() == AutocompleteInput::FORCED_QUERY)) 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick autocomplete_input_ = input; 51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Do some fixup on the user input before matching against it, so we provide 53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // good results for local file paths, input with spaces, etc. 54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // NOTE: This purposefully doesn't take input.desired_tld() into account; if 55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // it did, then holding "ctrl" would change all the results from the 56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // HistoryQuickProvider provider, not just the What You Typed Result. 5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16 fixed_text(FixupUserInput(input)); 58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (fixed_text.empty()) { 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Conceivably fixup could result in an empty string (although I don't 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // have cases where this happens offhand). We can't do anything with 61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // empty input, so just bail; otherwise we'd crash later. 62731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick autocomplete_input_.set_text(fixed_text); 65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(pkasting): We should just block here until this loads. Any time 67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // someone unloads the history backend, we'll get inconsistent inline 68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // autocomplete behavior here. 69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (GetIndex()) { 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeTicks start_time = base::TimeTicks::Now(); 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DoAutocomplete(); 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (input.text().size() < 6) { 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeTicks end_time = base::TimeTicks::Now(); 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string name = "HistoryQuickProvider.QueryIndexTime." + 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::IntToString(input.text().size()); 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Histogram* counter = base::Histogram::FactoryGet( 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag); 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen counter->Add(static_cast<int>((end_time - start_time).InMilliseconds())); 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UpdateStarredStateOfMatches(); 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// HistoryQuickProvider matches are currently not deletable. 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// TODO(mrossetti): Determine when a match should be deletable. 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid HistoryQuickProvider::DeleteMatch(const AutocompleteMatch& match) {} 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid HistoryQuickProvider::DoAutocomplete() { 89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Get the matching URLs from the DB. 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen string16 term_string = autocomplete_input_.text(); 91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick term_string = UnescapeURLComponent(term_string, 92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); 93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick history::InMemoryURLIndex::String16Vector terms( 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen InMemoryURLIndex::WordVectorFromString16(term_string, false)); 95731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ScoredHistoryMatches matches = GetIndex()->HistoryItemsForTerms(terms); 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (matches.empty()) 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Artificially reduce the score of high-scoring results which should not be 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // inline autocompletd. Each such result gets the next available 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // |next_dont_inline_score|. Upon use of next_dont_inline_score it is 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // decremented. 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int next_dont_inline_score = 1199; 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t match_num = matches.size() - 1; 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (ScoredHistoryMatches::const_iterator match_iter = matches.begin(); 106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match_iter != matches.end(); ++match_iter, --match_num) { 107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ScoredHistoryMatch& history_match(*match_iter); 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (history_match.raw_score > 0) { 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AutocompleteMatch ac_match = 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen QuickMatchToACMatch(history_match, match_num, 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen autocomplete_input_.prevent_inline_autocomplete(), 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &next_dont_inline_score); 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen matches_.push_back(ac_match); 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 118731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickAutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const ScoredHistoryMatch& history_match, 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t match_number, 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool prevent_inline_autocomplete, 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int* next_dont_inline_score) { 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(next_dont_inline_score); 124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const history::URLRow& info = history_match.url_info; 125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int score = CalculateRelevance(history_match.raw_score, 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick autocomplete_input_.type(), 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NORMAL, match_number); 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Discount a very high score when a) a match doesn't start at the beginning 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // of the URL, or b) there are more than one substring matches in the URL, or 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // c) the type of request does not allow inline autocompletion. This prevents 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the URL from being offered as an inline completion. 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const int kMaxDontInlineScore = 1199; 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (score > kMaxDontInlineScore && 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (prevent_inline_autocomplete || history_match.url_matches.size() > 1 || 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history_match.url_matches[0].offset > 0)) { 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen score = std::min(*next_dont_inline_score, score); 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen --*next_dont_inline_score; 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteMatch match(this, score, !!info.visit_count(), 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history_match.url_matches.empty() ? 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AutocompleteMatch::HISTORY_URL : 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AutocompleteMatch::HISTORY_TITLE); 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.destination_url = info.url(); 147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(match.destination_url.is_valid()); 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Format the fill_into_edit and determine its offset. 150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t inline_autocomplete_offset = 151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick history_match.input_location + autocomplete_input_.text().length(); 152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.fill_into_edit = 153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteInput::FormattedStringWithEquivalentMeaning(info.url(), 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::FormatUrl(info.url(), languages_, net::kFormatUrlOmitAll, 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnescapeRule::SPACES, NULL, NULL, &inline_autocomplete_offset)); 156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!autocomplete_input_.prevent_inline_autocomplete()) 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick match.inline_autocomplete_offset = inline_autocomplete_offset; 15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK((match.inline_autocomplete_offset == string16::npos) || 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (match.inline_autocomplete_offset <= match.fill_into_edit.length())); 160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Format the URL autocomplete presentation. 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<size_t> offsets = 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen InMemoryURLIndex::OffsetsFromTermMatches(history_match.url_matches); 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen match.contents = 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::FormatUrlWithOffsets(info.url(), languages_, net::kFormatUrlOmitAll, 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UnescapeRule::SPACES, NULL, NULL, &offsets); 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history::TermMatches new_matches = 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen InMemoryURLIndex::ReplaceOffsetsInTermMatches(history_match.url_matches, 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen offsets); 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen match.contents_class = SpansFromTermMatch(new_matches, match.contents.size()); 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Format the description autocomplete presentation. 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen match.description = info.title(); 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen match.description_class = SpansFromTermMatch(history_match.title_matches, 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen match.description.size()); 176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return match; 178bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 179731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 180731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickhistory::InMemoryURLIndex* HistoryQuickProvider::GetIndex() { 181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (index_for_testing_.get()) 182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return index_for_testing_.get(); 183731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 184731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick HistoryService* const history_service = 185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); 186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!history_service) 187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return NULL; 188731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return history_service->InMemoryIndex(); 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 191731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid HistoryQuickProvider::SetIndexForTesting( 193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick history::InMemoryURLIndex* index) { 194731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(index); 195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick index_for_testing_.reset(index); 196731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 198731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint HistoryQuickProvider::CalculateRelevance(int raw_score, 200731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick AutocompleteInput::Type input_type, 201731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick MatchType match_type, 202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick size_t match_number) { 203731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick switch (match_type) { 204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case INLINE_AUTOCOMPLETE: 205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return 1400; 206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 207731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick case WHAT_YOU_TYPED: 208731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return 1200; 209731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 210731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick default: 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return raw_score; 212731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 213731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenACMatchClassifications HistoryQuickProvider::SpansFromTermMatch( 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const history::TermMatches& matches, 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t text_length) { 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ACMatchClassifications spans; 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (matches.empty()) { 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (text_length) 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen spans.push_back(ACMatchClassification(0, ACMatchClassification::DIM)); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return spans; 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (matches[0].offset) 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen spans.push_back(ACMatchClassification(0, ACMatchClassification::NONE)); 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t match_count = matches.size(); 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < match_count;) { 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen size_t offset = matches[i].offset; 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen spans.push_back(ACMatchClassification(offset, 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ACMatchClassification::MATCH)); 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Skip all adjacent matches. 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen do { 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen offset += matches[i].length; 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ++i; 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } while ((i < match_count) && (offset == matches[i].offset)); 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (offset < text_length) { 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen spans.push_back(ACMatchClassification(offset, 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ACMatchClassification::NONE)); 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return spans; 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 245