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