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