omnibox_provider.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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/autocomplete/search_provider.h" 12#include "chrome/browser/ui/app_list/search/chrome_search_result.h" 13#include "chrome/browser/ui/browser_navigator.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 base::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 ~AutocompleteProvider::TYPE_ZERO_SUGGEST)) { 140 controller_->search_provider()->set_in_app_list(); 141} 142 143OmniboxProvider::~OmniboxProvider() {} 144 145void OmniboxProvider::Start(const base::string16& query) { 146 controller_->Start(AutocompleteInput(query, 147 base::string16::npos, 148 base::string16(), 149 GURL(), 150 AutocompleteInput::INVALID_SPEC, 151 false, 152 false, 153 true, 154 true)); 155} 156 157void OmniboxProvider::Stop() { 158 controller_->Stop(false); 159} 160 161void OmniboxProvider::PopulateFromACResult(const AutocompleteResult& result) { 162 ClearResults(); 163 for (ACMatches::const_iterator it = result.begin(); 164 it != result.end(); 165 ++it) { 166 if (!it->destination_url.is_valid()) 167 continue; 168 169 Add(scoped_ptr<SearchResult>(new OmniboxResult(profile_, *it))); 170 } 171} 172 173void OmniboxProvider::OnResultChanged(bool default_match_changed) { 174 const AutocompleteResult& result = controller_->result(); 175 PopulateFromACResult(result); 176} 177 178} // namespace app_list 179