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