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
116namespace chromeos {
117
118namespace {
119
120// The minimum session length limit that can be set.
121const int kSessionLengthLimitMinMs = 30 * 1000;  // 30 seconds.
122
123// The maximum session length limit that can be set.
124const int kSessionLengthLimitMaxMs = 24 * 60 * 60 * 1000;  // 24 hours.
125
126const char kDisplaySettingsSubPageName[] = "display";
127const char kDisplayOverscanSettingsSubPageName[] = "displayOverscan";
128
129void 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
139gfx::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
154void BluetoothPowerFailure() {
155  // TODO(sad): Show an error bubble?
156}
157
158void BluetoothSetDiscoveringError() {
159  LOG(ERROR) << "BluetoothSetDiscovering failed.";
160}
161
162void BluetoothDeviceConnectError(
163    device::BluetoothDevice::ConnectErrorCode error_code) {
164  // TODO(sad): Do something?
165}
166
167void ShowSettingsSubPageForActiveUser(const std::string& sub_page) {
168  chrome::ShowSettingsSubPageForProfile(
169      ProfileManager::GetActiveUserProfile(), sub_page);
170}
171
172void 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
179void 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
187SystemTrayDelegateChromeOS::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
229void 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
252void SystemTrayDelegateChromeOS::Shutdown() {
253  device_settings_observer_.reset();
254}
255
256void 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
286SystemTrayDelegateChromeOS::~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:
321bool SystemTrayDelegateChromeOS::GetTrayVisibilityOnStartup() {
322  // In case of OOBE / sign in screen tray will be shown later.
323  return LoginState::Get()->IsUserLoggedIn();
324}
325
326ash::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
359void SystemTrayDelegateChromeOS::ChangeProfilePicture() {
360  content::RecordAction(
361      base::UserMetricsAction("OpenChangeProfilePictureDialog"));
362  ShowSettingsSubPageForActiveUser(chrome::kChangeProfilePictureSubPage);
363}
364
365const std::string SystemTrayDelegateChromeOS::GetEnterpriseDomain() const {
366  return enterprise_domain_;
367}
368
369const 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
376const 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
385const base::string16
386SystemTrayDelegateChromeOS::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
395const 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
404bool SystemTrayDelegateChromeOS::IsUserSupervised() const {
405  user_manager::User* user = user_manager::UserManager::Get()->GetActiveUser();
406  return user && user->IsSupervised();
407}
408
409bool SystemTrayDelegateChromeOS::SystemShouldUpgrade() const {
410  return UpgradeDetector::GetInstance()->notify_upgrade();
411}
412
413base::HourClockType SystemTrayDelegateChromeOS::GetHourClockType() const {
414  return clock_type_;
415}
416
417void SystemTrayDelegateChromeOS::ShowSettings() {
418  ShowSettingsSubPageForActiveUser("");
419}
420
421bool SystemTrayDelegateChromeOS::ShouldShowSettings() {
422  return ChromeUserManager::Get()->GetCurrentUserFlow()->ShouldShowSettings() &&
423         !ash::Shell::GetInstance()
424              ->session_state_delegate()
425              ->IsInSecondaryLoginScreen();
426}
427
428void 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
437void SystemTrayDelegateChromeOS::ShowSetTimeDialog() {
438  SetTimeDialog::ShowDialog(GetNativeWindow());
439}
440
441void 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
452void SystemTrayDelegateChromeOS::ShowBluetoothSettings() {
453  // TODO(sad): Make this work.
454}
455
456void SystemTrayDelegateChromeOS::ShowDisplaySettings() {
457  content::RecordAction(base::UserMetricsAction("ShowDisplayOptions"));
458  ShowSettingsSubPageForActiveUser(kDisplaySettingsSubPageName);
459}
460
461void SystemTrayDelegateChromeOS::ShowChromeSlow() {
462  chrome::ScopedTabbedBrowserDisplayer displayer(
463      ProfileManager::GetPrimaryUserProfile(), chrome::HOST_DESKTOP_TYPE_ASH);
464  chrome::ShowSlow(displayer.browser());
465}
466
467bool 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
490void SystemTrayDelegateChromeOS::ShowIMESettings() {
491  content::RecordAction(base::UserMetricsAction("OpenLanguageOptionsDialog"));
492  ShowSettingsSubPageForActiveUser(chrome::kLanguageOptionsSubPage);
493}
494
495void SystemTrayDelegateChromeOS::ShowHelp() {
496  chrome::ShowHelpForProfile(ProfileManager::GetActiveUserProfile(),
497                             chrome::HOST_DESKTOP_TYPE_ASH,
498                             chrome::HELP_SOURCE_MENU);
499}
500
501void SystemTrayDelegateChromeOS::ShowAccessibilityHelp() {
502  chrome::ScopedTabbedBrowserDisplayer displayer(
503      ProfileManager::GetActiveUserProfile(), chrome::HOST_DESKTOP_TYPE_ASH);
504  accessibility::ShowAccessibilityHelp(displayer.browser());
505}
506
507void 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
515void SystemTrayDelegateChromeOS::ShowPublicAccountInfo() {
516  chrome::ScopedTabbedBrowserDisplayer displayer(
517      ProfileManager::GetActiveUserProfile(), chrome::HOST_DESKTOP_TYPE_ASH);
518  chrome::ShowPolicy(displayer.browser());
519}
520
521void SystemTrayDelegateChromeOS::ShowSupervisedUserInfo() {
522  // TODO(antrim): find out what should we show in this case.
523  // http://crbug.com/229762
524}
525
526void 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
545void 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
590bool 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
600bool SystemTrayDelegateChromeOS::IsSpringChargerReplacementDialogVisible() {
601  return ChargerReplacementDialog::IsDialogVisible();
602}
603
604bool SystemTrayDelegateChromeOS::HasUserConfirmedSafeSpringCharger() {
605  return ChargerReplacementHandler::GetChargerStatusPref() ==
606         ChargerReplacementHandler::CONFIRM_SAFE_CHARGER;
607}
608
609void SystemTrayDelegateChromeOS::ShutDown() {
610  ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
611}
612
613void SystemTrayDelegateChromeOS::SignOut() {
614  chrome::AttemptUserExit();
615}
616
617void 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
623void SystemTrayDelegateChromeOS::RequestRestartForUpdate() {
624  // We expect that UpdateEngine is in "Reboot for update" state now.
625  chrome::NotifyAndTerminate(true /* fast path */);
626}
627
628void 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
644void 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
657void 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
668void 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
693bool SystemTrayDelegateChromeOS::IsBluetoothDiscovering() {
694  return bluetooth_adapter_->IsDiscovering();
695}
696
697void 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
707void 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
724void 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
738void SystemTrayDelegateChromeOS::SwitchIME(const std::string& ime_id) {
739  input_method::InputMethodManager::Get()
740      ->GetActiveIMEState()
741      ->ChangeInputMethod(ime_id, false /* show_message */);
742}
743
744void SystemTrayDelegateChromeOS::ActivateIMEProperty(const std::string& key) {
745  input_method::InputMethodManager::Get()->ActivateInputMethodMenuItem(key);
746}
747
748void SystemTrayDelegateChromeOS::ShowNetworkConfigure(
749    const std::string& network_id) {
750  NetworkConfigView::Show(network_id, GetNativeWindow());
751}
752
753bool SystemTrayDelegateChromeOS::EnrollNetwork(
754    const std::string& network_id) {
755  return enrollment::CreateDialog(network_id, GetNativeWindow());
756}
757
758void 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
766void SystemTrayDelegateChromeOS::ToggleBluetooth() {
767  bluetooth_adapter_->SetPowered(!bluetooth_adapter_->IsPowered(),
768                                 base::Bind(&base::DoNothing),
769                                 base::Bind(&BluetoothPowerFailure));
770}
771
772void SystemTrayDelegateChromeOS::ShowMobileSimDialog() {
773  SimDialogDelegate::ShowDialog(GetNativeWindow(),
774                                SimDialogDelegate::SIM_DIALOG_UNLOCK);
775}
776
777void SystemTrayDelegateChromeOS::ShowMobileSetupDialog(
778    const std::string& service_path) {
779  MobileSetupDialog::Show(service_path);
780}
781
782void 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
791bool SystemTrayDelegateChromeOS::GetBluetoothAvailable() {
792  return bluetooth_adapter_->IsPresent();
793}
794
795bool SystemTrayDelegateChromeOS::GetBluetoothEnabled() {
796  return bluetooth_adapter_->IsPowered();
797}
798
799bool SystemTrayDelegateChromeOS::GetBluetoothDiscovering() {
800  return (bluetooth_discovery_session_.get() &&
801      bluetooth_discovery_session_->IsActive());
802}
803
804void SystemTrayDelegateChromeOS::ChangeProxySettings() {
805  CHECK(GetUserLoginStatus() == ash::user::LOGGED_IN_NONE);
806  LoginDisplayHostImpl::default_host()->OpenProxySettings();
807}
808
809ash::VolumeControlDelegate*
810SystemTrayDelegateChromeOS::GetVolumeControlDelegate() const {
811  return volume_control_delegate_.get();
812}
813
814void SystemTrayDelegateChromeOS::SetVolumeControlDelegate(
815    scoped_ptr<ash::VolumeControlDelegate> delegate) {
816  volume_control_delegate_.swap(delegate);
817}
818
819bool SystemTrayDelegateChromeOS::GetSessionStartTime(
820    base::TimeTicks* session_start_time) {
821  *session_start_time = session_start_time_;
822  return have_session_start_time_;
823}
824
825bool SystemTrayDelegateChromeOS::GetSessionLengthLimit(
826    base::TimeDelta* session_length_limit) {
827  *session_length_limit = session_length_limit_;
828  return have_session_length_limit_;
829}
830
831int SystemTrayDelegateChromeOS::GetSystemTrayMenuWidth() {
832  return l10n_util::GetLocalizedContentsWidthInPixels(
833      IDS_SYSTEM_TRAY_MENU_BUBBLE_WIDTH_PIXELS);
834}
835
836void SystemTrayDelegateChromeOS::ActiveUserWasChanged() {
837  GetSystemTrayNotifier()->NotifyUserUpdate();
838}
839
840bool SystemTrayDelegateChromeOS::IsSearchKeyMappedToCapsLock() {
841  return search_key_mapped_to_ == input_method::kCapsLockKey;
842}
843
844ash::tray::UserAccountsDelegate*
845SystemTrayDelegateChromeOS::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
860ash::SystemTray* SystemTrayDelegateChromeOS::GetPrimarySystemTray() {
861  return ash::Shell::GetInstance()->GetPrimarySystemTray();
862}
863
864ash::SystemTrayNotifier* SystemTrayDelegateChromeOS::GetSystemTrayNotifier() {
865  return ash::Shell::GetInstance()->system_tray_notifier();
866}
867
868void 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
924bool 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
932bool SystemTrayDelegateChromeOS::GetShouldUse24HourClockForTesting() const {
933  return ShouldUse24HourClock();
934}
935
936bool 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
962void 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
972void SystemTrayDelegateChromeOS::UpdateShowLogoutButtonInTray() {
973  GetSystemTrayNotifier()->NotifyShowLoginButtonChanged(
974      user_pref_registrar_->prefs()->GetBoolean(
975          prefs::kShowLogoutButtonInTray));
976}
977
978void 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
985void 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
998void 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
1013void 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
1024void 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.
1049void 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.
1066void SystemTrayDelegateChromeOS::ScreenIsLocked() {
1067  screen_locked_ = true;
1068  ash::Shell::GetInstance()->UpdateAfterLoginStatusChange(GetUserLoginStatus());
1069}
1070
1071void SystemTrayDelegateChromeOS::ScreenIsUnlocked() {
1072  screen_locked_ = false;
1073  ash::Shell::GetInstance()->UpdateAfterLoginStatusChange(GetUserLoginStatus());
1074}
1075
1076gfx::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.
1084void 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
1149void SystemTrayDelegateChromeOS::OnLanguageRemapSearchKeyToChanged() {
1150  search_key_mapped_to_ = user_pref_registrar_->prefs()->GetInteger(
1151      prefs::kLanguageRemapSearchKeyTo);
1152}
1153
1154void SystemTrayDelegateChromeOS::OnAccessibilityModeChanged(
1155    ash::AccessibilityNotificationVisibility notify) {
1156  GetSystemTrayNotifier()->NotifyAccessibilityModeChanged(notify);
1157}
1158
1159void 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.
1168void SystemTrayDelegateChromeOS::InputMethodChanged(
1169    input_method::InputMethodManager* manager,
1170    bool show_message) {
1171  GetSystemTrayNotifier()->NotifyRefreshIME();
1172}
1173
1174// Overridden from InputMethodMenuManager::Observer.
1175void SystemTrayDelegateChromeOS::InputMethodMenuItemChanged(
1176    ash::ime::InputMethodMenuManager* manager) {
1177  GetSystemTrayNotifier()->NotifyRefreshIME();
1178}
1179
1180// Overridden from CrasAudioHandler::AudioObserver.
1181void SystemTrayDelegateChromeOS::OnOutputVolumeChanged() {
1182  GetSystemTrayNotifier()->NotifyAudioOutputVolumeChanged();
1183}
1184
1185void SystemTrayDelegateChromeOS::OnOutputMuteChanged() {
1186  GetSystemTrayNotifier()->NotifyAudioOutputMuteChanged();
1187}
1188
1189void SystemTrayDelegateChromeOS::OnInputGainChanged() {
1190}
1191
1192void SystemTrayDelegateChromeOS::OnInputMuteChanged() {
1193}
1194
1195void SystemTrayDelegateChromeOS::OnAudioNodesChanged() {
1196  GetSystemTrayNotifier()->NotifyAudioNodesChanged();
1197}
1198
1199void SystemTrayDelegateChromeOS::OnActiveOutputNodeChanged() {
1200  GetSystemTrayNotifier()->NotifyAudioActiveOutputNodeChanged();
1201}
1202
1203void SystemTrayDelegateChromeOS::OnActiveInputNodeChanged() {
1204  GetSystemTrayNotifier()->NotifyAudioActiveInputNodeChanged();
1205}
1206
1207// Overridden from BluetoothAdapter::Observer.
1208void SystemTrayDelegateChromeOS::AdapterPresentChanged(
1209    device::BluetoothAdapter* adapter,
1210    bool present) {
1211  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
1212}
1213
1214void SystemTrayDelegateChromeOS::AdapterPoweredChanged(
1215    device::BluetoothAdapter* adapter,
1216    bool powered) {
1217  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
1218}
1219
1220void SystemTrayDelegateChromeOS::AdapterDiscoveringChanged(
1221    device::BluetoothAdapter* adapter,
1222    bool discovering) {
1223  GetSystemTrayNotifier()->NotifyBluetoothDiscoveringChanged();
1224}
1225
1226void SystemTrayDelegateChromeOS::DeviceAdded(device::BluetoothAdapter* adapter,
1227                                             device::BluetoothDevice* device) {
1228  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
1229}
1230
1231void SystemTrayDelegateChromeOS::DeviceChanged(
1232    device::BluetoothAdapter* adapter,
1233    device::BluetoothDevice* device) {
1234  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
1235}
1236
1237void SystemTrayDelegateChromeOS::DeviceRemoved(
1238    device::BluetoothAdapter* adapter,
1239    device::BluetoothDevice* device) {
1240  GetSystemTrayNotifier()->NotifyRefreshBluetooth();
1241}
1242
1243void 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
1255void 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
1266void SystemTrayDelegateChromeOS::OnStoreLoaded(
1267    policy::CloudPolicyStore* store) {
1268  UpdateEnterpriseDomain();
1269}
1270
1271void SystemTrayDelegateChromeOS::OnStoreError(policy::CloudPolicyStore* store) {
1272  UpdateEnterpriseDomain();
1273}
1274
1275// Overridden from ash::SessionStateObserver
1276void SystemTrayDelegateChromeOS::UserAddedToSession(
1277    const std::string& user_id) {
1278  GetSystemTrayNotifier()->NotifyUserAddedToSession();
1279}
1280
1281// Overridden from chrome::BrowserListObserver.
1282void SystemTrayDelegateChromeOS::OnBrowserRemoved(Browser* browser) {
1283  NotifyIfLastWindowClosed();
1284}
1285
1286// Overridden from extensions::AppWindowRegistry::Observer.
1287void SystemTrayDelegateChromeOS::OnAppWindowRemoved(
1288    extensions::AppWindow* app_window) {
1289  NotifyIfLastWindowClosed();
1290}
1291
1292void 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
1300ash::SystemTrayDelegate* CreateSystemTrayDelegate() {
1301  return new SystemTrayDelegateChromeOS();
1302}
1303
1304}  // namespace chromeos
1305