| // Copyright 2014 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/chromeos/system/device_disabling_manager.h" |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/logging.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/browser_process_platform_part.h" |
| #include "chrome/browser/chromeos/login/existing_user_controller.h" |
| #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| #include "chrome/browser/chromeos/policy/server_backed_device_state.h" |
| #include "chrome/browser/chromeos/settings/install_attributes.h" |
| #include "chrome/common/pref_names.h" |
| #include "chromeos/chromeos_switches.h" |
| #include "chromeos/settings/cros_settings_names.h" |
| #include "chromeos/settings/cros_settings_provider.h" |
| #include "components/policy/core/common/cloud/cloud_policy_constants.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/user_manager/user_manager.h" |
| |
| namespace chromeos { |
| namespace system { |
| |
| DeviceDisablingManager::Observer::~Observer() { |
| } |
| |
| DeviceDisablingManager::Delegate::~Delegate() { |
| } |
| |
| DeviceDisablingManager::DeviceDisablingManager( |
| Delegate* delegate, |
| CrosSettings* cros_settings, |
| user_manager::UserManager* user_manager) |
| : delegate_(delegate), |
| browser_policy_connector_(g_browser_process->platform_part()-> |
| browser_policy_connector_chromeos()), |
| cros_settings_(cros_settings), |
| user_manager_(user_manager), |
| device_disabled_(false), |
| weak_factory_(this) { |
| CHECK(delegate_); |
| Init(); |
| } |
| |
| DeviceDisablingManager::~DeviceDisablingManager() { |
| } |
| |
| void DeviceDisablingManager::AddObserver(Observer* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void DeviceDisablingManager::RemoveObserver(Observer* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| void DeviceDisablingManager::Init() { |
| if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kDisableDeviceDisabling)) { |
| // If device disabling is turned off by flags, do not start monitoring cros |
| // settings. |
| return; |
| } |
| |
| device_disabled_subscription_ = cros_settings_->AddSettingsObserver( |
| kDeviceDisabled, |
| base::Bind(&DeviceDisablingManager::UpdateFromCrosSettings, |
| weak_factory_.GetWeakPtr())); |
| disabled_message_subscription_ = cros_settings_->AddSettingsObserver( |
| kDeviceDisabledMessage, |
| base::Bind(&DeviceDisablingManager::UpdateFromCrosSettings, |
| weak_factory_.GetWeakPtr())); |
| |
| UpdateFromCrosSettings(); |
| } |
| |
| void DeviceDisablingManager::CacheDisabledMessageAndNotify( |
| const std::string& disabled_message) { |
| if (disabled_message == disabled_message_) |
| return; |
| |
| disabled_message_ = disabled_message; |
| for (auto& observer : observers_) |
| observer.OnDisabledMessageChanged(disabled_message_); |
| } |
| |
| void DeviceDisablingManager::CheckWhetherDeviceDisabledDuringOOBE( |
| const DeviceDisabledCheckCallback& callback) { |
| if (policy::GetRestoreMode() != policy::RESTORE_MODE_DISABLED || |
| base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kDisableDeviceDisabling)) { |
| // Indicate that the device is not disabled if it is not marked as such in |
| // local state or device disabling has been turned off by flag. |
| callback.Run(false); |
| return; |
| } |
| |
| if (browser_policy_connector_->GetDeviceMode() == |
| policy::DEVICE_MODE_PENDING) { |
| // If the device mode is not known yet, request to be called back once it |
| // becomes known. |
| browser_policy_connector_->GetInstallAttributes()->ReadImmutableAttributes( |
| base::Bind( |
| &DeviceDisablingManager::CheckWhetherDeviceDisabledDuringOOBE, |
| weak_factory_.GetWeakPtr(), |
| callback)); |
| return; |
| } |
| |
| if (browser_policy_connector_->GetDeviceMode() != |
| policy::DEVICE_MODE_NOT_SET) { |
| // If the device is owned already, this method must have been called after |
| // OOBE, which is an error. Indicate that the device is not disabled to |
| // prevent spurious disabling. Actual device disabling after OOBE will be |
| // handled elsewhere, by checking for disabled state in cros settings. |
| LOG(ERROR) << "CheckWhetherDeviceDisabledDuringOOBE() called after OOBE."; |
| callback.Run(false); |
| return; |
| } |
| |
| // The device is marked as disabled in local state (based on the device state |
| // retrieved early during OOBE). Since device disabling has not been turned |
| // off by flag and the device is still unowned, we honor the information in |
| // local state and consider the device disabled. |
| |
| // Update the enrollment domain. |
| enrollment_domain_.clear(); |
| g_browser_process->local_state()->GetDictionary( |
| prefs::kServerBackedDeviceState)->GetString( |
| policy::kDeviceStateManagementDomain, |
| &enrollment_domain_); |
| |
| // Update the disabled message. |
| std::string disabled_message; |
| g_browser_process->local_state()->GetDictionary( |
| prefs::kServerBackedDeviceState)->GetString( |
| policy::kDeviceStateDisabledMessage, |
| &disabled_message); |
| CacheDisabledMessageAndNotify(disabled_message); |
| |
| // Indicate that the device is disabled. |
| callback.Run(true); |
| } |
| |
| // static |
| bool DeviceDisablingManager::HonorDeviceDisablingDuringNormalOperation() { |
| // Device disabling should be honored when the device is enterprise managed |
| // and device disabling has not been turned off by flag. |
| return g_browser_process->platform_part() |
| ->browser_policy_connector_chromeos() |
| ->IsEnterpriseManaged() && |
| !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kDisableDeviceDisabling); |
| } |
| |
| void DeviceDisablingManager::UpdateFromCrosSettings() { |
| if (cros_settings_->PrepareTrustedValues(base::Bind( |
| &DeviceDisablingManager::UpdateFromCrosSettings, |
| weak_factory_.GetWeakPtr())) != CrosSettingsProvider::TRUSTED) { |
| // If the cros settings are not trusted yet, request to be called back |
| // later. |
| return; |
| } |
| |
| if (!HonorDeviceDisablingDuringNormalOperation()) { |
| // If the device is not enterprise managed or device disabling has been |
| // turned of by flag, device disabling is not available. |
| return; |
| } |
| |
| bool should_device_be_disabled = false; |
| if (!cros_settings_->GetBoolean(kDeviceDisabled, |
| &should_device_be_disabled) || |
| !should_device_be_disabled) { |
| // The device should not be disabled. |
| |
| if (!device_disabled_) { |
| // If the device is currently not disabled, there is nothing to do. |
| return; |
| } |
| |
| // Re-enable the device. |
| device_disabled_ = false; |
| |
| // The device was disabled and has been re-enabled. Normal function should |
| // be resumed. Since the device disabled screen abruptly interrupts the |
| // regular login screen flows, Chrome should be restarted to return to a |
| // well-defined state. |
| delegate_->RestartToLoginScreen(); |
| return; |
| } |
| |
| // Update the disabled message. |
| std::string disabled_message; |
| cros_settings_->GetString(kDeviceDisabledMessage, &disabled_message); |
| CacheDisabledMessageAndNotify(disabled_message); |
| |
| if (device_disabled_) { |
| // If the device was disabled already, updating the disabled message is the |
| // only action required. |
| return; |
| } |
| device_disabled_ = true; |
| |
| const ExistingUserController* existing_user_controller = |
| ExistingUserController::current_controller(); |
| if (user_manager_->GetActiveUser() || |
| (existing_user_controller && |
| existing_user_controller->IsSigninInProgress())) { |
| // If a session or a login is in progress, restart Chrome and return to the |
| // login screen. Chrome will show the device disabled screen after the |
| // restart. |
| delegate_->RestartToLoginScreen(); |
| return; |
| } |
| |
| // Cache the enrollment domain. |
| enrollment_domain_ = browser_policy_connector_->GetEnterpriseDomain(); |
| |
| // If no session or login is in progress, show the device disabled screen. |
| delegate_->ShowDeviceDisabledScreen(); |
| } |
| |
| } // namespace system |
| } // namespace chromeos |