app_list_view_delegate.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/app_list_service.h"
20#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
21#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
22#include "chrome/browser/ui/app_list/search/search_controller.h"
23#include "chrome/browser/ui/app_list/start_page_service.h"
24#include "chrome/browser/ui/browser_finder.h"
25#include "chrome/browser/ui/chrome_pages.h"
26#include "chrome/browser/ui/host_desktop.h"
27#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
28#include "chrome/browser/ui/web_applications/web_app_ui.h"
29#include "chrome/browser/web_applications/web_app.h"
30#include "chrome/common/extensions/extension_constants.h"
31#include "chrome/common/url_constants.h"
32#include "content/public/browser/browser_thread.h"
33#include "content/public/browser/notification_service.h"
34#include "content/public/browser/notification_source.h"
35#include "content/public/browser/page_navigator.h"
36#include "content/public/browser/user_metrics.h"
37#include "ui/app_list/search_box_model.h"
38
39#if defined(USE_ASH)
40#include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h"
41#endif
42
43#if defined(OS_WIN)
44#include "chrome/browser/web_applications/web_app_win.h"
45#endif
46
47namespace {
48
49#if defined(OS_WIN)
50void CreateShortcutInWebAppDir(
51    const base::FilePath& app_data_dir,
52    base::Callback<void(const base::FilePath&)> callback,
53    const ShellIntegration::ShortcutInfo& info) {
54  content::BrowserThread::PostTaskAndReplyWithResult(
55      content::BrowserThread::FILE,
56      FROM_HERE,
57      base::Bind(web_app::CreateShortcutInWebAppDir, app_data_dir, info),
58      callback);
59}
60#endif
61
62void PopulateUsers(const ProfileInfoCache& profile_info,
63                   const base::FilePath& active_profile_path,
64                   app_list::AppListViewDelegate::Users* users) {
65  users->clear();
66  const size_t count = profile_info.GetNumberOfProfiles();
67  for (size_t i = 0; i < count; ++i) {
68    // Don't display managed users.
69    if (profile_info.ProfileIsManagedAtIndex(i))
70      continue;
71
72    app_list::AppListViewDelegate::User user;
73    user.name = profile_info.GetNameOfProfileAtIndex(i);
74    user.email = profile_info.GetUserNameOfProfileAtIndex(i);
75    user.profile_path = profile_info.GetPathOfProfileAtIndex(i);
76    user.active = active_profile_path == user.profile_path;
77    users->push_back(user);
78  }
79}
80
81}  // namespace
82
83AppListViewDelegate::AppListViewDelegate(Profile* profile,
84                                         AppListControllerDelegate* controller)
85    : controller_(controller),
86      profile_(profile),
87      model_(NULL) {
88  CHECK(controller_);
89  RegisterForNotifications();
90  g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver(this);
91  OnProfileChanged();  // sets model_
92  app_list::StartPageService* service =
93      app_list::StartPageService::Get(profile_);
94  if (service)
95    service->AddObserver(this);
96}
97
98AppListViewDelegate::~AppListViewDelegate() {
99  app_list::StartPageService* service =
100      app_list::StartPageService::Get(profile_);
101  if (service)
102    service->RemoveObserver(this);
103  g_browser_process->
104      profile_manager()->GetProfileInfoCache().RemoveObserver(this);
105}
106
107void AppListViewDelegate::RegisterForNotifications() {
108  registrar_.RemoveAll();
109  DCHECK(profile_);
110
111  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
112                 content::NotificationService::AllSources());
113  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
114                 content::NotificationService::AllSources());
115  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
116                 content::NotificationService::AllSources());
117}
118
119void AppListViewDelegate::OnProfileChanged() {
120  model_ = app_list::AppListSyncableServiceFactory::GetForProfile(
121      profile_)->model();
122
123  search_controller_.reset(new app_list::SearchController(
124      profile_, model_->search_box(), model_->results(), controller_));
125
126  signin_delegate_.SetProfile(profile_);
127
128#if defined(USE_ASH)
129  app_sync_ui_state_watcher_.reset(new AppSyncUIStateWatcher(profile_, model_));
130#endif
131
132  model_->SetSignedIn(!GetSigninDelegate()->NeedSignin());
133
134  // Don't populate the app list users if we are on the ash desktop.
135  chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow(
136      controller_->GetAppListWindow());
137  if (desktop == chrome::HOST_DESKTOP_TYPE_ASH)
138    return;
139
140  // Populate the app list users.
141  PopulateUsers(g_browser_process->profile_manager()->GetProfileInfoCache(),
142                profile_->GetPath(), &users_);
143}
144
145bool AppListViewDelegate::ForceNativeDesktop() const {
146  return controller_->ForceNativeDesktop();
147}
148
149void AppListViewDelegate::SetProfileByPath(const base::FilePath& profile_path) {
150  DCHECK(model_);
151
152  // The profile must be loaded before this is called.
153  profile_ =
154      g_browser_process->profile_manager()->GetProfileByPath(profile_path);
155  DCHECK(profile_);
156
157  RegisterForNotifications();
158
159  OnProfileChanged();
160
161  // Clear search query.
162  model_->search_box()->SetText(base::string16());
163}
164
165app_list::AppListModel* AppListViewDelegate::GetModel() {
166  return model_;
167}
168
169app_list::SigninDelegate* AppListViewDelegate::GetSigninDelegate() {
170  return &signin_delegate_;
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  chrome::ScopedTabbedBrowserDisplayer displayer(profile_, desktop);
251  content::OpenURLParams params(GURL(chrome::kAppLauncherHelpURL),
252                                content::Referrer(),
253                                NEW_FOREGROUND_TAB,
254                                content::PAGE_TRANSITION_LINK,
255                                false);
256  displayer.browser()->OpenURL(params);
257}
258
259void AppListViewDelegate::OpenFeedback() {
260  chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow(
261      controller_->GetAppListWindow());
262  Browser* browser = chrome::FindTabbedBrowser(profile_, false, desktop);
263  chrome::ShowFeedbackPage(browser, std::string(),
264                           chrome::kAppLauncherCategoryTag);
265}
266
267void AppListViewDelegate::ToggleSpeechRecognition() {
268  app_list::StartPageService* service =
269      app_list::StartPageService::Get(profile_);
270  if (service)
271    service->ToggleSpeechRecognition();
272}
273
274void AppListViewDelegate::ShowForProfileByPath(
275    const base::FilePath& profile_path) {
276  controller_->ShowForProfileByPath(profile_path);
277}
278
279void AppListViewDelegate::OnSearch(const base::string16& query) {
280  model_->search_box()->SetText(query);
281}
282
283void AppListViewDelegate::OnSpeechRecognitionStateChanged(bool recognizing) {
284  model_->search_box()->SetSpeechRecognitionButtonState(recognizing);
285}
286
287void AppListViewDelegate::Observe(
288    int type,
289    const content::NotificationSource& source,
290    const content::NotificationDetails& details) {
291  OnProfileChanged();
292}
293
294void AppListViewDelegate::OnProfileAdded(const base::FilePath& profile_path) {
295  OnProfileChanged();
296}
297
298void AppListViewDelegate::OnProfileWasRemoved(
299    const base::FilePath& profile_path, const base::string16& profile_name) {
300  OnProfileChanged();
301}
302
303void AppListViewDelegate::OnProfileNameChanged(
304    const base::FilePath& profile_path,
305    const base::string16& old_profile_name) {
306  OnProfileChanged();
307}
308
309content::WebContents* AppListViewDelegate::GetStartPageContents() {
310  app_list::StartPageService* service =
311      app_list::StartPageService::Get(profile_);
312  if (!service)
313    return NULL;
314
315  return service->contents();
316}
317
318const app_list::AppListViewDelegate::Users&
319AppListViewDelegate::GetUsers() const {
320  return users_;
321}
322