blob: 39ae63e1db4e0861e3c86534d0faf584d2f6b383 [file] [log] [blame]
// Copyright 2018 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/run_loop.h"
#include "chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_mock.h"
#include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/oobe_screen.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.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/shill_service_client.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
namespace chromeos {
namespace {
constexpr char kDefaultNetworkServicePath[] = "/service/eth1";
} // namespace
// Hands-off enrollment flow test.
class HandsOffEnrollmentTest : public InProcessBrowserTest {
protected:
HandsOffEnrollmentTest() {}
~HandsOffEnrollmentTest() override = default;
// InProcessBrowserTest:
void SetUpCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpCommandLine(command_line);
command_line->AppendArg(switches::kLoginManager);
command_line->AppendSwitchASCII(
switches::kEnterpriseEnableZeroTouchEnrollment, "hands-off");
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
ShowLoginWizard(OobeScreen::SCREEN_TEST_NO_WINDOW);
// Set official build so EULA screen is not skipped by default.
WizardController::default_controller()->is_official_build_ = true;
// Sets all network services into idle state to simulate disconnected state.
NetworkStateHandler::NetworkStateList networks;
NetworkHandler::Get()->network_state_handler()->GetNetworkListByType(
NetworkTypePattern::Default(),
true, // configured_only
false, // visible_only,
0, // no limit to number of results
&networks);
ShillServiceClient::TestInterface* service =
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
for (const auto* const network : networks) {
service->SetServiceProperty(network->path(), shill::kStateProperty,
base::Value(shill::kStateIdle));
}
base::RunLoop().RunUntilIdle();
}
// Simulates device being connected to the network.
void SimulateNetworkConnected() {
ShillServiceClient::TestInterface* service =
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
service->SetServiceProperty(kDefaultNetworkServicePath,
shill::kStateProperty,
base::Value(shill::kStateOnline));
base::RunLoop().RunUntilIdle();
}
// Result of attestation based enrollment used by
// EnterpriseEnrollmentHelperMock.
enum class AttestationEnrollmentResult { SUCCESS, ERROR };
// Helper method that mocks EnterpriseEnrollmentHelper for hands-off
// enrollment. It simulates specified attestation based enrollment |result|.
template <AttestationEnrollmentResult result>
static EnterpriseEnrollmentHelper* MockEnrollmentHelperCreator(
EnterpriseEnrollmentHelper::EnrollmentStatusConsumer* status_consumer,
const policy::EnrollmentConfig& enrollment_config,
const std::string& enrolling_user_domain) {
EnterpriseEnrollmentHelperMock* mock =
new EnterpriseEnrollmentHelperMock(status_consumer);
if (result == AttestationEnrollmentResult::SUCCESS) {
// Simulate successful attestation based enrollment.
EXPECT_CALL(*mock, EnrollUsingAttestation())
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Invoke(
[mock]() { mock->status_consumer()->OnDeviceEnrolled(); }));
EXPECT_CALL(*mock, GetDeviceAttributeUpdatePermission())
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Invoke([mock]() {
mock->status_consumer()->OnDeviceAttributeUpdatePermission(false);
}));
} else {
// Simulate error during attestation based enrollment.
const policy::EnrollmentStatus enrollment_status =
policy::EnrollmentStatus::ForRegistrationError(
policy::DeviceManagementStatus::DM_STATUS_TEMPORARY_UNAVAILABLE);
EXPECT_CALL(*mock, GetDeviceAttributeUpdatePermission())
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Invoke([mock, enrollment_status]() {
mock->status_consumer()->OnEnrollmentError(enrollment_status);
}));
}
// Define behavior of ClearAuth to only run the callback it is given.
EXPECT_CALL(*mock, ClearAuth(testing::_))
.Times(testing::AnyNumber())
.WillRepeatedly(testing::Invoke(
[](const base::RepeatingClosure& callback) { callback.Run(); }));
return mock;
}
private:
DISALLOW_COPY_AND_ASSIGN(HandsOffEnrollmentTest);
};
IN_PROC_BROWSER_TEST_F(HandsOffEnrollmentTest, NetworkConnectionReady) {
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockEnrollmentHelperCreator<AttestationEnrollmentResult::SUCCESS>);
SimulateNetworkConnected();
WizardController::default_controller()->AdvanceToScreen(
OobeScreen::SCREEN_OOBE_WELCOME);
OobeScreenWaiter(OobeScreen::SCREEN_OOBE_NETWORK).Wait();
OobeScreenWaiter(OobeScreen::SCREEN_OOBE_ENROLLMENT).Wait();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(StartupUtils::IsOobeCompleted());
EXPECT_TRUE(StartupUtils::IsDeviceRegistered());
EXPECT_TRUE(ExistingUserController::current_controller());
}
IN_PROC_BROWSER_TEST_F(HandsOffEnrollmentTest, WaitForNetworkConnection) {
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockEnrollmentHelperCreator<AttestationEnrollmentResult::SUCCESS>);
WizardController::default_controller()->AdvanceToScreen(
OobeScreen::SCREEN_OOBE_WELCOME);
OobeScreenWaiter(OobeScreen::SCREEN_OOBE_NETWORK).Wait();
SimulateNetworkConnected();
OobeScreenWaiter(OobeScreen::SCREEN_OOBE_ENROLLMENT).Wait();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(ExistingUserController::current_controller());
EXPECT_TRUE(StartupUtils::IsOobeCompleted());
EXPECT_TRUE(StartupUtils::IsDeviceRegistered());
}
IN_PROC_BROWSER_TEST_F(HandsOffEnrollmentTest, EnrollmentError) {
EnterpriseEnrollmentHelper::SetupEnrollmentHelperMock(
&MockEnrollmentHelperCreator<AttestationEnrollmentResult::ERROR>);
SimulateNetworkConnected();
WizardController::default_controller()->AdvanceToScreen(
OobeScreen::SCREEN_OOBE_WELCOME);
OobeScreenWaiter(OobeScreen::SCREEN_OOBE_NETWORK).Wait();
OobeScreenWaiter(OobeScreen::SCREEN_OOBE_ENROLLMENT).Wait();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(
OobeScreen::SCREEN_OOBE_ENROLLMENT,
WizardController::default_controller()->current_screen()->screen_id());
EXPECT_FALSE(ExistingUserController::current_controller());
EXPECT_FALSE(StartupUtils::IsOobeCompleted());
EXPECT_FALSE(StartupUtils::IsDeviceRegistered());
}
} // namespace chromeos