OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/app_list/search/mixer.h" | 5 #include "ui/app_list/search/mixer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/metrics/field_trial.h" | 15 #include "base/metrics/field_trial.h" |
16 #include "ui/app_list/app_list_switches.h" | 16 #include "ui/app_list/app_list_switches.h" |
17 #include "ui/app_list/search_provider.h" | 17 #include "ui/app_list/search_provider.h" |
18 #include "ui/app_list/search_result.h" | 18 #include "ui/app_list/search_result.h" |
19 | 19 |
20 namespace app_list { | 20 namespace app_list { |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 // Maximum number of results to show. Ignored if the AppListMixer field trial is | |
25 // "Blended". | |
26 const size_t kMaxResults = 6; | |
27 | |
28 // The minimum number of results to show, if the AppListMixer field trial is | 24 // The minimum number of results to show, if the AppListMixer field trial is |
29 // "Blended". If this quota is not reached, the per-group limitations are | 25 // "Blended". If this quota is not reached, the per-group limitations are |
30 // removed and we try again. (We may still not reach the minumum, but at least | 26 // removed and we try again. (We may still not reach the minumum, but at least |
31 // we tried.) Ignored if the field trial is off. | 27 // we tried.) Ignored if the field trial is off. |
32 const size_t kMinBlendedResults = 6; | 28 const size_t kMinBlendedResults = 6; |
33 | 29 |
34 const char kAppListMixerFieldTrialName[] = "AppListMixer"; | 30 const char kAppListMixerFieldTrialName[] = "AppListMixer"; |
35 const char kAppListMixerFieldTrialEnabled[] = "Blended"; | 31 const char kAppListMixerFieldTrialEnabled[] = "Blended"; |
36 const char kAppListMixerFieldTrialDisabled[] = "Control"; | 32 const char kAppListMixerFieldTrialDisabled[] = "Control"; |
37 | 33 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 omnibox_group_ = id; | 190 omnibox_group_ = id; |
195 has_omnibox_group_ = true; | 191 has_omnibox_group_ = true; |
196 return id; | 192 return id; |
197 } | 193 } |
198 | 194 |
199 void Mixer::AddProviderToGroup(size_t group_id, SearchProvider* provider) { | 195 void Mixer::AddProviderToGroup(size_t group_id, SearchProvider* provider) { |
200 groups_[group_id]->AddProvider(provider); | 196 groups_[group_id]->AddProvider(provider); |
201 } | 197 } |
202 | 198 |
203 void Mixer::MixAndPublish(bool is_voice_query, | 199 void Mixer::MixAndPublish(bool is_voice_query, |
204 const KnownResults& known_results) { | 200 const KnownResults& known_results, |
| 201 size_t num_max_results) { |
205 FetchResults(is_voice_query, known_results); | 202 FetchResults(is_voice_query, known_results); |
206 | 203 |
207 SortedResults results; | 204 SortedResults results; |
208 | 205 |
209 if (IsBlendedMixerTrialEnabled()) { | 206 if (IsBlendedMixerTrialEnabled()) { |
210 results.reserve(kMinBlendedResults); | 207 results.reserve(kMinBlendedResults); |
211 | 208 |
212 // Add results from each group. Limit to the maximum number of results in | 209 // Add results from each group. Limit to the maximum number of results in |
213 // each group. | 210 // each group. |
214 for (const Group* group : groups_) { | 211 for (const Group* group : groups_) { |
(...skipping 20 matching lines...) Expand all Loading... |
235 } | 232 } |
236 RemoveDuplicates(&results); | 233 RemoveDuplicates(&results); |
237 // Sort just the newly added results. This ensures that, for example, if | 234 // Sort just the newly added results. This ensures that, for example, if |
238 // there are 6 Omnibox results (score = 0.8) and 1 People result (score = | 235 // there are 6 Omnibox results (score = 0.8) and 1 People result (score = |
239 // 0.4) that the People result will be 5th, not 7th, because the Omnibox | 236 // 0.4) that the People result will be 5th, not 7th, because the Omnibox |
240 // group has a soft maximum of 4 results. (Otherwise, the People result | 237 // group has a soft maximum of 4 results. (Otherwise, the People result |
241 // would not be seen at all once the result list is truncated.) | 238 // would not be seen at all once the result list is truncated.) |
242 std::sort(results.begin() + original_size, results.end()); | 239 std::sort(results.begin() + original_size, results.end()); |
243 } | 240 } |
244 } else { | 241 } else { |
245 results.reserve(kMaxResults); | 242 results.reserve(num_max_results); |
246 | 243 |
247 // Add results from non-omnibox groups first. Limit to the maximum number of | 244 // Add results from non-omnibox groups first. Limit to the maximum number of |
248 // results in each group. | 245 // results in each group. |
249 for (size_t i = 0; i < groups_.size(); ++i) { | 246 for (size_t i = 0; i < groups_.size(); ++i) { |
250 if (!has_omnibox_group_ || i != omnibox_group_) { | 247 if (!has_omnibox_group_ || i != omnibox_group_) { |
251 const Group& group = *groups_[i]; | 248 const Group& group = *groups_[i]; |
252 size_t num_results = | 249 size_t num_results = |
253 std::min(group.results().size(), group.max_results()); | 250 std::min(group.results().size(), group.max_results()); |
254 results.insert(results.end(), group.results().begin(), | 251 results.insert(results.end(), group.results().begin(), |
255 group.results().begin() + num_results); | 252 group.results().begin() + num_results); |
256 } | 253 } |
257 } | 254 } |
258 | 255 |
259 // Collapse duplicate apps from local and web store. | 256 // Collapse duplicate apps from local and web store. |
260 RemoveDuplicates(&results); | 257 RemoveDuplicates(&results); |
261 | 258 |
262 // Fill the remaining slots with omnibox results. Always add at least one | 259 // Fill the remaining slots with omnibox results. Always add at least one |
263 // omnibox result (even if there are no more slots; if we over-fill the | 260 // omnibox result (even if there are no more slots; if we over-fill the |
264 // vector, the web store and people results will be removed in a later | 261 // vector, the web store and people results will be removed in a later |
265 // step). Note: max_results() is ignored for the omnibox group. | 262 // step). Note: max_results() is ignored for the omnibox group. |
266 if (has_omnibox_group_) { | 263 if (has_omnibox_group_) { |
267 CHECK_LT(omnibox_group_, groups_.size()); | 264 CHECK_LT(omnibox_group_, groups_.size()); |
268 const Group& omnibox_group = *groups_[omnibox_group_]; | 265 const Group& omnibox_group = *groups_[omnibox_group_]; |
269 const size_t omnibox_results = std::min( | 266 const size_t omnibox_results = std::min( |
270 omnibox_group.results().size(), | 267 omnibox_group.results().size(), results.size() < num_max_results |
271 results.size() < kMaxResults ? kMaxResults - results.size() : 1); | 268 ? num_max_results - results.size() |
| 269 : 1); |
272 results.insert(results.end(), omnibox_group.results().begin(), | 270 results.insert(results.end(), omnibox_group.results().begin(), |
273 omnibox_group.results().begin() + omnibox_results); | 271 omnibox_group.results().begin() + omnibox_results); |
274 } | 272 } |
275 | 273 |
276 std::sort(results.begin(), results.end()); | 274 std::sort(results.begin(), results.end()); |
277 RemoveDuplicates(&results); | 275 RemoveDuplicates(&results); |
278 if (results.size() > kMaxResults) | 276 if (results.size() > num_max_results) |
279 results.resize(kMaxResults); | 277 results.resize(num_max_results); |
280 } | 278 } |
281 | 279 |
282 Publish(results, ui_results_); | 280 Publish(results, ui_results_); |
283 } | 281 } |
284 | 282 |
285 void Mixer::Publish(const SortedResults& new_results, | 283 void Mixer::Publish(const SortedResults& new_results, |
286 AppListModel::SearchResults* ui_results) { | 284 AppListModel::SearchResults* ui_results) { |
287 typedef std::map<std::string, SearchResult*> IdToResultMap; | 285 typedef std::map<std::string, SearchResult*> IdToResultMap; |
288 | 286 |
289 // The following algorithm is used: | 287 // The following algorithm is used: |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 results->swap(final); | 348 results->swap(final); |
351 } | 349 } |
352 | 350 |
353 void Mixer::FetchResults(bool is_voice_query, | 351 void Mixer::FetchResults(bool is_voice_query, |
354 const KnownResults& known_results) { | 352 const KnownResults& known_results) { |
355 for (auto* group : groups_) | 353 for (auto* group : groups_) |
356 group->FetchResults(is_voice_query, known_results); | 354 group->FetchResults(is_voice_query, known_results); |
357 } | 355 } |
358 | 356 |
359 } // namespace app_list | 357 } // namespace app_list |
OLD | NEW |