app_result.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_result.h"
6
7#include "chrome/browser/extensions/extension_service.h"
8#include "chrome/browser/extensions/extension_system_factory.h"
9#include "chrome/browser/extensions/install_tracker.h"
10#include "chrome/browser/extensions/install_tracker_factory.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/ui/app_list/app_context_menu.h"
13#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
14#include "chrome/browser/ui/app_list/search/tokenized_string.h"
15#include "chrome/browser/ui/app_list/search/tokenized_string_match.h"
16#include "chrome/browser/ui/extensions/extension_enable_flow.h"
17#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
18#include "chrome/common/extensions/extension.h"
19#include "chrome/common/extensions/extension_icon_set.h"
20#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
21#include "content/public/browser/user_metrics.h"
22#include "ui/gfx/color_utils.h"
23#include "ui/gfx/image/image_skia_operations.h"
24
25namespace app_list {
26
27AppResult::AppResult(Profile* profile,
28                     const std::string& app_id,
29                     AppListControllerDelegate* controller)
30    : profile_(profile),
31      app_id_(app_id),
32      controller_(controller),
33      install_tracker_(NULL) {
34  set_id(extensions::Extension::GetBaseURLFromExtensionId(app_id_).spec());
35
36  const extensions::Extension* extension =
37      extensions::ExtensionSystem::Get(profile_)->extension_service()
38          ->GetInstalledExtension(app_id_);
39  DCHECK(extension);
40
41  is_platform_app_ = extension->is_platform_app();
42
43  icon_.reset(new extensions::IconImage(
44      profile_,
45      extension,
46      extensions::IconsInfo::GetIcons(extension),
47      extension_misc::EXTENSION_ICON_SMALL,
48      extensions::IconsInfo::GetDefaultAppIcon(),
49      this));
50  UpdateIcon();
51  StartObservingInstall();
52}
53
54AppResult::~AppResult() {
55  StopObservingInstall();
56}
57
58void AppResult::UpdateFromMatch(const TokenizedString& title,
59                                const TokenizedStringMatch& match) {
60  const TokenizedStringMatch::Hits& hits = match.hits();
61
62  Tags tags;
63  tags.reserve(hits.size());
64  for (size_t i = 0; i < hits.size(); ++i)
65    tags.push_back(Tag(Tag::MATCH, hits[i].start(), hits[i].end()));
66
67  set_title(title.text());
68  set_title_tags(tags);
69  set_relevance(match.relevance());
70}
71
72void AppResult::Open(int event_flags) {
73  const extensions::Extension* extension =
74      extensions::ExtensionSystem::Get(profile_)->extension_service()
75          ->GetInstalledExtension(app_id_);
76  if (!extension)
77    return;
78
79  // Check if enable flow is already running or should be started
80  if (RunExtensionEnableFlow())
81    return;
82
83  CoreAppLauncherHandler::RecordAppListSearchLaunch(extension);
84  content::RecordAction(
85      content::UserMetricsAction("AppList_ClickOnAppFromSearch"));
86
87  controller_->ActivateApp(profile_, extension, event_flags);
88}
89
90void AppResult::InvokeAction(int action_index, int event_flags) {}
91
92scoped_ptr<ChromeSearchResult> AppResult::Duplicate() {
93  scoped_ptr<ChromeSearchResult> copy(
94      new AppResult(profile_, app_id_, controller_));
95  copy->set_title(title());
96  copy->set_title_tags(title_tags());
97
98  return copy.Pass();
99}
100
101ChromeSearchResultType AppResult::GetType() {
102  return APP_SEARCH_RESULT;
103}
104
105ui::MenuModel* AppResult::GetContextMenuModel() {
106  if (!context_menu_) {
107    context_menu_.reset(new AppContextMenu(
108        this, profile_, app_id_, controller_, is_platform_app_));
109  }
110
111  return context_menu_->GetMenuModel();
112}
113
114void AppResult::StartObservingInstall() {
115  DCHECK(!install_tracker_);
116
117  install_tracker_ = extensions::InstallTrackerFactory::GetForProfile(profile_);
118  install_tracker_->AddObserver(this);
119}
120
121void AppResult::StopObservingInstall() {
122  if (install_tracker_)
123    install_tracker_->RemoveObserver(this);
124
125  install_tracker_ = NULL;
126}
127
128bool AppResult::RunExtensionEnableFlow() {
129  const ExtensionService* service =
130      extensions::ExtensionSystem::Get(profile_)->extension_service();
131  if (service->IsExtensionEnabledForLauncher(app_id_))
132    return false;
133
134  if (!extension_enable_flow_) {
135    controller_->OnShowExtensionPrompt();
136
137    extension_enable_flow_.reset(new ExtensionEnableFlow(
138        profile_, app_id_, this));
139    extension_enable_flow_->StartForNativeWindow(
140        controller_->GetAppListWindow());
141  }
142  return true;
143}
144
145void AppResult::UpdateIcon() {
146  gfx::ImageSkia icon = icon_->image_skia();
147
148  const ExtensionService* service =
149      extensions::ExtensionSystem::Get(profile_)->extension_service();
150  const bool enabled = service->IsExtensionEnabledForLauncher(app_id_);
151  if (!enabled) {
152    const color_utils::HSL shift = {-1, 0, 0.6};
153    icon = gfx::ImageSkiaOperations::CreateHSLShiftedImage(icon, shift);
154  }
155
156  SetIcon(icon);
157}
158
159void AppResult::OnExtensionIconImageChanged(extensions::IconImage* image) {
160  DCHECK_EQ(icon_.get(), image);
161  UpdateIcon();
162}
163
164void AppResult::ExecuteLaunchCommand(int event_flags) {
165  Open(event_flags);
166}
167
168void AppResult::ExtensionEnableFlowFinished() {
169  extension_enable_flow_.reset();
170  controller_->OnCloseExtensionPrompt();
171
172  // Automatically open app after enabling.
173  Open(ui::EF_NONE);
174}
175
176void AppResult::ExtensionEnableFlowAborted(bool user_initiated) {
177  extension_enable_flow_.reset();
178  controller_->OnCloseExtensionPrompt();
179}
180
181void AppResult::OnBeginExtensionInstall(const std::string& extension_id,
182                                        const std::string& extension_name,
183                                        const gfx::ImageSkia& installing_icon,
184                                        bool is_app,
185                                        bool is_platform_app) {}
186
187void AppResult::OnDownloadProgress(const std::string& extension_id,
188                                   int percent_downloaded) {}
189
190void AppResult::OnInstallFailure(const std::string& extension_id) {}
191
192void AppResult::OnExtensionInstalled(const extensions::Extension* extension) {}
193
194void AppResult::OnExtensionLoaded(const extensions::Extension* extension) {
195  UpdateIcon();
196}
197
198void AppResult::OnExtensionUnloaded(const extensions::Extension* extension) {}
199
200void AppResult::OnExtensionUninstalled(const extensions::Extension* extension) {
201  if (extension->id() != app_id_)
202    return;
203
204  NotifyItemUninstalled();
205}
206
207void AppResult::OnAppsReordered() {}
208
209void AppResult::OnAppInstalledToAppList(const std::string& extension_id) {}
210
211void AppResult::OnShutdown() { StopObservingInstall(); }
212
213}  // namespace app_list
214