// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <string>
#include <vector>
#include "base/bind.h"
#include "base/run_loop.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/mock_login_utils.h"
+#include "chrome/browser/chromeos/login/screens/mock_base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.h"
#include "chrome/browser/chromeos/login/ui/mock_login_display.h"
#include "chrome/browser/chromeos/login/ui/mock_login_display_host.h"
+#include "chrome/browser/chromeos/login/user_flow.h"
#include "chrome/browser/chromeos/login/users/mock_user_manager.h"
#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.h"
+#include "chrome/grit/generated_resources.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/chromeos_switches.h"
#include "chromeos/dbus/fake_session_manager_client.h"
#include "chromeos/login/auth/authenticator.h"
#include "chromeos/login/auth/mock_authenticator.h"
#include "chromeos/login/auth/mock_url_fetchers.h"
#include "chromeos/login/auth/user_context.h"
+#include "chromeos/login/user_names.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/policy/core/common/cloud/cloud_policy_core.h"
#include "components/policy/core/common/cloud/cloud_policy_store.h"
#include "content/public/test/mock_notification_observer.h"
#include "content/public/test/test_utils.h"
#include "google_apis/gaia/mock_url_fetcher_factory.h"
+#include "policy/proto/device_management_backend.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
const char kUsername[] = "test_user@gmail.com";
const char kNewUsername[] = "test_new_user@gmail.com";
+const char kSupervisedUserID[] = "supervised_user@locally-managed.localhost";
const char kPassword[] = "test_password";
const char kPublicSessionAccountId[] = "public_session_user@localhost";
return new MockAuthenticator(arg0, user_context);
}
+void DeleteUserFlow(UserFlow* user_flow) {
+ delete user_flow;
+}
+
+// Wait for cros settings to become permanently untrusted and run |callback|.
+void WaitForPermanentlyUntrustedStatusAndRun(const base::Closure& callback) {
+ while (true) {
+ const CrosSettingsProvider::TrustedStatus status =
+ CrosSettings::Get()->PrepareTrustedValues(base::Bind(
+ &WaitForPermanentlyUntrustedStatusAndRun,
+ callback));
+ switch (status) {
+ case CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
+ callback.Run();
+ return;
+ case CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
+ return;
+ case CrosSettingsProvider::TRUSTED:
+ content::RunAllPendingInMessageLoop();
+ break;
+ }
+ }
+}
+
} // namespace
class ExistingUserControllerTest : public policy::DevicePolicyCrosBrowserTest {
return ExistingUserController::current_controller();
}
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ virtual void SetUpInProcessBrowserTestFixture() override {
SetUpSessionManager();
DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
LoginUtils::Set(mock_login_utils_);
EXPECT_CALL(*mock_login_utils_, DelegateDeleted(_))
.Times(1);
+ EXPECT_CALL(*mock_login_utils_, RestartToApplyPerSessionFlagsIfNeed(_, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(false));
mock_login_display_host_.reset(new MockLoginDisplayHost());
mock_login_display_ = new MockLoginDisplay();
.Times(1);
}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ virtual void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(switches::kLoginManager);
}
.WillRepeatedly(Return(false));
EXPECT_CALL(*mock_user_manager_, Shutdown())
.Times(1);
+ EXPECT_CALL(*mock_user_manager_, FindUser(_))
+ .Times(AnyNumber())
+ .WillRepeatedly(ReturnNull());
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ virtual void SetUpOnMainThread() override {
testing_profile_.reset(new TestingProfile());
SetUpUserManager();
existing_user_controller_.reset(
profile_prepared_cb_ =
base::Bind(&ExistingUserController::OnProfilePrepared,
base::Unretained(existing_user_controller()),
- testing_profile_.get());
+ testing_profile_.get(),
+ false);
}
- virtual void TearDownOnMainThread() OVERRIDE {
+ virtual void TearDownOnMainThread() 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
user_manager_enabler_.reset();
}
+ void ExpectLoginFailure() {
+ EXPECT_CALL(*mock_login_display_, SetUIEnabled(false))
+ .Times(1);
+ EXPECT_CALL(*mock_login_display_,
+ ShowError(IDS_LOGIN_ERROR_OWNER_KEY_LOST,
+ 1,
+ HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT))
+ .Times(1);
+ EXPECT_CALL(*mock_login_display_, SetUIEnabled(true))
+ .Times(1);
+ }
+
// ExistingUserController private member accessors.
base::OneShotTimer<ExistingUserController>* auto_login_timer() {
return existing_user_controller()->auto_login_timer_.get();
};
IN_PROC_BROWSER_TEST_F(ExistingUserControllerTest, ExistingUserLogin) {
- // This is disabled twice: once right after signin but before checking for
- // auto-enrollment, and again after doing an ownership status check.
EXPECT_CALL(*mock_login_display_, SetUIEnabled(false))
.Times(2);
UserContext user_context(kUsername);
.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_, SetUIEnabled(true))
.Times(1);
EXPECT_CALL(*mock_login_display_host_,
StartWizardPtr(WizardController::kEnrollmentScreenName,
_))
.Times(0);
- EXPECT_CALL(*mock_login_display_host_,
- StartWizardPtr(WizardController::kTermsOfServiceScreenName,
- NULL))
- .Times(1);
UserContext user_context(kNewUsername);
user_context.SetKey(Key(kPassword));
user_context.SetUserIDHash(kNewUsername);
// This is disabled twice: once right after signin but before checking for
// auto-enrollment, and again after doing an ownership status check.
EXPECT_CALL(*mock_login_display_, SetUIEnabled(false))
- .Times(2)
+ .Times(1)
.InSequence(uiEnabledSequence);
EXPECT_CALL(*mock_login_display_, SetUIEnabled(true))
.Times(1)
content::RunAllPendingInMessageLoop();
}
+// Verifies that when the cros settings are untrusted, no new session can be
+// started.
+class ExistingUserControllerUntrustedTest : public ExistingUserControllerTest {
+ public:
+ ExistingUserControllerUntrustedTest();
+
+ void SetUpInProcessBrowserTestFixture() override;
+
+ void SetUpSessionManager() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ExistingUserControllerUntrustedTest);
+};
+
+ExistingUserControllerUntrustedTest::ExistingUserControllerUntrustedTest() {
+}
+
+void ExistingUserControllerUntrustedTest::SetUpInProcessBrowserTestFixture() {
+ ExistingUserControllerTest::SetUpInProcessBrowserTestFixture();
+
+ ExpectLoginFailure();
+}
+
+void ExistingUserControllerUntrustedTest::SetUpSessionManager() {
+ InstallOwnerKey();
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest,
+ UserLoginForbidden) {
+ UserContext user_context(kUsername);
+ user_context.SetKey(Key(kPassword));
+ user_context.SetUserIDHash(kUsername);
+ existing_user_controller()->Login(user_context, SigninSpecifics());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest,
+ CreateAccountForbidden) {
+ existing_user_controller()->CreateAccount();
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest,
+ GuestLoginForbidden) {
+ existing_user_controller()->Login(
+ UserContext(user_manager::USER_TYPE_GUEST, std::string()),
+ SigninSpecifics());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest,
+ RetailModeLoginForbidden) {
+ existing_user_controller()->Login(
+ UserContext(user_manager::USER_TYPE_RETAIL_MODE,
+ chromeos::login::kRetailModeUserName),
+ SigninSpecifics());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest,
+ SupervisedUserLoginForbidden) {
+ UserContext user_context(kSupervisedUserID);
+ user_context.SetKey(Key(kPassword));
+ user_context.SetUserIDHash(kUsername);
+ existing_user_controller()->Login(user_context, SigninSpecifics());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerUntrustedTest,
+ SupervisedUserCreationForbidden) {
+ MockBaseScreenDelegate mock_base_screen_delegate;
+ SupervisedUserCreationScreenHandler supervised_user_creation_screen_handler;
+ SupervisedUserCreationScreen supervised_user_creation_screen(
+ &mock_base_screen_delegate,
+ &supervised_user_creation_screen_handler);
+
+ EXPECT_CALL(*mock_user_manager_, SetUserFlow(kUsername, _))
+ .Times(1)
+ .WillOnce(WithArg<1>(Invoke(DeleteUserFlow)));
+ supervised_user_creation_screen.AuthenticateManager(kUsername, kPassword);
+}
+
MATCHER_P(HasDetails, expected, "") {
return expected == *content::Details<const std::string>(arg).ptr();
}
policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION)) {
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ virtual void SetUpOnMainThread() override {
ExistingUserControllerTest::SetUpOnMainThread();
// Wait for the public session user to be created.
}
}
- virtual void SetUpSessionManager() OVERRIDE {
+ virtual void SetUpSessionManager() override {
InstallOwnerKey();
// Setup the device policy.
device_local_account_policy.GetBlob());
}
- virtual void SetUpLoginDisplay() OVERRIDE {
+ virtual void SetUpLoginDisplay() override {
EXPECT_CALL(*mock_login_display_host_.get(), CreateLoginDisplay(_))
.Times(1)
.WillOnce(Return(mock_login_display_));
.Times(AnyNumber());
}
- virtual void SetUpUserManager() OVERRIDE {
+ virtual void SetUpUserManager() override {
}
void ExpectSuccessfulLogin(const UserContext& user_context) {
.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_, SetUIEnabled(true))
.Times(1);
EXPECT_CALL(*mock_login_display_host_,
existing_user_controller()->OnPublicSessionAutoLoginTimerFire();
}
+ void MakeCrosSettingsPermanentlyUntrusted() {
+ device_policy()->policy().set_policy_data_signature("bad signature");
+ session_manager_client()->set_device_policy(device_policy()->GetBlob());
+ session_manager_client()->OnPropertyChangeComplete(true);
+
+ base::RunLoop run_loop;
+ WaitForPermanentlyUntrustedStatusAndRun(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
const std::string public_session_user_id_;
private:
existing_user_controller()->OnSigninScreenReady();
SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay);
- ASSERT_TRUE(auto_login_timer());
+ EXPECT_TRUE(auto_login_timer());
// Log in and check that it stopped the timer.
existing_user_controller()->Login(user_context, SigninSpecifics());
IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
GuestModeLoginStopsAutoLogin) {
EXPECT_CALL(*mock_login_display_, SetUIEnabled(false))
- .Times(1);
+ .Times(2);
UserContext user_context(kUsername);
user_context.SetKey(Key(kPassword));
EXPECT_CALL(*mock_login_utils_, CreateAuthenticator(_))
.Times(1)
.WillOnce(WithArg<0>(CreateAuthenticator(user_context)));
- EXPECT_CALL(*mock_login_utils_, CompleteOffTheRecordLogin(_))
- .Times(1);
existing_user_controller()->OnSigninScreenReady();
SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay);
- ASSERT_TRUE(auto_login_timer());
+ EXPECT_TRUE(auto_login_timer());
// Login and check that it stopped the timer.
- existing_user_controller()->LoginAsGuest();
+ existing_user_controller()->Login(UserContext(user_manager::USER_TYPE_GUEST,
+ std::string()),
+ SigninSpecifics());
EXPECT_TRUE(is_login_in_progress());
ASSERT_TRUE(auto_login_timer());
EXPECT_FALSE(auto_login_timer()->IsRunning());
existing_user_controller()->OnSigninScreenReady();
SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay);
- ASSERT_TRUE(auto_login_timer());
+ EXPECT_TRUE(auto_login_timer());
// Check that login completes and stops the timer.
existing_user_controller()->CompleteLogin(user_context);
ExpectSuccessfulLogin(user_context);
existing_user_controller()->OnSigninScreenReady();
SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay);
- ASSERT_TRUE(auto_login_timer());
+ EXPECT_TRUE(auto_login_timer());
// Login and check that it stopped the timer.
- existing_user_controller()->LoginAsPublicSession(UserContext(
- user_manager::USER_TYPE_PUBLIC_ACCOUNT,
- public_session_user_id_));
+ existing_user_controller()->Login(
+ UserContext(user_manager::USER_TYPE_PUBLIC_ACCOUNT,
+ public_session_user_id_),
+ SigninSpecifics());
EXPECT_TRUE(is_login_in_progress());
ASSERT_TRUE(auto_login_timer());
}
IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ LoginForbiddenWhenUntrusted) {
+ // Make cros settings untrusted.
+ MakeCrosSettingsPermanentlyUntrusted();
+
+ // Check that the attempt to start a public session fails with an error.
+ ExpectLoginFailure();
+ UserContext user_context(kUsername);
+ user_context.SetKey(Key(kPassword));
+ user_context.SetUserIDHash(user_context.GetUserID());
+ existing_user_controller()->Login(user_context, SigninSpecifics());
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
+ NoAutoLoginWhenUntrusted) {
+ // Start the public session timer.
+ SetAutoLoginPolicy(kPublicSessionAccountId, kAutoLoginLongDelay);
+ existing_user_controller()->OnSigninScreenReady();
+ EXPECT_TRUE(auto_login_timer());
+
+ // Make cros settings untrusted.
+ MakeCrosSettingsPermanentlyUntrusted();
+
+ // Check that when the timer fires, auto-login fails with an error.
+ ExpectLoginFailure();
+ FireAutoLogin();
+}
+
+IN_PROC_BROWSER_TEST_F(ExistingUserControllerPublicSessionTest,
PRE_TestLoadingPublicUsersFromLocalState) {
// First run propagates public accounts and stores them in Local State.
}