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.
5 #include "ui/app_list/search_controller.h"
10 #include "base/bind.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/metrics/user_metrics.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "ui/app_list/app_list_constants.h"
17 #include "ui/app_list/search/history.h"
18 #include "ui/app_list/search_box_model.h"
19 #include "ui/app_list/search_provider.h"
20 #include "ui/app_list/search_result.h"
24 // Maximum time (in milliseconds) to wait to the search providers to finish.
25 const int kStopTimeMS
= 1500;
30 SearchController::SearchController(SearchBoxModel
* search_box
,
31 AppListModel::SearchResults
* results
,
33 : search_box_(search_box
),
34 dispatching_query_(false),
35 mixer_(new Mixer(results
)),
37 is_voice_query_(false) {
40 SearchController::~SearchController() {
43 void SearchController::Start(bool is_voice_query
) {
47 base::TrimWhitespace(search_box_
->text(), base::TRIM_ALL
, &query
);
49 dispatching_query_
= true;
50 for (Providers::iterator it
= providers_
.begin();
51 it
!= providers_
.end();
53 (*it
)->Start(is_voice_query
, query
);
55 dispatching_query_
= false;
57 is_voice_query_
= is_voice_query
;
61 stop_timer_
.Start(FROM_HERE
,
62 base::TimeDelta::FromMilliseconds(kStopTimeMS
),
63 base::Bind(&SearchController::Stop
,
64 base::Unretained(this)));
67 void SearchController::Stop() {
70 for (Providers::iterator it
= providers_
.begin();
71 it
!= providers_
.end();
77 void SearchController::OpenResult(SearchResult
* result
, int event_flags
) {
78 // Count AppList.Search here because it is composed of search + action.
79 base::RecordAction(base::UserMetricsAction("AppList_Search"));
81 UMA_HISTOGRAM_ENUMERATION(kSearchResultOpenDisplayTypeHistogram
,
82 result
->display_type(),
83 SearchResult::DISPLAY_TYPE_LAST
);
85 if (result
->display_type() != SearchResult::DISPLAY_RECOMMENDATION
) {
86 UMA_HISTOGRAM_COUNTS_100(kSearchQueryLength
, search_box_
->text().size());
88 if (result
->distance_from_origin() >= 0) {
89 UMA_HISTOGRAM_COUNTS_100(kSearchResultDistanceFromOrigin
,
90 result
->distance_from_origin());
94 result
->Open(event_flags
);
96 if (history_
&& history_
->IsReady()) {
97 history_
->AddLaunchEvent(base::UTF16ToUTF8(search_box_
->text()),
102 void SearchController::InvokeResultAction(SearchResult
* result
,
105 // TODO(xiyuan): Hook up with user learning.
106 result
->InvokeAction(action_index
, event_flags
);
109 size_t SearchController::AddGroup(size_t max_results
,
112 return mixer_
->AddGroup(max_results
, boost
, multiplier
);
115 size_t SearchController::AddOmniboxGroup(size_t max_results
,
118 return mixer_
->AddOmniboxGroup(max_results
, boost
, multiplier
);
121 void SearchController::AddProvider(size_t group_id
,
122 scoped_ptr
<SearchProvider
> provider
) {
123 provider
->set_result_changed_callback(base::Bind(
124 &SearchController::OnResultsChanged
,
125 base::Unretained(this)));
126 mixer_
->AddProviderToGroup(group_id
, provider
.get());
127 providers_
.push_back(provider
.Pass());
130 void SearchController::OnResultsChanged() {
131 if (dispatching_query_
)
134 KnownResults known_results
;
135 if (history_
&& history_
->IsReady()) {
136 history_
->GetKnownResults(base::UTF16ToUTF8(search_box_
->text()))
137 ->swap(known_results
);
140 mixer_
->MixAndPublish(is_voice_query_
, known_results
);
143 } // namespace app_list