app_search_provider.cc revision 3551c9c881056c480085172ff9840cab31610854
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.
4
5#include "chrome/browser/ui/app_list/search/app_search_provider.h"
6
7#include <string>
8
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/browser/chrome_notification_types.h"
11#include "chrome/browser/extensions/extension_service.h"
12#include "chrome/browser/extensions/extension_system_factory.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/browser/ui/app_list/search/app_result.h"
15#include "chrome/browser/ui/app_list/search/tokenized_string.h"
16#include "chrome/browser/ui/app_list/search/tokenized_string_match.h"
17#include "content/public/browser/notification_details.h"
18#include "content/public/browser/notification_source.h"
19
20namespace app_list {
21
22class AppSearchProvider::App {
23 public:
24  explicit App(const extensions::Extension* extension)
25      : app_id_(extension->id()),
26        indexed_name_(UTF8ToUTF16(extension->name())) {
27  }
28  ~App() {}
29
30  const std::string& app_id() const { return app_id_; }
31  const TokenizedString& indexed_name() const { return indexed_name_; }
32
33 private:
34  const std::string app_id_;
35  TokenizedString indexed_name_;
36
37  DISALLOW_COPY_AND_ASSIGN(App);
38};
39
40AppSearchProvider::AppSearchProvider(
41    Profile* profile,
42    AppListControllerDelegate* list_controller)
43    : profile_(profile),
44      list_controller_(list_controller) {
45  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
46                 content::Source<Profile>(profile_->GetOriginalProfile()));
47  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
48                 content::Source<Profile>(profile_->GetOriginalProfile()));
49  RefreshApps();
50}
51
52AppSearchProvider::~AppSearchProvider() {}
53
54void AppSearchProvider::Start(const string16& query) {
55  const TokenizedString query_terms(query);
56
57  ClearResults();
58
59  TokenizedStringMatch match;
60  for (Apps::const_iterator app_it = apps_.begin();
61       app_it != apps_.end();
62       ++app_it) {
63    if (!match.Calculate(query_terms, (*app_it)->indexed_name()))
64      continue;
65
66    scoped_ptr<AppResult> result(
67        new AppResult(profile_, (*app_it)->app_id(), list_controller_));
68    result->UpdateFromMatch((*app_it)->indexed_name(), match);
69    Add(result.PassAs<ChromeSearchResult>());
70  }
71}
72
73void AppSearchProvider::Stop() {}
74
75void AppSearchProvider::AddApps(const ExtensionSet* extensions,
76                                ExtensionService* service) {
77  for (ExtensionSet::const_iterator iter = extensions->begin();
78       iter != extensions->end(); ++iter) {
79    const extensions::Extension* app = iter->get();
80
81    if (!app->ShouldDisplayInAppLauncher())
82      continue;
83
84    if (profile_->IsOffTheRecord() &&
85        !service->CanLoadInIncognito(app))
86      continue;
87    apps_.push_back(new App(app));
88  }
89}
90
91void AppSearchProvider::RefreshApps() {
92  ExtensionService* extension_service =
93      extensions::ExtensionSystemFactory::GetForProfile(profile_)->
94      extension_service();
95  if (!extension_service)
96    return;  // During testing, there is no extension service.
97
98  apps_.clear();
99
100  AddApps(extension_service->extensions(), extension_service);
101  AddApps(extension_service->disabled_extensions(), extension_service);
102  AddApps(extension_service->terminated_extensions(), extension_service);
103}
104
105void AppSearchProvider::Observe(int type,
106                                const content::NotificationSource& source,
107                                const content::NotificationDetails& detaila) {
108  RefreshApps();
109}
110
111}  // namespace app_list
112