1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file. 4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/logging.h" 6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/autocomplete/autocomplete_match.h" 7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "grit/theme_resources.h" 8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// AutocompleteMatch ---------------------------------------------------------- 10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 11513209b27ff55e2841eac0e4120199c23acce758Ben MurdochAutocompleteMatch::AutocompleteMatch() 12513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : provider(NULL), 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch relevance(0), 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch deletable(false), 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen inline_autocomplete_offset(string16::npos), 16513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch transition(PageTransition::GENERATED), 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch is_history_what_you_typed_match(false), 18513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch type(SEARCH_WHAT_YOU_TYPED), 19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch template_url(NULL), 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen starred(false), 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen from_previous(false) { 22513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 23513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 24513209b27ff55e2841eac0e4120199c23acce758Ben MurdochAutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider, 25513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int relevance, 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool deletable, 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Type type) 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : provider(provider), 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch relevance(relevance), 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch deletable(deletable), 3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen inline_autocomplete_offset(string16::npos), 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch transition(PageTransition::TYPED), 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch is_history_what_you_typed_match(false), 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch type(type), 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch template_url(NULL), 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen starred(false), 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen from_previous(false) { 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 40513209b27ff55e2841eac0e4120199c23acce758Ben MurdochAutocompleteMatch::~AutocompleteMatch() { 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstd::string AutocompleteMatch::TypeToString(Type type) { 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const char* strings[NUM_TYPES] = { 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "url-what-you-typed", 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "history-url", 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "history-title", 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "history-body", 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "history-keyword", 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "navsuggest", 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "search-what-you-typed", 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "search-history", 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "search-suggest", 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch "search-other-engine", 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "extension-app", 57513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch }; 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(arraysize(strings) == NUM_TYPES); 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return strings[type]; 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint AutocompleteMatch::TypeToIcon(Type type) { 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int icons[NUM_TYPES] = { 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_HTTP, 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_HTTP, 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_HISTORY, 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_HISTORY, 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_HISTORY, 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_HTTP, 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_SEARCH, 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_SEARCH, 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_SEARCH, 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch IDR_OMNIBOX_SEARCH, 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IDR_OMNIBOX_EXTENSION_APP, 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch }; 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(arraysize(icons) == NUM_TYPES); 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return icons[type]; 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool AutocompleteMatch::MoreRelevant(const AutocompleteMatch& elem1, 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const AutocompleteMatch& elem2) { 84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // For equal-relevance matches, we sort alphabetically, so that providers 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // who return multiple elements at the same priority get a "stable" sort 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // across multiple updates. 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (elem1.relevance == elem2.relevance) 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return elem1.contents > elem2.contents; 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return elem1.relevance > elem2.relevance; 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool AutocompleteMatch::DestinationSortFunc(const AutocompleteMatch& elem1, 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const AutocompleteMatch& elem2) { 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Sort identical destination_urls together. Place the most relevant matches 97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // first, so that when we call std::unique(), these are the ones that get 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // preserved. 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return (elem1.destination_url != elem2.destination_url) ? 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (elem1.destination_url < elem2.destination_url) : 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch MoreRelevant(elem1, elem2); 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool AutocompleteMatch::DestinationsEqual(const AutocompleteMatch& elem1, 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const AutocompleteMatch& elem2) { 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return elem1.destination_url == elem2.destination_url; 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::ClassifyMatchInString( 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& find_text, 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& text, 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int style, 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ACMatchClassifications* classification) { 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ClassifyLocationInString(text.find(find_text), find_text.length(), 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch text.length(), style, classification); 118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::ClassifyLocationInString( 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size_t match_location, 122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size_t match_length, 123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size_t overall_length, 124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int style, 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ACMatchClassifications* classification) { 126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch classification->clear(); 127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Don't classify anything about an empty string 129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // (AutocompleteMatch::Validate() checks this). 130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (overall_length == 0) 131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Mark pre-match portion of string (if any). 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (match_location != 0) { 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch classification->push_back(ACMatchClassification(0, style)); 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Mark matching portion of string. 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (match_location == string16::npos) { 140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // No match, above classification will suffice for whole string. 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Classifying an empty match makes no sense and will lead to validation 144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // errors later. 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(match_length > 0); 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch classification->push_back(ACMatchClassification(match_location, 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (style | ACMatchClassification::MATCH) & ~ACMatchClassification::DIM)); 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Mark post-match portion of string (if any). 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const size_t after_match(match_location + match_length); 151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (after_match < overall_length) { 152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch classification->push_back(ACMatchClassification(after_match, style)); 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 156513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#ifndef NDEBUG 157513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::Validate() const { 158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ValidateClassifications(contents, contents_class); 159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ValidateClassifications(description, description_class); 160513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid AutocompleteMatch::ValidateClassifications( 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const string16& text, 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const ACMatchClassifications& classifications) const { 165513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (text.empty()) { 166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(classifications.size() == 0); 167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The classifications should always cover the whole string. 171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!classifications.empty()) << "No classification for text"; 172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(classifications[0].offset == 0) << "Classification misses beginning"; 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (classifications.size() == 1) 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The classifications should always be sorted. 177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size_t last_offset = classifications[0].offset; 178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (ACMatchClassifications::const_iterator i(classifications.begin() + 1); 179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch i != classifications.end(); ++i) { 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(i->offset > last_offset) << "Classification unsorted"; 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(i->offset < text.length()) << "Classification out of bounds"; 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch last_offset = i->offset; 183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif 186