Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5900)

Unified Diff: chrome/browser/chromeos/login/existing_user_controller_browsertest.cc

Issue 12218078: Implement a policy to autologin a public account. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: r3b@$3 Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index 9ffb78128b7cd3c39779e2330b910dfe9dfa2c76..28d26f056b98fc74744a81dceafa573df002b99e 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -2,31 +2,60 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
+
#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/location.h"
+#include "base/memory/ref_counted.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/cros_mock.h"
#include "chrome/browser/chromeos/cros/mock_network_library.h"
+#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/helper.h"
-#include "chrome/browser/chromeos/login/login_display.h"
-#include "chrome/browser/chromeos/login/login_display_host.h"
-#include "chrome/browser/chromeos/login/login_performer.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
-#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/mock_authenticator.h"
+#include "chrome/browser/chromeos/login/mock_login_display.h"
+#include "chrome/browser/chromeos/login/mock_login_display_host.h"
#include "chrome/browser/chromeos/login/mock_login_utils.h"
#include "chrome/browser/chromeos/login/mock_url_fetchers.h"
#include "chrome/browser/chromeos/login/mock_user_manager.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
+#include "chrome/browser/chromeos/policy/device_policy_builder.h"
+#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/cros_settings_names.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
+#include "chrome/browser/policy/cloud/cloud_policy_core.h"
+#include "chrome/browser/policy/cloud/cloud_policy_store.h"
+#include "chrome/browser/policy/cloud/mock_cloud_policy_store.h"
+#include "chrome/browser/policy/cloud/policy_builder.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "chromeos/dbus/fake_session_manager_client.h"
#include "chromeos/dbus/mock_dbus_thread_manager.h"
#include "chromeos/dbus/mock_session_manager_client.h"
#include "chromeos/dbus/mock_shill_manager_client.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/test/mock_notification_observer.h"
+#include "content/public/test/test_utils.h"
+#include "crypto/rsa_private_key.h"
#include "google_apis/gaia/mock_url_fetcher_factory.h"
#include "grit/generated_resources.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -43,6 +72,8 @@ using ::testing::ReturnNull;
using ::testing::Sequence;
using ::testing::WithArg;
+namespace em = enterprise_management;
+
namespace chromeos {
namespace {
@@ -51,56 +82,10 @@ const char kUsername[] = "test_user@gmail.com";
const char kNewUsername[] = "test_new_user@gmail.com";
const char kPassword[] = "test_password";
-class MockLoginDisplay : public LoginDisplay {
- public:
- MockLoginDisplay()
- : LoginDisplay(NULL, gfx::Rect()) {
- }
-
- MOCK_METHOD4(Init, void(const UserList&, bool, bool, bool));
- MOCK_METHOD0(OnPreferencesChanged, void(void));
- MOCK_METHOD1(OnUserImageChanged, void(const User&));
- MOCK_METHOD0(OnFadeOut, void(void));
- MOCK_METHOD1(OnLoginSuccess, void(const std::string&));
- MOCK_METHOD1(SetUIEnabled, void(bool));
- MOCK_METHOD1(SelectPod, void(int));
- MOCK_METHOD3(ShowError, void(int, int, HelpAppLauncher::HelpTopic));
- MOCK_METHOD1(ShowErrorScreen, void(LoginDisplay::SigninError));
- MOCK_METHOD1(ShowGaiaPasswordChanged, void(const std::string&));
- MOCK_METHOD1(ShowPasswordChangedDialog, void(bool));
- MOCK_METHOD1(ShowSigninUI, void(const std::string&));
- MOCK_METHOD1(OnBeforeUserRemoved, void(const std::string&));
- MOCK_METHOD1(OnUserRemoved, void(const std::string&));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockLoginDisplay);
-};
-
-class MockLoginDisplayHost : public LoginDisplayHost {
- public:
- MockLoginDisplayHost() {
- }
-
- MOCK_METHOD1(CreateLoginDisplay, LoginDisplay*(LoginDisplay::Delegate*));
- MOCK_CONST_METHOD0(GetNativeWindow, gfx::NativeWindow(void));
- MOCK_CONST_METHOD0(GetWidget, views::Widget*(void));
- MOCK_METHOD0(BeforeSessionStart, void(void));
- MOCK_METHOD0(OnSessionStart, void(void));
- MOCK_METHOD0(OnCompleteLogin, void(void));
- MOCK_METHOD0(OpenProxySettings, void(void));
- MOCK_METHOD1(SetOobeProgressBarVisible, void(bool));
- MOCK_METHOD1(SetShutdownButtonEnabled, void(bool));
- MOCK_METHOD1(SetStatusAreaVisible, void(bool));
- MOCK_METHOD0(ShowBackground, void(void));
- MOCK_METHOD0(CheckForAutoEnrollment, void(void));
- MOCK_METHOD2(StartWizard, void(const std::string&, DictionaryValue*));
- MOCK_METHOD0(StartSignInScreen, void(void));
- MOCK_METHOD0(ResumeSignInScreen, void(void));
- MOCK_METHOD0(OnPreferencesChanged, void(void));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockLoginDisplayHost);
-};
+const char kAutoLoginUsername[] = "public_session_user@localhost";
+const int kAutoLoginNoDelay = 0;
+const int kAutoLoginShortDelay = 1;
+const int kAutoLoginLongDelay = 10000;
scoped_refptr<Authenticator> CreateAuthenticator(
LoginStatusConsumer* consumer) {
@@ -112,6 +97,49 @@ scoped_refptr<Authenticator> CreateAuthenticatorNewUser(
return new MockAuthenticator(consumer, kNewUsername, kPassword);
}
+scoped_refptr<Authenticator> CreateAuthenticatorForPublicSession(
+ LoginStatusConsumer* consumer) {
+ return new MockAuthenticator(consumer, kAutoLoginUsername, "");
+}
+
+// Observes a specific notification type and quits the message loop once a
+// condition holds.
+class NotificationWatcher : public content::NotificationObserver {
+ public:
+ // Callback invoked on notifications. Should return true when the condition
+ // that the caller is waiting for is satisfied.
+ typedef base::Callback<bool(void)> ConditionTestCallback;
+
+ explicit NotificationWatcher(int notification_type,
+ const ConditionTestCallback& callback)
+ : type_(notification_type),
+ callback_(callback) {}
+
+ void Run() {
+ if (callback_.Run())
+ return;
+
+ content::NotificationRegistrar registrar;
+ registrar.Add(this, type_, content::NotificationService::AllSources());
+ run_loop_.Run();
+ }
+
+ // content::NotificationObserver:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE {
+ if (callback_.Run())
+ run_loop_.Quit();
+ }
+
+ private:
+ int type_;
+ ConditionTestCallback callback_;
+ base::RunLoop run_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationWatcher);
+};
+
} // namespace
class ExistingUserControllerTest : public CrosInProcessBrowserTest {
@@ -127,6 +155,10 @@ class ExistingUserControllerTest : public CrosInProcessBrowserTest {
return ExistingUserController::current_controller();
}
+ const ExistingUserController* existing_user_controller() const {
+ return ExistingUserController::current_controller();
+ }
+
virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
MockDBusThreadManager* mock_dbus_thread_manager =
new MockDBusThreadManager;
@@ -144,6 +176,9 @@ class ExistingUserControllerTest : public CrosInProcessBrowserTest {
EXPECT_CALL(*mock_dbus_thread_manager->mock_shill_manager_client(),
RemovePropertyChangedObserver(_))
.Times(AnyNumber());
+
+ SetUpSessionManager(mock_dbus_thread_manager);
+
DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
CrosInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
cros_mock_->InitStatusAreaMocks();
@@ -155,13 +190,6 @@ class ExistingUserControllerTest : public CrosInProcessBrowserTest {
EXPECT_CALL(*mock_network_library_, LoadOncNetworks(_, _, _, _))
.WillRepeatedly(Return(true));
- MockSessionManagerClient* mock_session_manager_client =
- mock_dbus_thread_manager->mock_session_manager_client();
- EXPECT_CALL(*mock_session_manager_client, EmitLoginPromptReady())
- .Times(1);
- EXPECT_CALL(*mock_session_manager_client, RetrieveDevicePolicy(_))
- .Times(AnyNumber());
-
mock_login_utils_ = new MockLoginUtils();
LoginUtils::Set(mock_login_utils_);
EXPECT_CALL(*mock_login_utils_, PrewarmAuthentication())
@@ -172,32 +200,50 @@ class ExistingUserControllerTest : public CrosInProcessBrowserTest {
.Times(1);
mock_login_display_host_.reset(new MockLoginDisplayHost());
+ mock_login_display_ = new MockLoginDisplay();
+ SetUpLoginDisplay();
+ }
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsKnownUser(kUsername))
+ virtual void SetUpSessionManager(
+ MockDBusThreadManager* mock_dbus_thread_manager) {
+ mock_user_manager_.reset(new ScopedMockUserManagerEnabler);
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsKnownUser(kUsername))
.Times(AnyNumber())
.WillRepeatedly(Return(true));
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsKnownUser(kNewUsername))
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsKnownUser(kNewUsername))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsUserLoggedIn())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsUserLoggedIn())
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsLoggedInAsGuest())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsLoggedInAsGuest())
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsLoggedInAsDemoUser())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsLoggedInAsDemoUser())
+ EXPECT_CALL(*mock_user_manager_->user_manager(),
+ IsLoggedInAsPublicAccount())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsLoggedInAsPublicAccount())
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsSessionStarted())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsSessionStarted())
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsCurrentUserNew())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
+ EXPECT_CALL(*mock_user_manager_->user_manager(), Shutdown())
+ .Times(1);
- // |mock_login_display_| is owned by the ExistingUserController, which calls
- // CreateLoginDisplay() on the |mock_login_display_host_| to get it.
- mock_login_display_ = new MockLoginDisplay();
+ MockSessionManagerClient* mock_session_manager_client =
+ mock_dbus_thread_manager->mock_session_manager_client();
+ EXPECT_CALL(*mock_session_manager_client, EmitLoginPromptReady())
+ .Times(1);
+ EXPECT_CALL(*mock_session_manager_client, RetrieveDevicePolicy(_))
+ .Times(AnyNumber());
+ }
+
+ virtual void SetUpLoginDisplay() {
EXPECT_CALL(*mock_login_display_host_.get(), CreateLoginDisplay(_))
.Times(1)
.WillOnce(Return(mock_login_display_));
@@ -227,6 +273,12 @@ class ExistingUserControllerTest : public CrosInProcessBrowserTest {
}
virtual void CleanUpOnMainThread() OVERRIDE {
+ // ExistingUserController must be deleted before the thread is cleaned up:
+ // If there is an outstanding login attempt when ExistingUserController is
+ // deleted, its LoginPerformer instance will be deleted, which in turn
+ // deletes its OnlineAttemptHost instance. However, OnlineAttemptHost must
+ // be deleted on the UI thread.
+ existing_user_controller_.reset();
CrosInProcessBrowserTest::CleanUpOnMainThread();
testing_profile_.reset(NULL);
}
@@ -236,15 +288,34 @@ class ExistingUserControllerTest : public CrosInProcessBrowserTest {
DBusThreadManager::Shutdown();
}
+ // ExistingUserController private member accessors.
+ base::OneShotTimer<ExistingUserController>* auto_login_timer() {
+ return existing_user_controller()->auto_login_timer_.get();
+ }
+
+ const std::string& auto_login_username() const {
+ return existing_user_controller()->public_session_auto_login_username_;
+ }
+
+ int auto_login_delay() const {
+ return existing_user_controller()->public_session_auto_login_delay_;
+ }
+
+ bool is_login_in_progress() const {
+ return existing_user_controller()->is_login_in_progress_;
+ }
+
scoped_ptr<ExistingUserController> existing_user_controller_;
// These mocks are owned by CrosLibrary class.
MockNetworkLibrary* mock_network_library_;
+ // |mock_login_display_| is owned by the ExistingUserController, which calls
+ // CreateLoginDisplay() on the |mock_login_display_host_| to get it.
MockLoginDisplay* mock_login_display_;
scoped_ptr<MockLoginDisplayHost> mock_login_display_host_;
- ScopedMockUserManagerEnabler mock_user_manager_;
+ scoped_ptr<ScopedMockUserManagerEnabler> mock_user_manager_;
// Owned by LoginUtilsWrapper.
MockLoginUtils* mock_login_utils_;
@@ -286,7 +357,7 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerTest, ExistingUserLogin) {
EXPECT_CALL(*mock_login_display_host_,
StartWizard(WizardController::kTermsOfServiceScreenName, NULL))
.Times(0);
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsCurrentUserNew())
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsCurrentUserNew())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
existing_user_controller()->Login(kUsername, kPassword);
@@ -301,7 +372,7 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerTest, AutoEnrollAfterSignIn) {
.Times(1);
EXPECT_CALL(*mock_login_display_host_.get(), OnCompleteLogin())
.Times(1);
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsCurrentUserNew())
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsCurrentUserNew())
.Times(AnyNumber())
.WillRepeatedly(Return(false));
// The order of these expected calls matters: the UI if first disabled
@@ -346,7 +417,7 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerTest,
.Times(1);
EXPECT_CALL(*mock_login_display_host_.get(), OnCompleteLogin())
.Times(1);
- EXPECT_CALL(*mock_user_manager_.user_manager(), IsCurrentUserNew())
+ EXPECT_CALL(*mock_user_manager_->user_manager(), IsCurrentUserNew())
.Times(AnyNumber())
.WillRepeatedly(Return(true));
@@ -366,4 +437,373 @@ IN_PROC_BROWSER_TEST_F(ExistingUserControllerTest,
content::RunAllPendingInMessageLoop();
}
+MATCHER_P(HasDetails, expected, "") {
+ return expected == *content::Details<const std::string>(arg).ptr();
+}
+
+class ExistingUserControllerPublicSessionTest
+ : public ExistingUserControllerTest {
+ protected:
+ ExistingUserControllerPublicSessionTest() {
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ ExistingUserControllerTest::SetUpOnMainThread();
+
+ // Wait for the public session user to be created.
+ if (!chromeos::UserManager::Get()->IsKnownUser(kAutoLoginUsername)) {
+ NotificationWatcher(
+ chrome::NOTIFICATION_USER_LIST_CHANGED,
+ base::Bind(&chromeos::UserManager::IsKnownUser,
+ base::Unretained(chromeos::UserManager::Get()),
+ kAutoLoginUsername)).Run();
+ }
+
+ // Wait for the device local account policy to be installed.
+ policy::MockCloudPolicyStoreObserver observer;
+ scoped_refptr<content::MessageLoopRunner> runner =
+ new content::MessageLoopRunner;
+ policy::CloudPolicyStore* store = TestingBrowserProcess::GetGlobal()->
+ browser_policy_connector()->GetDeviceLocalAccountPolicyService()->
+ GetBrokerForAccount(kAutoLoginUsername)->core()->store();
+ store->AddObserver(&observer);
+ EXPECT_CALL(observer, OnStoreLoaded(store))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(runner.get(),
+ &content::MessageLoopRunner::Quit));
+ runner->Run();
+ store->RemoveObserver(&observer);
+ }
+
+ virtual void SetUpSessionManager(
+ MockDBusThreadManager* mock_dbus_thread_manager) OVERRIDE {
+ EXPECT_CALL(*mock_dbus_thread_manager, GetSessionManagerClient())
+ .WillRepeatedly(Return(&session_manager_client_));
+
+ // Install the owner key.
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ base::FilePath owner_key_file = temp_dir_.path().AppendASCII("owner.key");
+ std::vector<uint8> owner_key_bits;
+ ASSERT_TRUE(device_policy_.signing_key()->ExportPublicKey(&owner_key_bits));
+ ASSERT_EQ(
+ file_util::WriteFile(
+ owner_key_file,
+ reinterpret_cast<const char*>(vector_as_array(&owner_key_bits)),
+ owner_key_bits.size()),
+ static_cast<int>(owner_key_bits.size()));
+ ASSERT_TRUE(PathService::Override(chrome::FILE_OWNER_KEY, owner_key_file));
+
+ // Setup the device policy.
+ em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
+ proto.mutable_device_local_accounts()->add_account()->set_id(
+ kAutoLoginUsername);
+ RefreshDevicePolicy();
+
+ // Setup the device local account policy.
+ policy::UserPolicyBuilder device_local_account_policy;
+ device_local_account_policy.policy_data().set_username(kAutoLoginUsername);
+ device_local_account_policy.policy_data().set_policy_type(
+ policy::dm_protocol::kChromePublicAccountPolicyType);
+ device_local_account_policy.policy_data().set_settings_entity_id(
+ kAutoLoginUsername);
+ device_local_account_policy.Build();
+ session_manager_client_.set_device_local_account_policy(
+ kAutoLoginUsername,
+ device_local_account_policy.GetBlob());
+ }
+
+ virtual void SetUpLoginDisplay() OVERRIDE {
+ EXPECT_CALL(*mock_login_display_host_.get(), CreateLoginDisplay(_))
+ .Times(1)
+ .WillOnce(Return(mock_login_display_));
+ EXPECT_CALL(*mock_login_display_host_.get(), GetNativeWindow())
+ .Times(AnyNumber())
+ .WillRepeatedly(ReturnNull());
+ EXPECT_CALL(*mock_login_display_host_.get(), OnPreferencesChanged())
+ .Times(AnyNumber());
+ EXPECT_CALL(*mock_login_display_, Init(_, _, _, _))
+ .Times(AnyNumber());
+ }
+
+ void ExpectSuccessfulLogin(const std::string& username,
+ const std::string& password,
+ scoped_refptr<Authenticator> create_authenticator(
+ LoginStatusConsumer* consumer)) {
+ EXPECT_CALL(*mock_login_display_, SetUIEnabled(false))
+ .Times(AnyNumber());
+ EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_))
+ .Times(1)
+ .WillOnce(WithArg<0>(Invoke(create_authenticator)));
+ EXPECT_CALL(*mock_login_utils_,
+ PrepareProfile(username, _, password, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(&profile_prepared_cb_,
+ &base::Callback<void(void)>::Run));
+ EXPECT_CALL(*mock_login_utils_,
+ DoBrowserLaunch(testing_profile_.get(),
+ mock_login_display_host_.get()))
+ .Times(1);
+ EXPECT_CALL(*mock_login_display_, OnLoginSuccess(username))
+ .Times(1);
+ EXPECT_CALL(*mock_login_display_, SetUIEnabled(true))
+ .Times(1);
+ EXPECT_CALL(*mock_login_display_, OnFadeOut())
+ .Times(1);
+ EXPECT_CALL(*mock_login_display_host_,
+ StartWizard(WizardController::kTermsOfServiceScreenName, NULL))
+ .Times(0);
+ }
+
+ scoped_refptr<content::MessageLoopRunner> CreateSettingsObserverRunLoop(
+ content::MockNotificationObserver& observer, const char* setting) {
+ scoped_refptr<content::MessageLoopRunner> runner =
+ new content::MessageLoopRunner;
+ EXPECT_CALL(observer, Observe(chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED,
+ _, HasDetails(setting)))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(runner.get(),
+ &content::MessageLoopRunner::Quit));
+ CrosSettings::Get()->AddSettingsObserver(setting, &observer);
+ return runner;
+ }
+
+ void RefreshDevicePolicy() {
+ // Reset the key to its original state.
+ device_policy_.set_signing_key(
+ policy::PolicyBuilder::CreateTestSigningKey());
+ device_policy_.Build();
+ // Trick the device into thinking it's enterprise-enrolled by
+ // removing the local private key. This will allow it to accept
+ // cloud policy for device owner settings.
+ device_policy_.set_signing_key(
+ make_scoped_ptr<crypto::RSAPrivateKey>(NULL));
+ device_policy_.set_new_signing_key(
+ make_scoped_ptr<crypto::RSAPrivateKey>(NULL));
+ session_manager_client_.set_device_policy(device_policy_.GetBlob());
+ session_manager_client_.OnPropertyChangeComplete(true);
+ }
+
+ void SetAutoLoginPolicy(const std::string& username, int delay) {
+ // Wait until ExistingUserController has finished auto-login
+ // configuration by observing the same settings that trigger
+ // ConfigurePublicSessionAutoLogin.
+ content::MockNotificationObserver observer;
+
+ em::ChromeDeviceSettingsProto& proto(device_policy_.payload());
+
+ // If both settings have changed we need to wait for both to
+ // propagate, so check the new values against the old ones.
+ scoped_refptr<content::MessageLoopRunner> runner1 = NULL;
+ if (!proto.has_device_local_accounts() ||
+ !proto.device_local_accounts().has_auto_login_id() ||
+ proto.device_local_accounts().auto_login_id() != username) {
+ runner1 = CreateSettingsObserverRunLoop(
+ observer, kAccountsPrefDeviceLocalAccountAutoLoginId);
+ }
+ scoped_refptr<content::MessageLoopRunner> runner2 = NULL;
+ if (!proto.has_device_local_accounts() ||
+ !proto.device_local_accounts().has_auto_login_delay() ||
+ proto.device_local_accounts().auto_login_delay() != delay) {
+ runner2 = CreateSettingsObserverRunLoop(
+ observer, kAccountsPrefDeviceLocalAccountAutoLoginDelay);
+ }
+
+ // Update the policy.
+ proto.mutable_device_local_accounts()->set_auto_login_id(username);
+ proto.mutable_device_local_accounts()->set_auto_login_delay(delay);
+ RefreshDevicePolicy();
+
+ // Wait for ExistingUserController to read the updated settings.
+ if (runner1)
+ runner1->Run();
+ if (runner2)
+ runner2->Run();
+
+ // Clean up.
+ CrosSettings::Get()->RemoveSettingsObserver(
+ kAccountsPrefDeviceLocalAccountAutoLoginId,
+ &observer);
+ CrosSettings::Get()->RemoveSettingsObserver(
+ kAccountsPrefDeviceLocalAccountAutoLoginDelay,
+ &observer);
+ }
+
+ void ConfigureAutoLogin() {
+ existing_user_controller()->ConfigurePublicSessionAutoLogin();
+ }
+
+ void FireAutoLogin() {
+ existing_user_controller()->OnPublicSessionAutoLoginTimerFire();
+ }
+
+ // Mock out policy loads/stores from/to the device.
+ FakeSessionManagerClient session_manager_client_;
+
+ // Stores the device owner key.
+ base::ScopedTempDir temp_dir_;
+
+ // Carries Chrome OS device policies for tests.
+ policy::DevicePolicyBuilder device_policy_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ExistingUserControllerPublicSessionTest);
+};
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ ConfigureAutoLoginUsingPolicy) {
+ existing_user_controller()->OnSigninScreenReady();
+ EXPECT_EQ("", auto_login_username());
+ EXPECT_EQ(0, auto_login_delay());
+ EXPECT_FALSE(auto_login_timer());
+
+ // Set the policy.
+ SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay);
+ EXPECT_EQ(kAutoLoginUsername, auto_login_username());
+ EXPECT_EQ(kAutoLoginLongDelay, auto_login_delay());
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_TRUE(auto_login_timer()->IsRunning());
+
+ // Unset the policy.
+ SetAutoLoginPolicy("", 0);
+ EXPECT_EQ("", auto_login_username());
+ EXPECT_EQ(0, auto_login_delay());
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ AutoLoginNoDelay) {
+ // Set up mocks to check login success.
+ ExpectSuccessfulLogin(kAutoLoginUsername, "",
+ CreateAuthenticatorForPublicSession);
+ existing_user_controller()->OnSigninScreenReady();
+
+ // Start auto-login and wait for login tasks to complete.
+ SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginNoDelay);
+ content::RunAllPendingInMessageLoop();
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ AutoLoginShortDelay) {
+ // Set up mocks to check login success.
+ ExpectSuccessfulLogin(kAutoLoginUsername, "",
+ CreateAuthenticatorForPublicSession);
+ existing_user_controller()->OnSigninScreenReady();
+ SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginShortDelay);
+ ASSERT_TRUE(auto_login_timer());
+ // Don't assert that timer is running: with the short delay sometimes
+ // the trigger happens before the assert. We've already tested that
+ // the timer starts when it should.
+
+ // Wait for the timer to fire.
+ scoped_refptr<content::MessageLoopRunner> runner
+ = new content::MessageLoopRunner;
+ base::OneShotTimer<content::MessageLoopRunner> timer;
+ timer.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kAutoLoginShortDelay + 1),
+ base::Bind(&content::MessageLoopRunner::Quit, runner));
+ runner->Run();
+
+ // Wait for login tasks to complete.
+ content::RunAllPendingInMessageLoop();
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ LoginStopsAutoLogin) {
+ // Set up mocks to check login success.
+ ExpectSuccessfulLogin(kUsername, kPassword, CreateAuthenticator);
+
+ existing_user_controller()->OnSigninScreenReady();
+ SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay);
+ ASSERT_TRUE(auto_login_timer());
+
+ // Login and check that it stopped the timer.
+ existing_user_controller()->Login(kUsername, kPassword);
+ EXPECT_TRUE(is_login_in_progress());
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+
+ // Wait for login tasks to complete.
+ content::RunAllPendingInMessageLoop();
+
+ // Timer should still be stopped after login completes.
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ GuestModeLoginStopsAutoLogin) {
+ EXPECT_CALL(*mock_login_display_, SetUIEnabled(false))
+ .Times(1);
+ EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_))
+ .Times(1)
+ .WillOnce(WithArg<0>(Invoke(CreateAuthenticator)));
+ EXPECT_CALL(*mock_login_utils_, CompleteOffTheRecordLogin(_))
+ .Times(1);
+
+ existing_user_controller()->OnSigninScreenReady();
+ SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay);
+ ASSERT_TRUE(auto_login_timer());
+
+ // Login and check that it stopped the timer.
+ existing_user_controller()->LoginAsGuest();
+ EXPECT_TRUE(is_login_in_progress());
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+
+ // Wait for login tasks to complete.
+ content::RunAllPendingInMessageLoop();
+
+ // Timer should still be stopped after login completes.
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ CompleteLoginStopsAutoLogin) {
+ // Set up mocks to check login success.
+ ExpectSuccessfulLogin(kUsername, kPassword, CreateAuthenticator);
+ EXPECT_CALL(*mock_login_display_host_, OnCompleteLogin())
+ .Times(1);
+
+ existing_user_controller()->OnSigninScreenReady();
+ SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay);
+ ASSERT_TRUE(auto_login_timer());
+
+ // Check that login completes and stops the timer.
+ existing_user_controller()->CompleteLogin(kUsername, kPassword);
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+
+ // Wait for login tasks to complete.
+ content::RunAllPendingInMessageLoop();
+
+ // Timer should still be stopped after login completes.
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ PublicSessionLoginStopsAutoLogin) {
+ // Set up mocks to check login success.
+ ExpectSuccessfulLogin(kAutoLoginUsername, "",
+ CreateAuthenticatorForPublicSession);
+ existing_user_controller()->OnSigninScreenReady();
+ SetAutoLoginPolicy(kAutoLoginUsername, kAutoLoginLongDelay);
+ ASSERT_TRUE(auto_login_timer());
+
+ // Login and check that it stopped the timer.
+ existing_user_controller()->LoginAsPublicAccount(kAutoLoginUsername);
+ EXPECT_TRUE(is_login_in_progress());
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+
+ // Wait for login tasks to complete.
+ content::RunAllPendingInMessageLoop();
+
+ // Timer should still be stopped after login completes.
+ ASSERT_TRUE(auto_login_timer());
+ EXPECT_FALSE(auto_login_timer()->IsRunning());
+}
+
} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698