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/app_list_view_delegate_observer.h" 38#include "ui/app_list/search_box_model.h" 39#include "ui/app_list/speech_ui_model.h" 40 41#if defined(USE_ASH) 42#include "chrome/browser/ui/ash/app_list/app_sync_ui_state_watcher.h" 43#endif 44 45#if defined(OS_WIN) 46#include "chrome/browser/web_applications/web_app_win.h" 47#endif 48 49namespace { 50 51#if defined(OS_WIN) 52void CreateShortcutInWebAppDir( 53 const base::FilePath& app_data_dir, 54 base::Callback<void(const base::FilePath&)> callback, 55 const ShellIntegration::ShortcutInfo& info) { 56 content::BrowserThread::PostTaskAndReplyWithResult( 57 content::BrowserThread::FILE, 58 FROM_HERE, 59 base::Bind(web_app::CreateShortcutInWebAppDir, app_data_dir, info), 60 callback); 61} 62#endif 63 64void PopulateUsers(const ProfileInfoCache& profile_info, 65 const base::FilePath& active_profile_path, 66 app_list::AppListViewDelegate::Users* users) { 67 users->clear(); 68 const size_t count = profile_info.GetNumberOfProfiles(); 69 for (size_t i = 0; i < count; ++i) { 70 // Don't display managed users. 71 if (profile_info.ProfileIsManagedAtIndex(i)) 72 continue; 73 74 app_list::AppListViewDelegate::User user; 75 user.name = profile_info.GetNameOfProfileAtIndex(i); 76 user.email = profile_info.GetUserNameOfProfileAtIndex(i); 77 user.profile_path = profile_info.GetPathOfProfileAtIndex(i); 78 user.active = active_profile_path == user.profile_path; 79 users->push_back(user); 80 } 81} 82 83} // namespace 84 85AppListViewDelegate::AppListViewDelegate(Profile* profile, 86 AppListControllerDelegate* controller) 87 : controller_(controller), 88 profile_(profile), 89 model_(NULL) { 90 CHECK(controller_); 91 RegisterForNotifications(); 92 g_browser_process->profile_manager()->GetProfileInfoCache().AddObserver(this); 93 OnProfileChanged(); // sets model_ 94 app_list::StartPageService* service = 95 app_list::StartPageService::Get(profile_); 96 if (service) 97 service->AddObserver(this); 98} 99 100AppListViewDelegate::~AppListViewDelegate() { 101 app_list::StartPageService* service = 102 app_list::StartPageService::Get(profile_); 103 if (service) 104 service->RemoveObserver(this); 105 g_browser_process-> 106 profile_manager()->GetProfileInfoCache().RemoveObserver(this); 107} 108 109void AppListViewDelegate::RegisterForNotifications() { 110 registrar_.RemoveAll(); 111 DCHECK(profile_); 112 113 registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, 114 content::NotificationService::AllSources()); 115 registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED, 116 content::NotificationService::AllSources()); 117 registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, 118 content::NotificationService::AllSources()); 119} 120 121void AppListViewDelegate::OnProfileChanged() { 122 model_ = app_list::AppListSyncableServiceFactory::GetForProfile( 123 profile_)->model(); 124 125 search_controller_.reset(new app_list::SearchController( 126 profile_, model_->search_box(), model_->results(), controller_)); 127 128 signin_delegate_.SetProfile(profile_); 129 130#if defined(USE_ASH) 131 app_sync_ui_state_watcher_.reset(new AppSyncUIStateWatcher(profile_, model_)); 132#endif 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 FOR_EACH_OBSERVER(app_list::AppListViewDelegateObserver, 145 observers_, 146 OnProfilesChanged()); 147} 148 149bool AppListViewDelegate::ForceNativeDesktop() const { 150 return controller_->ForceNativeDesktop(); 151} 152 153void AppListViewDelegate::SetProfileByPath(const base::FilePath& profile_path) { 154 DCHECK(model_); 155 156 // The profile must be loaded before this is called. 157 profile_ = 158 g_browser_process->profile_manager()->GetProfileByPath(profile_path); 159 DCHECK(profile_); 160 161 RegisterForNotifications(); 162 163 OnProfileChanged(); 164 165 // Clear search query. 166 model_->search_box()->SetText(base::string16()); 167} 168 169app_list::AppListModel* AppListViewDelegate::GetModel() { 170 return model_; 171} 172 173app_list::SigninDelegate* AppListViewDelegate::GetSigninDelegate() { 174 return &signin_delegate_; 175} 176 177app_list::SpeechUIModel* AppListViewDelegate::GetSpeechUI() { 178 return &speech_ui_; 179} 180 181void AppListViewDelegate::GetShortcutPathForApp( 182 const std::string& app_id, 183 const base::Callback<void(const base::FilePath&)>& callback) { 184#if defined(OS_WIN) 185 ExtensionService* service = profile_->GetExtensionService(); 186 DCHECK(service); 187 const extensions::Extension* extension = 188 service->GetInstalledExtension(app_id); 189 if (!extension) { 190 callback.Run(base::FilePath()); 191 return; 192 } 193 194 base::FilePath app_data_dir( 195 web_app::GetWebAppDataDirectory(profile_->GetPath(), 196 extension->id(), 197 GURL())); 198 199 web_app::UpdateShortcutInfoAndIconForApp( 200 *extension, 201 profile_, 202 base::Bind(CreateShortcutInWebAppDir, app_data_dir, callback)); 203#else 204 callback.Run(base::FilePath()); 205#endif 206} 207 208void AppListViewDelegate::StartSearch() { 209 if (search_controller_) 210 search_controller_->Start(); 211} 212 213void AppListViewDelegate::StopSearch() { 214 if (search_controller_) 215 search_controller_->Stop(); 216} 217 218void AppListViewDelegate::OpenSearchResult( 219 app_list::SearchResult* result, 220 int event_flags) { 221 search_controller_->OpenResult(result, event_flags); 222} 223 224void AppListViewDelegate::InvokeSearchResultAction( 225 app_list::SearchResult* result, 226 int action_index, 227 int event_flags) { 228 search_controller_->InvokeResultAction(result, action_index, event_flags); 229} 230 231void AppListViewDelegate::Dismiss() { 232 controller_->DismissView(); 233} 234 235void AppListViewDelegate::ViewClosing() { 236 controller_->ViewClosing(); 237} 238 239gfx::ImageSkia AppListViewDelegate::GetWindowIcon() { 240 return controller_->GetWindowIcon(); 241} 242 243void AppListViewDelegate::OpenSettings() { 244 ExtensionService* service = profile_->GetExtensionService(); 245 DCHECK(service); 246 const extensions::Extension* extension = service->GetInstalledExtension( 247 extension_misc::kSettingsAppId); 248 DCHECK(extension); 249 controller_->ActivateApp(profile_, 250 extension, 251 AppListControllerDelegate::LAUNCH_FROM_UNKNOWN, 252 0); 253} 254 255void AppListViewDelegate::OpenHelp() { 256 chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow( 257 controller_->GetAppListWindow()); 258 chrome::ScopedTabbedBrowserDisplayer displayer(profile_, desktop); 259 content::OpenURLParams params(GURL(chrome::kAppLauncherHelpURL), 260 content::Referrer(), 261 NEW_FOREGROUND_TAB, 262 content::PAGE_TRANSITION_LINK, 263 false); 264 displayer.browser()->OpenURL(params); 265} 266 267void AppListViewDelegate::OpenFeedback() { 268 chrome::HostDesktopType desktop = chrome::GetHostDesktopTypeForNativeWindow( 269 controller_->GetAppListWindow()); 270 Browser* browser = chrome::FindTabbedBrowser(profile_, false, desktop); 271 chrome::ShowFeedbackPage(browser, std::string(), 272 chrome::kAppLauncherCategoryTag); 273} 274 275void AppListViewDelegate::ToggleSpeechRecognition() { 276 app_list::StartPageService* service = 277 app_list::StartPageService::Get(profile_); 278 if (service) 279 service->ToggleSpeechRecognition(); 280} 281 282void AppListViewDelegate::ShowForProfileByPath( 283 const base::FilePath& profile_path) { 284 controller_->ShowForProfileByPath(profile_path); 285} 286 287void AppListViewDelegate::OnSpeechResult(const base::string16& result, 288 bool is_final) { 289 speech_ui_.SetSpeechResult(result, is_final); 290 if (is_final) 291 model_->search_box()->SetText(result); 292} 293 294void AppListViewDelegate::OnSpeechSoundLevelChanged(int16 level) { 295 speech_ui_.UpdateSoundLevel(level); 296} 297 298void AppListViewDelegate::OnSpeechRecognitionStateChanged( 299 app_list::SpeechRecognitionState new_state) { 300 speech_ui_.SetSpeechRecognitionState(new_state); 301} 302 303void AppListViewDelegate::Observe( 304 int type, 305 const content::NotificationSource& source, 306 const content::NotificationDetails& details) { 307 OnProfileChanged(); 308} 309 310void AppListViewDelegate::OnProfileAdded(const base::FilePath& profile_path) { 311 OnProfileChanged(); 312} 313 314void AppListViewDelegate::OnProfileWasRemoved( 315 const base::FilePath& profile_path, const base::string16& profile_name) { 316 OnProfileChanged(); 317} 318 319void AppListViewDelegate::OnProfileNameChanged( 320 const base::FilePath& profile_path, 321 const base::string16& old_profile_name) { 322 OnProfileChanged(); 323} 324 325content::WebContents* AppListViewDelegate::GetStartPageContents() { 326 app_list::StartPageService* service = 327 app_list::StartPageService::Get(profile_); 328 if (!service) 329 return NULL; 330 331 return service->contents(); 332} 333 334const app_list::AppListViewDelegate::Users& 335AppListViewDelegate::GetUsers() const { 336 return users_; 337} 338 339void AppListViewDelegate::AddObserver( 340 app_list::AppListViewDelegateObserver* observer) { 341 observers_.AddObserver(observer); 342} 343 344void AppListViewDelegate::RemoveObserver( 345 app_list::AppListViewDelegateObserver* observer) { 346 observers_.RemoveObserver(observer); 347} 348