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