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/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/brightness/brightness_observer.h"
     21 #include "ash/system/chromeos/network/network_observer.h"
     22 #include "ash/system/chromeos/network/network_tray_delegate.h"
     23 #include "ash/system/date/clock_observer.h"
     24 #include "ash/system/drive/drive_observer.h"
     25 #include "ash/system/ime/ime_observer.h"
     26 #include "ash/system/logout_button/logout_button_observer.h"
     27 #include "ash/system/tray/system_tray.h"
     28 #include "ash/system/tray/system_tray_delegate.h"
     29 #include "ash/system/tray/system_tray_notifier.h"
     30 #include "ash/system/tray_accessibility.h"
     31 #include "ash/system/tray_caps_lock.h"
     32 #include "ash/system/user/login_status.h"
     33 #include "ash/system/user/update_observer.h"
     34 #include "ash/system/user/user_observer.h"
     35 #include "ash/volume_control_delegate.h"
     36 #include "ash/wm/lock_state_controller.h"
     37 #include "base/bind_helpers.h"
     38 #include "base/callback.h"
     39 #include "base/chromeos/chromeos_version.h"
     40 #include "base/command_line.h"
     41 #include "base/logging.h"
     42 #include "base/memory/weak_ptr.h"
     43 #include "base/prefs/pref_service.h"
     44 #include "base/strings/stringprintf.h"
     45 #include "base/strings/utf_string_conversions.h"
     46 #include "base/time/time.h"
     47 #include "chrome/browser/browser_process.h"
     48 #include "chrome/browser/chrome_notification_types.h"
     49 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
     50 #include "chrome/browser/chromeos/accessibility/magnification_manager.h"
     51 #include "chrome/browser/chromeos/bluetooth/bluetooth_pairing_dialog.h"
     52 #include "chrome/browser/chromeos/choose_mobile_network_dialog.h"
     53 #include "chrome/browser/chromeos/cros/network_library.h"
     54 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
     55 #include "chrome/browser/chromeos/drive/job_list.h"
     56 #include "chrome/browser/chromeos/input_method/input_method_util.h"
     57 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
     58 #include "chrome/browser/chromeos/login/help_app_launcher.h"
     59 #include "chrome/browser/chromeos/login/login_display_host.h"
     60 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
     61 #include "chrome/browser/chromeos/login/login_wizard.h"
     62 #include "chrome/browser/chromeos/login/startup_utils.h"
     63 #include "chrome/browser/chromeos/login/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/mobile_config.h"
     67 #include "chrome/browser/chromeos/options/network_config_view.h"
     68 #include "chrome/browser/chromeos/options/network_connect.h"
     69 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
     70 #include "chrome/browser/chromeos/settings/cros_settings.h"
     71 #include "chrome/browser/chromeos/sim_dialog_delegate.h"
     72 #include "chrome/browser/chromeos/status/data_promo_notification.h"
     73 #include "chrome/browser/chromeos/system/timezone_settings.h"
     74 #include "chrome/browser/chromeos/system_key_event_listener.h"
     75 #include "chrome/browser/drive/drive_service_interface.h"
     76 #include "chrome/browser/feedback/tracing_manager.h"
     77 #include "chrome/browser/google/google_util.h"
     78 #include "chrome/browser/lifetime/application_lifetime.h"
     79 #include "chrome/browser/policy/browser_policy_connector.h"
     80 #include "chrome/browser/policy/cloud/cloud_policy_store.h"
     81 #include "chrome/browser/profiles/profile_manager.h"
     82 #include "chrome/browser/ui/ash/volume_controller_chromeos.h"
     83 #include "chrome/browser/ui/browser.h"
     84 #include "chrome/browser/ui/browser_finder.h"
     85 #include "chrome/browser/ui/chrome_pages.h"
     86 #include "chrome/browser/ui/host_desktop.h"
     87 #include "chrome/browser/ui/singleton_tabs.h"
     88 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     89 #include "chrome/browser/upgrade_detector.h"
     90 #include "chrome/common/pref_names.h"
     91 #include "chrome/common/url_constants.h"
     92 #include "chromeos/chromeos_switches.h"
     93 #include "chromeos/dbus/dbus_thread_manager.h"
     94 #include "chromeos/dbus/power_manager_client.h"
     95 #include "chromeos/dbus/session_manager_client.h"
     96 #include "chromeos/dbus/system_clock_client.h"
     97 #include "chromeos/ime/extension_ime_util.h"
     98 #include "chromeos/ime/input_method_manager.h"
     99 #include "chromeos/ime/xkeyboard.h"
    100 #include "chromeos/login/login_state.h"
    101 #include "chromeos/network/network_state.h"
    102 #include "chromeos/network/network_state_handler.h"
    103 #include "content/public/browser/browser_thread.h"
    104 #include "content/public/browser/notification_observer.h"
    105 #include "content/public/browser/notification_service.h"
    106 #include "content/public/browser/user_metrics.h"
    107 #include "content/public/browser/web_contents.h"
    108 #include "device/bluetooth/bluetooth_adapter.h"
    109 #include "device/bluetooth/bluetooth_adapter_factory.h"
    110 #include "device/bluetooth/bluetooth_device.h"
    111 #include "grit/ash_strings.h"
    112 #include "grit/generated_resources.h"
    113 #include "grit/locale_settings.h"
    114 #include "net/base/escape.h"
    115 #include "third_party/cros_system_api/dbus/service_constants.h"
    116 #include "ui/base/l10n/l10n_util.h"
    117 #include "ui/base/l10n/time_format.h"
    118 
    119 using drive::DriveIntegrationService;
    120 using drive::DriveIntegrationServiceFactory;
    121 
    122 namespace chromeos {
    123 
    124 namespace {
    125 
    126 // The minimum session length limit that can be set.
    127 const int kSessionLengthLimitMinMs = 30 * 1000;  // 30 seconds.
    128 
    129 // The maximum session length limit that can be set.
    130 const int kSessionLengthLimitMaxMs = 24 * 60 * 60 * 1000;  // 24 hours.
    131 
    132 const char kDisplaySettingsSubPageName[] = "display";
    133 const char kDisplayOverscanSettingsSubPageName[] = "displayOverscan";
    134 
    135 void ExtractIMEInfo(const input_method::InputMethodDescriptor& ime,
    136                     const input_method::InputMethodUtil& util,
    137                     ash::IMEInfo* info) {
    138   info->id = ime.id();
    139   info->name = util.GetInputMethodLongName(ime);
    140   info->medium_name = util.GetInputMethodMediumName(ime);
    141   info->short_name = util.GetInputMethodShortName(ime);
    142   info->third_party = extension_ime_util::IsExtensionIME(ime.id());
    143 }
    144 
    145 gfx::NativeWindow GetNativeWindowByStatus(
    146     ash::user::LoginStatus login_status) {
    147   int container_id =
    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 BluetoothDiscoveryFailure() {
    213   // TODO(sad): Show an error bubble?
    214 }
    215 
    216 void BluetoothSetDiscoveringError() {
    217   LOG(ERROR) << "BluetoothSetDiscovering failed.";
    218 }
    219 
    220 void BluetoothDeviceConnectError(
    221     device::BluetoothDevice::ConnectErrorCode error_code) {
    222   // TODO(sad): Do something?
    223 }
    224 
    225 ash::NetworkObserver::NetworkType NetworkTypeForCellular(
    226     const CellularNetwork* cellular) {
    227   if (cellular->network_technology() == NETWORK_TECHNOLOGY_LTE ||
    228       cellular->network_technology() == NETWORK_TECHNOLOGY_LTE_ADVANCED)
    229     return ash::NetworkObserver::NETWORK_CELLULAR_LTE;
    230   return ash::NetworkObserver::NETWORK_CELLULAR;
    231 }
    232 
    233 class SystemTrayDelegate : public ash::SystemTrayDelegate,
    234                            public PowerManagerClient::Observer,
    235                            public SessionManagerClient::Observer,
    236                            public NetworkLibrary::NetworkManagerObserver,
    237                            public drive::JobListObserver,
    238                            public content::NotificationObserver,
    239                            public input_method::InputMethodManager::Observer,
    240                            public system::TimezoneSettings::Observer,
    241                            public chromeos::LoginState::Observer,
    242                            public chromeos::SystemClockClient::Observer,
    243                            public device::BluetoothAdapter::Observer,
    244                            public SystemKeyEventListener::CapsLockObserver,
    245                            public ash::NetworkTrayDelegate,
    246                            public policy::CloudPolicyStore::Observer,
    247                            public ash::SessionStateObserver {
    248  public:
    249   SystemTrayDelegate()
    250       : ui_weak_ptr_factory_(
    251           new base::WeakPtrFactory<SystemTrayDelegate>(this)),
    252         user_profile_(NULL),
    253         clock_type_(base::GetHourClockType()),
    254         search_key_mapped_to_(input_method::kSearchKey),
    255         screen_locked_(false),
    256         have_session_start_time_(false),
    257         have_session_length_limit_(false),
    258         data_promo_notification_(new DataPromoNotification()),
    259         cellular_activating_(false),
    260         cellular_out_of_credits_(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()->GetPowerManagerClient()->AddObserver(this);
    298     DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
    299 
    300     NetworkLibrary* crosnet = NetworkLibrary::Get();
    301     crosnet->AddNetworkManagerObserver(this);
    302     OnNetworkManagerChanged(crosnet);
    303 
    304     input_method::InputMethodManager::Get()->AddObserver(this);
    305     UpdateClockType();
    306 
    307     system::TimezoneSettings::GetInstance()->AddObserver(this);
    308     DBusThreadManager::Get()->GetSystemClockClient()->AddObserver(this);
    309 
    310     if (SystemKeyEventListener::GetInstance())
    311       SystemKeyEventListener::GetInstance()->AddCapsLockObserver(this);
    312 
    313     device::BluetoothAdapterFactory::GetAdapter(
    314         base::Bind(&SystemTrayDelegate::InitializeOnAdapterReady,
    315                    ui_weak_ptr_factory_->GetWeakPtr()));
    316 
    317     ash::Shell::GetInstance()->session_state_delegate()->
    318         AddSessionStateObserver(this);
    319 
    320     if (LoginState::IsInitialized())
    321       LoginState::Get()->AddObserver(this);
    322   }
    323 
    324   virtual void Shutdown() OVERRIDE {
    325     data_promo_notification_.reset();
    326   }
    327 
    328   void InitializeOnAdapterReady(
    329       scoped_refptr<device::BluetoothAdapter> adapter) {
    330     bluetooth_adapter_ = adapter;
    331     CHECK(bluetooth_adapter_.get());
    332     bluetooth_adapter_->AddObserver(this);
    333 
    334     local_state_registrar_.reset(new PrefChangeRegistrar);
    335     local_state_registrar_->Init(g_browser_process->local_state());
    336 
    337     UpdateSessionStartTime();
    338     UpdateSessionLengthLimit();
    339 
    340     local_state_registrar_->Add(
    341         prefs::kSessionStartTime,
    342         base::Bind(&SystemTrayDelegate::UpdateSessionStartTime,
    343                    base::Unretained(this)));
    344     local_state_registrar_->Add(
    345         prefs::kSessionLengthLimit,
    346         base::Bind(&SystemTrayDelegate::UpdateSessionLengthLimit,
    347                    base::Unretained(this)));
    348 
    349     policy::BrowserPolicyConnector* policy_connector =
    350         g_browser_process->browser_policy_connector();
    351     policy::DeviceCloudPolicyManagerChromeOS* policy_manager =
    352         policy_connector->GetDeviceCloudPolicyManager();
    353     if (policy_manager)
    354       policy_manager->core()->store()->AddObserver(this);
    355     UpdateEnterpriseDomain();
    356   }
    357 
    358   virtual ~SystemTrayDelegate() {
    359     // Unregister PrefChangeRegistrars.
    360     local_state_registrar_.reset();
    361     user_pref_registrar_.reset();
    362 
    363     // Unregister content notifications befure destroying any components.
    364     registrar_.reset();
    365 
    366     DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
    367     DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this);
    368     DBusThreadManager::Get()->GetSystemClockClient()->RemoveObserver(this);
    369     NetworkLibrary* crosnet = NetworkLibrary::Get();
    370     if (crosnet)
    371       crosnet->RemoveNetworkManagerObserver(this);
    372     input_method::InputMethodManager::Get()->RemoveObserver(this);
    373     system::TimezoneSettings::GetInstance()->RemoveObserver(this);
    374     if (SystemKeyEventListener::GetInstance())
    375       SystemKeyEventListener::GetInstance()->RemoveCapsLockObserver(this);
    376     bluetooth_adapter_->RemoveObserver(this);
    377     ash::Shell::GetInstance()->session_state_delegate()->
    378         RemoveSessionStateObserver(this);
    379     LoginState::Get()->RemoveObserver(this);
    380 
    381     // Stop observing Drive operations.
    382     UnobserveDriveUpdates();
    383 
    384     policy::DeviceCloudPolicyManagerChromeOS* policy_manager =
    385         g_browser_process->browser_policy_connector()->
    386            GetDeviceCloudPolicyManager();
    387     if (policy_manager)
    388       policy_manager->core()->store()->RemoveObserver(this);
    389   }
    390 
    391   // Overridden from ash::SystemTrayDelegate:
    392   virtual bool GetTrayVisibilityOnStartup() OVERRIDE {
    393     // In case of OOBE / sign in screen tray will be shown later.
    394     return LoginState::Get()->IsUserLoggedIn();
    395   }
    396 
    397   virtual ash::user::LoginStatus GetUserLoginStatus() const OVERRIDE {
    398     // Map ChromeOS specific LOGGED_IN states to Ash LOGGED_IN states.
    399     LoginState::LoggedInState state = LoginState::Get()->GetLoggedInState();
    400     if (state == LoginState::LOGGED_IN_OOBE ||
    401         state == LoginState::LOGGED_IN_NONE) {
    402       return ash::user::LOGGED_IN_NONE;
    403     }
    404     if (screen_locked_)
    405       return ash::user::LOGGED_IN_LOCKED;
    406 
    407     LoginState::LoggedInUserType user_type =
    408         LoginState::Get()->GetLoggedInUserType();
    409     switch (user_type) {
    410       case LoginState::LOGGED_IN_USER_NONE:
    411         return ash::user::LOGGED_IN_NONE;
    412       case LoginState::LOGGED_IN_USER_REGULAR:
    413         return ash::user::LOGGED_IN_USER;
    414       case LoginState::LOGGED_IN_USER_OWNER:
    415         return ash::user::LOGGED_IN_OWNER;
    416       case LoginState::LOGGED_IN_USER_GUEST:
    417         return ash::user::LOGGED_IN_GUEST;
    418       case LoginState::LOGGED_IN_USER_RETAIL_MODE:
    419         return ash::user::LOGGED_IN_RETAIL_MODE;
    420       case LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT:
    421         return ash::user::LOGGED_IN_PUBLIC;
    422       case LoginState::LOGGED_IN_USER_LOCALLY_MANAGED:
    423         return ash::user::LOGGED_IN_LOCALLY_MANAGED;
    424       case LoginState::LOGGED_IN_USER_KIOSK_APP:
    425         return ash::user::LOGGED_IN_KIOSK_APP;
    426     }
    427     NOTREACHED();
    428     return ash::user::LOGGED_IN_NONE;
    429   }
    430 
    431   virtual bool IsOobeCompleted() const OVERRIDE {
    432     if (!base::chromeos::IsRunningOnChromeOS() &&
    433         LoginState::Get()->GetLoggedInState() == LoginState::LOGGED_IN_ACTIVE)
    434       return true;
    435     return StartupUtils::IsOobeCompleted();
    436   }
    437 
    438   virtual void ChangeProfilePicture() OVERRIDE {
    439     content::RecordAction(
    440         content::UserMetricsAction("OpenChangeProfilePictureDialog"));
    441     chrome::ShowSettingsSubPage(GetAppropriateBrowser(),
    442                                 chrome::kChangeProfilePictureSubPage);
    443   }
    444 
    445   virtual const std::string GetEnterpriseDomain() const OVERRIDE {
    446     return enterprise_domain_;
    447   }
    448 
    449   virtual const string16 GetEnterpriseMessage() const OVERRIDE {
    450     if (GetEnterpriseDomain().empty())
    451         return string16();
    452     return l10n_util::GetStringFUTF16(IDS_DEVICE_OWNED_BY_NOTICE,
    453                                       UTF8ToUTF16(GetEnterpriseDomain()));
    454   }
    455 
    456   virtual const std::string GetLocallyManagedUserManager() const OVERRIDE {
    457     if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED)
    458       return std::string();
    459     return UserManager::Get()->GetManagerDisplayEmailForManagedUser(
    460         chromeos::UserManager::Get()->GetActiveUser()->email());
    461   }
    462 
    463   virtual const string16 GetLocallyManagedUserManagerName() const OVERRIDE {
    464     if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED)
    465       return string16();
    466     return UserManager::Get()->GetManagerDisplayNameForManagedUser(
    467         chromeos::UserManager::Get()->GetActiveUser()->email());
    468   }
    469 
    470   virtual const string16 GetLocallyManagedUserMessage() const OVERRIDE {
    471     if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED)
    472         return string16();
    473     return l10n_util::GetStringFUTF16(
    474         IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE,
    475         UTF8ToUTF16(GetLocallyManagedUserManager()));
    476   }
    477 
    478   virtual bool SystemShouldUpgrade() const OVERRIDE {
    479     return UpgradeDetector::GetInstance()->notify_upgrade();
    480   }
    481 
    482   virtual base::HourClockType GetHourClockType() const OVERRIDE {
    483     return clock_type_;
    484   }
    485 
    486   virtual void ShowSettings() OVERRIDE {
    487     chrome::ShowSettings(GetAppropriateBrowser());
    488   }
    489 
    490   virtual bool ShouldShowSettings() OVERRIDE {
    491     return UserManager::Get()->GetCurrentUserFlow()->ShouldShowSettings();
    492   }
    493 
    494   virtual void ShowDateSettings() OVERRIDE {
    495     content::RecordAction(content::UserMetricsAction("ShowDateOptions"));
    496     std::string sub_page = std::string(chrome::kSearchSubPage) + "#" +
    497         l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME);
    498     chrome::ShowSettingsSubPage(GetAppropriateBrowser(), sub_page);
    499   }
    500 
    501   virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE {
    502     if (!LoginState::Get()->IsUserLoggedIn())
    503       return;
    504     network_connect::ShowNetworkSettings(service_path);
    505   }
    506 
    507   virtual void ShowBluetoothSettings() OVERRIDE {
    508     // TODO(sad): Make this work.
    509   }
    510 
    511   virtual void ShowDisplaySettings() OVERRIDE {
    512     content::RecordAction(content::UserMetricsAction("ShowDisplayOptions"));
    513     chrome::ShowSettingsSubPage(GetAppropriateBrowser(),
    514                                 kDisplaySettingsSubPageName);
    515   }
    516 
    517   virtual void ShowChromeSlow() OVERRIDE {
    518     chrome::ShowSlow(GetAppropriateBrowser());
    519   }
    520 
    521   virtual bool ShouldShowDisplayNotification() OVERRIDE {
    522     // Packaged app is not counted as 'last active', so if a browser opening the
    523     // display settings is in background of a packaged app, it will return true.
    524     // TODO(mukai): fix this.
    525     Browser* active_browser = chrome::FindLastActiveWithHostDesktopType(
    526         chrome::HOST_DESKTOP_TYPE_ASH);
    527     if (!active_browser)
    528       return true;
    529 
    530     content::WebContents* active_contents =
    531         active_browser->tab_strip_model()->GetActiveWebContents();
    532     if (!active_contents)
    533       return true;
    534 
    535     GURL visible_url = active_contents->GetLastCommittedURL();
    536     std::string display_settings_url =
    537         std::string(chrome::kChromeUISettingsURL) + kDisplaySettingsSubPageName;
    538     std::string display_overscan_url =
    539         std::string(chrome::kChromeUISettingsURL) +
    540         kDisplayOverscanSettingsSubPageName;
    541     return (visible_url.spec() != display_settings_url) &&
    542         (visible_url.spec() != display_overscan_url);
    543   }
    544 
    545   virtual void ShowDriveSettings() OVERRIDE {
    546     // TODO(hshi): Open the drive-specific settings page once we put it in.
    547     // For now just show search result for downoads settings.
    548     std::string sub_page = std::string(chrome::kSearchSubPage) + "#" +
    549         l10n_util::GetStringUTF8(IDS_OPTIONS_DOWNLOADLOCATION_GROUP_NAME);
    550     chrome::ShowSettingsSubPage(GetAppropriateBrowser(), sub_page);
    551   }
    552 
    553   virtual void ShowIMESettings() OVERRIDE {
    554     content::RecordAction(
    555         content::UserMetricsAction("OpenLanguageOptionsDialog"));
    556     chrome::ShowSettingsSubPage(GetAppropriateBrowser(),
    557                                 chrome::kLanguageOptionsSubPage);
    558   }
    559 
    560   virtual void ShowHelp() OVERRIDE {
    561     chrome::ShowHelp(GetAppropriateBrowser(), chrome::HELP_SOURCE_MENU);
    562   }
    563 
    564   virtual void ShowAccessibilityHelp() OVERRIDE {
    565     accessibility::ShowAccessibilityHelp(GetAppropriateBrowser());
    566   }
    567 
    568   virtual void ShowAccessibilitySettings() OVERRIDE {
    569     content::RecordAction(
    570         content::UserMetricsAction("ShowAccessibilitySettings"));
    571     std::string sub_page = std::string(chrome::kSearchSubPage) + "#" +
    572         l10n_util::GetStringUTF8(
    573             IDS_OPTIONS_SETTINGS_SECTION_TITLE_ACCESSIBILITY);
    574     chrome::ShowSettingsSubPage(GetAppropriateBrowser(), sub_page);
    575   }
    576 
    577   virtual void ShowPublicAccountInfo() OVERRIDE {
    578     chrome::ShowPolicy(GetAppropriateBrowser());
    579   }
    580 
    581   virtual void ShowLocallyManagedUserInfo() OVERRIDE {
    582     // TODO(antrim): find out what should we show in this case.
    583     // http://crbug.com/229762
    584   }
    585 
    586   virtual void ShowEnterpriseInfo() OVERRIDE {
    587     ash::user::LoginStatus status = GetUserLoginStatus();
    588     if (status == ash::user::LOGGED_IN_NONE ||
    589         status == ash::user::LOGGED_IN_LOCKED) {
    590       scoped_refptr<chromeos::HelpAppLauncher> help_app(
    591          new chromeos::HelpAppLauncher(GetNativeWindow()));
    592       help_app->ShowHelpTopic(chromeos::HelpAppLauncher::HELP_ENTERPRISE);
    593     } else {
    594       GURL url(google_util::StringAppendGoogleLocaleParam(
    595           chrome::kLearnMoreEnterpriseURL));
    596       chrome::ShowSingletonTab(GetAppropriateBrowser(), url);
    597     }
    598   }
    599 
    600   virtual void ShowUserLogin() OVERRIDE {
    601     if (!ash::Shell::GetInstance()->delegate()->IsMultiProfilesEnabled())
    602       return;
    603 
    604     // Only regular users could add other users to current session.
    605     if (UserManager::Get()->GetActiveUser()->GetType() !=
    606             User::USER_TYPE_REGULAR) {
    607       return;
    608     }
    609 
    610     // TODO(nkostylev): Show some UI messages why no more users could be added
    611     // to this session. http://crbug.com/230863
    612     // We limit list of logged in users to 3 due to memory constraints.
    613     // TODO(nkostylev): Adjust this limitation based on device capabilites.
    614     // http://crbug.com/230865
    615     if (UserManager::Get()->GetLoggedInUsers().size() >= 3)
    616       return;
    617 
    618     // Launch sign in screen to add another user to current session.
    619     if (UserManager::Get()->GetUsersAdmittedForMultiProfile().size())
    620       UserAddingScreen::Get()->Start();
    621   }
    622 
    623   virtual void ShutDown() OVERRIDE {
    624     ash::Shell::GetInstance()->lock_state_controller()->RequestShutdown();
    625   }
    626 
    627   virtual void SignOut() OVERRIDE {
    628     chrome::AttemptUserExit();
    629   }
    630 
    631   virtual void RequestLockScreen() OVERRIDE {
    632     // TODO(antrim) : additional logging for crbug/173178
    633     LOG(WARNING) << "Requesting screen lock from AshSystemTrayDelegate";
    634     DBusThreadManager::Get()->GetSessionManagerClient()->RequestLockScreen();
    635   }
    636 
    637   virtual void RequestRestartForUpdate() OVERRIDE {
    638     // We expect that UpdateEngine is in "Reboot for update" state now.
    639     chrome::NotifyAndTerminate(true /* fast path */);
    640   }
    641 
    642   virtual void GetAvailableBluetoothDevices(
    643       ash::BluetoothDeviceList* list) OVERRIDE {
    644     device::BluetoothAdapter::DeviceList devices =
    645         bluetooth_adapter_->GetDevices();
    646     for (size_t i = 0; i < devices.size(); ++i) {
    647       device::BluetoothDevice* device = devices[i];
    648       ash::BluetoothDeviceInfo info;
    649       info.address = device->GetAddress();
    650       info.display_name = device->GetName();
    651       info.connected = device->IsConnected();
    652       info.connecting = device->IsConnecting();
    653       info.paired = device->IsPaired();
    654       list->push_back(info);
    655     }
    656   }
    657 
    658   virtual void BluetoothStartDiscovering() OVERRIDE {
    659     bluetooth_adapter_->StartDiscovering(
    660         base::Bind(&base::DoNothing),
    661         base::Bind(&BluetoothSetDiscoveringError));
    662   }
    663 
    664   virtual void BluetoothStopDiscovering() OVERRIDE {
    665     bluetooth_adapter_->StopDiscovering(
    666         base::Bind(&base::DoNothing),
    667         base::Bind(&BluetoothSetDiscoveringError));
    668   }
    669 
    670   virtual void ConnectToBluetoothDevice(const std::string& address) OVERRIDE {
    671     device::BluetoothDevice* device = bluetooth_adapter_->GetDevice(address);
    672     if (!device || device->IsConnecting() ||
    673         (device->IsConnected() && device->IsPaired())) {
    674       return;
    675     }
    676     if (device->IsPaired() && !device->IsConnectable())
    677       return;
    678     if (device->IsPaired() || !device->IsPairable()) {
    679       device->Connect(
    680           NULL,
    681           base::Bind(&base::DoNothing),
    682           base::Bind(&BluetoothDeviceConnectError));
    683     } else {  // Show paring dialog for the unpaired device.
    684       BluetoothPairingDialog* dialog =
    685           new BluetoothPairingDialog(GetNativeWindow(), device);
    686       // The dialog deletes itself on close.
    687       dialog->Show();
    688     }
    689   }
    690 
    691   virtual bool IsBluetoothDiscovering() OVERRIDE {
    692     return bluetooth_adapter_->IsDiscovering();
    693   }
    694 
    695   virtual void GetCurrentIME(ash::IMEInfo* info) OVERRIDE {
    696     input_method::InputMethodManager* manager =
    697         input_method::InputMethodManager::Get();
    698     input_method::InputMethodUtil* util = manager->GetInputMethodUtil();
    699     input_method::InputMethodDescriptor ime = manager->GetCurrentInputMethod();
    700     ExtractIMEInfo(ime, *util, info);
    701     info->selected = true;
    702   }
    703 
    704   virtual void GetAvailableIMEList(ash::IMEInfoList* list) OVERRIDE {
    705     input_method::InputMethodManager* manager =
    706         input_method::InputMethodManager::Get();
    707     input_method::InputMethodUtil* util = manager->GetInputMethodUtil();
    708     scoped_ptr<input_method::InputMethodDescriptors> ime_descriptors(
    709         manager->GetActiveInputMethods());
    710     std::string current = manager->GetCurrentInputMethod().id();
    711     for (size_t i = 0; i < ime_descriptors->size(); i++) {
    712       input_method::InputMethodDescriptor& ime = ime_descriptors->at(i);
    713       ash::IMEInfo info;
    714       ExtractIMEInfo(ime, *util, &info);
    715       info.selected = ime.id() == current;
    716       list->push_back(info);
    717     }
    718   }
    719 
    720   virtual void GetCurrentIMEProperties(
    721       ash::IMEPropertyInfoList* list) OVERRIDE {
    722     input_method::InputMethodManager* manager =
    723         input_method::InputMethodManager::Get();
    724     input_method::InputMethodUtil* util = manager->GetInputMethodUtil();
    725     input_method::InputMethodPropertyList properties =
    726         manager->GetCurrentInputMethodProperties();
    727     for (size_t i = 0; i < properties.size(); ++i) {
    728       ash::IMEPropertyInfo property;
    729       property.key = properties[i].key;
    730       property.name = util->TranslateString(properties[i].label);
    731       property.selected = properties[i].is_selection_item_checked;
    732       list->push_back(property);
    733     }
    734   }
    735 
    736   virtual void SwitchIME(const std::string& ime_id) OVERRIDE {
    737     input_method::InputMethodManager::Get()->ChangeInputMethod(ime_id);
    738   }
    739 
    740   virtual void ActivateIMEProperty(const std::string& key) OVERRIDE {
    741     input_method::InputMethodManager::Get()->
    742         ActivateInputMethodProperty(key);
    743   }
    744 
    745   virtual void CancelDriveOperation(int32 operation_id) OVERRIDE {
    746     DriveIntegrationService* integration_service =
    747         FindDriveIntegrationService();
    748     if (!integration_service)
    749       return;
    750 
    751     integration_service->job_list()->CancelJob(operation_id);
    752   }
    753 
    754   virtual void GetDriveOperationStatusList(
    755       ash::DriveOperationStatusList* list) OVERRIDE {
    756     DriveIntegrationService* integration_service =
    757         FindDriveIntegrationService();
    758     if (!integration_service)
    759       return;
    760 
    761     *list = ConvertToDriveStatusList(
    762         integration_service->job_list()->GetJobInfoList());
    763   }
    764 
    765   virtual void ConfigureNetwork(const std::string& network_id) OVERRIDE {
    766     network_connect::HandleUnconfiguredNetwork(network_id, GetNativeWindow());
    767   }
    768 
    769   virtual void EnrollOrConfigureNetwork(
    770       const std::string& network_id,
    771       gfx::NativeWindow parent_window) OVERRIDE {
    772     if (network_connect::EnrollNetwork(network_id, parent_window))
    773       return;
    774     network_connect::HandleUnconfiguredNetwork(network_id, parent_window);
    775   }
    776 
    777   virtual void ManageBluetoothDevices() OVERRIDE {
    778     content::RecordAction(
    779         content::UserMetricsAction("ShowBluetoothSettingsPage"));
    780     std::string sub_page = std::string(chrome::kSearchSubPage) + "#" +
    781         l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH);
    782     chrome::ShowSettingsSubPage(GetAppropriateBrowser(), sub_page);
    783   }
    784 
    785   virtual void ToggleBluetooth() OVERRIDE {
    786     bluetooth_adapter_->SetPowered(!bluetooth_adapter_->IsPowered(),
    787                                    base::Bind(&base::DoNothing),
    788                                    base::Bind(&BluetoothPowerFailure));
    789   }
    790 
    791   virtual void ShowMobileSimDialog() OVERRIDE {
    792     SimDialogDelegate::ShowDialog(GetNativeWindow(),
    793                                   SimDialogDelegate::SIM_DIALOG_UNLOCK);
    794   }
    795 
    796   virtual void ShowMobileSetup(const std::string& network_id) OVERRIDE {
    797     network_connect::ShowMobileSetup(network_id);
    798   }
    799 
    800   virtual void ShowOtherWifi() OVERRIDE {
    801     NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow());
    802   }
    803 
    804   virtual void ShowOtherVPN() OVERRIDE {
    805     NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow());
    806   }
    807 
    808   virtual void ShowOtherCellular() OVERRIDE {
    809     ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow());
    810   }
    811 
    812   virtual bool GetBluetoothAvailable() OVERRIDE {
    813     return bluetooth_adapter_->IsPresent();
    814   }
    815 
    816   virtual bool GetBluetoothEnabled() OVERRIDE {
    817     return bluetooth_adapter_->IsPowered();
    818   }
    819 
    820   virtual bool GetCellularCarrierInfo(std::string* carrier_id,
    821                                       std::string* topup_url,
    822                                       std::string* setup_url) OVERRIDE {
    823     bool result = false;
    824     NetworkLibrary* crosnet = NetworkLibrary::Get();
    825     const NetworkDevice* cellular = crosnet->FindCellularDevice();
    826     if (!cellular)
    827       return false;
    828 
    829     MobileConfig* config = MobileConfig::GetInstance();
    830     if (config->IsReady()) {
    831       *carrier_id = crosnet->GetCellularHomeCarrierId();
    832       const MobileConfig::Carrier* carrier = config->GetCarrier(*carrier_id);
    833       if (carrier) {
    834         *topup_url = carrier->top_up_url();
    835         result = true;
    836       }
    837       const MobileConfig::LocaleConfig* locale_config =
    838           config->GetLocaleConfig();
    839       if (locale_config) {
    840         // Only link to setup URL if SIM card is not inserted.
    841         if (cellular->is_sim_absent()) {
    842           *setup_url = locale_config->setup_url();
    843           result = true;
    844         }
    845       }
    846     }
    847     return result;
    848   }
    849 
    850   virtual void ShowCellularURL(const std::string& url) OVERRIDE {
    851     chrome::ShowSingletonTab(GetAppropriateBrowser(), GURL(url));
    852   }
    853 
    854   virtual void ChangeProxySettings() OVERRIDE {
    855     CHECK(GetUserLoginStatus() == ash::user::LOGGED_IN_NONE);
    856     LoginDisplayHostImpl::default_host()->OpenProxySettings();
    857   }
    858 
    859   virtual ash::VolumeControlDelegate*
    860   GetVolumeControlDelegate() const OVERRIDE {
    861     return volume_control_delegate_.get();
    862   }
    863 
    864   virtual void SetVolumeControlDelegate(
    865       scoped_ptr<ash::VolumeControlDelegate> delegate) OVERRIDE {
    866     volume_control_delegate_.swap(delegate);
    867   }
    868 
    869   virtual bool GetSessionStartTime(
    870       base::TimeTicks* session_start_time) OVERRIDE {
    871     *session_start_time = session_start_time_;
    872     return have_session_start_time_;
    873   }
    874 
    875   virtual bool GetSessionLengthLimit(
    876       base::TimeDelta* session_length_limit) OVERRIDE {
    877     *session_length_limit = session_length_limit_;
    878     return have_session_length_limit_;
    879   }
    880 
    881   virtual int GetSystemTrayMenuWidth() OVERRIDE {
    882     return l10n_util::GetLocalizedContentsWidthInPixels(
    883         IDS_SYSTEM_TRAY_MENU_BUBBLE_WIDTH_PIXELS);
    884   }
    885 
    886   virtual string16 FormatTimeDuration(
    887       const base::TimeDelta& delta) const OVERRIDE {
    888     return ui::TimeFormat::TimeDurationLong(delta);
    889   }
    890 
    891   virtual void MaybeSpeak(const std::string& utterance) const OVERRIDE {
    892     AccessibilityManager::Get()->MaybeSpeak(utterance);
    893   }
    894 
    895  private:
    896   ash::SystemTray* GetPrimarySystemTray() {
    897     return ash::Shell::GetInstance()->GetPrimarySystemTray();
    898   }
    899 
    900   ash::SystemTrayNotifier* GetSystemTrayNotifier() {
    901     return ash::Shell::GetInstance()->system_tray_notifier();
    902   }
    903 
    904   // Returns the last active browser. If there is no such browser, creates a new
    905   // browser window with an empty tab and returns it.
    906   Browser* GetAppropriateBrowser() {
    907     return chrome::FindOrCreateTabbedBrowser(
    908         ProfileManager::GetDefaultProfileOrOffTheRecord(),
    909         chrome::HOST_DESKTOP_TYPE_ASH);
    910   }
    911 
    912   void SetProfile(Profile* profile) {
    913     // Stop observing the current |user_profile_| on Drive integration status.
    914     UnobserveDriveUpdates();
    915 
    916     user_profile_ = profile;
    917 
    918     // Restart observation, now for the newly set |profile|.
    919     ObserveDriveUpdates();
    920 
    921     PrefService* prefs = profile->GetPrefs();
    922     user_pref_registrar_.reset(new PrefChangeRegistrar);
    923     user_pref_registrar_->Init(prefs);
    924     user_pref_registrar_->Add(
    925         prefs::kUse24HourClock,
    926         base::Bind(&SystemTrayDelegate::UpdateClockType,
    927                    base::Unretained(this)));
    928     user_pref_registrar_->Add(
    929         prefs::kLanguageRemapSearchKeyTo,
    930         base::Bind(&SystemTrayDelegate::OnLanguageRemapSearchKeyToChanged,
    931                    base::Unretained(this)));
    932     user_pref_registrar_->Add(
    933         prefs::kShowLogoutButtonInTray,
    934         base::Bind(&SystemTrayDelegate::UpdateShowLogoutButtonInTray,
    935                    base::Unretained(this)));
    936     user_pref_registrar_->Add(
    937         prefs::kLargeCursorEnabled,
    938         base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged,
    939                    base::Unretained(this),
    940                    ash::A11Y_NOTIFICATION_NONE));
    941     user_pref_registrar_->Add(
    942         prefs::kShouldAlwaysShowAccessibilityMenu,
    943         base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged,
    944                    base::Unretained(this),
    945                    ash::A11Y_NOTIFICATION_NONE));
    946     user_pref_registrar_->Add(
    947         prefs::kPerformanceTracingEnabled,
    948         base::Bind(&SystemTrayDelegate::UpdatePerformanceTracing,
    949                    base::Unretained(this)));
    950 
    951     UpdateClockType();
    952     UpdateShowLogoutButtonInTray();
    953     UpdatePerformanceTracing();
    954     search_key_mapped_to_ =
    955         profile->GetPrefs()->GetInteger(prefs::kLanguageRemapSearchKeyTo);
    956   }
    957 
    958   bool UnsetProfile(Profile* profile) {
    959     if (profile != user_profile_)
    960       return false;
    961     user_pref_registrar_.reset();
    962     return true;
    963   }
    964 
    965   void ObserveDriveUpdates() {
    966     DriveIntegrationService* integration_service =
    967         FindDriveIntegrationService();
    968     if (integration_service)
    969       integration_service->job_list()->AddObserver(this);
    970   }
    971 
    972   void UnobserveDriveUpdates() {
    973     DriveIntegrationService* integration_service =
    974         FindDriveIntegrationService();
    975     if (integration_service)
    976       integration_service->job_list()->RemoveObserver(this);
    977   }
    978 
    979   bool ShouldUse24HourClock() const {
    980     // On login screen and in guest mode owner default is used for
    981     // kUse24HourClock preference.
    982     // All other modes default to the default locale value.
    983     const ash::user::LoginStatus status = GetUserLoginStatus();
    984     const CrosSettings* const cros_settings = CrosSettings::Get();
    985     bool system_use_24_hour_clock = true;
    986     const bool system_value_found = cros_settings->GetBoolean(
    987         kSystemUse24HourClock, &system_use_24_hour_clock);
    988 
    989     if (status == ash::user::LOGGED_IN_NONE)
    990       return (system_value_found
    991                   ? system_use_24_hour_clock
    992                   : (base::GetHourClockType() == base::k24HourClock));
    993 
    994     const PrefService::Preference* user_pref =
    995         user_pref_registrar_->prefs()->FindPreference(prefs::kUse24HourClock);
    996     if (status == ash::user::LOGGED_IN_GUEST && user_pref->IsDefaultValue())
    997       return (system_value_found
    998                   ? system_use_24_hour_clock
    999                   : (base::GetHourClockType() == base::k24HourClock));
   1000 
   1001     bool use_24_hour_clock = true;
   1002     user_pref->GetValue()->GetAsBoolean(&use_24_hour_clock);
   1003     return use_24_hour_clock;
   1004   }
   1005 
   1006   void UpdateClockType() {
   1007     if (!user_pref_registrar_)
   1008       return;
   1009 
   1010     const bool use_24_hour_clock = ShouldUse24HourClock();
   1011     clock_type_ = use_24_hour_clock ? base::k24HourClock : base::k12HourClock;
   1012     GetSystemTrayNotifier()->NotifyDateFormatChanged();
   1013     // This also works for enterprise-managed devices because they never have
   1014     // local owner.
   1015     if (chromeos::UserManager::Get()->IsCurrentUserOwner())
   1016       CrosSettings::Get()->SetBoolean(kSystemUse24HourClock, use_24_hour_clock);
   1017   }
   1018 
   1019   void UpdateShowLogoutButtonInTray() {
   1020     GetSystemTrayNotifier()->NotifyShowLoginButtonChanged(
   1021         user_pref_registrar_->prefs()->GetBoolean(
   1022             prefs::kShowLogoutButtonInTray));
   1023   }
   1024 
   1025   void UpdateSessionStartTime() {
   1026     const PrefService* local_state = local_state_registrar_->prefs();
   1027     if (local_state->HasPrefPath(prefs::kSessionStartTime)) {
   1028       have_session_start_time_ = true;
   1029       session_start_time_ = base::TimeTicks::FromInternalValue(
   1030           local_state->GetInt64(prefs::kSessionStartTime));
   1031     } else {
   1032       have_session_start_time_ = false;
   1033       session_start_time_ = base::TimeTicks();
   1034     }
   1035     GetSystemTrayNotifier()->NotifySessionStartTimeChanged();
   1036   }
   1037 
   1038   void UpdateSessionLengthLimit() {
   1039     const PrefService* local_state = local_state_registrar_->prefs();
   1040     if (local_state->HasPrefPath(prefs::kSessionLengthLimit)) {
   1041       have_session_length_limit_ = true;
   1042       session_length_limit_ = base::TimeDelta::FromMilliseconds(
   1043           std::min(std::max(local_state->GetInteger(prefs::kSessionLengthLimit),
   1044                             kSessionLengthLimitMinMs),
   1045                    kSessionLengthLimitMaxMs));
   1046     } else {
   1047       have_session_length_limit_ = false;
   1048       session_length_limit_ = base::TimeDelta();
   1049     }
   1050     GetSystemTrayNotifier()->NotifySessionLengthLimitChanged();
   1051   }
   1052 
   1053   // LoginState::Observer overrides.
   1054   virtual void LoggedInStateChanged(
   1055       chromeos::LoginState::LoggedInState state) OVERRIDE {
   1056     UpdateClockType();
   1057   }
   1058 
   1059   // Overridden from PowerManagerClient::Observer.
   1060   virtual void BrightnessChanged(int level, bool user_initiated) OVERRIDE {
   1061     double leveld = static_cast<double>(level);
   1062     GetSystemTrayNotifier()->NotifyBrightnessChanged(leveld, user_initiated);
   1063   }
   1064 
   1065   // Overridden from PowerManagerClient::Observer:
   1066   virtual void SystemResumed(const base::TimeDelta& sleep_duration) OVERRIDE {
   1067     GetSystemTrayNotifier()->NotifyRefreshClock();
   1068   }
   1069 
   1070   // Overridden from SessionManagerClient::Observer.
   1071   virtual void LockScreen() OVERRIDE {
   1072     screen_locked_ = true;
   1073     ash::Shell::GetInstance()->UpdateAfterLoginStatusChange(
   1074         GetUserLoginStatus());
   1075   }
   1076 
   1077   virtual void UnlockScreen() OVERRIDE {
   1078     screen_locked_ = false;
   1079     ash::Shell::GetInstance()->UpdateAfterLoginStatusChange(
   1080         GetUserLoginStatus());
   1081   }
   1082 
   1083   // TODO(sad): Override more from PowerManagerClient::Observer here.
   1084 
   1085   gfx::NativeWindow GetNativeWindow() const {
   1086     return GetNativeWindowByStatus(GetUserLoginStatus());
   1087   }
   1088 
   1089   // Overridden from NetworkLibrary::NetworkManagerObserver.
   1090   virtual void OnNetworkManagerChanged(NetworkLibrary* crosnet) OVERRIDE {
   1091     // TODO(stevenjb): Migrate to NetworkStateHandler.
   1092     data_promo_notification_->ShowOptionalMobileDataPromoNotification(
   1093         crosnet, GetPrimarySystemTray(), this);
   1094     UpdateCellular();
   1095   }
   1096 
   1097   // content::NotificationObserver implementation.
   1098   virtual void Observe(int type,
   1099                        const content::NotificationSource& source,
   1100                        const content::NotificationDetails& details) OVERRIDE {
   1101     switch (type) {
   1102       case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: {
   1103         UpgradeDetector* detector =
   1104             content::Source<UpgradeDetector>(source).ptr();
   1105         ash::UpdateObserver::UpdateSeverity severity =
   1106             ash::UpdateObserver::UPDATE_NORMAL;
   1107         switch (detector->upgrade_notification_stage()) {
   1108           case UpgradeDetector::UPGRADE_ANNOYANCE_SEVERE:
   1109             severity = ash::UpdateObserver::UPDATE_SEVERE_RED;
   1110             break;
   1111 
   1112           case UpgradeDetector::UPGRADE_ANNOYANCE_HIGH:
   1113             severity = ash::UpdateObserver::UPDATE_HIGH_ORANGE;
   1114             break;
   1115 
   1116           case UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED:
   1117             severity = ash::UpdateObserver::UPDATE_LOW_GREEN;
   1118             break;
   1119 
   1120           case UpgradeDetector::UPGRADE_ANNOYANCE_LOW:
   1121           default:
   1122             severity = ash::UpdateObserver::UPDATE_NORMAL;
   1123             break;
   1124         }
   1125         GetSystemTrayNotifier()->NotifyUpdateRecommended(severity);
   1126         break;
   1127       }
   1128       case chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED: {
   1129         // This notification is also sent on login screen when user avatar
   1130         // is loaded from file.
   1131         if (GetUserLoginStatus() != ash::user::LOGGED_IN_NONE) {
   1132           GetSystemTrayNotifier()->NotifyUserUpdate();
   1133         }
   1134         break;
   1135       }
   1136       case chrome::NOTIFICATION_PROFILE_CREATED: {
   1137         SetProfile(content::Source<Profile>(source).ptr());
   1138         registrar_->Remove(this,
   1139                            chrome::NOTIFICATION_PROFILE_CREATED,
   1140                            content::NotificationService::AllSources());
   1141         break;
   1142       }
   1143       case chrome::NOTIFICATION_PROFILE_DESTROYED: {
   1144         if (UnsetProfile(content::Source<Profile>(source).ptr())) {
   1145           registrar_->Remove(this,
   1146                              chrome::NOTIFICATION_PROFILE_DESTROYED,
   1147                              content::NotificationService::AllSources());
   1148         }
   1149         break;
   1150       }
   1151       case chrome::NOTIFICATION_SESSION_STARTED: {
   1152         ash::Shell::GetInstance()->UpdateAfterLoginStatusChange(
   1153             GetUserLoginStatus());
   1154         SetProfile(ProfileManager::GetDefaultProfile());
   1155         break;
   1156       }
   1157       case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK:
   1158       case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE:
   1159       case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER: {
   1160         AccessibilityStatusEventDetails* accessibility_status =
   1161             content::Details<AccessibilityStatusEventDetails>(details).ptr();
   1162         OnAccessibilityModeChanged(accessibility_status->notify);
   1163         break;
   1164       }
   1165       default:
   1166         NOTREACHED();
   1167     }
   1168   }
   1169 
   1170   void OnLanguageRemapSearchKeyToChanged() {
   1171     search_key_mapped_to_ = user_pref_registrar_->prefs()->GetInteger(
   1172         prefs::kLanguageRemapSearchKeyTo);
   1173   }
   1174 
   1175   void OnAccessibilityModeChanged(
   1176       ash::AccessibilityNotificationVisibility notify) {
   1177     GetSystemTrayNotifier()->NotifyAccessibilityModeChanged(notify);
   1178   }
   1179 
   1180   void UpdatePerformanceTracing() {
   1181     if (!user_pref_registrar_)
   1182       return;
   1183     bool value =
   1184         user_pref_registrar_->prefs()->GetBoolean(
   1185             prefs::kPerformanceTracingEnabled);
   1186     GetSystemTrayNotifier()->NotifyTracingModeChanged(value);
   1187   }
   1188 
   1189   // Overridden from InputMethodManager::Observer.
   1190   virtual void InputMethodChanged(
   1191       input_method::InputMethodManager* manager, bool show_message) OVERRIDE {
   1192     GetSystemTrayNotifier()->NotifyRefreshIME(show_message);
   1193   }
   1194 
   1195   virtual void InputMethodPropertyChanged(
   1196       input_method::InputMethodManager* manager) OVERRIDE {
   1197     GetSystemTrayNotifier()->NotifyRefreshIME(false);
   1198   }
   1199 
   1200   // drive::JobListObserver overrides.
   1201   virtual void OnJobAdded(const drive::JobInfo& job_info) OVERRIDE {
   1202     OnJobUpdated(job_info);
   1203   }
   1204 
   1205   virtual void OnJobDone(const drive::JobInfo& job_info,
   1206                          drive::FileError error) OVERRIDE {
   1207     ash::DriveOperationStatus status;
   1208     if (ConvertToFinishedDriveOperationStatus(job_info, error, &status))
   1209       GetSystemTrayNotifier()->NotifyDriveJobUpdated(status);
   1210   }
   1211 
   1212   virtual void OnJobUpdated(const drive::JobInfo& job_info) OVERRIDE {
   1213     ash::DriveOperationStatus status;
   1214     if (ConvertToDriveOperationStatus(job_info, &status))
   1215       GetSystemTrayNotifier()->NotifyDriveJobUpdated(status);
   1216   }
   1217 
   1218   DriveIntegrationService* FindDriveIntegrationService() {
   1219     return user_profile_ ?
   1220         DriveIntegrationServiceFactory::FindForProfile(user_profile_) : NULL;
   1221   }
   1222 
   1223   // Overridden from system::TimezoneSettings::Observer.
   1224   virtual void TimezoneChanged(const icu::TimeZone& timezone) OVERRIDE {
   1225     GetSystemTrayNotifier()->NotifyRefreshClock();
   1226   }
   1227 
   1228   // Overridden from SystemClockClient::Observer.
   1229   virtual void SystemClockUpdated() OVERRIDE {
   1230     GetSystemTrayNotifier()->NotifySystemClockTimeUpdated();
   1231   }
   1232 
   1233   // Overridden from BluetoothAdapter::Observer.
   1234   virtual void AdapterPresentChanged(device::BluetoothAdapter* adapter,
   1235                                      bool present) OVERRIDE {
   1236     GetSystemTrayNotifier()->NotifyRefreshBluetooth();
   1237   }
   1238 
   1239   virtual void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
   1240                                      bool powered) OVERRIDE {
   1241     GetSystemTrayNotifier()->NotifyRefreshBluetooth();
   1242   }
   1243 
   1244   virtual void AdapterDiscoveringChanged(device::BluetoothAdapter* adapter,
   1245                                          bool discovering) OVERRIDE {
   1246     GetSystemTrayNotifier()->NotifyBluetoothDiscoveringChanged();
   1247   }
   1248 
   1249   virtual void DeviceAdded(device::BluetoothAdapter* adapter,
   1250                            device::BluetoothDevice* device) OVERRIDE {
   1251     GetSystemTrayNotifier()->NotifyRefreshBluetooth();
   1252   }
   1253 
   1254   virtual void DeviceChanged(device::BluetoothAdapter* adapter,
   1255                              device::BluetoothDevice* device) OVERRIDE {
   1256     GetSystemTrayNotifier()->NotifyRefreshBluetooth();
   1257   }
   1258 
   1259   virtual void DeviceRemoved(device::BluetoothAdapter* adapter,
   1260                              device::BluetoothDevice* device) OVERRIDE {
   1261     GetSystemTrayNotifier()->NotifyRefreshBluetooth();
   1262   }
   1263 
   1264   // Overridden from SystemKeyEventListener::CapsLockObserver.
   1265   virtual void OnCapsLockChange(bool enabled) OVERRIDE {
   1266     bool search_mapped_to_caps_lock = false;
   1267     if (!base::chromeos::IsRunningOnChromeOS() ||
   1268         search_key_mapped_to_ == input_method::kCapsLockKey)
   1269       search_mapped_to_caps_lock = true;
   1270     GetSystemTrayNotifier()->NotifyCapsLockChanged(
   1271         enabled, search_mapped_to_caps_lock);
   1272   }
   1273 
   1274   // Overridden from ash::NetworkTrayDelegate
   1275   virtual void NotificationLinkClicked(
   1276       ash::NetworkObserver::MessageType message_type,
   1277       size_t link_index) OVERRIDE {
   1278     if (message_type == ash::NetworkObserver::ERROR_OUT_OF_CREDITS) {
   1279       const NetworkState* cellular =
   1280           NetworkHandler::Get()->network_state_handler()->
   1281           FirstNetworkByType(flimflam::kTypeCellular);
   1282       std::string service_path = cellular ? cellular->path() : "";
   1283       ShowNetworkSettings(service_path);
   1284 
   1285       ash::Shell::GetInstance()->system_tray_notifier()->
   1286           NotifyClearNetworkMessage(message_type);
   1287     }
   1288     if (message_type != ash::NetworkObserver::MESSAGE_DATA_PROMO)
   1289       return;
   1290     // If we have deal info URL defined that means that there're
   1291     // 2 links in bubble. Let the user close it manually then thus giving
   1292     // ability to navigate to second link.
   1293     // mobile_data_bubble_ will be set to NULL in BubbleClosing callback.
   1294     std::string deal_info_url = data_promo_notification_->deal_info_url();
   1295     std::string deal_topup_url = data_promo_notification_->deal_topup_url();
   1296     if (deal_info_url.empty())
   1297       data_promo_notification_->CloseNotification();
   1298 
   1299     std::string deal_url_to_open;
   1300     if (link_index == 0) {
   1301       if (!deal_topup_url.empty()) {
   1302         deal_url_to_open = deal_topup_url;
   1303       } else {
   1304         const Network* cellular =
   1305             NetworkLibrary::Get()->cellular_network();
   1306         if (!cellular)
   1307           return;
   1308         ShowNetworkSettings(cellular->service_path());
   1309         return;
   1310       }
   1311     } else if (link_index == 1) {
   1312       deal_url_to_open = deal_info_url;
   1313     }
   1314 
   1315     if (!deal_url_to_open.empty()) {
   1316       Browser* browser = GetAppropriateBrowser();
   1317       if (!browser)
   1318         return;
   1319       chrome::ShowSingletonTab(browser, GURL(deal_url_to_open));
   1320     }
   1321   }
   1322 
   1323   virtual void UpdateEnterpriseDomain() {
   1324     std::string enterprise_domain =
   1325         g_browser_process->browser_policy_connector()->GetEnterpriseDomain();
   1326     if (enterprise_domain_ != enterprise_domain) {
   1327        enterprise_domain_ = enterprise_domain;
   1328        GetSystemTrayNotifier()->NotifyEnterpriseDomainChanged();
   1329     }
   1330   }
   1331 
   1332   // Overridden from CloudPolicyStore::Observer
   1333   virtual void OnStoreLoaded(policy::CloudPolicyStore* store) OVERRIDE {
   1334     UpdateEnterpriseDomain();
   1335   }
   1336 
   1337   virtual void OnStoreError(policy::CloudPolicyStore* store) OVERRIDE {
   1338     UpdateEnterpriseDomain();
   1339   }
   1340 
   1341   // Overridden from ash::SessionStateObserver
   1342   virtual void ActiveUserChanged(const std::string& user_id) OVERRIDE {
   1343     GetSystemTrayNotifier()->NotifyUserUpdate();
   1344   }
   1345 
   1346   void UpdateCellular() {
   1347     const CellularNetworkVector& cellular_networks =
   1348         NetworkLibrary::Get()->cellular_networks();
   1349     if (cellular_networks.empty())
   1350       return;
   1351     // We only care about the first cellular network (in practice there will
   1352     // only ever be one)
   1353     const CellularNetwork* cellular = cellular_networks[0];
   1354     if (cellular->activation_state() == ACTIVATION_STATE_ACTIVATING) {
   1355       cellular_activating_ = true;
   1356     } else if (cellular->activated() && cellular_activating_) {
   1357       cellular_activating_ = false;
   1358       ash::NetworkObserver::NetworkType type = NetworkTypeForCellular(cellular);
   1359       ash::Shell::GetInstance()->system_tray_notifier()->
   1360           NotifySetNetworkMessage(
   1361               NULL,
   1362               ash::NetworkObserver::MESSAGE_DATA_PROMO,
   1363               type,
   1364               l10n_util::GetStringUTF16(IDS_NETWORK_CELLULAR_ACTIVATED_TITLE),
   1365               l10n_util::GetStringFUTF16(IDS_NETWORK_CELLULAR_ACTIVATED,
   1366                                          UTF8ToUTF16((cellular->name()))),
   1367               std::vector<string16>());
   1368     }
   1369   }
   1370 
   1371   scoped_ptr<base::WeakPtrFactory<SystemTrayDelegate> > ui_weak_ptr_factory_;
   1372   scoped_ptr<content::NotificationRegistrar> registrar_;
   1373   scoped_ptr<PrefChangeRegistrar> local_state_registrar_;
   1374   scoped_ptr<PrefChangeRegistrar> user_pref_registrar_;
   1375   Profile* user_profile_;
   1376   std::string active_network_path_;
   1377   base::HourClockType clock_type_;
   1378   int search_key_mapped_to_;
   1379   bool screen_locked_;
   1380   bool have_session_start_time_;
   1381   base::TimeTicks session_start_time_;
   1382   bool have_session_length_limit_;
   1383   base::TimeDelta session_length_limit_;
   1384   std::string enterprise_domain_;
   1385 
   1386   scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_;
   1387 
   1388   scoped_ptr<DataPromoNotification> data_promo_notification_;
   1389   bool cellular_activating_;
   1390   bool cellular_out_of_credits_;
   1391 
   1392   scoped_ptr<ash::VolumeControlDelegate> volume_control_delegate_;
   1393 
   1394   DISALLOW_COPY_AND_ASSIGN(SystemTrayDelegate);
   1395 };
   1396 
   1397 }  // namespace
   1398 
   1399 ash::SystemTrayDelegate* CreateSystemTrayDelegate() {
   1400   return new chromeos::SystemTrayDelegate();
   1401 }
   1402 
   1403 }  // namespace chromeos
   1404