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.
5 #include "chrome/browser/ui/app_list/app_list_view_delegate.h"
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 "grit/theme_resources.h"
38 #include "ui/app_list/app_list_switches.h"
39 #include "ui/app_list/app_list_view_delegate_observer.h"
40 #include "ui/app_list/search_box_model.h"
41 #include "ui/app_list/speech_ui_model.h"
42 #include "ui/base/resource/resource_bundle.h"
45 #include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h"
49 #include "chrome/browser/web_applications/web_app_win.h"
54 const int kAutoLaunchDefaultTimeoutSec
= 3;
57 void CreateShortcutInWebAppDir(
58 const base::FilePath
& app_data_dir
,
59 base::Callback
<void(const base::FilePath
&)> callback
,
60 const ShellIntegration::ShortcutInfo
& info
) {
61 content::BrowserThread::PostTaskAndReplyWithResult(
62 content::BrowserThread::FILE,
64 base::Bind(web_app::CreateShortcutInWebAppDir
, app_data_dir
, info
),
69 void PopulateUsers(const ProfileInfoCache
& profile_info
,
70 const base::FilePath
& active_profile_path
,
71 app_list::AppListViewDelegate::Users
* users
) {
73 const size_t count
= profile_info
.GetNumberOfProfiles();
74 for (size_t i
= 0; i
< count
; ++i
) {
75 // Don't display managed users.
76 if (profile_info
.ProfileIsManagedAtIndex(i
))
79 app_list::AppListViewDelegate::User user
;
80 user
.name
= profile_info
.GetNameOfProfileAtIndex(i
);
81 user
.email
= profile_info
.GetUserNameOfProfileAtIndex(i
);
82 user
.profile_path
= profile_info
.GetPathOfProfileAtIndex(i
);
83 user
.active
= active_profile_path
== user
.profile_path
;
84 users
->push_back(user
);
90 AppListViewDelegate::AppListViewDelegate(Profile
* profile
,
91 AppListControllerDelegate
* controller
)
92 : controller_(controller
),
96 RegisterForNotifications();
97 g_browser_process
->profile_manager()->GetProfileInfoCache().AddObserver(this);
98 OnProfileChanged(); // sets model_
99 app_list::StartPageService
* service
=
100 app_list::StartPageService::Get(profile_
);
102 service
->AddObserver(this);
104 // Hotword listening is on by default in ChromeOS right now. Here shouldn't
105 // use the current state in the webui because it will be changed to 'hotword
106 // listening' state from 'ready' after the view is initialized.
107 speech_ui_
.reset(new app_list::SpeechUIModel(
108 #if defined(OS_CHROMEOS)
109 app_list::switches::IsVoiceSearchEnabled() ?
110 app_list::SPEECH_RECOGNITION_HOTWORD_LISTENING
:
112 app_list::SPEECH_RECOGNITION_OFF
));
114 #if defined(GOOGLE_CHROME_BUILD)
115 speech_ui_
->set_logo(
116 *ui::ResourceBundle::GetSharedInstance().
117 GetImageSkiaNamed(IDR_APP_LIST_GOOGLE_LOGO_VOICE_SEARCH
));
121 AppListViewDelegate::~AppListViewDelegate() {
122 app_list::StartPageService
* service
=
123 app_list::StartPageService::Get(profile_
);
125 service
->RemoveObserver(this);
127 profile_manager()->GetProfileInfoCache().RemoveObserver(this);
130 void AppListViewDelegate::RegisterForNotifications() {
131 registrar_
.RemoveAll();
134 registrar_
.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL
,
135 content::NotificationService::AllSources());
136 registrar_
.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED
,
137 content::NotificationService::AllSources());
138 registrar_
.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT
,
139 content::NotificationService::AllSources());
142 void AppListViewDelegate::OnProfileChanged() {
143 model_
= app_list::AppListSyncableServiceFactory::GetForProfile(
146 search_controller_
.reset(new app_list::SearchController(
147 profile_
, model_
->search_box(), model_
->results(), controller_
));
149 signin_delegate_
.SetProfile(profile_
);
152 app_sync_ui_state_watcher_
.reset(new AppSyncUIStateWatcher(profile_
, model_
));
155 // Don't populate the app list users if we are on the ash desktop.
156 chrome::HostDesktopType desktop
= chrome::GetHostDesktopTypeForNativeWindow(
157 controller_
->GetAppListWindow());
158 if (desktop
== chrome::HOST_DESKTOP_TYPE_ASH
)
161 // Populate the app list users.
162 PopulateUsers(g_browser_process
->profile_manager()->GetProfileInfoCache(),
163 profile_
->GetPath(), &users_
);
165 FOR_EACH_OBSERVER(app_list::AppListViewDelegateObserver
,
167 OnProfilesChanged());
170 bool AppListViewDelegate::ForceNativeDesktop() const {
171 return controller_
->ForceNativeDesktop();
174 void AppListViewDelegate::SetProfileByPath(const base::FilePath
& profile_path
) {
177 // The profile must be loaded before this is called.
179 g_browser_process
->profile_manager()->GetProfileByPath(profile_path
);
182 RegisterForNotifications();
186 // Clear search query.
187 model_
->search_box()->SetText(base::string16());
190 app_list::AppListModel
* AppListViewDelegate::GetModel() {
194 app_list::SigninDelegate
* AppListViewDelegate::GetSigninDelegate() {
195 return &signin_delegate_
;
198 app_list::SpeechUIModel
* AppListViewDelegate::GetSpeechUI() {
199 return speech_ui_
.get();
202 void AppListViewDelegate::GetShortcutPathForApp(
203 const std::string
& app_id
,
204 const base::Callback
<void(const base::FilePath
&)>& callback
) {
206 ExtensionService
* service
= profile_
->GetExtensionService();
208 const extensions::Extension
* extension
=
209 service
->GetInstalledExtension(app_id
);
211 callback
.Run(base::FilePath());
215 base::FilePath
app_data_dir(
216 web_app::GetWebAppDataDirectory(profile_
->GetPath(),
220 web_app::UpdateShortcutInfoAndIconForApp(
223 base::Bind(CreateShortcutInWebAppDir
, app_data_dir
, callback
));
225 callback
.Run(base::FilePath());
229 void AppListViewDelegate::StartSearch() {
230 if (search_controller_
)
231 search_controller_
->Start();
234 void AppListViewDelegate::StopSearch() {
235 if (search_controller_
)
236 search_controller_
->Stop();
239 void AppListViewDelegate::OpenSearchResult(
240 app_list::SearchResult
* result
,
242 search_controller_
->OpenResult(result
, event_flags
);
245 void AppListViewDelegate::InvokeSearchResultAction(
246 app_list::SearchResult
* result
,
249 search_controller_
->InvokeResultAction(result
, action_index
, event_flags
);
252 base::TimeDelta
AppListViewDelegate::GetAutoLaunchTimeout() {
253 return auto_launch_timeout_
;
256 void AppListViewDelegate::AutoLaunchCanceled() {
257 auto_launch_timeout_
= base::TimeDelta();
260 void AppListViewDelegate::ViewInitialized() {
261 content::WebContents
* contents
= GetSpeechRecognitionContents();
263 contents
->GetWebUI()->CallJavascriptFunction(
264 "appList.startPage.onAppListShown");
268 void AppListViewDelegate::Dismiss() {
269 controller_
->DismissView();
272 void AppListViewDelegate::ViewClosing() {
273 controller_
->ViewClosing();
275 content::WebContents
* contents
= GetSpeechRecognitionContents();
277 contents
->GetWebUI()->CallJavascriptFunction(
278 "appList.startPage.onAppListHidden");
282 gfx::ImageSkia
AppListViewDelegate::GetWindowIcon() {
283 return controller_
->GetWindowIcon();
286 void AppListViewDelegate::OpenSettings() {
287 ExtensionService
* service
= profile_
->GetExtensionService();
289 const extensions::Extension
* extension
= service
->GetInstalledExtension(
290 extension_misc::kSettingsAppId
);
292 controller_
->ActivateApp(profile_
,
294 AppListControllerDelegate::LAUNCH_FROM_UNKNOWN
,
298 void AppListViewDelegate::OpenHelp() {
299 chrome::HostDesktopType desktop
= chrome::GetHostDesktopTypeForNativeWindow(
300 controller_
->GetAppListWindow());
301 chrome::ScopedTabbedBrowserDisplayer
displayer(profile_
, desktop
);
302 content::OpenURLParams
params(GURL(chrome::kAppLauncherHelpURL
),
305 content::PAGE_TRANSITION_LINK
,
307 displayer
.browser()->OpenURL(params
);
310 void AppListViewDelegate::OpenFeedback() {
311 chrome::HostDesktopType desktop
= chrome::GetHostDesktopTypeForNativeWindow(
312 controller_
->GetAppListWindow());
313 Browser
* browser
= chrome::FindTabbedBrowser(profile_
, false, desktop
);
314 chrome::ShowFeedbackPage(browser
, std::string(),
315 chrome::kAppLauncherCategoryTag
);
318 void AppListViewDelegate::ToggleSpeechRecognition() {
319 app_list::StartPageService
* service
=
320 app_list::StartPageService::Get(profile_
);
322 service
->ToggleSpeechRecognition();
325 void AppListViewDelegate::ShowForProfileByPath(
326 const base::FilePath
& profile_path
) {
327 controller_
->ShowForProfileByPath(profile_path
);
330 void AppListViewDelegate::OnSpeechResult(const base::string16
& result
,
332 speech_ui_
->SetSpeechResult(result
, is_final
);
334 auto_launch_timeout_
= base::TimeDelta::FromSeconds(
335 kAutoLaunchDefaultTimeoutSec
);
336 model_
->search_box()->SetText(result
);
340 void AppListViewDelegate::OnSpeechSoundLevelChanged(int16 level
) {
341 speech_ui_
->UpdateSoundLevel(level
);
344 void AppListViewDelegate::OnSpeechRecognitionStateChanged(
345 app_list::SpeechRecognitionState new_state
) {
346 speech_ui_
->SetSpeechRecognitionState(new_state
);
349 void AppListViewDelegate::Observe(
351 const content::NotificationSource
& source
,
352 const content::NotificationDetails
& details
) {
356 void AppListViewDelegate::OnProfileAdded(const base::FilePath
& profile_path
) {
360 void AppListViewDelegate::OnProfileWasRemoved(
361 const base::FilePath
& profile_path
, const base::string16
& profile_name
) {
365 void AppListViewDelegate::OnProfileNameChanged(
366 const base::FilePath
& profile_path
,
367 const base::string16
& old_profile_name
) {
371 content::WebContents
* AppListViewDelegate::GetStartPageContents() {
372 app_list::StartPageService
* service
=
373 app_list::StartPageService::Get(profile_
);
377 return service
->GetStartPageContents();
380 content::WebContents
* AppListViewDelegate::GetSpeechRecognitionContents() {
381 app_list::StartPageService
* service
=
382 app_list::StartPageService::Get(profile_
);
386 return service
->GetSpeechRecognitionContents();
389 const app_list::AppListViewDelegate::Users
&
390 AppListViewDelegate::GetUsers() const {
394 void AppListViewDelegate::AddObserver(
395 app_list::AppListViewDelegateObserver
* observer
) {
396 observers_
.AddObserver(observer
);
399 void AppListViewDelegate::RemoveObserver(
400 app_list::AppListViewDelegateObserver
* observer
) {
401 observers_
.RemoveObserver(observer
);