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/chromeos/system/ash_system_tray_delegate.h" 6 7 #include <algorithm> 8 #include <set> 9 #include <string> 10 #include <vector> 11 12 #include "ash/ash_switches.h" 13 #include "ash/desktop_background/desktop_background_controller.h" 14 #include "ash/metrics/user_metrics_recorder.h" 15 #include "ash/session_state_delegate.h" 16 #include "ash/session_state_observer.h" 17 #include "ash/shell.h" 18 #include "ash/shell_delegate.h" 19 #include "ash/shell_window_ids.h" 20 #include "ash/system/bluetooth/bluetooth_observer.h" 21 #include "ash/system/date/clock_observer.h" 22 #include "ash/system/drive/drive_observer.h" 23 #include "ash/system/ime/ime_observer.h" 24 #include "ash/system/logout_button/logout_button_observer.h" 25 #include "ash/system/tray/system_tray.h" 26 #include "ash/system/tray/system_tray_delegate.h" 27 #include "ash/system/tray/system_tray_notifier.h" 28 #include "ash/system/tray_accessibility.h" 29 #include "ash/system/tray_caps_lock.h" 30 #include "ash/system/user/login_status.h" 31 #include "ash/system/user/update_observer.h" 32 #include "ash/system/user/user_observer.h" 33 #include "ash/volume_control_delegate.h" 34 #include "ash/wm/lock_state_controller.h" 35 #include "base/bind_helpers.h" 36 #include "base/callback.h" 37 #include "base/command_line.h" 38 #include "base/logging.h" 39 #include "base/memory/weak_ptr.h" 40 #include "base/prefs/pref_service.h" 41 #include "base/strings/stringprintf.h" 42 #include "base/strings/utf_string_conversions.h" 43 #include "base/sys_info.h" 44 #include "base/time/time.h" 45 #include "chrome/browser/browser_process.h" 46 #include "chrome/browser/chrome_notification_types.h" 47 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" 48 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" 49 #include "chrome/browser/chromeos/bluetooth/bluetooth_pairing_dialog.h" 50 #include "chrome/browser/chromeos/charger_replace/charger_replacement_dialog.h" 51 #include "chrome/browser/chromeos/choose_mobile_network_dialog.h" 52 #include "chrome/browser/chromeos/drive/drive_integration_service.h" 53 #include "chrome/browser/chromeos/drive/job_list.h" 54 #include "chrome/browser/chromeos/enrollment_dialog_view.h" 55 #include "chrome/browser/chromeos/input_method/input_method_util.h" 56 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h" 57 #include "chrome/browser/chromeos/login/help_app_launcher.h" 58 #include "chrome/browser/chromeos/login/login_display_host.h" 59 #include "chrome/browser/chromeos/login/login_display_host_impl.h" 60 #include "chrome/browser/chromeos/login/login_wizard.h" 61 #include "chrome/browser/chromeos/login/startup_utils.h" 62 #include "chrome/browser/chromeos/login/supervised_user_manager.h" 63 #include "chrome/browser/chromeos/login/user.h" 64 #include "chrome/browser/chromeos/login/user_adding_screen.h" 65 #include "chrome/browser/chromeos/login/user_manager.h" 66 #include "chrome/browser/chromeos/options/network_config_view.h" 67 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 68 #include "chrome/browser/chromeos/settings/cros_settings.h" 69 #include "chrome/browser/chromeos/sim_dialog_delegate.h" 70 #include "chrome/browser/chromeos/system_key_event_listener.h" 71 #include "chrome/browser/drive/drive_service_interface.h" 72 #include "chrome/browser/feedback/tracing_manager.h" 73 #include "chrome/browser/google/google_util.h" 74 #include "chrome/browser/lifetime/application_lifetime.h" 75 #include "chrome/browser/policy/browser_policy_connector.h" 76 #include "chrome/browser/profiles/profile_manager.h" 77 #include "chrome/browser/ui/ash/volume_controller_chromeos.h" 78 #include "chrome/browser/ui/browser.h" 79 #include "chrome/browser/ui/browser_finder.h" 80 #include "chrome/browser/ui/chrome_pages.h" 81 #include "chrome/browser/ui/host_desktop.h" 82 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" 83 #include "chrome/browser/ui/singleton_tabs.h" 84 #include "chrome/browser/ui/tabs/tab_strip_model.h" 85 #include "chrome/browser/ui/webui/chromeos/charger_replacement_handler.h" 86 #include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h" 87 #include "chrome/browser/upgrade_detector.h" 88 #include "chrome/common/pref_names.h" 89 #include "chrome/common/url_constants.h" 90 #include "chromeos/chromeos_switches.h" 91 #include "chromeos/dbus/dbus_thread_manager.h" 92 #include "chromeos/dbus/session_manager_client.h" 93 #include "chromeos/ime/extension_ime_util.h" 94 #include "chromeos/ime/input_method_manager.h" 95 #include "chromeos/ime/xkeyboard.h" 96 #include "chromeos/login/login_state.h" 97 #include "components/policy/core/common/cloud/cloud_policy_store.h" 98 #include "content/public/browser/browser_thread.h" 99 #include "content/public/browser/notification_observer.h" 100 #include "content/public/browser/notification_service.h" 101 #include "content/public/browser/user_metrics.h" 102 #include "content/public/browser/web_contents.h" 103 #include "device/bluetooth/bluetooth_adapter.h" 104 #include "device/bluetooth/bluetooth_adapter_factory.h" 105 #include "device/bluetooth/bluetooth_device.h" 106 #include "grit/ash_strings.h" 107 #include "grit/generated_resources.h" 108 #include "grit/locale_settings.h" 109 #include "net/base/escape.h" 110 #include "third_party/cros_system_api/dbus/service_constants.h" 111 #include "ui/base/l10n/l10n_util.h" 112 #include "ui/base/l10n/time_format.h" 113 114 using drive::DriveIntegrationService; 115 using drive::DriveIntegrationServiceFactory; 116 117 namespace chromeos { 118 119 namespace { 120 121 // The minimum session length limit that can be set. 122 const int kSessionLengthLimitMinMs = 30 * 1000; // 30 seconds. 123 124 // The maximum session length limit that can be set. 125 const int kSessionLengthLimitMaxMs = 24 * 60 * 60 * 1000; // 24 hours. 126 127 const char kDisplaySettingsSubPageName[] = "display"; 128 const char kDisplayOverscanSettingsSubPageName[] = "displayOverscan"; 129 130 // The URL for the Google Drive settings page. 131 const char kDriveSettingsPageURL[] = "https://drive.google.com"; 132 133 void ExtractIMEInfo(const input_method::InputMethodDescriptor& ime, 134 const input_method::InputMethodUtil& util, 135 ash::IMEInfo* info) { 136 info->id = ime.id(); 137 info->name = util.GetInputMethodLongName(ime); 138 info->medium_name = util.GetInputMethodMediumName(ime); 139 info->short_name = util.GetInputMethodShortName(ime); 140 info->third_party = extension_ime_util::IsExtensionIME(ime.id()); 141 } 142 143 gfx::NativeWindow GetNativeWindowByStatus( 144 ash::user::LoginStatus login_status, 145 bool session_started) { 146 int container_id = 147 (!session_started || 148 login_status == ash::user::LOGGED_IN_NONE || 149 login_status == ash::user::LOGGED_IN_LOCKED) ? 150 ash::internal::kShellWindowId_LockSystemModalContainer : 151 ash::internal::kShellWindowId_SystemModalContainer; 152 return ash::Shell::GetContainer(ash::Shell::GetPrimaryRootWindow(), 153 container_id); 154 } 155 156 // Converts drive::JobInfo to ash::DriveOperationStatus. 157 // If the job is not of type that ash tray is interested, returns false. 158 bool ConvertToDriveOperationStatus(const drive::JobInfo& info, 159 ash::DriveOperationStatus* status) { 160 if (info.job_type == drive::TYPE_DOWNLOAD_FILE) { 161 status->type = ash::DriveOperationStatus::OPERATION_DOWNLOAD; 162 } else if (info.job_type == drive::TYPE_UPLOAD_NEW_FILE || 163 info.job_type == drive::TYPE_UPLOAD_EXISTING_FILE) { 164 status->type = ash::DriveOperationStatus::OPERATION_UPLOAD; 165 } else { 166 return false; 167 } 168 169 if (info.state == drive::STATE_NONE) 170 status->state = ash::DriveOperationStatus::OPERATION_NOT_STARTED; 171 else 172 status->state = ash::DriveOperationStatus::OPERATION_IN_PROGRESS; 173 174 status->id = info.job_id; 175 status->file_path = info.file_path; 176 status->progress = info.num_total_bytes == 0 ? 0.0 : 177 static_cast<double>(info.num_completed_bytes) / 178 static_cast<double>(info.num_total_bytes); 179 return true; 180 } 181 182 // Converts drive::JobInfo that has finished in |error| state 183 // to ash::DriveOperationStatus. 184 // If the job is not of type that ash tray is interested, returns false. 185 bool ConvertToFinishedDriveOperationStatus(const drive::JobInfo& info, 186 drive::FileError error, 187 ash::DriveOperationStatus* status) { 188 if (!ConvertToDriveOperationStatus(info, status)) 189 return false; 190 status->state = (error == drive::FILE_ERROR_OK) ? 191 ash::DriveOperationStatus::OPERATION_COMPLETED : 192 ash::DriveOperationStatus::OPERATION_FAILED; 193 return true; 194 } 195 196 // Converts a list of drive::JobInfo to a list of ash::DriveOperationStatusList. 197 ash::DriveOperationStatusList ConvertToDriveStatusList( 198 const std::vector<drive::JobInfo>& list) { 199 ash::DriveOperationStatusList results; 200 for (size_t i = 0; i < list.size(); ++i) { 201 ash::DriveOperationStatus status; 202 if (ConvertToDriveOperationStatus(list[i], &status)) 203 results.push_back(status); 204 } 205 return results; 206 } 207 208 void BluetoothPowerFailure() { 209 // TODO(sad): Show an error bubble? 210 } 211 212 void BluetoothSetDiscoveringError() { 213 LOG(ERROR) << "BluetoothSetDiscovering failed."; 214 } 215 216 void BluetoothDeviceConnectError( 217 device::BluetoothDevice::ConnectErrorCode error_code) { 218 // TODO(sad): Do something? 219 } 220 221 // Shows the settings sub page in the last active browser. If there is no such 222 // browser, creates a new browser with the settings sub page. 223 void ShowSettingsSubPageForAppropriateBrowser( 224 const std::string& sub_page, 225 Profile* profile) { 226 chrome::ScopedTabbedBrowserDisplayer displayer(profile, 227 chrome::HOST_DESKTOP_TYPE_ASH); 228 chrome::ShowSettingsSubPage(displayer.browser(), sub_page); 229 } 230 231 void ShowNetworkSettingsPage(const std::string& service_path) { 232 std::string page = chrome::kInternetOptionsSubPage; 233 page += "?servicePath=" + net::EscapeUrlEncodedData(service_path, true); 234 content::RecordAction( 235 content::UserMetricsAction("OpenInternetOptionsDialog")); 236 ShowSettingsSubPageForAppropriateBrowser( 237 page, 238 ProfileManager::GetPrimaryUserProfile()); 239 } 240 241 class SystemTrayDelegate : public ash::SystemTrayDelegate, 242 public SessionManagerClient::Observer, 243 public drive::JobListObserver, 244 public content::NotificationObserver, 245 public input_method::InputMethodManager::Observer, 246 public chromeos::LoginState::Observer, 247 public device::BluetoothAdapter::Observer, 248 public SystemKeyEventListener::CapsLockObserver, 249 public policy::CloudPolicyStore::Observer, 250 public ash::SessionStateObserver { 251 public: 252 SystemTrayDelegate() 253 : ui_weak_ptr_factory_( 254 new base::WeakPtrFactory<SystemTrayDelegate>(this)), 255 user_profile_(NULL), 256 clock_type_(base::GetHourClockType()), 257 search_key_mapped_to_(input_method::kSearchKey), 258 screen_locked_(false), 259 have_session_start_time_(false), 260 have_session_length_limit_(false), 261 volume_control_delegate_(new VolumeController()) { 262 // Register notifications on construction so that events such as 263 // PROFILE_CREATED do not get missed if they happen before Initialize(). 264 registrar_.reset(new content::NotificationRegistrar); 265 registrar_->Add(this, 266 chrome::NOTIFICATION_UPGRADE_RECOMMENDED, 267 content::NotificationService::AllSources()); 268 registrar_->Add(this, 269 chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED, 270 content::NotificationService::AllSources()); 271 if (GetUserLoginStatus() == ash::user::LOGGED_IN_NONE) { 272 registrar_->Add(this, 273 chrome::NOTIFICATION_SESSION_STARTED, 274 content::NotificationService::AllSources()); 275 } 276 registrar_->Add(this, 277 chrome::NOTIFICATION_PROFILE_CREATED, 278 content::NotificationService::AllSources()); 279 registrar_->Add(this, 280 chrome::NOTIFICATION_PROFILE_DESTROYED, 281 content::NotificationService::AllSources()); 282 registrar_->Add( 283 this, 284 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER, 285 content::NotificationService::AllSources()); 286 registrar_->Add( 287 this, 288 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK, 289 content::NotificationService::AllSources()); 290 registrar_->Add( 291 this, 292 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE, 293 content::NotificationService::AllSources()); 294 } 295 296 virtual void Initialize() OVERRIDE { 297 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this); 298 299 input_method::InputMethodManager::Get()->AddObserver(this); 300 UpdateClockType(); 301 302 if (SystemKeyEventListener::GetInstance()) 303 SystemKeyEventListener::GetInstance()->AddCapsLockObserver(this); 304 305 device::BluetoothAdapterFactory::GetAdapter( 306 base::Bind(&SystemTrayDelegate::InitializeOnAdapterReady, 307 ui_weak_ptr_factory_->GetWeakPtr())); 308 309 ash::Shell::GetInstance()->session_state_delegate()-> 310 AddSessionStateObserver(this); 311 312 if (LoginState::IsInitialized()) 313 LoginState::Get()->AddObserver(this); 314 } 315 316 virtual void Shutdown() OVERRIDE { 317 } 318 319 void InitializeOnAdapterReady( 320 scoped_refptr<device::BluetoothAdapter> adapter) { 321 bluetooth_adapter_ = adapter; 322 CHECK(bluetooth_adapter_.get()); 323 bluetooth_adapter_->AddObserver(this); 324 325 local_state_registrar_.reset(new PrefChangeRegistrar); 326 local_state_registrar_->Init(g_browser_process->local_state()); 327 328 UpdateSessionStartTime(); 329 UpdateSessionLengthLimit(); 330 331 local_state_registrar_->Add( 332 prefs::kSessionStartTime, 333 base::Bind(&SystemTrayDelegate::UpdateSessionStartTime, 334 base::Unretained(this))); 335 local_state_registrar_->Add( 336 prefs::kSessionLengthLimit, 337 base::Bind(&SystemTrayDelegate::UpdateSessionLengthLimit, 338 base::Unretained(this))); 339 340 policy::BrowserPolicyConnector* policy_connector = 341 g_browser_process->browser_policy_connector(); 342 policy::DeviceCloudPolicyManagerChromeOS* policy_manager = 343 policy_connector->GetDeviceCloudPolicyManager(); 344 if (policy_manager) 345 policy_manager->core()->store()->AddObserver(this); 346 UpdateEnterpriseDomain(); 347 } 348 349 virtual ~SystemTrayDelegate() { 350 // Unregister PrefChangeRegistrars. 351 local_state_registrar_.reset(); 352 user_pref_registrar_.reset(); 353 354 // Unregister content notifications befure destroying any components. 355 registrar_.reset(); 356 357 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this); 358 input_method::InputMethodManager::Get()->RemoveObserver(this); 359 if (SystemKeyEventListener::GetInstance()) 360 SystemKeyEventListener::GetInstance()->RemoveCapsLockObserver(this); 361 bluetooth_adapter_->RemoveObserver(this); 362 ash::Shell::GetInstance()->session_state_delegate()-> 363 RemoveSessionStateObserver(this); 364 LoginState::Get()->RemoveObserver(this); 365 366 // Stop observing Drive operations. 367 UnobserveDriveUpdates(); 368 369 policy::DeviceCloudPolicyManagerChromeOS* policy_manager = 370 g_browser_process->browser_policy_connector()-> 371 GetDeviceCloudPolicyManager(); 372 if (policy_manager) 373 policy_manager->core()->store()->RemoveObserver(this); 374 } 375 376 // Overridden from ash::SystemTrayDelegate: 377 virtual bool GetTrayVisibilityOnStartup() OVERRIDE { 378 // In case of OOBE / sign in screen tray will be shown later. 379 return LoginState::Get()->IsUserLoggedIn(); 380 } 381 382 virtual ash::user::LoginStatus GetUserLoginStatus() const OVERRIDE { 383 // All non-logged in ChromeOS specific LOGGED_IN states map to the same 384 // Ash specific LOGGED_IN state. 385 if (!LoginState::Get()->IsUserLoggedIn()) 386 return ash::user::LOGGED_IN_NONE; 387 388 if (screen_locked_) 389 return ash::user::LOGGED_IN_LOCKED; 390 391 LoginState::LoggedInUserType user_type = 392 LoginState::Get()->GetLoggedInUserType(); 393 switch (user_type) { 394 case LoginState::LOGGED_IN_USER_NONE: 395 return ash::user::LOGGED_IN_NONE; 396 case LoginState::LOGGED_IN_USER_REGULAR: 397 return ash::user::LOGGED_IN_USER; 398 case LoginState::LOGGED_IN_USER_OWNER: 399 return ash::user::LOGGED_IN_OWNER; 400 case LoginState::LOGGED_IN_USER_GUEST: 401 return ash::user::LOGGED_IN_GUEST; 402 case LoginState::LOGGED_IN_USER_RETAIL_MODE: 403 return ash::user::LOGGED_IN_RETAIL_MODE; 404 case LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT: 405 return ash::user::LOGGED_IN_PUBLIC; 406 case LoginState::LOGGED_IN_USER_LOCALLY_MANAGED: 407 return ash::user::LOGGED_IN_LOCALLY_MANAGED; 408 case LoginState::LOGGED_IN_USER_KIOSK_APP: 409 return ash::user::LOGGED_IN_KIOSK_APP; 410 } 411 NOTREACHED(); 412 return ash::user::LOGGED_IN_NONE; 413 } 414 415 virtual bool IsOobeCompleted() const OVERRIDE { 416 if (!base::SysInfo::IsRunningOnChromeOS() && 417 LoginState::Get()->IsUserLoggedIn()) 418 return true; 419 return StartupUtils::IsOobeCompleted(); 420 } 421 422 virtual void ChangeProfilePicture() OVERRIDE { 423 content::RecordAction( 424 content::UserMetricsAction("OpenChangeProfilePictureDialog")); 425 ShowSettingsSubPageForAppropriateBrowser( 426 chrome::kChangeProfilePictureSubPage, 427 ProfileManager::GetActiveUserProfile()); 428 } 429 430 virtual const std::string GetEnterpriseDomain() const OVERRIDE { 431 return enterprise_domain_; 432 } 433 434 virtual const base::string16 GetEnterpriseMessage() const OVERRIDE { 435 if (GetEnterpriseDomain().empty()) 436 return base::string16(); 437 return l10n_util::GetStringFUTF16(IDS_DEVICE_OWNED_BY_NOTICE, 438 UTF8ToUTF16(GetEnterpriseDomain())); 439 } 440 441 virtual const std::string GetLocallyManagedUserManager() const OVERRIDE { 442 if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED) 443 return std::string(); 444 return UserManager::Get()->GetSupervisedUserManager()-> 445 GetManagerDisplayEmail( 446 chromeos::UserManager::Get()->GetActiveUser()->email()); 447 } 448 449 virtual const base::string16 450 GetLocallyManagedUserManagerName() const OVERRIDE { 451 if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED) 452 return base::string16(); 453 return UserManager::Get()->GetSupervisedUserManager()-> 454 GetManagerDisplayName( 455 chromeos::UserManager::Get()->GetActiveUser()->email()); 456 } 457 458 virtual const base::string16 GetLocallyManagedUserMessage() const OVERRIDE { 459 if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED) 460 return base::string16(); 461 return l10n_util::GetStringFUTF16( 462 IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE, 463 UTF8ToUTF16(GetLocallyManagedUserManager())); 464 } 465 466 virtual bool SystemShouldUpgrade() const OVERRIDE { 467 return UpgradeDetector::GetInstance()->notify_upgrade(); 468 } 469 470 virtual base::HourClockType GetHourClockType() const OVERRIDE { 471 return clock_type_; 472 } 473 474 virtual void ShowSettings() OVERRIDE { 475 chrome::ScopedTabbedBrowserDisplayer displayer( 476 ProfileManager::GetActiveUserProfile(), 477 chrome::HOST_DESKTOP_TYPE_ASH); 478 chrome::ShowSettings(displayer.browser()); 479 } 480 481 virtual bool ShouldShowSettings() OVERRIDE { 482 return UserManager::Get()->GetCurrentUserFlow()->ShouldShowSettings(); 483 } 484 485 virtual void ShowDateSettings() OVERRIDE { 486 content::RecordAction(content::UserMetricsAction("ShowDateOptions")); 487 std::string sub_page = std::string(chrome::kSearchSubPage) + "#" + 488 l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME); 489 // Everybody can change the time zone (even though it is a device setting). 490 ShowSettingsSubPageForAppropriateBrowser( 491 sub_page, 492 ProfileManager::GetActiveUserProfile()); 493 } 494 495 virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE { 496 if (!LoginState::Get()->IsUserLoggedIn()) 497 return; 498 ShowNetworkSettingsPage(service_path); 499 } 500 501 virtual void ShowBluetoothSettings() OVERRIDE { 502 // TODO(sad): Make this work. 503 } 504 505 virtual void ShowDisplaySettings() OVERRIDE { 506 content::RecordAction(content::UserMetricsAction("ShowDisplayOptions")); 507 ShowSettingsSubPageForAppropriateBrowser( 508 kDisplaySettingsSubPageName, 509 ProfileManager::GetActiveUserProfile()); 510 } 511 512 virtual void ShowChromeSlow() OVERRIDE { 513 chrome::ScopedTabbedBrowserDisplayer displayer( 514 ProfileManager::GetPrimaryUserProfile(), 515 chrome::HOST_DESKTOP_TYPE_ASH); 516 chrome::ShowSlow(displayer.browser()); 517 } 518 519 virtual bool ShouldShowDisplayNotification() OVERRIDE { 520 // Packaged app is not counted as 'last active', so if a browser opening the 521 // display settings is in background of a packaged app, it will return true. 522 // TODO(mukai): fix this. 523 Browser* active_browser = chrome::FindLastActiveWithHostDesktopType( 524 chrome::HOST_DESKTOP_TYPE_ASH); 525 if (!active_browser) 526 return true; 527 528 content::WebContents* active_contents = 529 active_browser->tab_strip_model()->GetActiveWebContents(); 530 if (!active_contents) 531 return true; 532 533 GURL visible_url = active_contents->GetLastCommittedURL(); 534 std::string display_settings_url = 535 std::string(chrome::kChromeUISettingsURL) + kDisplaySettingsSubPageName; 536 std::string display_overscan_url = 537 std::string(chrome::kChromeUISettingsURL) + 538 kDisplayOverscanSettingsSubPageName; 539 return (visible_url.spec() != display_settings_url) && 540 (visible_url.spec() != display_overscan_url); 541 } 542 543 virtual void ShowDriveSettings() OVERRIDE { 544 // TODO(tengs): Open the drive-specific settings page once we put it in. 545 // For now just show Google Drive main page. 546 chrome::ScopedTabbedBrowserDisplayer displayer( 547 ProfileManager::GetActiveUserProfile(), 548 chrome::HOST_DESKTOP_TYPE_ASH); 549 chrome::ShowSingletonTabOverwritingNTP( 550 displayer.browser(), 551 chrome::GetSingletonTabNavigateParams(displayer.browser(), 552 GURL(kDriveSettingsPageURL))); 553 } 554 555 virtual void ShowIMESettings() OVERRIDE { 556 content::RecordAction( 557 content::UserMetricsAction("OpenLanguageOptionsDialog")); 558 ShowSettingsSubPageForAppropriateBrowser( 559 chrome::kLanguageOptionsSubPage, 560 ProfileManager::GetActiveUserProfile()); 561 } 562 563 virtual void ShowHelp() OVERRIDE { 564 chrome::ShowHelpForProfile(ProfileManager::GetActiveUserProfile(), 565 chrome::HOST_DESKTOP_TYPE_ASH, 566 chrome::HELP_SOURCE_MENU); 567 } 568 569 virtual void ShowAccessibilityHelp() OVERRIDE { 570 chrome::ScopedTabbedBrowserDisplayer displayer( 571 ProfileManager::GetActiveUserProfile(), 572 chrome::HOST_DESKTOP_TYPE_ASH); 573 accessibility::ShowAccessibilityHelp(displayer.browser()); 574 } 575 576 virtual void ShowAccessibilitySettings() OVERRIDE { 577 content::RecordAction( 578 content::UserMetricsAction("ShowAccessibilitySettings")); 579 std::string sub_page = std::string(chrome::kSearchSubPage) + "#" + 580 l10n_util::GetStringUTF8( 581 IDS_OPTIONS_SETTINGS_SECTION_TITLE_ACCESSIBILITY); 582 ShowSettingsSubPageForAppropriateBrowser( 583 sub_page, 584 ProfileManager::GetActiveUserProfile()); 585 } 586 587 virtual void ShowPublicAccountInfo() OVERRIDE { 588 chrome::ScopedTabbedBrowserDisplayer displayer( 589 ProfileManager::GetActiveUserProfile(), 590 chrome::HOST_DESKTOP_TYPE_ASH); 591 chrome::ShowPolicy(displayer.browser()); 592 } 593 594 virtual void ShowLocallyManagedUserInfo() OVERRIDE { 595 // TODO(antrim): find out what should we show in this case. 596 // http://crbug.com/229762 597 } 598 599 virtual void ShowEnterpriseInfo() OVERRIDE { 600 ash::user::LoginStatus status = GetUserLoginStatus(); 601 if (status == ash::user::LOGGED_IN_NONE || 602 status == ash::user::LOGGED_IN_LOCKED) { 603 scoped_refptr<chromeos::HelpAppLauncher> help_app( 604 new chromeos::HelpAppLauncher(GetNativeWindow())); 605 help_app->ShowHelpTopic(chromeos::HelpAppLauncher::HELP_ENTERPRISE); 606 } else { 607 GURL url(google_util::StringAppendGoogleLocaleParam( 608 chrome::kLearnMoreEnterpriseURL)); 609 chrome::ScopedTabbedBrowserDisplayer displayer( 610 ProfileManager::GetActiveUserProfile(), 611 chrome::HOST_DESKTOP_TYPE_ASH); 612 chrome::ShowSingletonTab(displayer.browser(), url); 613 } 614 } 615 616 virtual void ShowUserLogin() OVERRIDE { 617 ash::Shell* shell = ash::Shell::GetInstance(); 618 if (!shell->delegate()->IsMultiProfilesEnabled()) 619 return; 620 621 // Only regular users could add other users to current session. 622 if (UserManager::Get()->GetActiveUser()->GetType() != 623 User::USER_TYPE_REGULAR) { 624 return; 625 } 626 627 if (static_cast<int>(UserManager::Get()->GetLoggedInUsers().size()) >= 628 shell->session_state_delegate()->GetMaximumNumberOfLoggedInUsers()) 629 return; 630 631 // Launch sign in screen to add another user to current session. 632 if (UserManager::Get()->GetUsersAdmittedForMultiProfile().size()) 633 UserAddingScreen::Get()->Start(); 634 } 635 636 virtual void ShowSpringChargerReplacementDialog() OVERRIDE { 637 if (!ChargerReplacementDialog::ShouldShowDialog()) 638 return; 639 640 ChargerReplacementDialog* dialog = 641 new ChargerReplacementDialog(GetNativeWindow()); 642 dialog->Show(); 643 } 644 645 virtual bool HasUserConfirmedSafeSpringCharger() OVERRIDE { 646 return ChargerReplacementHandler::GetChargerStatusPref() == 647 ChargerReplacementHandler::CONFIRM_SAFE_CHARGER; 648 } 649 650 virtual void ShutDown() OVERRIDE { 651 ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown(); 652 } 653 654 virtual void SignOut() OVERRIDE { 655 chrome::AttemptUserExit(); 656 } 657 658 virtual void RequestLockScreen() OVERRIDE { 659 // TODO(antrim) : additional logging for crbug/173178 660 LOG(WARNING) << "Requesting screen lock from AshSystemTrayDelegate"; 661 DBusThreadManager::Get()->GetSessionManagerClient()->RequestLockScreen(); 662 } 663 664 virtual void RequestRestartForUpdate() OVERRIDE { 665 // We expect that UpdateEngine is in "Reboot for update" state now. 666 chrome::NotifyAndTerminate(true /* fast path */); 667 } 668 669 virtual void GetAvailableBluetoothDevices( 670 ash::BluetoothDeviceList* list) OVERRIDE { 671 device::BluetoothAdapter::DeviceList devices = 672 bluetooth_adapter_->GetDevices(); 673 for (size_t i = 0; i < devices.size(); ++i) { 674 device::BluetoothDevice* device = devices[i]; 675 ash::BluetoothDeviceInfo info; 676 info.address = device->GetAddress(); 677 info.display_name = device->GetName(); 678 info.connected = device->IsConnected(); 679 info.connecting = device->IsConnecting(); 680 info.paired = device->IsPaired(); 681 list->push_back(info); 682 } 683 } 684 685 virtual void BluetoothStartDiscovering() OVERRIDE { 686 bluetooth_adapter_->StartDiscovering( 687 base::Bind(&base::DoNothing), 688 base::Bind(&BluetoothSetDiscoveringError)); 689 } 690 691 virtual void BluetoothStopDiscovering() OVERRIDE { 692 bluetooth_adapter_->StopDiscovering( 693 base::Bind(&base::DoNothing), 694 base::Bind(&BluetoothSetDiscoveringError)); 695 } 696 697 virtual void ConnectToBluetoothDevice(const std::string& address) OVERRIDE { 698 device::BluetoothDevice* device = bluetooth_adapter_->GetDevice(address); 699 if (!device || device->IsConnecting() || 700 (device->IsConnected() && device->IsPaired())) { 701 return; 702 } 703 if (device->IsPaired() && !device->IsConnectable()) 704 return; 705 if (device->IsPaired() || !device->IsPairable()) { 706 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( 707 ash::UMA_STATUS_AREA_BLUETOOTH_CONNECT_KNOWN_DEVICE); 708 device->Connect( 709 NULL, 710 base::Bind(&base::DoNothing), 711 base::Bind(&BluetoothDeviceConnectError)); 712 } else { // Show paring dialog for the unpaired device. 713 ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( 714 ash::UMA_STATUS_AREA_BLUETOOTH_CONNECT_UNKNOWN_DEVICE); 715 BluetoothPairingDialog* dialog = 716 new BluetoothPairingDialog(GetNativeWindow(), device); 717 // The dialog deletes itself on close. 718 dialog->Show(); 719 } 720 } 721 722 virtual bool IsBluetoothDiscovering() OVERRIDE { 723 return bluetooth_adapter_->IsDiscovering(); 724 } 725 726 virtual void GetCurrentIME(ash::IMEInfo* info) OVERRIDE { 727 input_method::InputMethodManager* manager = 728 input_method::InputMethodManager::Get(); 729 input_method::InputMethodUtil* util = manager->GetInputMethodUtil(); 730 input_method::InputMethodDescriptor ime = manager->GetCurrentInputMethod(); 731 ExtractIMEInfo(ime, *util, info); 732 info->selected = true; 733 } 734 735 virtual void GetAvailableIMEList(ash::IMEInfoList* list) OVERRIDE { 736 input_method::InputMethodManager* manager = 737 input_method::InputMethodManager::Get(); 738 input_method::InputMethodUtil* util = manager->GetInputMethodUtil(); 739 scoped_ptr<input_method::InputMethodDescriptors> ime_descriptors( 740 manager->GetActiveInputMethods()); 741 std::string current = manager->GetCurrentInputMethod().id(); 742 for (size_t i = 0; i < ime_descriptors->size(); i++) { 743 input_method::InputMethodDescriptor& ime = ime_descriptors->at(i); 744 ash::IMEInfo info; 745 ExtractIMEInfo(ime, *util, &info); 746 info.selected = ime.id() == current; 747 list->push_back(info); 748 } 749 } 750 751 virtual void GetCurrentIMEProperties( 752 ash::IMEPropertyInfoList* list) OVERRIDE { 753 input_method::InputMethodManager* manager = 754 input_method::InputMethodManager::Get(); 755 input_method::InputMethodPropertyList properties = 756 manager->GetCurrentInputMethodProperties(); 757 for (size_t i = 0; i < properties.size(); ++i) { 758 ash::IMEPropertyInfo property; 759 property.key = properties[i].key; 760 property.name = base::UTF8ToUTF16(properties[i].label); 761 property.selected = properties[i].is_selection_item_checked; 762 list->push_back(property); 763 } 764 } 765 766 virtual void SwitchIME(const std::string& ime_id) OVERRIDE { 767 input_method::InputMethodManager::Get()->ChangeInputMethod(ime_id); 768 } 769 770 virtual void ActivateIMEProperty(const std::string& key) OVERRIDE { 771 input_method::InputMethodManager::Get()-> 772 ActivateInputMethodProperty(key); 773 } 774 775 virtual void CancelDriveOperation(int32 operation_id) OVERRIDE { 776 DriveIntegrationService* integration_service = 777 FindDriveIntegrationService(); 778 if (!integration_service) 779 return; 780 781 integration_service->job_list()->CancelJob(operation_id); 782 } 783 784 virtual void GetDriveOperationStatusList( 785 ash::DriveOperationStatusList* list) OVERRIDE { 786 DriveIntegrationService* integration_service = 787 FindDriveIntegrationService(); 788 if (!integration_service) 789 return; 790 791 *list = ConvertToDriveStatusList( 792 integration_service->job_list()->GetJobInfoList()); 793 } 794 795 virtual void ShowNetworkConfigure(const std::string& network_id, 796 gfx::NativeWindow parent_window) OVERRIDE { 797 NetworkConfigView::Show(network_id, parent_window); 798 } 799 800 virtual bool EnrollNetwork(const std::string& network_id, 801 gfx::NativeWindow parent_window) OVERRIDE { 802 return enrollment::CreateDialog(network_id, parent_window); 803 } 804 805 virtual void ManageBluetoothDevices() OVERRIDE { 806 content::RecordAction( 807 content::UserMetricsAction("ShowBluetoothSettingsPage")); 808 std::string sub_page = std::string(chrome::kSearchSubPage) + "#" + 809 l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH); 810 ShowSettingsSubPageForAppropriateBrowser( 811 sub_page, 812 ProfileManager::GetPrimaryUserProfile()); 813 } 814 815 virtual void ToggleBluetooth() OVERRIDE { 816 bluetooth_adapter_->SetPowered(!bluetooth_adapter_->IsPowered(), 817 base::Bind(&base::DoNothing), 818 base::Bind(&BluetoothPowerFailure)); 819 } 820 821 virtual void ShowMobileSimDialog() OVERRIDE { 822 SimDialogDelegate::ShowDialog(GetNativeWindow(), 823 SimDialogDelegate::SIM_DIALOG_UNLOCK); 824 } 825 826 virtual void ShowMobileSetupDialog(const std::string& service_path) OVERRIDE { 827 MobileSetupDialog::Show(service_path); 828 } 829 830 virtual void ShowOtherNetworkDialog(const std::string& type) OVERRIDE { 831 if (type == shill::kTypeCellular) { 832 ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow()); 833 return; 834 } 835 NetworkConfigView::ShowForType(type, GetNativeWindow()); 836 } 837 838 virtual bool GetBluetoothAvailable() OVERRIDE { 839 return bluetooth_adapter_->IsPresent(); 840 } 841 842 virtual bool GetBluetoothEnabled() OVERRIDE { 843 return bluetooth_adapter_->IsPowered(); 844 } 845 846 virtual void ChangeProxySettings() OVERRIDE { 847 CHECK(GetUserLoginStatus() == ash::user::LOGGED_IN_NONE); 848 LoginDisplayHostImpl::default_host()->OpenProxySettings(); 849 } 850 851 virtual ash::VolumeControlDelegate* 852 GetVolumeControlDelegate() const OVERRIDE { 853 return volume_control_delegate_.get(); 854 } 855 856 virtual void SetVolumeControlDelegate( 857 scoped_ptr<ash::VolumeControlDelegate> delegate) OVERRIDE { 858 volume_control_delegate_.swap(delegate); 859 } 860 861 virtual bool GetSessionStartTime( 862 base::TimeTicks* session_start_time) OVERRIDE { 863 *session_start_time = session_start_time_; 864 return have_session_start_time_; 865 } 866 867 virtual bool GetSessionLengthLimit( 868 base::TimeDelta* session_length_limit) OVERRIDE { 869 *session_length_limit = session_length_limit_; 870 return have_session_length_limit_; 871 } 872 873 virtual int GetSystemTrayMenuWidth() OVERRIDE { 874 return l10n_util::GetLocalizedContentsWidthInPixels( 875 IDS_SYSTEM_TRAY_MENU_BUBBLE_WIDTH_PIXELS); 876 } 877 878 private: 879 ash::SystemTray* GetPrimarySystemTray() { 880 return ash::Shell::GetInstance()->GetPrimarySystemTray(); 881 } 882 883 ash::SystemTrayNotifier* GetSystemTrayNotifier() { 884 return ash::Shell::GetInstance()->system_tray_notifier(); 885 } 886 887 void SetProfile(Profile* profile) { 888 // Stop observing the current |user_profile_| on Drive integration status. 889 UnobserveDriveUpdates(); 890 891 user_profile_ = profile; 892 893 // Restart observation, now for the newly set |profile|. 894 ObserveDriveUpdates(); 895 896 PrefService* prefs = profile->GetPrefs(); 897 user_pref_registrar_.reset(new PrefChangeRegistrar); 898 user_pref_registrar_->Init(prefs); 899 user_pref_registrar_->Add( 900 prefs::kUse24HourClock, 901 base::Bind(&SystemTrayDelegate::UpdateClockType, 902 base::Unretained(this))); 903 user_pref_registrar_->Add( 904 prefs::kLanguageRemapSearchKeyTo, 905 base::Bind(&SystemTrayDelegate::OnLanguageRemapSearchKeyToChanged, 906 base::Unretained(this))); 907 user_pref_registrar_->Add( 908 prefs::kShowLogoutButtonInTray, 909 base::Bind(&SystemTrayDelegate::UpdateShowLogoutButtonInTray, 910 base::Unretained(this))); 911 user_pref_registrar_->Add( 912 prefs::kLargeCursorEnabled, 913 base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged, 914 base::Unretained(this), 915 ash::A11Y_NOTIFICATION_NONE)); 916 user_pref_registrar_->Add( 917 prefs::kAutoclickEnabled, 918 base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged, 919 base::Unretained(this), 920 ash::A11Y_NOTIFICATION_NONE)); 921 user_pref_registrar_->Add( 922 prefs::kShouldAlwaysShowAccessibilityMenu, 923 base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged, 924 base::Unretained(this), 925 ash::A11Y_NOTIFICATION_NONE)); 926 user_pref_registrar_->Add( 927 prefs::kPerformanceTracingEnabled, 928 base::Bind(&SystemTrayDelegate::UpdatePerformanceTracing, 929 base::Unretained(this))); 930 931 UpdateClockType(); 932 UpdateShowLogoutButtonInTray(); 933 UpdatePerformanceTracing(); 934 search_key_mapped_to_ = 935 profile->GetPrefs()->GetInteger(prefs::kLanguageRemapSearchKeyTo); 936 } 937 938 bool UnsetProfile(Profile* profile) { 939 if (profile != user_profile_) 940 return false; 941 user_pref_registrar_.reset(); 942 return true; 943 } 944 945 void ObserveDriveUpdates() { 946 DriveIntegrationService* integration_service = 947 FindDriveIntegrationService(); 948 if (integration_service) 949 integration_service->job_list()->AddObserver(this); 950 } 951 952 void UnobserveDriveUpdates() { 953 DriveIntegrationService* integration_service = 954 FindDriveIntegrationService(); 955 if (integration_service) 956 integration_service->job_list()->RemoveObserver(this); 957 } 958 959 bool ShouldUse24HourClock() const { 960 // On login screen and in guest mode owner default is used for 961 // kUse24HourClock preference. 962 const ash::user::LoginStatus status = GetUserLoginStatus(); 963 const CrosSettings* const cros_settings = CrosSettings::Get(); 964 bool system_use_24_hour_clock = true; 965 const bool system_value_found = cros_settings->GetBoolean( 966 kSystemUse24HourClock, &system_use_24_hour_clock); 967 968 if (status == ash::user::LOGGED_IN_NONE) 969 return (system_value_found 970 ? system_use_24_hour_clock 971 : (base::GetHourClockType() == base::k24HourClock)); 972 973 const PrefService::Preference* user_pref = 974 user_pref_registrar_->prefs()->FindPreference(prefs::kUse24HourClock); 975 if (status == ash::user::LOGGED_IN_GUEST && user_pref->IsDefaultValue()) 976 return (system_value_found 977 ? system_use_24_hour_clock 978 : (base::GetHourClockType() == base::k24HourClock)); 979 980 bool use_24_hour_clock = true; 981 user_pref->GetValue()->GetAsBoolean(&use_24_hour_clock); 982 return use_24_hour_clock; 983 } 984 985 void UpdateClockType() { 986 if (!user_pref_registrar_) 987 return; 988 989 const bool use_24_hour_clock = ShouldUse24HourClock(); 990 clock_type_ = use_24_hour_clock ? base::k24HourClock : base::k12HourClock; 991 GetSystemTrayNotifier()->NotifyDateFormatChanged(); 992 // This also works for enterprise-managed devices because they never have 993 // local owner. 994 if (chromeos::UserManager::Get()->IsCurrentUserOwner()) 995 CrosSettings::Get()->SetBoolean(kSystemUse24HourClock, use_24_hour_clock); 996 } 997 998 void UpdateShowLogoutButtonInTray() { 999 GetSystemTrayNotifier()->NotifyShowLoginButtonChanged( 1000 user_pref_registrar_->prefs()->GetBoolean( 1001 prefs::kShowLogoutButtonInTray)); 1002 } 1003 1004 void UpdateSessionStartTime() { 1005 const PrefService* local_state = local_state_registrar_->prefs(); 1006 if (local_state->HasPrefPath(prefs::kSessionStartTime)) { 1007 have_session_start_time_ = true; 1008 session_start_time_ = base::TimeTicks::FromInternalValue( 1009 local_state->GetInt64(prefs::kSessionStartTime)); 1010 } else { 1011 have_session_start_time_ = false; 1012 session_start_time_ = base::TimeTicks(); 1013 } 1014 GetSystemTrayNotifier()->NotifySessionStartTimeChanged(); 1015 } 1016 1017 void UpdateSessionLengthLimit() { 1018 const PrefService* local_state = local_state_registrar_->prefs(); 1019 if (local_state->HasPrefPath(prefs::kSessionLengthLimit)) { 1020 have_session_length_limit_ = true; 1021 session_length_limit_ = base::TimeDelta::FromMilliseconds( 1022 std::min(std::max(local_state->GetInteger(prefs::kSessionLengthLimit), 1023 kSessionLengthLimitMinMs), 1024 kSessionLengthLimitMaxMs)); 1025 } else { 1026 have_session_length_limit_ = false; 1027 session_length_limit_ = base::TimeDelta(); 1028 } 1029 GetSystemTrayNotifier()->NotifySessionLengthLimitChanged(); 1030 } 1031 1032 // LoginState::Observer overrides. 1033 virtual void LoggedInStateChanged() OVERRIDE { 1034 UpdateClockType(); 1035 } 1036 1037 // Overridden from SessionManagerClient::Observer. 1038 virtual void LockScreen() OVERRIDE { 1039 screen_locked_ = true; 1040 ash::Shell::GetInstance()->UpdateAfterLoginStatusChange( 1041 GetUserLoginStatus()); 1042 } 1043 1044 virtual void ScreenIsUnlocked() OVERRIDE { 1045 screen_locked_ = false; 1046 ash::Shell::GetInstance()->UpdateAfterLoginStatusChange( 1047 GetUserLoginStatus()); 1048 } 1049 1050 gfx::NativeWindow GetNativeWindow() const { 1051 bool session_started = ash::Shell::GetInstance()->session_state_delegate() 1052 ->IsActiveUserSessionStarted(); 1053 return GetNativeWindowByStatus(GetUserLoginStatus(), session_started); 1054 } 1055 1056 // content::NotificationObserver implementation. 1057 virtual void Observe(int type, 1058 const content::NotificationSource& source, 1059 const content::NotificationDetails& details) OVERRIDE { 1060 switch (type) { 1061 case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: { 1062 UpgradeDetector* detector = 1063 content::Source<UpgradeDetector>(source).ptr(); 1064 ash::UpdateObserver::UpdateSeverity severity = 1065 ash::UpdateObserver::UPDATE_NORMAL; 1066 switch (detector->upgrade_notification_stage()) { 1067 case UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE: 1068 severity = ash::UpdateObserver::UPDATE_SEVERE_RED; 1069 break; 1070 1071 case UpgradeDetector::UPGRADE_ANNOYANCE_HIGH: 1072 severity = ash::UpdateObserver::UPDATE_HIGH_ORANGE; 1073 break; 1074 1075 case UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED: 1076 severity = ash::UpdateObserver::UPDATE_LOW_GREEN; 1077 break; 1078 1079 case UpgradeDetector::UPGRADE_ANNOYANCE_LOW: 1080 default: 1081 severity = ash::UpdateObserver::UPDATE_NORMAL; 1082 break; 1083 } 1084 GetSystemTrayNotifier()->NotifyUpdateRecommended(severity); 1085 break; 1086 } 1087 case chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED: { 1088 // This notification is also sent on login screen when user avatar 1089 // is loaded from file. 1090 if (GetUserLoginStatus() != ash::user::LOGGED_IN_NONE) { 1091 GetSystemTrayNotifier()->NotifyUserUpdate(); 1092 } 1093 break; 1094 } 1095 case chrome::NOTIFICATION_PROFILE_CREATED: { 1096 SetProfile(content::Source<Profile>(source).ptr()); 1097 registrar_->Remove(this, 1098 chrome::NOTIFICATION_PROFILE_CREATED, 1099 content::NotificationService::AllSources()); 1100 break; 1101 } 1102 case chrome::NOTIFICATION_PROFILE_DESTROYED: { 1103 if (UnsetProfile(content::Source<Profile>(source).ptr())) { 1104 registrar_->Remove(this, 1105 chrome::NOTIFICATION_PROFILE_DESTROYED, 1106 content::NotificationService::AllSources()); 1107 } 1108 break; 1109 } 1110 case chrome::NOTIFICATION_SESSION_STARTED: { 1111 ash::Shell::GetInstance()->UpdateAfterLoginStatusChange( 1112 GetUserLoginStatus()); 1113 SetProfile(ProfileManager::GetActiveUserProfile()); 1114 break; 1115 } 1116 case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK: 1117 case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE: 1118 case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER: { 1119 AccessibilityStatusEventDetails* accessibility_status = 1120 content::Details<AccessibilityStatusEventDetails>(details).ptr(); 1121 OnAccessibilityModeChanged(accessibility_status->notify); 1122 break; 1123 } 1124 default: 1125 NOTREACHED(); 1126 } 1127 } 1128 1129 void OnLanguageRemapSearchKeyToChanged() { 1130 search_key_mapped_to_ = user_pref_registrar_->prefs()->GetInteger( 1131 prefs::kLanguageRemapSearchKeyTo); 1132 } 1133 1134 void OnAccessibilityModeChanged( 1135 ash::AccessibilityNotificationVisibility notify) { 1136 GetSystemTrayNotifier()->NotifyAccessibilityModeChanged(notify); 1137 } 1138 1139 void UpdatePerformanceTracing() { 1140 if (!user_pref_registrar_) 1141 return; 1142 bool value = 1143 user_pref_registrar_->prefs()->GetBoolean( 1144 prefs::kPerformanceTracingEnabled); 1145 GetSystemTrayNotifier()->NotifyTracingModeChanged(value); 1146 } 1147 1148 // Overridden from InputMethodManager::Observer. 1149 virtual void InputMethodChanged( 1150 input_method::InputMethodManager* manager, bool show_message) OVERRIDE { 1151 // |show_message| in ash means the message_center notifications 1152 // which should not be shown unless kDisableIMEModeIndicator is 1153 // on, since the mode indicator already notifies the user. 1154 if (!CommandLine::ForCurrentProcess()->HasSwitch( 1155 switches::kDisableIMEModeIndicator)) { 1156 show_message = false; 1157 } 1158 GetSystemTrayNotifier()->NotifyRefreshIME(show_message); 1159 } 1160 1161 virtual void InputMethodPropertyChanged( 1162 input_method::InputMethodManager* manager) OVERRIDE { 1163 GetSystemTrayNotifier()->NotifyRefreshIME(false); 1164 } 1165 1166 // drive::JobListObserver overrides. 1167 virtual void OnJobAdded(const drive::JobInfo& job_info) OVERRIDE { 1168 OnJobUpdated(job_info); 1169 } 1170 1171 virtual void OnJobDone(const drive::JobInfo& job_info, 1172 drive::FileError error) OVERRIDE { 1173 ash::DriveOperationStatus status; 1174 if (ConvertToFinishedDriveOperationStatus(job_info, error, &status)) 1175 GetSystemTrayNotifier()->NotifyDriveJobUpdated(status); 1176 } 1177 1178 virtual void OnJobUpdated(const drive::JobInfo& job_info) OVERRIDE { 1179 ash::DriveOperationStatus status; 1180 if (ConvertToDriveOperationStatus(job_info, &status)) 1181 GetSystemTrayNotifier()->NotifyDriveJobUpdated(status); 1182 } 1183 1184 DriveIntegrationService* FindDriveIntegrationService() { 1185 return user_profile_ ? 1186 DriveIntegrationServiceFactory::FindForProfile(user_profile_) : NULL; 1187 } 1188 1189 // Overridden from BluetoothAdapter::Observer. 1190 virtual void AdapterPresentChanged(device::BluetoothAdapter* adapter, 1191 bool present) OVERRIDE { 1192 GetSystemTrayNotifier()->NotifyRefreshBluetooth(); 1193 } 1194 1195 virtual void AdapterPoweredChanged(device::BluetoothAdapter* adapter, 1196 bool powered) OVERRIDE { 1197 GetSystemTrayNotifier()->NotifyRefreshBluetooth(); 1198 } 1199 1200 virtual void AdapterDiscoveringChanged(device::BluetoothAdapter* adapter, 1201 bool discovering) OVERRIDE { 1202 GetSystemTrayNotifier()->NotifyBluetoothDiscoveringChanged(); 1203 } 1204 1205 virtual void DeviceAdded(device::BluetoothAdapter* adapter, 1206 device::BluetoothDevice* device) OVERRIDE { 1207 GetSystemTrayNotifier()->NotifyRefreshBluetooth(); 1208 } 1209 1210 virtual void DeviceChanged(device::BluetoothAdapter* adapter, 1211 device::BluetoothDevice* device) OVERRIDE { 1212 GetSystemTrayNotifier()->NotifyRefreshBluetooth(); 1213 } 1214 1215 virtual void DeviceRemoved(device::BluetoothAdapter* adapter, 1216 device::BluetoothDevice* device) OVERRIDE { 1217 GetSystemTrayNotifier()->NotifyRefreshBluetooth(); 1218 } 1219 1220 // Overridden from SystemKeyEventListener::CapsLockObserver. 1221 virtual void OnCapsLockChange(bool enabled) OVERRIDE { 1222 bool search_mapped_to_caps_lock = false; 1223 if (!base::SysInfo::IsRunningOnChromeOS() || 1224 search_key_mapped_to_ == input_method::kCapsLockKey) 1225 search_mapped_to_caps_lock = true; 1226 GetSystemTrayNotifier()->NotifyCapsLockChanged( 1227 enabled, search_mapped_to_caps_lock); 1228 } 1229 1230 void UpdateEnterpriseDomain() { 1231 std::string enterprise_domain = 1232 g_browser_process->browser_policy_connector()->GetEnterpriseDomain(); 1233 if (enterprise_domain_ != enterprise_domain) { 1234 enterprise_domain_ = enterprise_domain; 1235 GetSystemTrayNotifier()->NotifyEnterpriseDomainChanged(); 1236 } 1237 } 1238 1239 // Overridden from CloudPolicyStore::Observer 1240 virtual void OnStoreLoaded(policy::CloudPolicyStore* store) OVERRIDE { 1241 UpdateEnterpriseDomain(); 1242 } 1243 1244 virtual void OnStoreError(policy::CloudPolicyStore* store) OVERRIDE { 1245 UpdateEnterpriseDomain(); 1246 } 1247 1248 // Overridden from ash::SessionStateObserver 1249 virtual void ActiveUserChanged(const std::string& user_id) OVERRIDE { 1250 GetSystemTrayNotifier()->NotifyUserUpdate(); 1251 } 1252 1253 virtual void UserAddedToSession(const std::string& user_id) OVERRIDE { 1254 GetSystemTrayNotifier()->NotifyUserAddedToSession(); 1255 } 1256 1257 scoped_ptr<base::WeakPtrFactory<SystemTrayDelegate> > ui_weak_ptr_factory_; 1258 scoped_ptr<content::NotificationRegistrar> registrar_; 1259 scoped_ptr<PrefChangeRegistrar> local_state_registrar_; 1260 scoped_ptr<PrefChangeRegistrar> user_pref_registrar_; 1261 Profile* user_profile_; 1262 base::HourClockType clock_type_; 1263 int search_key_mapped_to_; 1264 bool screen_locked_; 1265 bool have_session_start_time_; 1266 base::TimeTicks session_start_time_; 1267 bool have_session_length_limit_; 1268 base::TimeDelta session_length_limit_; 1269 std::string enterprise_domain_; 1270 1271 scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; 1272 scoped_ptr<ash::VolumeControlDelegate> volume_control_delegate_; 1273 1274 DISALLOW_COPY_AND_ASSIGN(SystemTrayDelegate); 1275 }; 1276 1277 } // namespace 1278 1279 ash::SystemTrayDelegate* CreateSystemTrayDelegate() { 1280 return new chromeos::SystemTrayDelegate(); 1281 } 1282 1283 } // namespace chromeos 1284