blob: b7898d733402690a8c9e49dc145312395526e752 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_APP_LIST_SEARCH_MIXER_H_
#define UI_APP_LIST_SEARCH_MIXER_H_
#include <stddef.h>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "ui/app_list/app_list_export.h"
#include "ui/app_list/app_list_model.h"
#include "ui/app_list/search/history_types.h"
namespace app_list {
namespace test {
FORWARD_DECLARE_TEST(MixerTest, Publish);
}
class SearchProvider;
class SearchResult;
// Mixer collects results from providers, sorts them and publishes them to the
// SearchResults UI model. The targeted results have 6 slots to hold the
// result. The search controller can specify any number of groups, each with a
// different number of results and priority boost. The "omnibox" group is
// expected to contain omnibox results, and will be treated specially.
class APP_LIST_EXPORT Mixer {
public:
explicit Mixer(AppListModel::SearchResults* ui_results);
~Mixer();
// Adds a new mixer group. A maximum of |max_results| results will be
// displayed from this group (if 0, will allow unlimited results from this
// group). Behaviour depends on the AppListMixer field trial:
// - If default: Each result in the group will have its score boosted by
// |boost|. |multiplier| is ignored.
// - If "Blended": |max_results| is a "soft" maximum; if there aren't enough
// results from all groups, more than |max_results| may be chosen from this
// group. Each result in the group will have its score multiplied by
// |multiplier|. |boost| is ignored.
// Returns the group's group_id.
size_t AddGroup(size_t max_results, double boost, double multiplier);
// Adds a new mixer group for the special "omnibox" group. This group will be
// treated specially by the Mixer (it will be truncated such that it fills the
// remaining slots without overflowing, but with at least one result). A
// maximum of one group should be added using this method.
size_t AddOmniboxGroup(size_t max_results, double boost, double multiplier);
// Associates a provider with a mixer group.
void AddProviderToGroup(size_t group_id, SearchProvider* provider);
// Collects the results, sorts and publishes them.
void MixAndPublish(bool is_voice_query, const KnownResults& known_results);
private:
FRIEND_TEST_ALL_PREFIXES(test::MixerTest, Publish);
// Used for sorting and mixing results.
struct APP_LIST_EXPORT SortData {
SortData();
SortData(SearchResult* result, double score);
bool operator<(const SortData& other) const;
SearchResult* result; // Not owned.
double score;
};
typedef std::vector<Mixer::SortData> SortedResults;
class Group;
typedef ScopedVector<Group> Groups;
// Publishes the given |new_results| to |ui_results|, deleting any existing
// results that are not in |new_results|. Results that already exist in
// |ui_results| are reused to avoid flickering caused by icon reload.
static void Publish(const SortedResults& results,
AppListModel::SearchResults* ui_results);
// Removes entries from |results| with duplicate IDs. When two or more results
// have the same ID, the earliest one in the |results| list is kept.
// NOTE: This is not necessarily the one with the highest *score*, as
// |results| may not have been sorted yet.
static void RemoveDuplicates(SortedResults* results);
void FetchResults(bool is_voice_query, const KnownResults& known_results);
AppListModel::SearchResults* ui_results_; // Not owned.
Groups groups_;
// The ID of the omnibox group. The group with this ID will be treated
// specially by the Mixer. Ignored if the AppListMixer field trial is
// "Blended".
// TODO(mgiuca): Remove this after the field trial is complete.
size_t omnibox_group_ = 0;
// Whether |omnibox_group_| has been set.
bool has_omnibox_group_ = false;
DISALLOW_COPY_AND_ASSIGN(Mixer);
};
} // namespace app_list
#endif // UI_APP_LIST_SEARCH_MIXER_H_