omnibox_provider.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 virtual ChromeSearchResultType GetType() OVERRIDE { 96 return OMNIBOX_SEARCH_RESULT; 97 } 98 99 private: 100 void UpdateIcon() { 101 int resource_id = match_.starred ? 102 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match_.type); 103 SetIcon(*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 104 resource_id)); 105 } 106 107 void UpdateTitleAndDetails() { 108 set_title(match_.contents); 109 SearchResult::Tags title_tags; 110 ACMatchClassificationsToTags(match_.contents, 111 match_.contents_class, 112 &title_tags); 113 set_title_tags(title_tags); 114 115 set_details(match_.description); 116 SearchResult::Tags details_tags; 117 ACMatchClassificationsToTags(match_.description, 118 match_.description_class, 119 &details_tags); 120 set_details_tags(details_tags); 121 } 122 123 Profile* profile_; 124 AutocompleteMatch match_; 125 126 DISALLOW_COPY_AND_ASSIGN(OmniboxResult); 127}; 128 129} // namespace 130 131OmniboxProvider::OmniboxProvider(Profile* profile) 132 : profile_(profile), 133 controller_(new AutocompleteController( 134 profile, 135 this, 136 AutocompleteClassifier::kDefaultOmniboxProviders)) { 137} 138 139OmniboxProvider::~OmniboxProvider() {} 140 141void OmniboxProvider::Start(const base::string16& query) { 142 controller_->Start(AutocompleteInput(query, 143 base::string16::npos, 144 base::string16(), 145 GURL(), 146 false, 147 false, 148 true, 149 AutocompleteInput::ALL_MATCHES)); 150} 151 152void OmniboxProvider::Stop() { 153 controller_->Stop(false); 154} 155 156void OmniboxProvider::PopulateFromACResult(const AutocompleteResult& result) { 157 ClearResults(); 158 for (ACMatches::const_iterator it = result.begin(); 159 it != result.end(); 160 ++it) { 161 if (!it->destination_url.is_valid()) 162 continue; 163 164 Add(scoped_ptr<ChromeSearchResult>( 165 new OmniboxResult(profile_, *it)).Pass()); 166 } 167} 168 169void OmniboxProvider::OnResultChanged(bool default_match_changed) { 170 const AutocompleteResult& result = controller_->result(); 171 PopulateFromACResult(result); 172} 173 174} // namespace app_list 175