1 // Copyright 2014 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.
5 #include "athena/main/url_search_provider.h"
7 #include "athena/activity/public/activity_factory.h"
8 #include "athena/activity/public/activity_manager.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "components/metrics/proto/omnibox_event.pb.h"
12 #include "components/metrics/proto/omnibox_input_type.pb.h"
13 #include "components/omnibox/autocomplete_input.h"
14 #include "components/omnibox/autocomplete_provider_client.h"
15 #include "components/omnibox/autocomplete_scheme_classifier.h"
16 #include "components/omnibox/search_provider.h"
17 #include "components/search_engines/search_terms_data.h"
18 #include "components/search_engines/template_url_service.h"
19 #include "components/search_engines/template_url_service_client.h"
20 #include "content/public/browser/browser_context.h"
21 #include "ui/app_list/search_result.h"
22 #include "ui/base/resource/resource_bundle.h"
29 // The SearchTermsData implementation for Athena.
30 class AthenaSearchTermsData
: public SearchTermsData
{
33 virtual std::string
GetSuggestClient() const OVERRIDE
{
38 // The AutocompleteSchemeClassifier implementation for Athena.
39 // TODO(mukai): Introduce supports of normal schemes like about: or blob:
40 class AthenaSchemeClassifier
: public AutocompleteSchemeClassifier
{
42 AthenaSchemeClassifier() {}
44 // AutocompleteSchemeClassifier:
45 virtual metrics::OmniboxInputType::Type
GetInputTypeForScheme(
46 const std::string
& scheme
) const OVERRIDE
{
47 if (net::URLRequest::IsHandledProtocol(scheme
))
48 return metrics::OmniboxInputType::URL
;
49 return metrics::OmniboxInputType::INVALID
;
53 // The templateURLServiceClient for Athena. Mainly for the interaction with
54 // history module (see chrome/browser/search_engines for Chrome implementation).
55 // TODO(mukai): Implement the contents of this class when it's necessary.
56 class AthenaTemplateURLServiceClient
: public TemplateURLServiceClient
{
58 AthenaTemplateURLServiceClient() {}
59 virtual ~AthenaTemplateURLServiceClient() {}
62 // TemplateURLServiceClient:
63 virtual void SetOwner(TemplateURLService
* owner
) OVERRIDE
{}
64 virtual void DeleteAllSearchTermsForKeyword(TemplateURLID id
) OVERRIDE
{}
65 virtual void SetKeywordSearchTermsForURL(
68 const base::string16
& term
) OVERRIDE
{}
69 virtual void AddKeywordGeneratedVisit(const GURL
& url
) OVERRIDE
{}
70 virtual void RestoreExtensionInfoIfNecessary(
71 TemplateURL
* template_url
) OVERRIDE
{}
73 DISALLOW_COPY_AND_ASSIGN(AthenaTemplateURLServiceClient
);
76 // The AutocompleteProviderClient for Athena.
77 class AthenaAutocompleteProviderClient
: public AutocompleteProviderClient
{
79 explicit AthenaAutocompleteProviderClient(
80 content::BrowserContext
* browser_context
)
81 : browser_context_(browser_context
) {}
82 virtual ~AthenaAutocompleteProviderClient() {}
84 virtual net::URLRequestContextGetter
* RequestContext() OVERRIDE
{
85 return browser_context_
->GetRequestContext();
87 virtual bool IsOffTheRecord() OVERRIDE
{
88 return browser_context_
->IsOffTheRecord();
90 virtual std::string
AcceptLanguages() OVERRIDE
{
91 // TODO(hashimoto): Return the value stored in the prefs.
94 virtual bool SearchSuggestEnabled() OVERRIDE
{ return true; }
95 virtual bool ShowBookmarkBar() OVERRIDE
{ return false; }
96 virtual const AutocompleteSchemeClassifier
& SchemeClassifier() OVERRIDE
{
97 return scheme_classifier_
;
99 virtual void Classify(
100 const base::string16
& text
,
102 bool allow_exact_keyword_match
,
103 metrics::OmniboxEventProto::PageClassification page_classification
,
104 AutocompleteMatch
* match
,
105 GURL
* alternate_nav_url
) OVERRIDE
{}
106 virtual history::URLDatabase
* InMemoryDatabase() OVERRIDE
{ return NULL
; }
107 virtual void DeleteMatchingURLsForKeywordFromHistory(
108 history::KeywordID keyword_id
,
109 const base::string16
& term
) OVERRIDE
{}
110 virtual bool TabSyncEnabledAndUnencrypted() OVERRIDE
{ return false; }
111 virtual void PrefetchImage(const GURL
& url
) OVERRIDE
{}
114 content::BrowserContext
* browser_context_
;
115 AthenaSchemeClassifier scheme_classifier_
;
117 DISALLOW_COPY_AND_ASSIGN(AthenaAutocompleteProviderClient
);
120 int ACMatchStyleToTagStyle(int styles
) {
122 if (styles
& ACMatchClassification::URL
)
123 tag_styles
|= app_list::SearchResult::Tag::URL
;
124 if (styles
& ACMatchClassification::MATCH
)
125 tag_styles
|= app_list::SearchResult::Tag::MATCH
;
126 if (styles
& ACMatchClassification::DIM
)
127 tag_styles
|= app_list::SearchResult::Tag::DIM
;
132 // Translates ACMatchClassifications into SearchResult tags.
133 void ACMatchClassificationsToTags(
134 const base::string16
& text
,
135 const ACMatchClassifications
& text_classes
,
136 app_list::SearchResult::Tags
* tags
) {
137 int tag_styles
= app_list::SearchResult::Tag::NONE
;
138 size_t tag_start
= 0;
140 for (size_t i
= 0; i
< text_classes
.size(); ++i
) {
141 const ACMatchClassification
& text_class
= text_classes
[i
];
143 // Closes current tag.
144 if (tag_styles
!= app_list::SearchResult::Tag::NONE
) {
145 tags
->push_back(app_list::SearchResult::Tag(
146 tag_styles
, tag_start
, text_class
.offset
));
147 tag_styles
= app_list::SearchResult::Tag::NONE
;
150 if (text_class
.style
== ACMatchClassification::NONE
)
153 tag_start
= text_class
.offset
;
154 tag_styles
= ACMatchStyleToTagStyle(text_class
.style
);
157 if (tag_styles
!= app_list::SearchResult::Tag::NONE
) {
158 tags
->push_back(app_list::SearchResult::Tag(
159 tag_styles
, tag_start
, text
.length()));
163 class UrlSearchResult
: public app_list::SearchResult
{
165 UrlSearchResult(content::BrowserContext
* browser_context
,
166 const AutocompleteMatch
& match
)
167 : browser_context_(browser_context
),
169 set_id(match_
.destination_url
.spec());
171 // Derive relevance from omnibox relevance and normalize it to [0, 1].
172 // The magic number 1500 is the highest score of an omnibox result.
173 // See comments in autocomplete_provider.h.
174 set_relevance(match_
.relevance
/ 1500.0);
177 UpdateTitleAndDetails();
180 virtual ~UrlSearchResult() {}
183 // Overriddenn from app_list::SearchResult:
184 virtual void Open(int event_flags
) OVERRIDE
{
185 ActivityManager::Get()->AddActivity(
186 ActivityFactory::Get()->CreateWebActivity(browser_context_
,
187 match_
.destination_url
));
191 SetIcon(*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
192 AutocompleteMatch::TypeToIcon(match_
.type
)));
195 void UpdateTitleAndDetails() {
196 set_title(match_
.contents
);
197 SearchResult::Tags title_tags
;
198 ACMatchClassificationsToTags(match_
.contents
,
199 match_
.contents_class
,
201 set_title_tags(title_tags
);
203 set_details(match_
.description
);
204 SearchResult::Tags details_tags
;
205 ACMatchClassificationsToTags(match_
.description
,
206 match_
.description_class
,
208 set_details_tags(details_tags
);
211 content::BrowserContext
* browser_context_
;
212 AutocompleteMatch match_
;
214 DISALLOW_COPY_AND_ASSIGN(UrlSearchResult
);
219 UrlSearchProvider::UrlSearchProvider(content::BrowserContext
* browser_context
)
220 : browser_context_(browser_context
),
221 // TODO(mukai): introduce the real parameters when it's necessary.
222 template_url_service_(
223 new TemplateURLService(NULL
/* prefs */,
224 scoped_ptr
<SearchTermsData
>(
225 new AthenaSearchTermsData()),
226 NULL
/* KeywordWebDataService */,
227 scoped_ptr
<TemplateURLServiceClient
>(
228 new AthenaTemplateURLServiceClient()),
229 NULL
/*GoogleURLTracker */,
230 NULL
/* RapporService */,
231 base::Closure() /* dsp_change_callback */)),
232 provider_(new ::SearchProvider(
234 template_url_service_
.get(),
235 scoped_ptr
<AutocompleteProviderClient
>(
236 new AthenaAutocompleteProviderClient(browser_context_
)))) {
237 template_url_service_
->Load();
240 UrlSearchProvider::~UrlSearchProvider() {
243 void UrlSearchProvider::Start(const base::string16
& query
) {
244 const bool minimal_changes
= query
== input_
.text();
245 input_
= AutocompleteInput(query
,
246 base::string16::npos
/* cursor_position */,
247 base::string16() /* desired_tld */,
248 GURL() /* current_url */,
249 metrics::OmniboxEventProto::INVALID_SPEC
,
250 false /* prevent_inline_autocomplete */,
251 false /* prefer_keyword */,
252 true /* allow_extract_keyword_match */,
253 true /* want_asynchronous_matches */,
254 AthenaSchemeClassifier());
256 provider_
->Start(input_
, minimal_changes
);
259 void UrlSearchProvider::Stop() {
260 provider_
->Stop(false);
263 void UrlSearchProvider::OnProviderUpdate(bool updated_matches
) {
264 if (!updated_matches
)
269 const ACMatches
& matches
= provider_
->matches();
270 for (ACMatches::const_iterator it
= matches
.begin(); it
!= matches
.end();
272 if (!it
->destination_url
.is_valid())
275 Add(scoped_ptr
<app_list::SearchResult
>(new UrlSearchResult(
276 browser_context_
, *it
)));
280 } // namespace athena