omnibox_provider.cc revision d3868032626d59662ff73b372b5d584c1d144c53
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/app_list/search/omnibox_provider.h" 6 7#include "chrome/browser/autocomplete/autocomplete_classifier.h" 8#include "chrome/browser/autocomplete/autocomplete_controller.h" 9#include "chrome/browser/autocomplete/autocomplete_input.h" 10#include "chrome/browser/autocomplete/autocomplete_match.h" 11#include "chrome/browser/ui/app_list/search/chrome_search_result.h" 12#include "chrome/browser/ui/browser_navigator.h" 13#include "chrome/common/metrics/proto/omnibox_event.pb.h" 14#include "grit/theme_resources.h" 15#include "ui/base/resource/resource_bundle.h" 16 17namespace app_list { 18 19namespace { 20 21int ACMatchStyleToTagStyle(int styles) { 22 int tag_styles = 0; 23 if (styles & ACMatchClassification::URL) 24 tag_styles |= SearchResult::Tag::URL; 25 if (styles & ACMatchClassification::MATCH) 26 tag_styles |= SearchResult::Tag::MATCH; 27 if (styles & ACMatchClassification::DIM) 28 tag_styles |= SearchResult::Tag::DIM; 29 30 return tag_styles; 31} 32 33// Translates ACMatchClassifications into SearchResult tags. 34void ACMatchClassificationsToTags( 35 const string16& text, 36 const ACMatchClassifications& text_classes, 37 SearchResult::Tags* tags) { 38 int tag_styles = SearchResult::Tag::NONE; 39 size_t tag_start = 0; 40 41 for (size_t i = 0; i < text_classes.size(); ++i) { 42 const ACMatchClassification& text_class = text_classes[i]; 43 44 // Closes current tag. 45 if (tag_styles != SearchResult::Tag::NONE) { 46 tags->push_back(SearchResult::Tag( 47 tag_styles, tag_start, text_class.offset)); 48 tag_styles = SearchResult::Tag::NONE; 49 } 50 51 if (text_class.style == ACMatchClassification::NONE) 52 continue; 53 54 tag_start = text_class.offset; 55 tag_styles = ACMatchStyleToTagStyle(text_class.style); 56 } 57 58 if (tag_styles != SearchResult::Tag::NONE) { 59 tags->push_back(SearchResult::Tag( 60 tag_styles, tag_start, text.length())); 61 } 62} 63 64class OmniboxResult : public ChromeSearchResult { 65 public: 66 OmniboxResult(Profile* profile, const AutocompleteMatch& match) 67 : profile_(profile), 68 match_(match) { 69 set_id(match.destination_url.spec()); 70 71 // Derive relevance from omnibox relevance and normalize it to [0, 1]. 72 // The magic number 1500 is the highest score of an omnibox result. 73 // See comments in autocomplete_provider.h. 74 set_relevance(match.relevance / 1500.0); 75 76 UpdateIcon(); 77 UpdateTitleAndDetails(); 78 } 79 virtual ~OmniboxResult() {} 80 81 // ChromeSearchResult overides: 82 virtual void Open(int event_flags) OVERRIDE { 83 chrome::NavigateParams params(profile_, 84 match_.destination_url, 85 match_.transition); 86 params.disposition = ui::DispositionFromEventFlags(event_flags); 87 chrome::Navigate(¶ms); 88 } 89 90 virtual void InvokeAction(int action_index, int event_flags) OVERRIDE {} 91 92 virtual scoped_ptr<ChromeSearchResult> Duplicate() OVERRIDE { 93 return scoped_ptr<ChromeSearchResult>( 94 new OmniboxResult(profile_, match_)).Pass(); 95 } 96 97 virtual ChromeSearchResultType GetType() OVERRIDE { 98 return OMNIBOX_SEARCH_RESULT; 99 } 100 101 private: 102 void UpdateIcon() { 103 int resource_id = match_.starred ? 104 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type); 105 SetIcon(*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 106 resource_id)); 107 } 108 109 void UpdateTitleAndDetails() { 110 set_title(match_.contents); 111 SearchResult::Tags title_tags; 112 ACMatchClassificationsToTags(match_.contents, 113 match_.contents_class, 114 &title_tags); 115 set_title_tags(title_tags); 116 117 set_details(match_.description); 118 SearchResult::Tags details_tags; 119 ACMatchClassificationsToTags(match_.description, 120 match_.description_class, 121 &details_tags); 122 set_details_tags(details_tags); 123 } 124 125 Profile* profile_; 126 AutocompleteMatch match_; 127 128 DISALLOW_COPY_AND_ASSIGN(OmniboxResult); 129}; 130 131} // namespace 132 133OmniboxProvider::OmniboxProvider(Profile* profile) 134 : profile_(profile), 135 controller_(new AutocompleteController( 136 profile, 137 this, 138 AutocompleteClassifier::kDefaultOmniboxProviders)) { 139} 140 141OmniboxProvider::~OmniboxProvider() {} 142 143void OmniboxProvider::Start(const base::string16& query) { 144 controller_->Start(AutocompleteInput(query, 145 base::string16::npos, 146 base::string16(), 147 GURL(), 148 AutocompleteInput::INVALID_SPEC, 149 false, 150 false, 151 true, 152 AutocompleteInput::ALL_MATCHES)); 153} 154 155void OmniboxProvider::Stop() { 156 controller_->Stop(false); 157} 158 159void OmniboxProvider::PopulateFromACResult(const AutocompleteResult& result) { 160 ClearResults(); 161 for (ACMatches::const_iterator it = result.begin(); 162 it != result.end(); 163 ++it) { 164 if (!it->destination_url.is_valid()) 165 continue; 166 167 Add(scoped_ptr<ChromeSearchResult>( 168 new OmniboxResult(profile_, *it)).Pass()); 169 } 170} 171 172void OmniboxProvider::OnResultChanged(bool default_match_changed) { 173 const AutocompleteResult& result = controller_->result(); 174 PopulateFromACResult(result); 175} 176 177} // namespace app_list 178