Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / app_list / search / app_search_provider.cc
blobc190f76ce7c1ae10618c72b4933e3f06ebc93f7d
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 "chrome/browser/ui/app_list/search/app_search_provider.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/time/clock.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/extension_ui_util.h"
17 #include "chrome/browser/extensions/extension_util.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
20 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
21 #include "chrome/browser/ui/app_list/search/app_result.h"
22 #include "extensions/browser/extension_prefs.h"
23 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/extension_system.h"
25 #include "extensions/common/extension.h"
26 #include "extensions/common/extension_set.h"
27 #include "ui/app_list/app_list_item.h"
28 #include "ui/app_list/app_list_model.h"
29 #include "ui/app_list/search/tokenized_string.h"
30 #include "ui/app_list/search/tokenized_string_match.h"
32 using extensions::ExtensionRegistry;
34 namespace {
36 // The size of each step unlaunched apps should increase their relevance by.
37 const double kUnlaunchedAppRelevanceStepSize = 0.0001;
40 namespace app_list {
42 class AppSearchProvider::App {
43 public:
44 explicit App(const extensions::Extension* extension,
45 const base::Time& last_launch_time)
46 : app_id_(extension->id()),
47 indexed_name_(base::UTF8ToUTF16(extension->short_name())),
48 last_launch_time_(last_launch_time) {}
49 ~App() {}
51 const std::string& app_id() const { return app_id_; }
52 const TokenizedString& indexed_name() const { return indexed_name_; }
53 const base::Time& last_launch_time() const { return last_launch_time_; }
55 private:
56 const std::string app_id_;
57 TokenizedString indexed_name_;
58 base::Time last_launch_time_;
60 DISALLOW_COPY_AND_ASSIGN(App);
63 AppSearchProvider::AppSearchProvider(Profile* profile,
64 AppListControllerDelegate* list_controller,
65 scoped_ptr<base::Clock> clock,
66 AppListItemList* top_level_item_list)
67 : profile_(profile),
68 list_controller_(list_controller),
69 extension_registry_observer_(this),
70 top_level_item_list_(top_level_item_list),
71 clock_(clock.Pass()),
72 update_results_factory_(this) {
73 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
74 RefreshApps();
77 AppSearchProvider::~AppSearchProvider() {}
79 void AppSearchProvider::Start(bool /*is_voice_query*/,
80 const base::string16& query) {
81 query_ = query;
82 const TokenizedString query_terms(query);
84 ClearResults();
86 bool show_recommendations = query.empty();
87 // Refresh list of apps to ensure we have the latest launch time information.
88 // This will also cause the results to update.
89 if (show_recommendations)
90 RefreshApps();
92 UpdateResults();
95 void AppSearchProvider::Stop() {
98 void AppSearchProvider::UpdateResults() {
99 const TokenizedString query_terms(query_);
100 bool show_recommendations = query_.empty();
101 ClearResults();
103 if (show_recommendations) {
104 // Build a map of app ids to their position in the app list.
105 std::map<std::string, size_t> id_to_app_list_index;
106 for (size_t i = 0; i < top_level_item_list_->item_count(); ++i) {
107 id_to_app_list_index[top_level_item_list_->item_at(i)->id()] = i;
110 for (const App* app : apps_) {
111 scoped_ptr<AppResult> result(
112 new AppResult(profile_, app->app_id(), list_controller_, true));
113 result->set_title(app->indexed_name().text());
115 // Use the app list order to tiebreak apps that have never been launched.
116 if (app->last_launch_time().is_null()) {
117 auto it = id_to_app_list_index.find(app->app_id());
118 // If it's in a folder, it won't be in |id_to_app_list_index|. Rank
119 // those as if they are at the end of the list.
120 size_t app_list_index =
121 it == id_to_app_list_index.end() ? apps_.size() : (*it).second;
122 if (app_list_index > apps_.size())
123 app_list_index = apps_.size();
125 result->set_relevance(kUnlaunchedAppRelevanceStepSize *
126 (apps_.size() - app_list_index));
127 } else {
128 result->UpdateFromLastLaunched(clock_->Now(), app->last_launch_time());
130 Add(result.Pass());
132 } else {
133 for (const App* app : apps_) {
134 scoped_ptr<AppResult> result(
135 new AppResult(profile_, app->app_id(), list_controller_, false));
136 TokenizedStringMatch match;
137 if (!match.Calculate(query_terms, app->indexed_name()))
138 continue;
140 result->UpdateFromMatch(app->indexed_name(), match);
141 Add(result.Pass());
145 update_results_factory_.InvalidateWeakPtrs();
148 void AppSearchProvider::AddApps(const extensions::ExtensionSet& extensions) {
149 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
150 for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
151 iter != extensions.end(); ++iter) {
152 const extensions::Extension* app = iter->get();
154 if (!extensions::ui_util::ShouldDisplayInAppLauncher(app, profile_))
155 continue;
157 if (profile_->IsOffTheRecord() &&
158 !extensions::util::CanLoadInIncognito(app, profile_))
159 continue;
161 apps_.push_back(new App(app, prefs->GetLastLaunchTime(app->id())));
165 void AppSearchProvider::RefreshApps() {
166 apps_.clear();
167 ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
168 AddApps(registry->enabled_extensions());
169 AddApps(registry->disabled_extensions());
170 AddApps(registry->terminated_extensions());
173 void AppSearchProvider::OnExtensionLoaded(
174 content::BrowserContext* browser_context,
175 const extensions::Extension* extension) {
176 RefreshApps();
177 if (!update_results_factory_.HasWeakPtrs()) {
178 base::ThreadTaskRunnerHandle::Get()->PostTask(
179 FROM_HERE, base::Bind(&AppSearchProvider::UpdateResults,
180 update_results_factory_.GetWeakPtr()));
184 void AppSearchProvider::OnExtensionUninstalled(
185 content::BrowserContext* browser_context,
186 const extensions::Extension* extension,
187 extensions::UninstallReason reason) {
188 RefreshApps();
189 if (!update_results_factory_.HasWeakPtrs()) {
190 base::ThreadTaskRunnerHandle::Get()->PostTask(
191 FROM_HERE, base::Bind(&AppSearchProvider::UpdateResults,
192 update_results_factory_.GetWeakPtr()));
196 } // namespace app_list