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