app_list_view_delegate.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1// Copyright (c) 2012 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/app_list_view_delegate.h"
6
7#include <vector>
8
9#include "base/callback.h"
10#include "base/files/file_path.h"
11#include "base/stl_util.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/chrome_notification_types.h"
14#include "chrome/browser/extensions/extension_service.h"
15#include "chrome/browser/feedback/feedback_util.h"
16#include "chrome/browser/profiles/profile_info_cache.h"
17#include "chrome/browser/profiles/profile_manager.h"
18#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
19#include "chrome/browser/ui/app_list/apps_model_builder.h"
20#include "chrome/browser/ui/app_list/chrome_app_list_item.h"
21#include "chrome/browser/ui/app_list/search/search_controller.h"
22#include "chrome/browser/ui/browser_finder.h"
23#include "chrome/browser/ui/chrome_pages.h"
24#include "chrome/browser/ui/host_desktop.h"
25#include "chrome/browser/ui/web_applications/web_app_ui.h"
26#include "chrome/browser/web_applications/web_app.h"
27#include "chrome/common/extensions/extension_constants.h"
28#include "chrome/common/url_constants.h"
29#include "content/public/browser/browser_thread.h"
30#include "content/public/browser/notification_source.h"
31#include "content/public/browser/page_navigator.h"
32#include "content/public/browser/user_metrics.h"
33#include "ui/app_list/search_box_model.h"
34
35#if defined(USE_ASH)
36#include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h"
37#endif
38
39#if defined(OS_WIN)
40#include "chrome/browser/web_applications/web_app_win.h"
41#endif
42
43namespace {
44
45#if defined(OS_WIN)
46void CreateShortcutInWebAppDir(
47    const base::FilePath& app_data_dir,
48    base::Callback<void(const base::FilePath&)> callback,
49    const ShellIntegration::ShortcutInfo& info) {
50  content::BrowserThread::PostTaskAndReplyWithResult(
51      content::BrowserThread::FILE,
52      FROM_HERE,
53      base::Bind(web_app::CreateShortcutInWebAppDir, app_data_dir, info),
54      callback);
55}
56#endif
57
58void PopulateUsers(const ProfileInfoCache& profile_info,
59                   const base::FilePath& active_profile_path,
60                   app_list::AppListModel::Users* users) {
61  const size_t count = profile_info.GetNumberOfProfiles();
62  for (size_t i = 0; i < count; ++i) {
63    // Don't display managed users.
64    if (profile_info.ProfileIsManagedAtIndex(i))
65      continue;
66
67    app_list::AppListModel::User user;
68    user.name = profile_info.GetNameOfProfileAtIndex(i);
69    user.email = profile_info.GetUserNameOfProfileAtIndex(i);
70    user.profile_path = profile_info.GetPathOfProfileAtIndex(i);
71    user.active = active_profile_path == user.profile_path;
72    users->push_back(user);
73  }
74}
75
76}  // namespace
77
78AppListViewDelegate::AppListViewDelegate(AppListControllerDelegate* controller,
79                                         Profile* profile)
80    : controller_(controller),
81      profile_(profile),
82      model_(NULL) {
83  RegisterForNotifications();
84  g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver(this);
85}
86
87AppListViewDelegate::~AppListViewDelegate() {
88  g_browser_process->
89      profile_manager()->GetProfileInfoCache().RemoveObserver(this);
90}
91
92void AppListViewDelegate::RegisterForNotifications() {
93  registrar_.RemoveAll();
94  DCHECK(profile_);
95
96  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
97                 content::Source<Profile>(profile_));
98  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
99                 content::Source<Profile>(profile_));
100  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
101                 content::Source<Profile>(profile_));
102}
103
104void AppListViewDelegate::OnProfileChanged() {
105  search_controller_.reset(new app_list::SearchController(
106      profile_, model_->search_box(), model_->results(), controller_.get()));
107
108  signin_delegate_.SetProfile(profile_);
109
110#if defined(USE_ASH)
111  app_sync_ui_state_watcher_.reset(new AppSyncUIStateWatcher(profile_,
112                                                             model_));
113#endif
114
115  model_->SetSignedIn(!GetSigninDelegate()->NeedSignin());
116
117  // Don't populate the app list users if we are on the ash desktop.
118  chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow(
119      controller_->GetAppListWindow());
120  if (desktop == chrome::HOST_DESKTOP_TYPE_ASH)
121    return;
122
123  // Populate the app list users.
124  app_list::AppListModel::Users users;
125  PopulateUsers(g_browser_process->profile_manager()->GetProfileInfoCache(),
126                profile_->GetPath(), &users);
127  model_->SetUsers(users);
128}
129
130void AppListViewDelegate::SetProfileByPath(const base::FilePath& profile_path) {
131  DCHECK(model_);
132
133  // The profile must be loaded before this is called.
134  profile_ =
135      g_browser_process->profile_manager()->GetProfileByPath(profile_path);
136  DCHECK(profile_);
137
138  RegisterForNotifications();
139
140  apps_builder_->SwitchProfile(profile_);
141
142  OnProfileChanged();
143
144  // Clear search query.
145  model_->search_box()->SetText(base::string16());
146}
147
148void AppListViewDelegate::InitModel(app_list::AppListModel* model) {
149  DCHECK(!model_);
150  DCHECK(model);
151  model_ = model;
152
153  // Initialize apps model.
154  apps_builder_.reset(new AppsModelBuilder(profile_,
155                                           model->apps(),
156                                           controller_.get()));
157
158  // Initialize the profile information in the app list menu.
159  OnProfileChanged();
160}
161
162app_list::SigninDelegate* AppListViewDelegate::GetSigninDelegate() {
163  return &signin_delegate_;
164}
165
166void AppListViewDelegate::ActivateAppListItem(
167    app_list::AppListItemModel* item,
168    int event_flags) {
169  content::RecordAction(content::UserMetricsAction("AppList_ClickOnApp"));
170  static_cast<ChromeAppListItem*>(item)->Activate(event_flags);
171}
172
173void AppListViewDelegate::GetShortcutPathForApp(
174    const std::string& app_id,
175    const base::Callback<void(const base::FilePath&)>& callback) {
176#if defined(OS_WIN)
177  ExtensionService* service = profile_->GetExtensionService();
178  DCHECK(service);
179  const extensions::Extension* extension =
180      service->GetInstalledExtension(app_id);
181  if (!extension) {
182    callback.Run(base::FilePath());
183    return;
184  }
185
186  base::FilePath app_data_dir(
187      web_app::GetWebAppDataDirectory(profile_->GetPath(),
188                                      extension->id(),
189                                      GURL()));
190
191  web_app::UpdateShortcutInfoAndIconForApp(
192      *extension,
193      profile_,
194      base::Bind(CreateShortcutInWebAppDir, app_data_dir, callback));
195#else
196  callback.Run(base::FilePath());
197#endif
198}
199
200void AppListViewDelegate::StartSearch() {
201  if (search_controller_)
202    search_controller_->Start();
203}
204
205void AppListViewDelegate::StopSearch() {
206  if (search_controller_)
207    search_controller_->Stop();
208}
209
210void AppListViewDelegate::OpenSearchResult(
211    app_list::SearchResult* result,
212    int event_flags) {
213  search_controller_->OpenResult(result, event_flags);
214}
215
216void AppListViewDelegate::InvokeSearchResultAction(
217    app_list::SearchResult* result,
218    int action_index,
219    int event_flags) {
220  search_controller_->InvokeResultAction(result, action_index, event_flags);
221}
222
223void AppListViewDelegate::Dismiss()  {
224  controller_->DismissView();
225}
226
227void AppListViewDelegate::ViewClosing() {
228  controller_->ViewClosing();
229}
230
231gfx::ImageSkia AppListViewDelegate::GetWindowIcon() {
232  return controller_->GetWindowIcon();
233}
234
235void AppListViewDelegate::OpenSettings() {
236  ExtensionService* service = profile_->GetExtensionService();
237  DCHECK(service);
238  const extensions::Extension* extension = service->GetInstalledExtension(
239      extension_misc::kSettingsAppId);
240  DCHECK(extension);
241  controller_->ActivateApp(profile_,
242                           extension,
243                           AppListControllerDelegate::LAUNCH_FROM_UNKNOWN,
244                           0);
245}
246
247void AppListViewDelegate::OpenHelp() {
248  chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow(
249      controller_->GetAppListWindow());
250  Browser* browser = chrome::FindOrCreateTabbedBrowser(
251      profile_, desktop);
252  browser->OpenURL(content::OpenURLParams(GURL(chrome::kAppLauncherHelpURL),
253                                          content::Referrer(),
254                                          NEW_FOREGROUND_TAB,
255                                          content::PAGE_TRANSITION_LINK,
256                                          false));
257}
258
259void AppListViewDelegate::OpenFeedback() {
260  chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow(
261      controller_->GetAppListWindow());
262  Browser* browser = chrome::FindOrCreateTabbedBrowser(
263      profile_, desktop);
264  chrome::ShowFeedbackPage(browser, std::string(),
265                           chrome::kAppLauncherCategoryTag);
266}
267
268void AppListViewDelegate::ShowForProfileByPath(
269    const base::FilePath& profile_path) {
270  controller_->ShowForProfileByPath(profile_path);
271}
272
273void AppListViewDelegate::Observe(
274    int type,
275    const content::NotificationSource& source,
276    const content::NotificationDetails& details) {
277  OnProfileChanged();
278}
279
280void AppListViewDelegate::OnProfileAdded(const base::FilePath& profile_path) {
281  OnProfileChanged();
282}
283
284void AppListViewDelegate::OnProfileWasRemoved(
285    const base::FilePath& profile_path, const base::string16& profile_name) {
286  OnProfileChanged();
287}
288
289void AppListViewDelegate::OnProfileNameChanged(
290    const base::FilePath& profile_path,
291    const base::string16& old_profile_name) {
292  OnProfileChanged();
293}
294