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