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