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