Commit 97cd34cb authored by Ryan Hansberry's avatar Ryan Hansberry Committed by Commit Bot

[SmartLock] Increase EasyUnlockServiceRegular test coverage.

Bring EasyUnlockServiceRegular above the 85% test coverage expectation.

This CL also removes unnecessary methods which remained in
EasyUnlockServiceRegular, correctly clears stored remote devices in
prefs when Smart Lock is no longer enabled, and includes minor
refactors necessary to make tests pass.

Coverage before this CL:
  easy_unlock_service.cc:         14.72% (91/618)
  easy_unlock_service_regular.cc: 22.58% (98/434)

Coverage as of this CL:
  easy_unlock_service.cc:         35.76% (221/618)
  easy_unlock_service_regular.cc: 91.96% (389/423)

Report created with:
$ python tools/code_coverage/coverage.py unit_tests \
    -b out/coverage \
    -o out/report \
    -c 'out/coverage/unit_tests --gtest_filter=*EasyUnlockService*' \
    -f chrome/browser/chromeos/login/easy_unlock/

Bug: 949209
Change-Id: I037776f197373ff94099d2f5fc38726d60165cc5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1788552
Commit-Queue: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695843}
parent e473bbcf
...@@ -2882,6 +2882,7 @@ source_set("unit_tests") { ...@@ -2882,6 +2882,7 @@ source_set("unit_tests") {
"//chromeos/audio", "//chromeos/audio",
"//chromeos/components/multidevice:test_support", "//chromeos/components/multidevice:test_support",
"//chromeos/components/proximity_auth", "//chromeos/components/proximity_auth",
"//chromeos/components/proximity_auth:test_support",
"//chromeos/components/tether:test_support", "//chromeos/components/tether:test_support",
"//chromeos/constants", "//chromeos/constants",
"//chromeos/cryptohome:test_support", "//chromeos/cryptohome:test_support",
......
...@@ -127,6 +127,7 @@ void EasyUnlockServiceRegular::LoadRemoteDevices() { ...@@ -127,6 +127,7 @@ void EasyUnlockServiceRegular::LoadRemoteDevices() {
// OnFeatureStatesChanged() will call back on this method when feature state // OnFeatureStatesChanged() will call back on this method when feature state
// changes. // changes.
PA_LOG(VERBOSE) << "Smart Lock is not enabled by user; aborting."; PA_LOG(VERBOSE) << "Smart Lock is not enabled by user; aborting.";
SetStoredRemoteDevices(base::ListValue());
SetProximityAuthDevices(GetAccountId(), multidevice::RemoteDeviceRefList(), SetProximityAuthDevices(GetAccountId(), multidevice::RemoteDeviceRefList(),
base::nullopt /* local_device */); base::nullopt /* local_device */);
return; return;
...@@ -148,6 +149,7 @@ void EasyUnlockServiceRegular::LoadRemoteDevices() { ...@@ -148,6 +149,7 @@ void EasyUnlockServiceRegular::LoadRemoteDevices() {
} else { } else {
PA_LOG(ERROR) << "Smart Lock is enabled by user, but no unlock key is " PA_LOG(ERROR) << "Smart Lock is enabled by user, but no unlock key is "
"present; aborting."; "present; aborting.";
SetStoredRemoteDevices(base::ListValue());
SetProximityAuthDevices(GetAccountId(), multidevice::RemoteDeviceRefList(), SetProximityAuthDevices(GetAccountId(), multidevice::RemoteDeviceRefList(),
base::nullopt /* local_device */); base::nullopt /* local_device */);
...@@ -292,17 +294,6 @@ AccountId EasyUnlockServiceRegular::GetAccountId() const { ...@@ -292,17 +294,6 @@ AccountId EasyUnlockServiceRegular::GetAccountId() const {
return primary_user->GetAccountId(); return primary_user->GetAccountId();
} }
void EasyUnlockServiceRegular::SetHardlockAfterKeyOperation(
EasyUnlockScreenlockStateHandler::HardlockState state_on_success,
bool success) {
if (success)
SetHardlockStateForUser(GetAccountId(), state_on_success);
// Even if the refresh keys operation suceeded, we still fetch and check the
// cryptohome keys against the keys in local preferences as a sanity check.
CheckCryptohomeKeysAndMaybeHardlock();
}
void EasyUnlockServiceRegular::ClearPermitAccess() { void EasyUnlockServiceRegular::ClearPermitAccess() {
DictionaryPrefUpdate pairing_update(profile()->GetPrefs(), DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
prefs::kEasyUnlockPairing); prefs::kEasyUnlockPairing);
...@@ -319,10 +310,12 @@ const base::ListValue* EasyUnlockServiceRegular::GetRemoteDevices() const { ...@@ -319,10 +310,12 @@ const base::ListValue* EasyUnlockServiceRegular::GetRemoteDevices() const {
} }
std::string EasyUnlockServiceRegular::GetChallenge() const { std::string EasyUnlockServiceRegular::GetChallenge() const {
NOTREACHED();
return std::string(); return std::string();
} }
std::string EasyUnlockServiceRegular::GetWrappedSecret() const { std::string EasyUnlockServiceRegular::GetWrappedSecret() const {
NOTREACHED();
return std::string(); return std::string();
} }
...@@ -338,31 +331,29 @@ void EasyUnlockServiceRegular::RecordPasswordLoginEvent( ...@@ -338,31 +331,29 @@ void EasyUnlockServiceRegular::RecordPasswordLoginEvent(
} }
void EasyUnlockServiceRegular::InitializeInternal() { void EasyUnlockServiceRegular::InitializeInternal() {
pref_manager_.reset(new proximity_auth::ProximityAuthProfilePrefManager(
profile()->GetPrefs(), multidevice_setup_client_));
pref_manager_->StartSyncingToLocalState(g_browser_process->local_state(),
GetAccountId());
registrar_.Init(profile()->GetPrefs());
registrar_.Add(
proximity_auth::prefs::kProximityAuthIsChromeOSLoginEnabled,
base::Bind(&EasyUnlockServiceRegular::RefreshCryptohomeKeysIfPossible,
weak_ptr_factory_.GetWeakPtr()));
// If |device_sync_client_| is not ready yet, wait for it to call back on // If |device_sync_client_| is not ready yet, wait for it to call back on
// OnReady(). // OnReady().
if (device_sync_client_->is_ready()) if (device_sync_client_->is_ready())
OnReady(); OnReady();
device_sync_client_->AddObserver(this); device_sync_client_->AddObserver(this);
OnFeatureStatesChanged(multidevice_setup_client_->GetFeatureStates()); OnFeatureStatesChanged(multidevice_setup_client_->GetFeatureStates());
multidevice_setup_client_->AddObserver(this); multidevice_setup_client_->AddObserver(this);
proximity_auth::ScreenlockBridge::Get()->AddObserver(this); proximity_auth::ScreenlockBridge::Get()->AddObserver(this);
pref_manager_.reset(new proximity_auth::ProximityAuthProfilePrefManager(
profile()->GetPrefs(), multidevice_setup_client_));
pref_manager_->StartSyncingToLocalState(g_browser_process->local_state(),
GetAccountId());
LoadRemoteDevices(); LoadRemoteDevices();
registrar_.Init(profile()->GetPrefs());
registrar_.Add(
proximity_auth::prefs::kProximityAuthIsChromeOSLoginEnabled,
base::Bind(&EasyUnlockServiceRegular::RefreshCryptohomeKeysIfPossible,
weak_ptr_factory_.GetWeakPtr()));
} }
void EasyUnlockServiceRegular::ShutdownInternal() { void EasyUnlockServiceRegular::ShutdownInternal() {
...@@ -501,11 +492,6 @@ void EasyUnlockServiceRegular::ShowNotificationIfNewDevicePresent( ...@@ -501,11 +492,6 @@ void EasyUnlockServiceRegular::ShowNotificationIfNewDevicePresent(
} }
} }
void EasyUnlockServiceRegular::OnForceSyncCompleted(bool success) {
if (!success)
PA_LOG(WARNING) << "Failed to force device sync.";
}
void EasyUnlockServiceRegular::OnScreenDidLock( void EasyUnlockServiceRegular::OnScreenDidLock(
proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) {
set_will_authenticate_using_easy_unlock(false); set_will_authenticate_using_easy_unlock(false);
......
...@@ -115,8 +115,6 @@ class EasyUnlockServiceRegular ...@@ -115,8 +115,6 @@ class EasyUnlockServiceRegular
const std::set<std::string>& public_keys_before_sync, const std::set<std::string>& public_keys_before_sync,
const std::set<std::string>& public_keys_after_sync); const std::set<std::string>& public_keys_after_sync);
void OnForceSyncCompleted(bool success);
// proximity_auth::ScreenlockBridge::Observer implementation: // proximity_auth::ScreenlockBridge::Observer implementation:
void OnScreenDidLock(proximity_auth::ScreenlockBridge::LockHandler::ScreenType void OnScreenDidLock(proximity_auth::ScreenlockBridge::LockHandler::ScreenType
screen_type) override; screen_type) override;
...@@ -125,12 +123,6 @@ class EasyUnlockServiceRegular ...@@ -125,12 +123,6 @@ class EasyUnlockServiceRegular
override; override;
void OnFocusedUserChanged(const AccountId& account_id) override; void OnFocusedUserChanged(const AccountId& account_id) override;
// Called after a cryptohome RemoveKey or RefreshKey operation to set the
// proper hardlock state if the operation is successful.
void SetHardlockAfterKeyOperation(
EasyUnlockScreenlockStateHandler::HardlockState state_on_success,
bool success);
// Refreshes the ChromeOS cryptohome keys if the user has reauthed recently. // Refreshes the ChromeOS cryptohome keys if the user has reauthed recently.
// Otherwise, hardlock the device. // Otherwise, hardlock the device.
void RefreshCryptohomeKeysIfPossible(); void RefreshCryptohomeKeysIfPossible();
......
...@@ -16,19 +16,28 @@ ...@@ -16,19 +16,28 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h"
#include "chrome/browser/chromeos/login/session/chrome_session_manager.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/chromeos/login/users/mock_user_manager.h" #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "chromeos/components/multidevice/beacon_seed.h"
#include "chromeos/components/multidevice/remote_device_test_util.h"
#include "chromeos/components/proximity_auth/fake_lock_handler.h"
#include "chromeos/components/proximity_auth/screenlock_bridge.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/services/device_sync/proto/cryptauth_api.pb.h"
#include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h"
#include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h" #include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
#include "chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h" #include "chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h"
...@@ -40,6 +49,7 @@ ...@@ -40,6 +49,7 @@
#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "ui/views/test/test_views_delegate.h"
using device::MockBluetoothAdapter; using device::MockBluetoothAdapter;
using testing::_; using testing::_;
...@@ -66,14 +76,42 @@ class MockEasyUnlockNotificationController ...@@ -66,14 +76,42 @@ class MockEasyUnlockNotificationController
DISALLOW_COPY_AND_ASSIGN(MockEasyUnlockNotificationController); DISALLOW_COPY_AND_ASSIGN(MockEasyUnlockNotificationController);
}; };
// Define a stub MultiDeviceSetupDialog because the base class has a protected
// constructor and destructor (which prevents usage of smart pointers).
class FakeMultiDeviceSetupDialog
: public multidevice_setup::MultiDeviceSetupDialog {
public:
FakeMultiDeviceSetupDialog() = default;
};
} // namespace } // namespace
class EasyUnlockServiceRegularTest : public testing::Test { class EasyUnlockServiceRegularTest : public testing::Test {
protected: protected:
EasyUnlockServiceRegularTest() = default; EasyUnlockServiceRegularTest()
: test_local_device_(
multidevice::RemoteDeviceRefBuilder()
.SetPublicKey("local device")
.SetSoftwareFeatureState(
chromeos::multidevice::SoftwareFeature::kSmartLockClient,
chromeos::multidevice::SoftwareFeatureState::kEnabled)
.SetBeaconSeeds(multidevice::FromCryptAuthSeedList(
std::vector<cryptauth::BeaconSeed>(4)))
.Build()),
test_remote_device_smart_lock_host_(
multidevice::RemoteDeviceRefBuilder()
.SetPublicKey("local device")
.SetSoftwareFeatureState(
chromeos::multidevice::SoftwareFeature::kSmartLockHost,
chromeos::multidevice::SoftwareFeatureState::kEnabled)
.SetBeaconSeeds(multidevice::FromCryptAuthSeedList(
std::vector<cryptauth::BeaconSeed>(4)))
.Build()) {}
~EasyUnlockServiceRegularTest() override = default; ~EasyUnlockServiceRegularTest() override = default;
void SetUp() override { void SetUp() override {
PowerManagerClient::InitializeFake();
mock_adapter_ = new testing::NiceMock<MockBluetoothAdapter>(); mock_adapter_ = new testing::NiceMock<MockBluetoothAdapter>();
device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_); device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
EXPECT_CALL(*mock_adapter_, IsPresent()) EXPECT_CALL(*mock_adapter_, IsPresent())
...@@ -83,17 +121,28 @@ class EasyUnlockServiceRegularTest : public testing::Test { ...@@ -83,17 +121,28 @@ class EasyUnlockServiceRegularTest : public testing::Test {
TestingBrowserProcess::GetGlobal()->SetLocalState(&local_pref_service_); TestingBrowserProcess::GetGlobal()->SetLocalState(&local_pref_service_);
RegisterLocalState(local_pref_service_.registry()); RegisterLocalState(local_pref_service_.registry());
auto test_other_remote_device =
multidevice::RemoteDeviceRefBuilder()
.SetPublicKey("potential, but disabled, host device")
.SetSoftwareFeatureState(
chromeos::multidevice::SoftwareFeature::kSmartLockHost,
chromeos::multidevice::SoftwareFeatureState::kSupported)
.Build();
test_remote_devices_.push_back(test_remote_device_smart_lock_host_);
test_remote_devices_.push_back(test_other_remote_device);
fake_secure_channel_client_ = fake_secure_channel_client_ =
std::make_unique<chromeos::secure_channel::FakeSecureChannelClient>(); std::make_unique<chromeos::secure_channel::FakeSecureChannelClient>();
fake_device_sync_client_ = fake_device_sync_client_ =
std::make_unique<device_sync::FakeDeviceSyncClient>(); std::make_unique<device_sync::FakeDeviceSyncClient>();
fake_device_sync_client_->NotifyReady();
fake_multidevice_setup_client_ = std::make_unique< fake_multidevice_setup_client_ = std::make_unique<
chromeos::multidevice_setup::FakeMultiDeviceSetupClient>(); chromeos::multidevice_setup::FakeMultiDeviceSetupClient>();
TestingProfile::Builder builder; TestingProfile::Builder builder;
profile_ = builder.Build(); profile_ = builder.Build();
account_id_ = AccountId::FromUserEmail(profile_->GetProfileUserName());
auto fake_chrome_user_manager = auto fake_chrome_user_manager =
std::make_unique<chromeos::FakeChromeUserManager>(); std::make_unique<chromeos::FakeChromeUserManager>();
fake_chrome_user_manager_ = fake_chrome_user_manager.get(); fake_chrome_user_manager_ = fake_chrome_user_manager.get();
...@@ -101,18 +150,59 @@ class EasyUnlockServiceRegularTest : public testing::Test { ...@@ -101,18 +150,59 @@ class EasyUnlockServiceRegularTest : public testing::Test {
std::move(fake_chrome_user_manager)); std::move(fake_chrome_user_manager));
SetPrimaryUserLoggedIn(); SetPrimaryUserLoggedIn();
easy_unlock_service_regular_ = std::make_unique<EasyUnlockServiceRegular>( fake_lock_handler_ = std::make_unique<proximity_auth::FakeLockHandler>();
profile_.get(), fake_secure_channel_client_.get(), SetScreenLockState(false /* is_locked */);
std::make_unique<MockEasyUnlockNotificationController>(),
fake_device_sync_client_.get(), fake_multidevice_setup_client_.get());
easy_unlock_service_regular_->Initialize();
} }
void TearDown() override { void TearDown() override {
SetScreenLockState(false /* is_locked */);
easy_unlock_service_regular_->Shutdown(); easy_unlock_service_regular_->Shutdown();
PowerManagerClient::Shutdown();
TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr); TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
} }
// Most tests will want to pass |should_initialize_all_dependencies| == true,
// but may pass false if they wish to tweak the dependencies' state themselves
// before initializing the service.
void InitializeService(bool should_initialize_all_dependencies) {
if (should_initialize_all_dependencies) {
fake_device_sync_client_->NotifyReady();
SetLocalDevice(test_local_device_);
SetSyncedDevices(test_remote_devices_);
SetIsEnabled(true /* is_enabled */);
}
auto mock_notification_controller = std::make_unique<
testing::StrictMock<MockEasyUnlockNotificationController>>();
mock_notification_controller_ = mock_notification_controller.get();
easy_unlock_service_regular_ = std::make_unique<EasyUnlockServiceRegular>(
profile_.get(), fake_secure_channel_client_.get(),
std::move(mock_notification_controller), fake_device_sync_client_.get(),
fake_multidevice_setup_client_.get());
easy_unlock_service_regular_->Initialize();
}
void SetLocalDevice(
const base::Optional<multidevice::RemoteDeviceRef>& local_device) {
fake_device_sync_client_->set_local_device_metadata(test_local_device_);
fake_device_sync_client_->NotifyEnrollmentFinished();
}
void SetSyncedDevices(multidevice::RemoteDeviceRefList synced_devices) {
fake_device_sync_client_->set_synced_devices(synced_devices);
fake_device_sync_client_->NotifyNewDevicesSynced();
}
void SetIsEnabled(bool is_enabled) {
fake_multidevice_setup_client_->SetFeatureState(
chromeos::multidevice_setup::mojom::Feature::kSmartLock,
is_enabled
? chromeos::multidevice_setup::mojom::FeatureState::kEnabledByUser
: chromeos::multidevice_setup::mojom::FeatureState::
kDisabledByUser);
}
void SetEasyUnlockAllowedPolicy(bool allowed) { void SetEasyUnlockAllowedPolicy(bool allowed) {
profile_->GetTestingPrefService()->SetManagedPref( profile_->GetTestingPrefService()->SetManagedPref(
prefs::kEasyUnlockAllowed, std::make_unique<base::Value>(allowed)); prefs::kEasyUnlockAllowed, std::make_unique<base::Value>(allowed));
...@@ -126,18 +216,43 @@ class EasyUnlockServiceRegularTest : public testing::Test { ...@@ -126,18 +216,43 @@ class EasyUnlockServiceRegularTest : public testing::Test {
return is_bluetooth_adapter_present_; return is_bluetooth_adapter_present_;
} }
void SetScreenLockState(bool is_locked) {
if (is_locked)
proximity_auth::ScreenlockBridge::Get()->SetFocusedUser(account_id_);
proximity_auth::ScreenlockBridge::Get()->SetLockHandler(
is_locked ? fake_lock_handler_.get() : nullptr);
}
void VerifyGetRemoteDevices(bool are_local_and_remote_devices_expected) {
const base::ListValue* remote_devices =
static_cast<EasyUnlockService*>(easy_unlock_service_regular_.get())
->GetRemoteDevices();
if (are_local_and_remote_devices_expected)
// 2 devices are expected: the local device and the remote device.
EXPECT_EQ(2u, remote_devices->GetSize());
else
EXPECT_FALSE(remote_devices);
}
// Must outlive TestingProfiles. // Must outlive TestingProfiles.
content::BrowserTaskEnvironment task_environment_; content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_; std::unique_ptr<TestingProfile> profile_;
AccountId account_id_;
chromeos::FakeChromeUserManager* fake_chrome_user_manager_; chromeos::FakeChromeUserManager* fake_chrome_user_manager_;
std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
const multidevice::RemoteDeviceRef test_local_device_;
const multidevice::RemoteDeviceRef test_remote_device_smart_lock_host_;
multidevice::RemoteDeviceRefList test_remote_devices_;
std::unique_ptr<secure_channel::FakeSecureChannelClient> std::unique_ptr<secure_channel::FakeSecureChannelClient>
fake_secure_channel_client_; fake_secure_channel_client_;
std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_; std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_;
std::unique_ptr<multidevice_setup::MultiDeviceSetupClient> std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient>
fake_multidevice_setup_client_; fake_multidevice_setup_client_;
std::unique_ptr<proximity_auth::FakeLockHandler> fake_lock_handler_;
std::unique_ptr<EasyUnlockServiceRegular> easy_unlock_service_regular_; std::unique_ptr<EasyUnlockServiceRegular> easy_unlock_service_regular_;
std::string profile_gaia_id_; std::string profile_gaia_id_;
...@@ -145,16 +260,20 @@ class EasyUnlockServiceRegularTest : public testing::Test { ...@@ -145,16 +260,20 @@ class EasyUnlockServiceRegularTest : public testing::Test {
bool is_bluetooth_adapter_present_ = true; bool is_bluetooth_adapter_present_ = true;
scoped_refptr<testing::NiceMock<MockBluetoothAdapter>> mock_adapter_; scoped_refptr<testing::NiceMock<MockBluetoothAdapter>> mock_adapter_;
testing::StrictMock<MockEasyUnlockNotificationController>*
mock_notification_controller_;
// PrefService which contains the browser process' local storage. // PrefService which contains the browser process' local storage.
TestingPrefServiceSimple local_pref_service_; TestingPrefServiceSimple local_pref_service_;
views::TestViewsDelegate view_delegate_;
base::HistogramTester histogram_tester_;
private: private:
void SetPrimaryUserLoggedIn() { void SetPrimaryUserLoggedIn() {
const AccountId account_id(
AccountId::FromUserEmail(profile_->GetProfileUserName()));
const user_manager::User* user = const user_manager::User* user =
fake_chrome_user_manager_->AddPublicAccountUser(account_id); fake_chrome_user_manager_->AddPublicAccountUser(account_id_);
fake_chrome_user_manager_->UserLoggedIn(account_id, user->username_hash(), fake_chrome_user_manager_->UserLoggedIn(account_id_, user->username_hash(),
false /* browser_restart */, false /* browser_restart */,
false /* is_child */); false /* is_child */);
} }
...@@ -163,11 +282,24 @@ class EasyUnlockServiceRegularTest : public testing::Test { ...@@ -163,11 +282,24 @@ class EasyUnlockServiceRegularTest : public testing::Test {
}; };
TEST_F(EasyUnlockServiceRegularTest, NoBluetoothNoService) { TEST_F(EasyUnlockServiceRegularTest, NoBluetoothNoService) {
InitializeService(true /* should_initialize_all_dependencies */);
set_is_bluetooth_adapter_present(false); set_is_bluetooth_adapter_present(false);
EXPECT_FALSE(easy_unlock_service_regular_->IsAllowed()); EXPECT_FALSE(easy_unlock_service_regular_->IsAllowed());
} }
TEST_F(EasyUnlockServiceRegularTest, NotAllowedWhenProhibited) {
InitializeService(true /* should_initialize_all_dependencies */);
fake_multidevice_setup_client_->SetFeatureState(
chromeos::multidevice_setup::mojom::Feature::kSmartLock,
chromeos::multidevice_setup::mojom::FeatureState::kProhibitedByPolicy);
EXPECT_FALSE(easy_unlock_service_regular_->IsAllowed());
}
TEST_F(EasyUnlockServiceRegularTest, NotAllowedForEphemeralAccounts) { TEST_F(EasyUnlockServiceRegularTest, NotAllowedForEphemeralAccounts) {
InitializeService(true /* should_initialize_all_dependencies */);
// Only MockUserManager allows for stubbing // Only MockUserManager allows for stubbing
// IsCurrentUserNonCryptohomeDataEphemeral() to return false so we use one // IsCurrentUserNonCryptohomeDataEphemeral() to return false so we use one
// here in place of |fake_chrome_user_manager_|. Injecting it into a local // here in place of |fake_chrome_user_manager_|. Injecting it into a local
...@@ -182,4 +314,157 @@ TEST_F(EasyUnlockServiceRegularTest, NotAllowedForEphemeralAccounts) { ...@@ -182,4 +314,157 @@ TEST_F(EasyUnlockServiceRegularTest, NotAllowedForEphemeralAccounts) {
EXPECT_FALSE(easy_unlock_service_regular_->IsAllowed()); EXPECT_FALSE(easy_unlock_service_regular_->IsAllowed());
} }
TEST_F(EasyUnlockServiceRegularTest, GetProximityAuthPrefManager) {
InitializeService(true /* should_initialize_all_dependencies */);
EXPECT_TRUE(
static_cast<EasyUnlockService*>(easy_unlock_service_regular_.get())
->GetProximityAuthPrefManager());
}
TEST_F(EasyUnlockServiceRegularTest, GetRemoteDevices) {
InitializeService(true /* should_initialize_all_dependencies */);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
}
TEST_F(EasyUnlockServiceRegularTest, GetRemoteDevices_InitiallyNotReady) {
SetIsEnabled(true /* is_enabled */);
InitializeService(false /* should_initialize_all_dependencies */);
VerifyGetRemoteDevices(false /* are_local_and_remote_devices_expected */);
EXPECT_CALL(*mock_notification_controller_,
ShowChromebookAddedNotification());
fake_device_sync_client_->NotifyReady();
SetLocalDevice(test_local_device_);
SetSyncedDevices(test_remote_devices_);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
}
TEST_F(EasyUnlockServiceRegularTest,
GetRemoteDevices_InitiallyNoSyncedDevices) {
fake_device_sync_client_->NotifyReady();
SetLocalDevice(test_local_device_);
SetSyncedDevices(multidevice::RemoteDeviceRefList() /* synced_devices */);
SetIsEnabled(true /* is_enabled */);
InitializeService(false /* should_initialize_all_dependencies */);
VerifyGetRemoteDevices(false /* are_local_and_remote_devices_expected */);
EXPECT_CALL(*mock_notification_controller_,
ShowChromebookAddedNotification());
SetSyncedDevices(test_remote_devices_);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
}
// Test that the "Chromebook added" notification does not show while the
// MultiDeviceSetupDialog is active, and only shows once it is closed.
TEST_F(
EasyUnlockServiceRegularTest,
GetRemoteDevices_InitiallyNoSyncedDevices_MultiDeviceSetupDialogVisible) {
ChromeSessionManager manager;
auto dialog = std::make_unique<FakeMultiDeviceSetupDialog>();
multidevice_setup::MultiDeviceSetupDialog::SetInstanceForTesting(
dialog.get());
fake_device_sync_client_->NotifyReady();
SetLocalDevice(test_local_device_);
SetSyncedDevices(multidevice::RemoteDeviceRefList() /* synced_devices */);
SetIsEnabled(true /* is_enabled */);
InitializeService(false /* should_initialize_all_dependencies */);
VerifyGetRemoteDevices(false /* are_local_and_remote_devices_expected */);
// Calling SetSyncedDevices() below would usually cause the "Chromebook added"
// notification to appear, but it shouldn't because MultiDeviceSetupDialog is
// active.
EXPECT_CALL(*mock_notification_controller_, ShowChromebookAddedNotification())
.Times(0);
SetSyncedDevices(test_remote_devices_);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
// Now expect the "Chromebook added" notification to appear, and close the
// dialog by deleting it (this indirectly calls the dialog close callbacks).
// Using the real dialog Close() method invokes Ash and Widget code that is
// too cumbersome to stub out.
testing::Mock::VerifyAndClearExpectations(mock_notification_controller_);
EXPECT_CALL(*mock_notification_controller_,
ShowChromebookAddedNotification());
dialog.reset();
multidevice_setup::MultiDeviceSetupDialog::SetInstanceForTesting(nullptr);
}
TEST_F(EasyUnlockServiceRegularTest, GetRemoteDevices_InitiallyNotEnabled) {
fake_device_sync_client_->NotifyReady();
SetLocalDevice(test_local_device_);
SetSyncedDevices(test_remote_devices_);
SetIsEnabled(false /* is_enabled */);
InitializeService(false /* should_initialize_all_dependencies */);
VerifyGetRemoteDevices(false /* are_local_and_remote_devices_expected */);
SetIsEnabled(true /* is_enabled */);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
}
TEST_F(EasyUnlockServiceRegularTest,
GetRemoteDevices_DeferDeviceLoadUntilScreenIsUnlocked) {
SetScreenLockState(true /* is_locked */);
InitializeService(true /* should_initialize_all_dependencies */);
VerifyGetRemoteDevices(false /* are_local_and_remote_devices_expected */);
SetScreenLockState(false /* is_locked */);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
}
TEST_F(EasyUnlockServiceRegularTest, GetRemoteDevices_SmartLockHostRemoved) {
InitializeService(true /* should_initialize_all_dependencies */);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
SetSyncedDevices(multidevice::RemoteDeviceRefList() /* synced_devices */);
VerifyGetRemoteDevices(false /* are_local_and_remote_devices_expected */);
}
TEST_F(EasyUnlockServiceRegularTest, GetRemoteDevices_SmartLockHostChanged) {
InitializeService(true /* should_initialize_all_dependencies */);
SetScreenLockState(true /* is_locked */);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
auto new_remote_device =
multidevice::RemoteDeviceRefBuilder()
.SetPublicKey("new smartlock host")
.SetSoftwareFeatureState(
chromeos::multidevice::SoftwareFeature::kSmartLockHost,
chromeos::multidevice::SoftwareFeatureState::kEnabled)
.Build();
multidevice::RemoteDeviceRefList new_remote_devices;
new_remote_devices.push_back(new_remote_device);
EXPECT_CALL(*mock_notification_controller_, ShowPairingChangeNotification());
SetSyncedDevices(new_remote_devices /* synced_devices */);
VerifyGetRemoteDevices(true /* are_local_and_remote_devices_expected */);
EXPECT_CALL(*mock_notification_controller_,
ShowPairingChangeAppliedNotification(testing::_));
SetScreenLockState(false /* is_locked */);
}
// Test through the core flow of unlocking the screen with Smart Lock.
// Unfortunately, the only observable side effect we have available is verifying
// that the success metric is emitted.
TEST_F(EasyUnlockServiceRegularTest, AuthenticateWithEasyUnlock) {
InitializeService(true /* should_initialize_all_dependencies */);
SetScreenLockState(true /* is_locked */);
static_cast<EasyUnlockService*>(easy_unlock_service_regular_.get())
->AttemptAuth(account_id_);
static_cast<EasyUnlockService*>(easy_unlock_service_regular_.get())
->FinalizeUnlock(true);
histogram_tester_.ExpectBucketCount("SmartLock.AuthResult.Unlock", 1, 0);
SetScreenLockState(false /* is_locked */);
histogram_tester_.ExpectBucketCount("SmartLock.AuthResult.Unlock", 1, 1);
}
} // namespace chromeos } // namespace chromeos
...@@ -59,6 +59,12 @@ MultiDeviceSetupDialog* MultiDeviceSetupDialog::Get() { ...@@ -59,6 +59,12 @@ MultiDeviceSetupDialog* MultiDeviceSetupDialog::Get() {
return current_instance_; return current_instance_;
} }
// static
void MultiDeviceSetupDialog::SetInstanceForTesting(
MultiDeviceSetupDialog* instance) {
current_instance_ = instance;
}
void MultiDeviceSetupDialog::AddOnCloseCallback(base::OnceClosure callback) { void MultiDeviceSetupDialog::AddOnCloseCallback(base::OnceClosure callback) {
on_close_callbacks_.push_back(std::move(callback)); on_close_callbacks_.push_back(std::move(callback));
} }
......
...@@ -31,6 +31,8 @@ class MultiDeviceSetupDialog : public SystemWebDialogDelegate { ...@@ -31,6 +31,8 @@ class MultiDeviceSetupDialog : public SystemWebDialogDelegate {
// nullptr. // nullptr.
static MultiDeviceSetupDialog* Get(); static MultiDeviceSetupDialog* Get();
static void SetInstanceForTesting(MultiDeviceSetupDialog* instance);
// Registers a callback which will be called when the dialog is closed. // Registers a callback which will be called when the dialog is closed.
void AddOnCloseCallback(base::OnceClosure callback); void AddOnCloseCallback(base::OnceClosure callback);
......
...@@ -178,7 +178,7 @@ class ScreenlockBridge { ...@@ -178,7 +178,7 @@ class ScreenlockBridge {
ScreenlockBridge(); ScreenlockBridge();
~ScreenlockBridge(); ~ScreenlockBridge();
LockHandler* lock_handler_; // Not owned LockHandler* lock_handler_ = nullptr; // Not owned
// The last focused user's id. // The last focused user's id.
AccountId focused_account_id_; AccountId focused_account_id_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment