blob: d07ce2fa923a24906645d66ff2193cbaebc095d7 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/ash/system_tray_delegate_chromeos.h"
#include <stddef.h>
#include <algorithm>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "ash/common/login_status.h"
#include "ash/common/session/session_state_delegate.h"
#include "ash/common/session/session_state_observer.h"
#include "ash/common/shell_delegate.h"
#include "ash/common/system/chromeos/bluetooth/bluetooth_observer.h"
#include "ash/common/system/chromeos/power/power_status.h"
#include "ash/common/system/chromeos/session/logout_button_observer.h"
#include "ash/common/system/date/clock_observer.h"
#include "ash/common/system/ime/ime_observer.h"
#include "ash/common/system/tray/system_tray_notifier.h"
#include "ash/common/system/tray_accessibility.h"
#include "ash/common/system/update/update_observer.h"
#include "ash/common/system/user/user_observer.h"
#include "ash/common/wm_shell.h"
#include "ash/system/chromeos/rotation/tray_rotation_lock.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
#include "chrome/browser/chromeos/bluetooth/bluetooth_pairing_dialog.h"
#include "chrome/browser/chromeos/events/system_key_event_listener.h"
#include "chrome/browser/chromeos/input_method/input_method_switch_recorder.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/help_app_launcher.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
#include "chrome/browser/chromeos/login/user_flow.h"
#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
#include "chrome/browser/chromeos/profiles/multiprofiles_intro_dialog.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/cast_config_delegate_media_router.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/ash/networking_config_delegate_chromeos.h"
#include "chrome/browser/ui/ash/system_tray_client.h"
#include "chrome/browser/ui/ash/system_tray_delegate_utils.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/upgrade_detector.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/features.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/locale_settings.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/login/login_state.h"
#include "chromeos/network/portal_detector/network_portal_detector.h"
#include "components/google/core/browser/google_util.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_type.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/user_metrics.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "ui/base/ime/chromeos/extension_ime_util.h"
#include "ui/base/ime/chromeos/input_method_manager.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/time_format.h"
#include "ui/chromeos/ime/input_method_menu_item.h"
#include "ui/chromeos/ime/input_method_menu_manager.h"
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#endif
namespace chromeos {
namespace {
// The minimum session length limit that can be set.
const int kSessionLengthLimitMinMs = 30 * 1000; // 30 seconds.
// The maximum session length limit that can be set.
const int kSessionLengthLimitMaxMs = 24 * 60 * 60 * 1000; // 24 hours.
void ExtractIMEInfo(const input_method::InputMethodDescriptor& ime,
const input_method::InputMethodUtil& util,
ash::IMEInfo* info) {
info->id = ime.id();
info->name = util.GetInputMethodLongName(ime);
info->medium_name = util.GetInputMethodMediumName(ime);
info->short_name = util.GetInputMethodShortName(ime);
info->third_party = extension_ime_util::IsExtensionIME(ime.id());
}
void BluetoothSetDiscoveringError() {
LOG(ERROR) << "BluetoothSetDiscovering failed.";
}
void BluetoothDeviceConnectError(
device::BluetoothDevice::ConnectErrorCode error_code) {
}
void OnAcceptMultiprofilesIntro(bool no_show_again) {
PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs();
prefs->SetBoolean(prefs::kMultiProfileNeverShowIntro, no_show_again);
UserAddingScreen::Get()->Start();
}
bool IsSessionInSecondaryLoginScreen() {
return ash::WmShell::Get()
->GetSessionStateDelegate()
->IsInSecondaryLoginScreen();
}
} // namespace
SystemTrayDelegateChromeOS::SystemTrayDelegateChromeOS()
: cast_config_delegate_(base::MakeUnique<CastConfigDelegateMediaRouter>()),
networking_config_delegate_(new NetworkingConfigDelegateChromeos()),
weak_ptr_factory_(this) {
// Register notifications on construction so that events such as
// PROFILE_CREATED do not get missed if they happen before Initialize().
registrar_.reset(new content::NotificationRegistrar);
registrar_->Add(this,
chrome::NOTIFICATION_UPGRADE_RECOMMENDED,
content::NotificationService::AllSources());
registrar_->Add(this,
chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED,
content::NotificationService::AllSources());
if (GetUserLoginStatus() == ash::LoginStatus::NOT_LOGGED_IN) {
registrar_->Add(this,
chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources());
}
registrar_->Add(this,
chrome::NOTIFICATION_PROFILE_CREATED,
content::NotificationService::AllSources());
registrar_->Add(this,
chrome::NOTIFICATION_PROFILE_DESTROYED,
content::NotificationService::AllSources());
AccessibilityManager* accessibility_manager = AccessibilityManager::Get();
CHECK(accessibility_manager);
accessibility_subscription_ = accessibility_manager->RegisterCallback(
base::Bind(&SystemTrayDelegateChromeOS::OnAccessibilityStatusChanged,
base::Unretained(this)));
user_manager::UserManager::Get()->AddSessionStateObserver(this);
}
void SystemTrayDelegateChromeOS::Initialize() {
DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
input_method::InputMethodManager::Get()->AddObserver(this);
input_method::InputMethodManager::Get()->AddImeMenuObserver(this);
ui::ime::InputMethodMenuManager::GetInstance()->AddObserver(this);
device::BluetoothAdapterFactory::GetAdapter(
base::Bind(&SystemTrayDelegateChromeOS::InitializeOnAdapterReady,
weak_ptr_factory_.GetWeakPtr()));
ash::WmShell::Get()->GetSessionStateDelegate()->AddSessionStateObserver(this);
BrowserList::AddObserver(this);
}
void SystemTrayDelegateChromeOS::InitializeOnAdapterReady(
scoped_refptr<device::BluetoothAdapter> adapter) {
bluetooth_adapter_ = adapter;
CHECK(bluetooth_adapter_);
bluetooth_adapter_->AddObserver(this);
local_state_registrar_.reset(new PrefChangeRegistrar);
local_state_registrar_->Init(g_browser_process->local_state());
UpdateSessionStartTime();
UpdateSessionLengthLimit();
local_state_registrar_->Add(
prefs::kSessionStartTime,
base::Bind(&SystemTrayDelegateChromeOS::UpdateSessionStartTime,
base::Unretained(this)));
local_state_registrar_->Add(
prefs::kSessionLengthLimit,
base::Bind(&SystemTrayDelegateChromeOS::UpdateSessionLengthLimit,
base::Unretained(this)));
policy::BrowserPolicyConnectorChromeOS* policy_connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
policy::DeviceCloudPolicyManagerChromeOS* policy_manager =
policy_connector->GetDeviceCloudPolicyManager();
if (policy_manager)
policy_manager->core()->store()->AddObserver(this);
UpdateEnterpriseDomain();
}
SystemTrayDelegateChromeOS::~SystemTrayDelegateChromeOS() {
// Unregister PrefChangeRegistrars.
local_state_registrar_.reset();
user_pref_registrar_.reset();
// Unregister content notifications before destroying any components.
registrar_.reset();
// Unregister a11y status subscription.
accessibility_subscription_.reset();
DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
input_method::InputMethodManager::Get()->RemoveObserver(this);
ui::ime::InputMethodMenuManager::GetInstance()->RemoveObserver(this);
if (bluetooth_adapter_)
bluetooth_adapter_->RemoveObserver(this);
ash::WmShell::Get()->GetSessionStateDelegate()->RemoveSessionStateObserver(
this);
BrowserList::RemoveObserver(this);
StopObservingAppWindowRegistry();
StopObservingCustodianInfoChanges();
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
policy::DeviceCloudPolicyManagerChromeOS* policy_manager =
connector->GetDeviceCloudPolicyManager();
if (policy_manager)
policy_manager->core()->store()->RemoveObserver(this);
user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
}
ash::LoginStatus SystemTrayDelegateChromeOS::GetUserLoginStatus() const {
return SystemTrayClient::GetUserLoginStatus();
}
std::string SystemTrayDelegateChromeOS::GetEnterpriseDomain() const {
return enterprise_domain_;
}
std::string SystemTrayDelegateChromeOS::GetEnterpriseRealm() const {
return enterprise_realm_;
}
base::string16 SystemTrayDelegateChromeOS::GetEnterpriseMessage() const {
if (!GetEnterpriseRealm().empty()) {
// TODO(rsorokin): Maybe change a message for the Active Directory devices.
return l10n_util::GetStringFUTF16(IDS_DEVICE_OWNED_BY_NOTICE,
base::UTF8ToUTF16(GetEnterpriseRealm()));
}
if (!GetEnterpriseDomain().empty()) {
return l10n_util::GetStringFUTF16(IDS_DEVICE_OWNED_BY_NOTICE,
base::UTF8ToUTF16(GetEnterpriseDomain()));
}
return base::string16();
}
std::string SystemTrayDelegateChromeOS::GetSupervisedUserManager() const {
if (!IsUserSupervised())
return std::string();
return SupervisedUserServiceFactory::GetForProfile(user_profile_)->
GetCustodianEmailAddress();
}
base::string16
SystemTrayDelegateChromeOS::GetSupervisedUserManagerName() const {
if (!IsUserSupervised())
return base::string16();
return base::UTF8ToUTF16(SupervisedUserServiceFactory::GetForProfile(
user_profile_)->GetCustodianName());
}
base::string16 SystemTrayDelegateChromeOS::GetSupervisedUserMessage()
const {
if (!IsUserSupervised())
return base::string16();
if (IsUserChild())
return GetChildUserMessage();
return GetLegacySupervisedUserMessage();
}
bool SystemTrayDelegateChromeOS::IsUserSupervised() const {
user_manager::User* user = user_manager::UserManager::Get()->GetActiveUser();
return user && user->IsSupervised();
}
bool SystemTrayDelegateChromeOS::IsUserChild() const {
return user_manager::UserManager::Get()->IsLoggedInAsChildUser();
}
void SystemTrayDelegateChromeOS::GetSystemUpdateInfo(
ash::UpdateInfo* info) const {
GetUpdateInfo(UpgradeDetector::GetInstance(), info);
}
bool SystemTrayDelegateChromeOS::ShouldShowSettings() const {
// Show setting button only when the user flow allows and it's not in the
// multi-profile login screen.
return ChromeUserManager::Get()->GetCurrentUserFlow()->ShouldShowSettings() &&
!IsSessionInSecondaryLoginScreen();
}
bool SystemTrayDelegateChromeOS::ShouldShowNotificationTray() const {
// Show notification tray only when the user flow allows and it's not in the
// multi-profile login screen.
return ChromeUserManager::Get()
->GetCurrentUserFlow()
->ShouldShowNotificationTray() &&
!IsSessionInSecondaryLoginScreen();
}
void SystemTrayDelegateChromeOS::ShowEnterpriseInfo() {
// TODO(mash): Refactor out SessionStateDelegate and move to SystemTrayClient.
ash::LoginStatus status = GetUserLoginStatus();
if (status == ash::LoginStatus::NOT_LOGGED_IN ||
status == ash::LoginStatus::LOCKED || IsSessionInSecondaryLoginScreen()) {
scoped_refptr<chromeos::HelpAppLauncher> help_app(
new chromeos::HelpAppLauncher(nullptr /* parent_window */));
help_app->ShowHelpTopic(chromeos::HelpAppLauncher::HELP_ENTERPRISE);
} else {
chrome::ScopedTabbedBrowserDisplayer displayer(
ProfileManager::GetActiveUserProfile());
chrome::ShowSingletonTab(displayer.browser(),
GURL(chrome::kLearnMoreEnterpriseURL));
}
}
void SystemTrayDelegateChromeOS::ShowUserLogin() {
ash::WmShell* wm_shell = ash::WmShell::Get();
if (!wm_shell->delegate()->IsMultiProfilesEnabled())
return;
// Only regular non-supervised users could add other users to current session.
if (user_manager::UserManager::Get()->GetActiveUser()->GetType() !=
user_manager::USER_TYPE_REGULAR) {
return;
}
if (static_cast<int>(
user_manager::UserManager::Get()->GetLoggedInUsers().size()) >=
wm_shell->GetSessionStateDelegate()->GetMaximumNumberOfLoggedInUsers()) {
return;
}
// Launch sign in screen to add another user to current session.
if (user_manager::UserManager::Get()
->GetUsersAllowedForMultiProfile()
.size()) {
// Don't show dialog if any logged in user in multi-profiles session
// dismissed it.
bool show_intro = true;
const user_manager::UserList logged_in_users =
user_manager::UserManager::Get()->GetLoggedInUsers();
for (user_manager::UserList::const_iterator it = logged_in_users.begin();
it != logged_in_users.end();
++it) {
show_intro &=
!multi_user_util::GetProfileFromAccountId((*it)->GetAccountId())
->GetPrefs()
->GetBoolean(prefs::kMultiProfileNeverShowIntro);
if (!show_intro)
break;
}
if (show_intro) {
base::Callback<void(bool)> on_accept =
base::Bind(&OnAcceptMultiprofilesIntro);
ShowMultiprofilesIntroDialog(on_accept);
} else {
UserAddingScreen::Get()->Start();
}
}
}
void SystemTrayDelegateChromeOS::GetAvailableBluetoothDevices(
ash::BluetoothDeviceList* list) {
device::BluetoothAdapter::DeviceList devices =
bluetooth_adapter_->GetDevices();
for (size_t i = 0; i < devices.size(); ++i) {
device::BluetoothDevice* device = devices[i];
ash::BluetoothDeviceInfo info;
info.address = device->GetAddress();
info.display_name = device->GetNameForDisplay();
info.connected = device->IsConnected();
info.connecting = device->IsConnecting();
info.paired = device->IsPaired();
info.device_type = device->GetDeviceType();
list->push_back(info);
}
}
void SystemTrayDelegateChromeOS::BluetoothStartDiscovering() {
if (GetBluetoothDiscovering()) {
LOG(WARNING) << "Already have active Bluetooth device discovery session.";
return;
}
VLOG(1) << "Requesting new Bluetooth device discovery session.";
should_run_bluetooth_discovery_ = true;
bluetooth_adapter_->StartDiscoverySession(
base::Bind(&SystemTrayDelegateChromeOS::OnStartBluetoothDiscoverySession,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&BluetoothSetDiscoveringError));
}
void SystemTrayDelegateChromeOS::BluetoothStopDiscovering() {
should_run_bluetooth_discovery_ = false;
if (!GetBluetoothDiscovering()) {
LOG(WARNING) << "No active Bluetooth device discovery session.";
return;
}
VLOG(1) << "Stopping Bluetooth device discovery session.";
bluetooth_discovery_session_->Stop(
base::Bind(&base::DoNothing), base::Bind(&BluetoothSetDiscoveringError));
}
void SystemTrayDelegateChromeOS::ConnectToBluetoothDevice(
const std::string& address) {
device::BluetoothDevice* device = bluetooth_adapter_->GetDevice(address);
if (!device || device->IsConnecting() ||
(device->IsConnected() && device->IsPaired())) {
return;
}
if (device->IsPaired() && !device->IsConnectable())
return;
if (device->IsPaired() || !device->IsPairable()) {
base::RecordAction(
base::UserMetricsAction("StatusArea_Bluetooth_Connect_Known"));
device->Connect(NULL,
base::Bind(&base::DoNothing),
base::Bind(&BluetoothDeviceConnectError));
return;
}
// Show pairing dialog for the unpaired device.
base::RecordAction(
base::UserMetricsAction("StatusArea_Bluetooth_Connect_Unknown"));
BluetoothPairingDialog* dialog = new BluetoothPairingDialog(device);
// The dialog deletes itself on close.
dialog->ShowInContainer(SystemTrayClient::GetDialogParentContainerId());
}
bool SystemTrayDelegateChromeOS::IsBluetoothDiscovering() const {
return bluetooth_adapter_ && bluetooth_adapter_->IsDiscovering();
}
void SystemTrayDelegateChromeOS::GetCurrentIME(ash::IMEInfo* info) {
input_method::InputMethodManager* manager =
input_method::InputMethodManager::Get();
input_method::InputMethodUtil* util = manager->GetInputMethodUtil();
input_method::InputMethodDescriptor ime =
manager->GetActiveIMEState()->GetCurrentInputMethod();
ExtractIMEInfo(ime, *util, info);
info->selected = true;
}
void SystemTrayDelegateChromeOS::GetAvailableIMEList(ash::IMEInfoList* list) {
input_method::InputMethodManager* manager =
input_method::InputMethodManager::Get();
input_method::InputMethodUtil* util = manager->GetInputMethodUtil();
std::unique_ptr<input_method::InputMethodDescriptors> ime_descriptors(
manager->GetActiveIMEState()->GetActiveInputMethods());
std::string current =
manager->GetActiveIMEState()->GetCurrentInputMethod().id();
for (size_t i = 0; i < ime_descriptors->size(); i++) {
input_method::InputMethodDescriptor& ime = ime_descriptors->at(i);
ash::IMEInfo info;
ExtractIMEInfo(ime, *util, &info);
info.selected = ime.id() == current;
list->push_back(info);
}
}
void SystemTrayDelegateChromeOS::GetCurrentIMEProperties(
ash::IMEPropertyInfoList* list) {
ui::ime::InputMethodMenuItemList menu_list =
ui::ime::InputMethodMenuManager::GetInstance()->
GetCurrentInputMethodMenuItemList();
for (size_t i = 0; i < menu_list.size(); ++i) {
ash::IMEPropertyInfo property;
property.key = menu_list[i].key;
property.name = base::UTF8ToUTF16(menu_list[i].label);
property.selected = menu_list[i].is_selection_item_checked;
list->push_back(property);
}
}
void SystemTrayDelegateChromeOS::SwitchIME(const std::string& ime_id) {
input_method::InputMethodManager::Get()
->GetActiveIMEState()
->ChangeInputMethod(ime_id, false /* show_message */);
input_method::InputMethodSwitchRecorder::Get()->RecordSwitch(
true /* by_tray_menu */);
}
void SystemTrayDelegateChromeOS::ActivateIMEProperty(const std::string& key) {
input_method::InputMethodManager::Get()->ActivateInputMethodMenuItem(key);
}
void SystemTrayDelegateChromeOS::ManageBluetoothDevices() {
content::RecordAction(base::UserMetricsAction("ShowBluetoothSettingsPage"));
chrome::ShowSettingsSubPageForProfile(ProfileManager::GetActiveUserProfile(),
chrome::kBluetoothSubPage);
}
void SystemTrayDelegateChromeOS::ToggleBluetooth() {
bluetooth_adapter_->SetPowered(!bluetooth_adapter_->IsPowered(),
base::Bind(&base::DoNothing),
base::Bind(&base::DoNothing));
}
bool SystemTrayDelegateChromeOS::GetBluetoothAvailable() {
return bluetooth_adapter_ && bluetooth_adapter_->IsPresent();
}
bool SystemTrayDelegateChromeOS::GetBluetoothEnabled() {
return bluetooth_adapter_ && bluetooth_adapter_->IsPowered();
}
bool SystemTrayDelegateChromeOS::GetBluetoothDiscovering() {
return bluetooth_discovery_session_ &&
bluetooth_discovery_session_->IsActive();
}
ash::CastConfigDelegate* SystemTrayDelegateChromeOS::GetCastConfigDelegate() {
return cast_config_delegate_.get();
}
ash::NetworkingConfigDelegate*
SystemTrayDelegateChromeOS::GetNetworkingConfigDelegate() const {
return networking_config_delegate_.get();
}
bool SystemTrayDelegateChromeOS::GetSessionStartTime(
base::TimeTicks* session_start_time) {
*session_start_time = session_start_time_;
return have_session_start_time_;
}
bool SystemTrayDelegateChromeOS::GetSessionLengthLimit(
base::TimeDelta* session_length_limit) {
*session_length_limit = session_length_limit_;
return have_session_length_limit_;
}
int SystemTrayDelegateChromeOS::GetSystemTrayMenuWidth() {
return l10n_util::GetLocalizedContentsWidthInPixels(
IDS_SYSTEM_TRAY_MENU_BUBBLE_WIDTH_PIXELS);
}
void SystemTrayDelegateChromeOS::ActiveUserWasChanged() {
SetProfile(ProfileManager::GetActiveUserProfile());
GetSystemTrayNotifier()->NotifyUserUpdate();
}
bool SystemTrayDelegateChromeOS::IsSearchKeyMappedToCapsLock() {
return search_key_mapped_to_ == input_method::kCapsLockKey;
}
void SystemTrayDelegateChromeOS::AddCustodianInfoTrayObserver(
ash::CustodianInfoTrayObserver* observer) {
custodian_info_changed_observers_.AddObserver(observer);
}
void SystemTrayDelegateChromeOS::RemoveCustodianInfoTrayObserver(
ash::CustodianInfoTrayObserver* observer) {
custodian_info_changed_observers_.RemoveObserver(observer);
}
std::unique_ptr<ash::SystemTrayItem>
SystemTrayDelegateChromeOS::CreateRotationLockTrayItem(ash::SystemTray* tray) {
return base::MakeUnique<ash::TrayRotationLock>(tray);
}
void SystemTrayDelegateChromeOS::UserAddedToSession(
const user_manager::User* active_user) {
}
void SystemTrayDelegateChromeOS::ActiveUserChanged(
const user_manager::User* /* active_user */) {
}
void SystemTrayDelegateChromeOS::UserChangedChildStatus(
user_manager::User* user) {
Profile* user_profile = ProfileHelper::Get()->GetProfileByUser(user);
// Returned user_profile might be NULL on restoring Users on browser start.
// At some point profile is not yet fully initiated.
if (session_started_ && user_profile && user_profile_ == user_profile)
ash::WmShell::Get()->UpdateAfterLoginStatusChange(GetUserLoginStatus());
}
ash::SystemTrayNotifier* SystemTrayDelegateChromeOS::GetSystemTrayNotifier() {
return ash::WmShell::Get()->system_tray_notifier();
}
void SystemTrayDelegateChromeOS::SetProfile(Profile* profile) {
// Stop observing the AppWindowRegistry of the current |user_profile_|.
StopObservingAppWindowRegistry();
// Stop observing custodian info changes of the current |user_profile_|.
StopObservingCustodianInfoChanges();
user_profile_ = profile;
// Start observing the AppWindowRegistry of the newly set |user_profile_|.
extensions::AppWindowRegistry::Get(user_profile_)->AddObserver(this);
// Start observing custodian info changes of the newly set |user_profile_|.
SupervisedUserServiceFactory::GetForProfile(profile)->AddObserver(this);
PrefService* prefs = profile->GetPrefs();
user_pref_registrar_.reset(new PrefChangeRegistrar);
user_pref_registrar_->Init(prefs);
user_pref_registrar_->Add(
prefs::kLanguageRemapSearchKeyTo,
base::Bind(&SystemTrayDelegateChromeOS::OnLanguageRemapSearchKeyToChanged,
base::Unretained(this)));
user_pref_registrar_->Add(
prefs::kShowLogoutButtonInTray,
base::Bind(&SystemTrayDelegateChromeOS::UpdateShowLogoutButtonInTray,
base::Unretained(this)));
user_pref_registrar_->Add(
prefs::kLogoutDialogDurationMs,
base::Bind(&SystemTrayDelegateChromeOS::UpdateLogoutDialogDuration,
base::Unretained(this)));
user_pref_registrar_->Add(
prefs::kAccessibilityLargeCursorEnabled,
base::Bind(&SystemTrayDelegateChromeOS::OnAccessibilityModeChanged,
base::Unretained(this), ash::A11Y_NOTIFICATION_NONE));
user_pref_registrar_->Add(
prefs::kAccessibilityAutoclickEnabled,
base::Bind(&SystemTrayDelegateChromeOS::OnAccessibilityModeChanged,
base::Unretained(this), ash::A11Y_NOTIFICATION_NONE));
user_pref_registrar_->Add(
prefs::kShouldAlwaysShowAccessibilityMenu,
base::Bind(&SystemTrayDelegateChromeOS::OnAccessibilityModeChanged,
base::Unretained(this), ash::A11Y_NOTIFICATION_NONE));
user_pref_registrar_->Add(
prefs::kPerformanceTracingEnabled,
base::Bind(&SystemTrayDelegateChromeOS::UpdatePerformanceTracing,
base::Unretained(this)));
UpdateShowLogoutButtonInTray();
UpdateLogoutDialogDuration();
UpdatePerformanceTracing();
OnCustodianInfoChanged();
search_key_mapped_to_ =
profile->GetPrefs()->GetInteger(prefs::kLanguageRemapSearchKeyTo);
}
bool SystemTrayDelegateChromeOS::UnsetProfile(Profile* profile) {
if (profile != user_profile_)
return false;
user_pref_registrar_.reset();
user_profile_ = NULL;
return true;
}
void SystemTrayDelegateChromeOS::UpdateShowLogoutButtonInTray() {
GetSystemTrayNotifier()->NotifyShowLoginButtonChanged(
user_pref_registrar_->prefs()->GetBoolean(
prefs::kShowLogoutButtonInTray));
}
void SystemTrayDelegateChromeOS::UpdateLogoutDialogDuration() {
const int duration_ms =
user_pref_registrar_->prefs()->GetInteger(prefs::kLogoutDialogDurationMs);
GetSystemTrayNotifier()->NotifyLogoutDialogDurationChanged(
base::TimeDelta::FromMilliseconds(duration_ms));
}
void SystemTrayDelegateChromeOS::UpdateSessionStartTime() {
const PrefService* local_state = local_state_registrar_->prefs();
if (local_state->HasPrefPath(prefs::kSessionStartTime)) {
have_session_start_time_ = true;
session_start_time_ = base::TimeTicks::FromInternalValue(
local_state->GetInt64(prefs::kSessionStartTime));
} else {
have_session_start_time_ = false;
session_start_time_ = base::TimeTicks();
}
GetSystemTrayNotifier()->NotifySessionStartTimeChanged();
}
void SystemTrayDelegateChromeOS::UpdateSessionLengthLimit() {
const PrefService* local_state = local_state_registrar_->prefs();
if (local_state->HasPrefPath(prefs::kSessionLengthLimit)) {
have_session_length_limit_ = true;
session_length_limit_ = base::TimeDelta::FromMilliseconds(
std::min(std::max(local_state->GetInteger(prefs::kSessionLengthLimit),
kSessionLengthLimitMinMs),
kSessionLengthLimitMaxMs));
} else {
have_session_length_limit_ = false;
session_length_limit_ = base::TimeDelta();
}
GetSystemTrayNotifier()->NotifySessionLengthLimitChanged();
}
void SystemTrayDelegateChromeOS::StopObservingAppWindowRegistry() {
if (!user_profile_)
return;
extensions::AppWindowRegistry* registry =
extensions::AppWindowRegistry::Factory::GetForBrowserContext(
user_profile_, false);
if (registry)
registry->RemoveObserver(this);
}
void SystemTrayDelegateChromeOS::StopObservingCustodianInfoChanges() {
if (!user_profile_)
return;
SupervisedUserService* service = SupervisedUserServiceFactory::GetForProfile(
user_profile_);
if (service)
service->RemoveObserver(this);
}
void SystemTrayDelegateChromeOS::NotifyIfLastWindowClosed() {
if (!user_profile_)
return;
BrowserList* browser_list = BrowserList::GetInstance();
for (BrowserList::const_iterator it = browser_list->begin();
it != browser_list->end();
++it) {
if ((*it)->profile()->IsSameProfile(user_profile_)) {
// The current user has at least one open browser window.
return;
}
}
if (!extensions::AppWindowRegistry::Get(
user_profile_)->app_windows().empty()) {
// The current user has at least one open app window.
return;
}
GetSystemTrayNotifier()->NotifyLastWindowClosed();
}
// Overridden from SessionManagerClient::Observer.
void SystemTrayDelegateChromeOS::ScreenIsLocked() {
ash::WmShell::Get()->UpdateAfterLoginStatusChange(GetUserLoginStatus());
}
void SystemTrayDelegateChromeOS::ScreenIsUnlocked() {
ash::WmShell::Get()->UpdateAfterLoginStatusChange(GetUserLoginStatus());
}
// content::NotificationObserver implementation.
void SystemTrayDelegateChromeOS::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case chrome::NOTIFICATION_UPGRADE_RECOMMENDED: {
ash::UpdateInfo info;
GetUpdateInfo(content::Source<UpgradeDetector>(source).ptr(), &info);
GetSystemTrayNotifier()->NotifyUpdateRecommended(info);
break;
}
case chrome::NOTIFICATION_LOGIN_USER_IMAGE_CHANGED: {
// This notification is also sent on login screen when user avatar
// is loaded from file.
if (GetUserLoginStatus() != ash::LoginStatus::NOT_LOGGED_IN) {
GetSystemTrayNotifier()->NotifyUserUpdate();
}
break;
}
case chrome::NOTIFICATION_PROFILE_CREATED: {
SetProfile(content::Source<Profile>(source).ptr());
registrar_->Remove(this,
chrome::NOTIFICATION_PROFILE_CREATED,
content::NotificationService::AllSources());
break;
}
case chrome::NOTIFICATION_PROFILE_DESTROYED: {
if (UnsetProfile(content::Source<Profile>(source).ptr())) {
registrar_->Remove(this,
chrome::NOTIFICATION_PROFILE_DESTROYED,
content::NotificationService::AllSources());
}
break;
}
case chrome::NOTIFICATION_SESSION_STARTED: {
session_started_ = true;
ash::WmShell::Get()->UpdateAfterLoginStatusChange(GetUserLoginStatus());
SetProfile(ProfileManager::GetActiveUserProfile());
break;
}
default:
NOTREACHED();
}
}
void SystemTrayDelegateChromeOS::OnLanguageRemapSearchKeyToChanged() {
search_key_mapped_to_ = user_pref_registrar_->prefs()->GetInteger(
prefs::kLanguageRemapSearchKeyTo);
}
void SystemTrayDelegateChromeOS::OnAccessibilityModeChanged(
ash::AccessibilityNotificationVisibility notify) {
GetSystemTrayNotifier()->NotifyAccessibilityModeChanged(notify);
}
void SystemTrayDelegateChromeOS::UpdatePerformanceTracing() {
if (!user_pref_registrar_)
return;
bool value = user_pref_registrar_->prefs()->GetBoolean(
prefs::kPerformanceTracingEnabled);
GetSystemTrayNotifier()->NotifyTracingModeChanged(value);
}
// Overridden from InputMethodManager::Observer.
void SystemTrayDelegateChromeOS::InputMethodChanged(
input_method::InputMethodManager* manager,
Profile* /* profile */,
bool show_message) {
GetSystemTrayNotifier()->NotifyRefreshIME();
}
// Overridden from InputMethodMenuManager::Observer.
void SystemTrayDelegateChromeOS::InputMethodMenuItemChanged(
ui::ime::InputMethodMenuManager* manager) {
GetSystemTrayNotifier()->NotifyRefreshIME();
}
// Overridden from BluetoothAdapter::Observer.
void SystemTrayDelegateChromeOS::AdapterPresentChanged(
device::BluetoothAdapter* adapter,
bool present) {
GetSystemTrayNotifier()->NotifyRefreshBluetooth();
}
void SystemTrayDelegateChromeOS::AdapterPoweredChanged(
device::BluetoothAdapter* adapter,
bool powered) {
GetSystemTrayNotifier()->NotifyRefreshBluetooth();
}
void SystemTrayDelegateChromeOS::AdapterDiscoveringChanged(
device::BluetoothAdapter* adapter,
bool discovering) {
GetSystemTrayNotifier()->NotifyBluetoothDiscoveringChanged();
}
void SystemTrayDelegateChromeOS::DeviceAdded(device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) {
GetSystemTrayNotifier()->NotifyRefreshBluetooth();
}
void SystemTrayDelegateChromeOS::DeviceChanged(
device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) {
GetSystemTrayNotifier()->NotifyRefreshBluetooth();
}
void SystemTrayDelegateChromeOS::DeviceRemoved(
device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) {
GetSystemTrayNotifier()->NotifyRefreshBluetooth();
}
void SystemTrayDelegateChromeOS::OnStartBluetoothDiscoverySession(
std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
// If the discovery session was returned after a request to stop discovery
// (e.g. the user dismissed the Bluetooth detailed view before the call
// returned), don't claim the discovery session and let it clean up.
if (!should_run_bluetooth_discovery_)
return;
VLOG(1) << "Claiming new Bluetooth device discovery session.";
bluetooth_discovery_session_ = std::move(discovery_session);
GetSystemTrayNotifier()->NotifyBluetoothDiscoveringChanged();
}
void SystemTrayDelegateChromeOS::UpdateEnterpriseDomain() {
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
std::string enterprise_domain = connector->GetEnterpriseDomain();
std::string enterprise_realm = connector->GetRealm();
if (enterprise_domain_ != enterprise_domain ||
enterprise_realm_ != enterprise_realm) {
enterprise_domain_ = enterprise_domain;
enterprise_realm_ = enterprise_realm;
GetSystemTrayNotifier()->NotifyEnterpriseDomainChanged();
}
}
// Overridden from CloudPolicyStore::Observer
void SystemTrayDelegateChromeOS::OnStoreLoaded(
policy::CloudPolicyStore* store) {
UpdateEnterpriseDomain();
}
void SystemTrayDelegateChromeOS::OnStoreError(policy::CloudPolicyStore* store) {
UpdateEnterpriseDomain();
}
// Overridden from ash::SessionStateObserver
void SystemTrayDelegateChromeOS::UserAddedToSession(
const AccountId& /*account_id*/) {
GetSystemTrayNotifier()->NotifyUserAddedToSession();
}
void SystemTrayDelegateChromeOS::ActiveUserChanged(
const AccountId& /* user_id */) {}
// Overridden from chrome::BrowserListObserver.
void SystemTrayDelegateChromeOS::OnBrowserRemoved(Browser* browser) {
NotifyIfLastWindowClosed();
}
// Overridden from extensions::AppWindowRegistry::Observer.
void SystemTrayDelegateChromeOS::OnAppWindowRemoved(
extensions::AppWindow* app_window) {
NotifyIfLastWindowClosed();
}
// Overridden from SupervisedUserServiceObserver.
void SystemTrayDelegateChromeOS::OnCustodianInfoChanged() {
for (ash::CustodianInfoTrayObserver& observer :
custodian_info_changed_observers_) {
observer.OnCustodianInfoChanged();
}
}
void SystemTrayDelegateChromeOS::OnAccessibilityStatusChanged(
const AccessibilityStatusEventDetails& details) {
if (details.notification_type == ACCESSIBILITY_MANAGER_SHUTDOWN)
accessibility_subscription_.reset();
else
OnAccessibilityModeChanged(details.notify);
}
void SystemTrayDelegateChromeOS::ImeMenuActivationChanged(bool is_active) {
GetSystemTrayNotifier()->NotifyRefreshIMEMenu(is_active);
}
void SystemTrayDelegateChromeOS::ImeMenuListChanged() {}
void SystemTrayDelegateChromeOS::ImeMenuItemsChanged(
const std::string& engine_id,
const std::vector<input_method::InputMethodManager::MenuItem>& items) {}
const base::string16
SystemTrayDelegateChromeOS::GetLegacySupervisedUserMessage() const {
std::string user_manager_name = GetSupervisedUserManager();
return l10n_util::GetStringFUTF16(
IDS_USER_IS_SUPERVISED_BY_NOTICE,
base::UTF8ToUTF16(user_manager_name));
}
const base::string16
SystemTrayDelegateChromeOS::GetChildUserMessage() const {
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
SupervisedUserService* service =
SupervisedUserServiceFactory::GetForProfile(user_profile_);
base::string16 first_custodian =
base::UTF8ToUTF16(service->GetCustodianEmailAddress());
base::string16 second_custodian =
base::UTF8ToUTF16(service->GetSecondCustodianEmailAddress());
LOG_IF(WARNING, first_custodian.empty()) <<
"Returning incomplete child user message as manager not known yet.";
if (second_custodian.empty()) {
return l10n_util::GetStringFUTF16(
IDS_CHILD_USER_IS_MANAGED_BY_ONE_PARENT_NOTICE, first_custodian);
} else {
return l10n_util::GetStringFUTF16(
IDS_CHILD_USER_IS_MANAGED_BY_TWO_PARENTS_NOTICE,
first_custodian,
second_custodian);
}
#endif
LOG(WARNING) << "SystemTrayDelegateChromeOS::GetChildUserMessage call while "
<< "ENABLE_SUPERVISED_USERS undefined.";
return base::string16();
}
ash::SystemTrayDelegate* CreateSystemTrayDelegate() {
return new SystemTrayDelegateChromeOS();
}
} // namespace chromeos