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