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