diff options
author | bartfab <bartfab@chromium.org> | 2014-11-07 08:28:12 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-07 16:28:31 +0000 |
commit | 9ce0dc311ee3397218bd1b45f94e481f0b7b1ecd (patch) | |
tree | 3cffa7880628133fec014d2bbcbfe5e630caf6a3 | |
parent | ffec256edbd65acaf4cfc572edbd8bcc60c5ba0d (diff) | |
download | chromium_src-9ce0dc311ee3397218bd1b45f94e481f0b7b1ecd.zip chromium_src-9ce0dc311ee3397218bd1b45f94e481f0b7b1ecd.tar.gz chromium_src-9ce0dc311ee3397218bd1b45f94e481f0b7b1ecd.tar.bz2 |
Enable device disabling during normal operation
This CL enables device disabling during normal operation: The
management server can disable a device by sending the device disabled
flag with the next device policy update. The server can re-enable the
device by clearing the flag with a future policy update.
The flag is persisted along with the entire device policy blob on the
device. As long as the flag is set, the device will prevent logins and
will show a device disabled screen instead. When the flag first
becomes set, the device terminates the current session (if any) and
switches to the device disabled screen immediately.
BUG=425574
TEST=New unit and browser tests
Review URL: https://codereview.chromium.org/711433002
Cr-Commit-Position: refs/heads/master@{#303241}
19 files changed, 816 insertions, 67 deletions
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc index 85de24b..9ae7863 100644 --- a/chrome/browser/browser_process_platform_part_chromeos.cc +++ b/chrome/browser/browser_process_platform_part_chromeos.cc @@ -14,10 +14,13 @@ #include "chrome/browser/chromeos/memory/oom_priority_manager.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/system/automatic_reboot_manager.h" #include "chrome/browser/chromeos/system/device_disabling_manager.h" +#include "chrome/browser/chromeos/system/device_disabling_manager_default_delegate.h" #include "chrome/browser/profiles/profile.h" #include "components/session_manager/core/session_manager.h" +#include "components/user_manager/user_manager.h" BrowserProcessPlatformPart::BrowserProcessPlatformPart() : created_profile_helper_(false) { @@ -52,12 +55,17 @@ void BrowserProcessPlatformPart::DestroyChromeUserManager() { void BrowserProcessPlatformPart::InitializeDeviceDisablingManager() { DCHECK(!device_disabling_manager_); + device_disabling_manager_delegate_.reset( + new chromeos::system::DeviceDisablingManagerDefaultDelegate); device_disabling_manager_.reset(new chromeos::system::DeviceDisablingManager( - browser_policy_connector_chromeos())); + device_disabling_manager_delegate_.get(), + chromeos::CrosSettings::Get(), + user_manager::UserManager::Get())); } void BrowserProcessPlatformPart::ShutdownDeviceDisablingManager() { device_disabling_manager_.reset(); + device_disabling_manager_delegate_.reset(); } void BrowserProcessPlatformPart::InitializeSessionManager( diff --git a/chrome/browser/browser_process_platform_part_chromeos.h b/chrome/browser/browser_process_platform_part_chromeos.h index ef354ec..311a7c8 100644 --- a/chrome/browser/browser_process_platform_part_chromeos.h +++ b/chrome/browser/browser_process_platform_part_chromeos.h @@ -24,6 +24,7 @@ namespace chromeos { namespace system { class AutomaticRebootManager; class DeviceDisablingManager; +class DeviceDisablingManagerDefaultDelegate; } } @@ -106,6 +107,8 @@ class BrowserProcessPlatformPart : public BrowserProcessPlatformPartBase, scoped_ptr<chromeos::ChromeUserManager> chrome_user_manager_; + scoped_ptr<chromeos::system::DeviceDisablingManagerDefaultDelegate> + device_disabling_manager_delegate_; scoped_ptr<chromeos::system::DeviceDisablingManager> device_disabling_manager_; diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 512b528..c2d7a3c 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc @@ -751,6 +751,8 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { WallpaperManager::Get()->Shutdown(); #endif + // Let the DeviceDisablingManager unregister itself as an observer of the + // CrosSettings singleton before it is destroyed. g_browser_process->platform_part()->ShutdownDeviceDisablingManager(); // Let the AutomaticRebootManager unregister itself as an observer of several diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index 7fce49e..883dd94 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -41,6 +41,7 @@ #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/system/device_disabling_manager.h" #include "chrome/browser/signin/easy_unlock_service.h" #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" #include "chrome/common/chrome_switches.h" @@ -435,13 +436,26 @@ void ExistingUserController::Login(const UserContext& user_context, 1, HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); - // Reenable clicking on other windows and the status area. Do not start the + // Re-enable clicking on other windows and the status area. Do not start the // auto-login timer though. Without trusted |cros_settings_|, no auto-login // can succeed. login_display_->SetUIEnabled(true); return; } + bool device_disabled = false; + cros_settings_->GetBoolean(kDeviceDisabled, &device_disabled); + if (device_disabled && system::DeviceDisablingManager:: + HonorDeviceDisablingDuringNormalOperation()) { + // If the device is disabled, bail out. A device disabled screen will be + // shown by the DeviceDisablingManager. + + // Re-enable clicking on other windows and the status area. Do not start the + // auto-login timer though. On a disabled device, no auto-login can succeed. + login_display_->SetUIEnabled(true); + return; + } + if (is_login_in_progress_) { // If there is another login in progress, bail out. Do not re-enable // clicking on other windows and the status area. Do not start the diff --git a/chrome/browser/chromeos/login/screens/device_disabled_screen.cc b/chrome/browser/chromeos/login/screens/device_disabled_screen.cc index e7c5d7e..bcd4395 100644 --- a/chrome/browser/chromeos/login/screens/device_disabled_screen.cc +++ b/chrome/browser/chromeos/login/screens/device_disabled_screen.cc @@ -10,7 +10,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/login/wizard_controller.h" -#include "chrome/browser/chromeos/system/device_disabling_manager.h" namespace chromeos { @@ -18,16 +17,20 @@ DeviceDisabledScreen::DeviceDisabledScreen( BaseScreenDelegate* base_screen_delegate, DeviceDisabledScreenActor* actor) : BaseScreen(base_screen_delegate), - showing_(false), - actor_(actor) { + actor_(actor), + device_disabling_manager_(g_browser_process->platform_part()-> + device_disabling_manager()), + showing_(false) { DCHECK(actor_); if (actor_) actor_->SetDelegate(this); + device_disabling_manager_->AddObserver(this); } DeviceDisabledScreen::~DeviceDisabledScreen() { if (actor_) actor_->SetDelegate(nullptr); + device_disabling_manager_->RemoveObserver(this); } void DeviceDisabledScreen::PrepareToShow() { @@ -38,8 +41,7 @@ void DeviceDisabledScreen::Show() { return; showing_ = true; - actor_->Show(g_browser_process->platform_part()->device_disabling_manager()-> - disabled_message()); + actor_->Show(device_disabling_manager_->disabled_message()); } void DeviceDisabledScreen::Hide() { @@ -60,4 +62,10 @@ void DeviceDisabledScreen::OnActorDestroyed(DeviceDisabledScreenActor* actor) { actor_ = nullptr; } +void DeviceDisabledScreen::OnDisabledMessageChanged( + const std::string& disabled_message) { + if (actor_) + actor_->UpdateMessage(disabled_message); +} + } // namespace chromeos diff --git a/chrome/browser/chromeos/login/screens/device_disabled_screen.h b/chrome/browser/chromeos/login/screens/device_disabled_screen.h index 35bd8c1..b51ceb2 100644 --- a/chrome/browser/chromeos/login/screens/device_disabled_screen.h +++ b/chrome/browser/chromeos/login/screens/device_disabled_screen.h @@ -8,14 +8,20 @@ #include "base/macros.h" #include "chrome/browser/chromeos/login/screens/base_screen.h" #include "chrome/browser/chromeos/login/screens/device_disabled_screen_actor.h" +#include "chrome/browser/chromeos/system/device_disabling_manager.h" namespace chromeos { +namespace system { +class DeviceDisablingManager; +} + class BaseScreenDelegate; // Screen informing the user that the device has been disabled by its owner. class DeviceDisabledScreen : public BaseScreen, - public DeviceDisabledScreenActor::Delegate { + public DeviceDisabledScreenActor::Delegate, + public system::DeviceDisablingManager::Observer { public: DeviceDisabledScreen(BaseScreenDelegate* base_screen_delegate, DeviceDisabledScreenActor* actor); @@ -30,12 +36,16 @@ class DeviceDisabledScreen : public BaseScreen, // DeviceDisabledScreenActor::Delegate: void OnActorDestroyed(DeviceDisabledScreenActor* actor) override; + // system::DeviceDisablingManager::Observer: + void OnDisabledMessageChanged(const std::string& disabled_message) override; + private: + DeviceDisabledScreenActor* actor_; + system::DeviceDisablingManager* device_disabling_manager_; + // Whether the screen is currently showing. bool showing_; - DeviceDisabledScreenActor* actor_; - DISALLOW_COPY_AND_ASSIGN(DeviceDisabledScreen); }; diff --git a/chrome/browser/chromeos/login/screens/device_disabled_screen_actor.h b/chrome/browser/chromeos/login/screens/device_disabled_screen_actor.h index bbfae36..ab86330 100644 --- a/chrome/browser/chromeos/login/screens/device_disabled_screen_actor.h +++ b/chrome/browser/chromeos/login/screens/device_disabled_screen_actor.h @@ -29,6 +29,7 @@ class DeviceDisabledScreenActor { virtual void Show(const std::string& message) = 0; virtual void Hide() = 0; virtual void SetDelegate(Delegate* delegate) = 0; + virtual void UpdateMessage(const std::string& message) = 0; }; } // namespace chromeos diff --git a/chrome/browser/chromeos/login/screens/mock_device_disabled_screen_actor.h b/chrome/browser/chromeos/login/screens/mock_device_disabled_screen_actor.h index 3d18683..a8a631f 100644 --- a/chrome/browser/chromeos/login/screens/mock_device_disabled_screen_actor.h +++ b/chrome/browser/chromeos/login/screens/mock_device_disabled_screen_actor.h @@ -19,6 +19,7 @@ class MockDeviceDisabledScreenActor : public DeviceDisabledScreenActor { MOCK_METHOD1(Show, void(const std::string&)); MOCK_METHOD0(Hide, void()); + MOCK_METHOD1(UpdateMessage, void(const std::string& message)); private: MOCK_METHOD1(MockSetDelegate, void(Delegate* delegate)); diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 8253a2e..5d0ee9d 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc @@ -1119,6 +1119,15 @@ void WizardController::AutoLaunchKioskApp() { return; } + bool device_disabled = false; + CrosSettings::Get()->GetBoolean(kDeviceDisabled, &device_disabled); + if (device_disabled && system::DeviceDisablingManager:: + HonorDeviceDisablingDuringNormalOperation()) { + // If the device is disabled, bail out. A device disabled screen will be + // shown by the DeviceDisablingManager. + return; + } + host_->StartAppLaunch(app_id, false /* diagnostic_mode */); } diff --git a/chrome/browser/chromeos/system/device_disabling_browsertest.cc b/chrome/browser/chromeos/system/device_disabling_browsertest.cc new file mode 100644 index 0000000..79250c8 --- /dev/null +++ b/chrome/browser/chromeos/system/device_disabling_browsertest.cc @@ -0,0 +1,94 @@ +// 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 "base/command_line.h" +#include "base/memory/scoped_ptr.h" +#include "base/run_loop.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/policy/device_policy_builder.h" +#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/fake_session_manager_client.h" +#include "chromeos/settings/cros_settings_names.h" +#include "policy/proto/device_management_backend.pb.h" + +namespace chromeos { +namespace system { + +class DeviceDisablingTest : public InProcessBrowserTest { + public: + DeviceDisablingTest(); + + // Device policy is updated in two steps: + // - First, set up the policy builder that GetDevicePolicyBuilder() returns. + // - Second, call SimulatePolicyFetch() to build and flush the resulting + // policy blob to the browser. + policy::DevicePolicyBuilder* GetDevicePolicyBuilder(); + void SimulatePolicyFetch(); + + private: + // InProcessBrowserTest: + void SetUpInProcessBrowserTestFixture() override; + void SetUpCommandLine(CommandLine* command_line) override; + + FakeSessionManagerClient* fake_session_manager_client_; + policy::DevicePolicyCrosTestHelper test_helper_; + + DISALLOW_COPY_AND_ASSIGN(DeviceDisablingTest); +}; + + +DeviceDisablingTest::DeviceDisablingTest() + : fake_session_manager_client_(new FakeSessionManagerClient) { +} + +policy::DevicePolicyBuilder* DeviceDisablingTest::GetDevicePolicyBuilder() { + return test_helper_.device_policy(); +} + +void DeviceDisablingTest::SimulatePolicyFetch() { + GetDevicePolicyBuilder()->Build(); + fake_session_manager_client_->set_device_policy( + GetDevicePolicyBuilder()->GetBlob()); + fake_session_manager_client_->OnPropertyChangeComplete(true); +} + +void DeviceDisablingTest::SetUpInProcessBrowserTestFixture() { + DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient( + scoped_ptr<SessionManagerClient>(fake_session_manager_client_)); + + test_helper_.InstallOwnerKey(); + test_helper_.MarkAsEnterpriseOwned(); +} + +void DeviceDisablingTest::SetUpCommandLine(CommandLine* command_line) { + command_line->AppendSwitch(switches::kLoginManager); + command_line->AppendSwitch(switches::kForceLoginManagerInTests); +} + +IN_PROC_BROWSER_TEST_F(DeviceDisablingTest, DisableDuringNormalOperation) { + // Mark the device as disabled and wait until cros settings update. + base::RunLoop run_loop; + scoped_ptr<CrosSettings::ObserverSubscription> observer = + CrosSettings::Get()->AddSettingsObserver( + kDeviceDisabled, + run_loop.QuitClosure()); + GetDevicePolicyBuilder()->policy_data().mutable_device_state()-> + set_device_mode(enterprise_management::DeviceState::DEVICE_MODE_DISABLED); + SimulatePolicyFetch(); + run_loop.Run(); + + // Verify that the device disabled screen is being shown. + WizardController* wizard_controller = WizardController::default_controller(); + ASSERT_TRUE(wizard_controller); + EXPECT_EQ(wizard_controller->GetScreen( + WizardController::kDeviceDisabledScreenName), + wizard_controller->current_screen()); +} + +} // namespace system +} // namespace chromeos diff --git a/chrome/browser/chromeos/system/device_disabling_manager.cc b/chrome/browser/chromeos/system/device_disabling_manager.cc index ae2410e..59a3807 100644 --- a/chrome/browser/chromeos/system/device_disabling_manager.cc +++ b/chrome/browser/chromeos/system/device_disabling_manager.cc @@ -10,25 +10,84 @@ #include "base/prefs/pref_service.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/enterprise_install_attributes.h" #include "chrome/browser/chromeos/policy/server_backed_device_state.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/user_manager/user_manager.h" namespace chromeos { namespace system { +DeviceDisablingManager::Observer::~Observer() { +} + +DeviceDisablingManager::Delegate::~Delegate() { +} + DeviceDisablingManager::DeviceDisablingManager( - policy::BrowserPolicyConnectorChromeOS* browser_policy_connector) - : browser_policy_connector_(browser_policy_connector), + 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 (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_EACH_OBSERVER(Observer, + observers_, + OnDisabledMessageChanged(disabled_message_)); +} + void DeviceDisablingManager::CheckWhetherDeviceDisabledDuringOOBE( const DeviceDisabledCheckCallback& callback) { if (policy::GetRestoreMode() != policy::RESTORE_MODE_DISABLED || @@ -68,16 +127,88 @@ void DeviceDisablingManager::CheckWhetherDeviceDisabledDuringOOBE( // off by flag and the device is still unowned, we honor the information in // local state and consider the device disabled. - // Cache the disabled message. - disabled_message_.clear(); + // Update the disabled message. + std::string disabled_message; g_browser_process->local_state()->GetDictionary( prefs::kServerBackedDeviceState)->GetString( policy::kDeviceStateDisabledMessage, - &disabled_message_); + &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() && + !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 device_disabled = false; + if (!cros_settings_->GetBoolean(kDeviceDisabled, &device_disabled) || + !device_disabled) { + if (!device_disabled_) { + // If the device was not disabled and has not been disabled, there is + // nothing to do. + return; + } + 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; + } + + // If no session or login is in progress, show the device disabled screen. + delegate_->ShowDeviceDisabledScreen(); +} + } // namespace system } // namespace chromeos diff --git a/chrome/browser/chromeos/system/device_disabling_manager.h b/chrome/browser/chromeos/system/device_disabling_manager.h index eeded82..7dbf2cb 100644 --- a/chrome/browser/chromeos/system/device_disabling_manager.h +++ b/chrome/browser/chromeos/system/device_disabling_manager.h @@ -9,12 +9,19 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" namespace policy { class BrowserPolicyConnectorChromeOS; } +namespace user_manager { +class UserManager; +} + namespace chromeos { namespace system { @@ -31,29 +38,91 @@ namespace system { // device disabled screen. // - If the device has not been wiped, the disabled state is retrieved with // every device policy fetch as part of the |PolicyData| protobuf, parsed and -// written to the |chromeos::kDeviceDisabled| cros setting. -// -// TODO(bartfab): Make this class subscribe to the cros setting and trigger -// the device disabled screen. http://crbug.com/425574 +// written to the |chromeos::kDeviceDisabled| cros setting. This class +// monitors the cros setting. When the device becomes disabled, one of two +// actions is taken: +// 1) If no session is in progress, the device disabled screen is shown +// immediately. +// 2) If a session is in progress, the session is terminated. After Chrome has +// restarted on the login screen, the disabled screen is shown per 1). +// This ensures that when a device is disabled, there is never any user +// session running in the backround. +// When the device is re-enabled, Chrome is restarted once more to resume the +// regular login screen flows from a known-good point. class DeviceDisablingManager { public: using DeviceDisabledCheckCallback = base::Callback<void(bool)>; - explicit DeviceDisablingManager( - policy::BrowserPolicyConnectorChromeOS* browser_policy_connector); + class Observer { + public: + virtual ~Observer(); + + virtual void OnDisabledMessageChanged( + const std::string& disabled_message) = 0; + + private: + DISALLOW_ASSIGN(Observer); + }; + + class Delegate { + public: + virtual ~Delegate(); + + // Terminate the current session (if any) and restart Chrome to show the + // login screen. + virtual void RestartToLoginScreen() = 0; + + // Show the device disabled screen. + virtual void ShowDeviceDisabledScreen() = 0; + + private: + DISALLOW_ASSIGN(Delegate); + }; + + // |delegate| must outlive |this|. + DeviceDisablingManager(Delegate* delegate, + CrosSettings* cros_settings, + user_manager::UserManager* user_manager); ~DeviceDisablingManager(); + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + // Returns the cached disabled message. The message is only guaranteed to be // up to date if the disabled screen was triggered. const std::string& disabled_message() const { return disabled_message_; } - // Checks whether the device is disabled. |callback| will be invoked with the - // result of the check. + // Performs a check whether the device is disabled during OOBE. |callback| + // will be invoked with the result of the check. void CheckWhetherDeviceDisabledDuringOOBE( const DeviceDisabledCheckCallback& callback); + // Whenever trusted cros settings indicate that the device is disabled, this + // method should be used to check whether the device disabling is to be + // honored. If this method returns false, the device should not be disabled. + static bool HonorDeviceDisablingDuringNormalOperation(); + private: + void Init(); + + // Cache the disabled message and inform observers if it changed. + void CacheDisabledMessageAndNotify(const std::string& disabled_message); + + void UpdateFromCrosSettings(); + + Delegate* delegate_; policy::BrowserPolicyConnectorChromeOS* browser_policy_connector_; + CrosSettings* cros_settings_; + user_manager::UserManager* user_manager_; + + ObserverList<Observer> observers_; + + scoped_ptr<CrosSettings::ObserverSubscription> device_disabled_subscription_; + scoped_ptr<CrosSettings::ObserverSubscription> disabled_message_subscription_; + + // Indicates whether the device was disabled when the cros settings were last + // read. + bool device_disabled_; // A cached copy of the message to show on the device disabled screen. std::string disabled_message_; diff --git a/chrome/browser/chromeos/system/device_disabling_manager_default_delegate.cc b/chrome/browser/chromeos/system/device_disabling_manager_default_delegate.cc new file mode 100644 index 0000000..1ddf9e8 --- /dev/null +++ b/chrome/browser/chromeos/system/device_disabling_manager_default_delegate.cc @@ -0,0 +1,29 @@ +// 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_default_delegate.h" + +#include "chrome/browser/chromeos/login/ui/login_display_host.h" +#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/lifetime/application_lifetime.h" + +namespace chromeos { +namespace system { + +DeviceDisablingManagerDefaultDelegate::DeviceDisablingManagerDefaultDelegate() { +} + +void DeviceDisablingManagerDefaultDelegate::RestartToLoginScreen() { + chrome::AttemptUserExit(); +} + +void DeviceDisablingManagerDefaultDelegate::ShowDeviceDisabledScreen() { + LoginDisplayHostImpl::default_host()->StartWizard( + WizardController::kDeviceDisabledScreenName, + nullptr); +} + +} // namespace system +} // namespace chromeos diff --git a/chrome/browser/chromeos/system/device_disabling_manager_default_delegate.h b/chrome/browser/chromeos/system/device_disabling_manager_default_delegate.h new file mode 100644 index 0000000..2316e70 --- /dev/null +++ b/chrome/browser/chromeos/system/device_disabling_manager_default_delegate.h @@ -0,0 +1,30 @@ +// 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. + +#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_DEVICE_DISABLING_MANAGER_DEFAULT_DELEGATE_H_ +#define CHROME_BROWSER_CHROMEOS_SYSTEM_DEVICE_DISABLING_MANAGER_DEFAULT_DELEGATE_H_ + +#include "base/macros.h" +#include "chrome/browser/chromeos/system/device_disabling_manager.h" + +namespace chromeos { +namespace system { + +class DeviceDisablingManagerDefaultDelegate + : public DeviceDisablingManager::Delegate { + public: + DeviceDisablingManagerDefaultDelegate(); + + private: + // DeviceDisablingManager::Delegate: + void RestartToLoginScreen() override; + void ShowDeviceDisabledScreen() override; + + DISALLOW_COPY_AND_ASSIGN(DeviceDisablingManagerDefaultDelegate); +}; + +} // namespace system +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_DEVICE_DISABLING_MANAGER_DEFAULT_DELEGATE_H_ diff --git a/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc b/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc index 4ef3eef3..c10c6e7 100644 --- a/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc +++ b/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc @@ -7,92 +7,168 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ref_counted.h" #include "base/prefs/scoped_user_pref_update.h" #include "base/prefs/testing_pref_service.h" #include "base/run_loop.h" #include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/chromeos/login/users/fake_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/policy/device_policy_builder.h" #include "chrome/browser/chromeos/policy/server_backed_device_state.h" #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" +#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/chromeos_switches.h" +#include "components/ownership/mock_owner_key_util.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "policy/proto/device_management_backend.pb.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::_; +using testing::Mock; + namespace chromeos { namespace system { namespace { -const char kDisabledMessage[] = "Device disabled."; +const char kTestUser[] = "user@example.com"; +const char kDisabledMessage1[] = "Device disabled 1."; +const char kDisabledMessage2[] = "Device disabled 2."; } -class DeviceDisablingManagerTest : public testing::Test { +class DeviceDisablingManagerTestBase : public testing::Test, + public DeviceDisablingManager::Delegate { public: - DeviceDisablingManagerTest(); + DeviceDisablingManagerTestBase(); // testing::Test: + void TearDown() override; + + virtual void CreateDeviceDisablingManager(); + virtual void DestroyDeviceDisablingManager(); + + void SetRegistrationUser(const std::string& registration_user); + void SetDeviceMode(policy::DeviceMode device_mode); + void LogIn(); + + // DeviceDisablingManager::Delegate: + MOCK_METHOD0(RestartToLoginScreen, void()); + MOCK_METHOD0(ShowDeviceDisabledScreen, void()); + + DeviceDisablingManager* GetDeviceDisablingManager() { + return device_disabling_manager_.get(); + } + + private: + policy::ScopedStubEnterpriseInstallAttributes install_attributes_; + chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; + chromeos::ScopedTestCrosSettings test_cros_settings_; + FakeUserManager fake_user_manager_; + scoped_ptr<DeviceDisablingManager> device_disabling_manager_; + + DISALLOW_COPY_AND_ASSIGN(DeviceDisablingManagerTestBase); +}; + +DeviceDisablingManagerTestBase::DeviceDisablingManagerTestBase() + : install_attributes_("", "", "", policy::DEVICE_MODE_NOT_SET) { +} + +void DeviceDisablingManagerTestBase::TearDown() { + DestroyDeviceDisablingManager(); +} + +void DeviceDisablingManagerTestBase::CreateDeviceDisablingManager() { + device_disabling_manager_.reset(new DeviceDisablingManager( + this, + CrosSettings::Get(), + &fake_user_manager_)); +} + +void DeviceDisablingManagerTestBase::DestroyDeviceDisablingManager() { + device_disabling_manager_.reset(); +} + +void DeviceDisablingManagerTestBase::SetRegistrationUser( + const std::string& registration_user) { + reinterpret_cast<policy::StubEnterpriseInstallAttributes*>( + TestingBrowserProcess::GetGlobal()->platform_part()-> + browser_policy_connector_chromeos()->GetInstallAttributes())-> + SetRegistrationUser(registration_user); +} + +void DeviceDisablingManagerTestBase::SetDeviceMode( + policy::DeviceMode device_mode) { + reinterpret_cast<policy::StubEnterpriseInstallAttributes*>( + TestingBrowserProcess::GetGlobal()->platform_part()-> + browser_policy_connector_chromeos()->GetInstallAttributes())-> + SetMode(device_mode); +} + +void DeviceDisablingManagerTestBase::LogIn() { + fake_user_manager_.AddUser(kTestUser); +} + +// Base class for tests that verify device disabling behavior during OOBE, when +// the device is not owned yet. +class DeviceDisablingManagerOOBETest : public DeviceDisablingManagerTestBase { + public: + DeviceDisablingManagerOOBETest(); + + // DeviceDisablingManagerTestBase: void SetUp() override; void TearDown() override; bool device_disabled() const { return device_disabled_; } - const std::string& GetDisabledMessage() const; void CheckWhetherDeviceDisabledDuringOOBE(); void SetDeviceDisabled(bool disabled); - void SetDeviceMode(policy::DeviceMode device_mode); private: void OnDeviceDisabledChecked(bool device_disabled); - policy::ScopedStubEnterpriseInstallAttributes install_attributes_; TestingPrefServiceSimple local_state_; - scoped_ptr<DeviceDisablingManager> device_disabling_manager_; - base::RunLoop run_loop_; bool device_disabled_; - DISALLOW_COPY_AND_ASSIGN(DeviceDisablingManagerTest); + DISALLOW_COPY_AND_ASSIGN(DeviceDisablingManagerOOBETest); }; -DeviceDisablingManagerTest::DeviceDisablingManagerTest() - : install_attributes_("", "", "", policy::DEVICE_MODE_NOT_SET), - device_disabled_(false) { +DeviceDisablingManagerOOBETest::DeviceDisablingManagerOOBETest() + : device_disabled_(false) { + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); } -void DeviceDisablingManagerTest::SetUp() { +void DeviceDisablingManagerOOBETest::SetUp() { TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_); policy::DeviceCloudPolicyManagerChromeOS::RegisterPrefs( local_state_.registry()); - - device_disabling_manager_.reset(new DeviceDisablingManager( - TestingBrowserProcess::GetGlobal()->platform_part()-> - browser_policy_connector_chromeos())); + CreateDeviceDisablingManager(); } -void DeviceDisablingManagerTest::TearDown() { +void DeviceDisablingManagerOOBETest::TearDown() { + DeviceDisablingManagerTestBase::TearDown(); TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr); } -const std::string& DeviceDisablingManagerTest::GetDisabledMessage() const { - return device_disabling_manager_->disabled_message(); - -} - -void DeviceDisablingManagerTest::CheckWhetherDeviceDisabledDuringOOBE() { - device_disabling_manager_->CheckWhetherDeviceDisabledDuringOOBE( - base::Bind(&DeviceDisablingManagerTest::OnDeviceDisabledChecked, +void DeviceDisablingManagerOOBETest::CheckWhetherDeviceDisabledDuringOOBE() { + GetDeviceDisablingManager()->CheckWhetherDeviceDisabledDuringOOBE( + base::Bind(&DeviceDisablingManagerOOBETest::OnDeviceDisabledChecked, base::Unretained(this))); run_loop_.Run(); } -void DeviceDisablingManagerTest::SetDeviceDisabled(bool disabled) { +void DeviceDisablingManagerOOBETest::SetDeviceDisabled(bool disabled) { DictionaryPrefUpdate dict(&local_state_, prefs::kServerBackedDeviceState); if (disabled) { dict->SetString(policy::kDeviceStateRestoreMode, @@ -100,30 +176,24 @@ void DeviceDisablingManagerTest::SetDeviceDisabled(bool disabled) { } else { dict->Remove(policy::kDeviceStateRestoreMode, nullptr); } - dict->SetString(policy::kDeviceStateDisabledMessage, kDisabledMessage); -} - -void DeviceDisablingManagerTest::SetDeviceMode(policy::DeviceMode device_mode) { - reinterpret_cast<policy::StubEnterpriseInstallAttributes*>( - TestingBrowserProcess::GetGlobal()->platform_part()-> - browser_policy_connector_chromeos()->GetInstallAttributes())-> - SetMode(device_mode); + dict->SetString(policy::kDeviceStateDisabledMessage, kDisabledMessage1); } -void DeviceDisablingManagerTest::OnDeviceDisabledChecked(bool device_disabled) { +void DeviceDisablingManagerOOBETest::OnDeviceDisabledChecked( + bool device_disabled) { device_disabled_ = device_disabled; run_loop_.Quit(); } // Verifies that the device is not considered disabled during OOBE by default. -TEST_F(DeviceDisablingManagerTest, NotDisabledByDefault) { +TEST_F(DeviceDisablingManagerOOBETest, NotDisabledByDefault) { CheckWhetherDeviceDisabledDuringOOBE(); EXPECT_FALSE(device_disabled()); } // Verifies that the device is not considered disabled during OOBE when it is // explicitly marked as not disabled. -TEST_F(DeviceDisablingManagerTest, NotDisabledWhenExplicitlyNotDisabled) { +TEST_F(DeviceDisablingManagerOOBETest, NotDisabledWhenExplicitlyNotDisabled) { SetDeviceDisabled(false); CheckWhetherDeviceDisabledDuringOOBE(); EXPECT_FALSE(device_disabled()); @@ -131,7 +201,7 @@ TEST_F(DeviceDisablingManagerTest, NotDisabledWhenExplicitlyNotDisabled) { // Verifies that the device is not considered disabled during OOBE when device // disabling is turned off by flag, even if the device is marked as disabled. -TEST_F(DeviceDisablingManagerTest, NotDisabledWhenTurnedOffByFlag) { +TEST_F(DeviceDisablingManagerOOBETest, NotDisabledWhenTurnedOffByFlag) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kDisableDeviceDisabling); SetDeviceDisabled(true); @@ -141,7 +211,7 @@ TEST_F(DeviceDisablingManagerTest, NotDisabledWhenTurnedOffByFlag) { // Verifies that the device is not considered disabled during OOBE when it is // already enrolled, even if the device is marked as disabled. -TEST_F(DeviceDisablingManagerTest, DoNotShowWhenEnterpriseOwned) { +TEST_F(DeviceDisablingManagerOOBETest, NotDisabledWhenEnterpriseOwned) { SetDeviceMode(policy::DEVICE_MODE_ENTERPRISE); SetDeviceDisabled(true); CheckWhetherDeviceDisabledDuringOOBE(); @@ -150,7 +220,7 @@ TEST_F(DeviceDisablingManagerTest, DoNotShowWhenEnterpriseOwned) { // Verifies that the device is not considered disabled during OOBE when it is // already owned by a consumer, even if the device is marked as disabled. -TEST_F(DeviceDisablingManagerTest, DoNotShowWhenConsumerOwned) { +TEST_F(DeviceDisablingManagerOOBETest, NotDisabledWhenConsumerOwned) { SetDeviceMode(policy::DEVICE_MODE_CONSUMER); SetDeviceDisabled(true); CheckWhetherDeviceDisabledDuringOOBE(); @@ -160,11 +230,271 @@ TEST_F(DeviceDisablingManagerTest, DoNotShowWhenConsumerOwned) { // Verifies that the device is considered disabled during OOBE when it is marked // as disabled, device disabling is not turned off by flag and the device is not // owned yet. -TEST_F(DeviceDisablingManagerTest, ShowWhenDisabledAndNotOwned) { +TEST_F(DeviceDisablingManagerOOBETest, ShowWhenDisabledAndNotOwned) { SetDeviceDisabled(true); CheckWhetherDeviceDisabledDuringOOBE(); EXPECT_TRUE(device_disabled()); - EXPECT_EQ(kDisabledMessage, GetDisabledMessage()); + EXPECT_EQ(kDisabledMessage1, GetDeviceDisablingManager()->disabled_message()); +} + +// Base class for tests that verify device disabling behavior once the device is +// owned. +class DeviceDisablingManagerTest : public DeviceDisablingManagerTestBase, + public DeviceDisablingManager::Observer { + public: + DeviceDisablingManagerTest(); + + // DeviceDisablingManagerTestBase: + void TearDown() override; + void CreateDeviceDisablingManager() override; + void DestroyDeviceDisablingManager() override; + + //DeviceDisablingManager::Observer: + MOCK_METHOD1(OnDisabledMessageChanged, void(const std::string&)); + + void SetUnowned(); + void SetEnterpriseOwned(); + void SetConsumerOwned(); + void MakeCrosSettingsTrusted(); + + void SetDeviceDisabled(bool disabled); + void SetDisabledMessage(const std::string& disabled_message); + + private: + void SimulatePolicyFetch(); + + content::TestBrowserThreadBundle thread_bundle_; + chromeos::DeviceSettingsTestHelper device_settings_test_helper_; + policy::DevicePolicyBuilder device_policy_; + + DISALLOW_COPY_AND_ASSIGN(DeviceDisablingManagerTest); +}; + +DeviceDisablingManagerTest::DeviceDisablingManagerTest() { +} + +void DeviceDisablingManagerTest::TearDown() { + chromeos::DeviceSettingsService::Get()->UnsetSessionManager(); + DeviceDisablingManagerTestBase::TearDown(); +} + +void DeviceDisablingManagerTest::CreateDeviceDisablingManager() { + DeviceDisablingManagerTestBase::CreateDeviceDisablingManager(); + GetDeviceDisablingManager()->AddObserver(this); +} + +void DeviceDisablingManagerTest::DestroyDeviceDisablingManager() { + if (GetDeviceDisablingManager()) + GetDeviceDisablingManager()->RemoveObserver(this); + DeviceDisablingManagerTestBase::DestroyDeviceDisablingManager(); +} + +void DeviceDisablingManagerTest::SetUnowned() { + SetRegistrationUser(std::string()); + SetDeviceMode(policy::DEVICE_MODE_NOT_SET); +} + +void DeviceDisablingManagerTest::SetEnterpriseOwned() { + SetRegistrationUser(kTestUser); + SetDeviceMode(policy::DEVICE_MODE_ENTERPRISE); +} + +void DeviceDisablingManagerTest::SetConsumerOwned() { + SetDeviceMode(policy::DEVICE_MODE_CONSUMER); +} + +void DeviceDisablingManagerTest::MakeCrosSettingsTrusted() { + scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util( + new ownership::MockOwnerKeyUtil); + owner_key_util->SetPublicKeyFromPrivateKey(*device_policy_.GetSigningKey()); + chromeos::DeviceSettingsService::Get()->SetSessionManager( + &device_settings_test_helper_, + owner_key_util); + SimulatePolicyFetch(); +} + +void DeviceDisablingManagerTest::SetDeviceDisabled(bool disabled) { + if (disabled) { + device_policy_.policy_data().mutable_device_state()->set_device_mode( + enterprise_management::DeviceState::DEVICE_MODE_DISABLED); + } else { + device_policy_.policy_data().mutable_device_state()->clear_device_mode(); + } + SimulatePolicyFetch(); +} + +void DeviceDisablingManagerTest::SetDisabledMessage( + const std::string& disabled_message) { + device_policy_.policy_data().mutable_device_state()-> + mutable_disabled_state()->set_message(disabled_message); + SimulatePolicyFetch(); +} + +void DeviceDisablingManagerTest::SimulatePolicyFetch() { + device_policy_.Build(); + device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); + chromeos::DeviceSettingsService::Get()->OwnerKeySet(true); + device_settings_test_helper_.Flush(); +} + +// Verifies that the device is not considered disabled by default when it is +// enrolled for enterprise management. +TEST_F(DeviceDisablingManagerTest, NotDisabledByDefault) { + SetEnterpriseOwned(); + MakeCrosSettingsTrusted(); + + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + CreateDeviceDisablingManager(); +} + +// Verifies that the device is not considered disabled when it is explicitly +// marked as not disabled. +TEST_F(DeviceDisablingManagerTest, NotDisabledWhenExplicitlyNotDisabled) { + SetEnterpriseOwned(); + MakeCrosSettingsTrusted(); + SetDeviceDisabled(false); + + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + CreateDeviceDisablingManager(); +} + +// Verifies that the device is not considered disabled when device disabling is +// turned off by flag, even if the device is marked as disabled. +TEST_F(DeviceDisablingManagerTest, NotDisabledWhenTurnedOffByFlag) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisableDeviceDisabling); + SetEnterpriseOwned(); + MakeCrosSettingsTrusted(); + SetDeviceDisabled(true); + + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + CreateDeviceDisablingManager(); +} + +// Verifies that the device is not considered disabled when it is owned by a +// consumer, even if the device is marked as disabled. +TEST_F(DeviceDisablingManagerTest, NotDisabledWhenConsumerOwned) { + SetConsumerOwned(); + MakeCrosSettingsTrusted(); + SetDeviceDisabled(true); + + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + CreateDeviceDisablingManager(); +} + +// Verifies that the device disabled screen is shown immediately when the device +// is already marked as disabled on start-up. +TEST_F(DeviceDisablingManagerTest, DisabledOnLoginScreen) { + SetEnterpriseOwned(); + MakeCrosSettingsTrusted(); + SetDisabledMessage(kDisabledMessage1); + SetDeviceDisabled(true); + + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(1); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + CreateDeviceDisablingManager(); + EXPECT_EQ(kDisabledMessage1, GetDeviceDisablingManager()->disabled_message()); +} + +// Verifies that the device disabled screen is shown immediately when the device +// becomes disabled while the login screen is showing. Also verifies that Chrome +// restarts when the device becomes enabled again. +TEST_F(DeviceDisablingManagerTest, DisableAndReEnableOnLoginScreen) { + SetEnterpriseOwned(); + MakeCrosSettingsTrusted(); + SetDisabledMessage(kDisabledMessage1); + + // Verify that initially, the disabled screen is not shown and Chrome does not + // restart. + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + CreateDeviceDisablingManager(); + Mock::VerifyAndClearExpectations(this); + + // Mark the device as disabled. Verify that the device disabled screen is + // shown. + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(1); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(kDisabledMessage1)).Times(1); + SetDeviceDisabled(true); + Mock::VerifyAndClearExpectations(this); + EXPECT_EQ(kDisabledMessage1, GetDeviceDisablingManager()->disabled_message()); + + // Update the disabled message. Verify that the device disabled screen is + // updated. + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(kDisabledMessage2)).Times(1); + SetDisabledMessage(kDisabledMessage2); + Mock::VerifyAndClearExpectations(this); + EXPECT_EQ(kDisabledMessage2, GetDeviceDisablingManager()->disabled_message()); + + // Mark the device as enabled again. Verify that Chrome restarts. + EXPECT_CALL(*this, RestartToLoginScreen()).Times(1); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + SetDeviceDisabled(false); +} + +// Verifies that Chrome restarts when the device becomes disabled while a +// session is in progress. +TEST_F(DeviceDisablingManagerTest, DisableDuringSession) { + SetEnterpriseOwned(); + MakeCrosSettingsTrusted(); + SetDisabledMessage(kDisabledMessage1); + LogIn(); + + // Verify that initially, the disabled screen is not shown and Chrome does not + // restart. + EXPECT_CALL(*this, RestartToLoginScreen()).Times(0); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + CreateDeviceDisablingManager(); + Mock::VerifyAndClearExpectations(this); + + // Mark the device as disabled. Verify that Chrome restarts. + EXPECT_CALL(*this, RestartToLoginScreen()).Times(1); + EXPECT_CALL(*this, ShowDeviceDisabledScreen()).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(_)).Times(0); + EXPECT_CALL(*this, OnDisabledMessageChanged(kDisabledMessage1)).Times(1); + SetDeviceDisabled(true); +} + +// Verifies that the HonorDeviceDisablingDuringNormalOperation() method returns +// true iff the device is enterprise enrolled and device disabling is not turned +// off by flag. +TEST_F(DeviceDisablingManagerTest, HonorDeviceDisablingDuringNormalOperation) { + // Not enterprise owned, not disabled by flag. + EXPECT_FALSE( + DeviceDisablingManager::HonorDeviceDisablingDuringNormalOperation()); + + // Enterprise owned, not disabled by flag. + SetEnterpriseOwned(); + EXPECT_TRUE( + DeviceDisablingManager::HonorDeviceDisablingDuringNormalOperation()); + + // Enterprise owned, disabled by flag. + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisableDeviceDisabling); + EXPECT_FALSE( + DeviceDisablingManager::HonorDeviceDisablingDuringNormalOperation()); + + // Not enterprise owned, disabled by flag. + SetUnowned(); + EXPECT_FALSE( + DeviceDisablingManager::HonorDeviceDisablingDuringNormalOperation()); } } // namespace system diff --git a/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc index 0ec8a0c..62a99d3 100644 --- a/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc @@ -48,6 +48,12 @@ void DeviceDisabledScreenHandler::SetDelegate(Delegate* delegate) { Initialize(); } +void DeviceDisabledScreenHandler::UpdateMessage(const std::string& message) { + message_ = message; + if (page_is_ready()) + CallJS("setMessage", message); +} + void DeviceDisabledScreenHandler::DeclareLocalizedValues( LocalizedValuesBuilder* builder) { builder->Add("deviceDisabledHeading", IDS_DEVICE_DISABLED_HEADING); diff --git a/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h index f794b3c..4fee52b 100644 --- a/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h @@ -24,6 +24,7 @@ class DeviceDisabledScreenHandler : public DeviceDisabledScreenActor, void Show(const std::string& message) override; void Hide() override; void SetDelegate(Delegate* delegate) override; + void UpdateMessage(const std::string& message) override; // BaseScreenHandler: void DeclareLocalizedValues(LocalizedValuesBuilder* builder) override; diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 331d78e..98bfada 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -869,6 +869,8 @@ 'browser/chromeos/system/device_change_handler.h', 'browser/chromeos/system/device_disabling_manager.cc', 'browser/chromeos/system/device_disabling_manager.h', + 'browser/chromeos/system/device_disabling_manager_default_delegate.cc', + 'browser/chromeos/system/device_disabling_manager_default_delegate.h', 'browser/chromeos/system/input_device_settings.cc', 'browser/chromeos/system/input_device_settings.h', 'browser/chromeos/system/pointer_device_observer.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 5b9c7ed..44f7018 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -210,6 +210,7 @@ 'browser/chromeos/power/peripheral_battery_observer_browsertest.cc', 'browser/chromeos/preferences_browsertest.cc', 'browser/chromeos/profiles/profile_helper_browsertest.cc', + 'browser/chromeos/system/device_disabling_browsertest.cc', 'browser/chromeos/system/tray_accessibility_browsertest.cc', 'browser/chromeos/ui/idle_logout_dialog_view_browsertest.cc', 'browser/collected_cookies_browsertest.cc', |