blob: cdd4cff11ad0adff8e98db4283b622a9b1acdc70 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <string>
#include <utility>
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/ash/login/existing_user_controller_base_test.h"
#include "chrome/browser/ash/login/user_online_signin_notifier.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "components/user_manager/known_user.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ash {
namespace {
// Mock implementation of UserOnlineSigninNotifier::Observer.
class MockUserOnlineSigninNotifierObserver
: public UserOnlineSigninNotifier::Observer {
public:
MOCK_METHOD(void, OnOnlineSigninEnforced, (const AccountId& account_id));
};
constexpr base::TimeDelta kLoginOnlineShortDelay = base::Seconds(10);
constexpr base::TimeDelta kLoginOnlineLongDelay = base::Seconds(100);
constexpr base::TimeDelta kLoginOnlineVeryLongDelay = base::Seconds(1000);
constexpr base::TimeDelta kLoginOnlineOffset = base::Seconds(1);
} // namespace
class UserOnlineSigninNotifierTest : public ExistingUserControllerBaseTest {
public:
void SetUp() override {
mock_online_signin_notifier_observer_ =
std::make_unique<MockUserOnlineSigninNotifierObserver>();
}
UserOnlineSigninNotifier* user_online_signin_notifier() const {
return user_online_signin_notifier_.get();
}
// UserOnlineSigninNotifier private member accessors.
base::OneShotTimer* online_login_refresh_timer() {
return user_online_signin_notifier_->online_login_refresh_timer_.get();
}
protected:
std::unique_ptr<MockUserOnlineSigninNotifierObserver>
mock_online_signin_notifier_observer_;
std::unique_ptr<UserOnlineSigninNotifier> user_online_signin_notifier_;
};
// Tests login screen update when SAMLOfflineSigninTimeLimit policy is set.
TEST_F(UserOnlineSigninNotifierTest, SamlOnlineAuthSingleUser) {
const base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetLastOnlineSignin(saml_login_account1_id_, now);
known_user.SetOfflineSigninLimit(saml_login_account1_id_,
kLoginOnlineShortDelay);
auto* user_manager = GetFakeUserManager();
user_manager->AddSamlUser(saml_login_account1_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(saml_login_account1_id_))
.Times(1);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
// Check timer again 1s after its expected expiry.
task_environment_.FastForwardBy(kLoginOnlineShortDelay + kLoginOnlineOffset);
EXPECT_FALSE(online_login_refresh_timer()->IsRunning());
}
// Verfies that `OfflineSigninLimiter` does affect SAML and non SAML user.
TEST_F(UserOnlineSigninNotifierTest, OfflineLimiteOutOfSessionSAMLAndNonSAML) {
const base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetLastOnlineSignin(saml_login_account1_id_, now);
known_user.SetOfflineSigninLimit(saml_login_account1_id_,
kLoginOnlineShortDelay);
auto* user_manager = GetFakeUserManager();
user_manager->AddUser(saml_login_account1_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(saml_login_account1_id_))
.Times(0);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
// Expect true since user has a value set in `kOfflineSigninLimit`.
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
}
// Tests login screen update functionality for 2 SAML users.
TEST_F(UserOnlineSigninNotifierTest, SamlOnlineAuthTwoSamlUsers) {
base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetLastOnlineSignin(saml_login_account1_id_, now);
known_user.SetOfflineSigninLimit(saml_login_account1_id_,
kLoginOnlineLongDelay);
task_environment_.FastForwardBy(kLoginOnlineShortDelay);
now = base::DefaultClock::GetInstance()->Now();
known_user.SetLastOnlineSignin(saml_login_account2_id_, now);
known_user.SetOfflineSigninLimit(saml_login_account2_id_,
kLoginOnlineVeryLongDelay);
auto* user_manager = GetFakeUserManager();
user_manager->AddSamlUser(saml_login_account1_id_);
user_manager->AddSamlUser(saml_login_account2_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(saml_login_account1_id_))
.Times(1);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
// The timer should be re-started after
// (kLoginOnlineLongDelay - kLoginOnlineShortDelay) s.
task_environment_.FastForwardBy(kLoginOnlineLongDelay -
kLoginOnlineShortDelay + kLoginOnlineOffset);
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
}
// Tests login screen update functionality for 2 users: SAML and non-SAML.
TEST_F(UserOnlineSigninNotifierTest, SamlOnlineAuthSamlAndNonSamlUsers) {
const base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetLastOnlineSignin(saml_login_account1_id_, now);
known_user.SetLastOnlineSignin(saml_login_account2_id_, now);
known_user.SetOfflineSigninLimit(saml_login_account1_id_,
kLoginOnlineShortDelay);
known_user.SetOfflineSigninLimit(saml_login_account2_id_,
kLoginOnlineLongDelay);
auto* user_manager = GetFakeUserManager();
user_manager->AddSamlUser(saml_login_account1_id_);
user_manager->AddUser(saml_login_account2_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(saml_login_account1_id_))
.Times(1);
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(saml_login_account2_id_))
.Times(0);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
task_environment_.FastForwardBy(kLoginOnlineShortDelay + kLoginOnlineOffset);
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
}
// Tests unset policy value in local state.
TEST_F(UserOnlineSigninNotifierTest, SamlOnlineAuthSamlPolicyNotSet) {
const base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetLastOnlineSignin(saml_login_account1_id_, now);
known_user.SetOfflineSigninLimit(saml_login_account1_id_, std::nullopt);
auto* user_manager = GetFakeUserManager();
user_manager->AddSamlUser(saml_login_account1_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(saml_login_account1_id_))
.Times(0);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_FALSE(online_login_refresh_timer()->IsRunning());
}
// Tests login screen update when `GaiaOfflineSigninTimeLimitDays` policy is set
// and the last online sign in has not been set. This is the case for those
// devices that went through the online signin in the first login before the
// introduction of `GaiaOfflineSigninTimeLimitDays` policy logic which didn't
// store the last online sign in.
TEST_F(UserOnlineSigninNotifierTest,
GaiaOnlineAuthSingleUserNoLastOnlineSignin) {
const base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetOfflineSigninLimit(gaia_login_account1_id_,
kLoginOnlineShortDelay);
auto* user_manager = GetFakeUserManager();
user_manager->AddUser(gaia_login_account1_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account1_id_))
.Times(1);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
testing::Mock::VerifyAndClearExpectations(
mock_online_signin_notifier_observer_.get());
// Since `LastOnlineSignin` value is null and there is a limit, it will
// enforce the next login to be online. No timer should be running.
EXPECT_FALSE(online_login_refresh_timer()->IsRunning());
// User logged in online after enforcement.
known_user.SetLastOnlineSignin(gaia_login_account1_id_, now);
// Set the force_online_signin to false along with logged in,
// which is done often in OfflineSigninLimiter::SignedIn.
user_manager->SaveForceOnlineSignin(gaia_login_account1_id_, false);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account1_id_))
.Times(0);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
testing::Mock::VerifyAndClearExpectations(
mock_online_signin_notifier_observer_.get());
// Check timer again 1s after its expacted expiry.
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account1_id_))
.Times(1);
task_environment_.FastForwardBy(kLoginOnlineShortDelay + kLoginOnlineOffset);
EXPECT_FALSE(online_login_refresh_timer()->IsRunning());
testing::Mock::VerifyAndClearExpectations(
mock_online_signin_notifier_observer_.get());
}
// Tests login screen update when `GaiaOfflineSigninTimeLimitDays` policy is set
// and the last online sign in has been set.
TEST_F(UserOnlineSigninNotifierTest, GaiaOnlineAuthSingleUserLastOnlineSignin) {
const base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetLastOnlineSignin(gaia_login_account1_id_, now);
known_user.SetOfflineSigninLimit(gaia_login_account1_id_,
kLoginOnlineShortDelay);
auto* user_manager = GetFakeUserManager();
user_manager->AddUser(gaia_login_account1_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account1_id_))
.Times(1);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
// Check timer again 1s after its expacted expiry.
task_environment_.FastForwardBy(kLoginOnlineShortDelay + kLoginOnlineOffset);
EXPECT_FALSE(online_login_refresh_timer()->IsRunning());
}
// Tests login screen update functionality for 2 Gaia without SAML users.
TEST_F(UserOnlineSigninNotifierTest, GaiaOnlineAuthTwoGaiaUsers) {
base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
known_user.SetLastOnlineSignin(gaia_login_account1_id_, now);
known_user.SetOfflineSigninLimit(gaia_login_account1_id_,
kLoginOnlineLongDelay);
task_environment_.FastForwardBy(kLoginOnlineShortDelay);
now = base::DefaultClock::GetInstance()->Now();
known_user.SetLastOnlineSignin(gaia_login_account2_id_, now);
known_user.SetOfflineSigninLimit(gaia_login_account2_id_,
kLoginOnlineVeryLongDelay);
auto* user_manager = GetFakeUserManager();
user_manager->AddUser(gaia_login_account1_id_);
user_manager->AddUser(gaia_login_account2_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account1_id_))
.Times(1);
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account2_id_))
.Times(0);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
// The timer should be re-started after
// (kLoginOnlineLongDelay - kLoginOnlineShortDelay) s.
task_environment_.FastForwardBy(kLoginOnlineLongDelay -
kLoginOnlineShortDelay + kLoginOnlineOffset);
EXPECT_TRUE(online_login_refresh_timer()->IsRunning());
}
// Tests unset `GaiaOfflineTimeLimitDays` policy value in local state.
TEST_F(UserOnlineSigninNotifierTest, GaiaOnlineAuthGaiaPolicyNotSet) {
const base::Time now = base::DefaultClock::GetInstance()->Now();
user_manager::KnownUser known_user(g_browser_process->local_state());
// No `LastOnlineSignin` value, case where devices didn't store that value in
// the first Gaia login.
known_user.SetOfflineSigninLimit(gaia_login_account1_id_, std::nullopt);
// Case where the user has already stored last online signin.
known_user.SetLastOnlineSignin(gaia_login_account2_id_, now);
known_user.SetOfflineSigninLimit(gaia_login_account2_id_, std::nullopt);
auto* user_manager = GetFakeUserManager();
user_manager->AddUser(gaia_login_account1_id_);
user_manager->AddUser(gaia_login_account2_id_);
user_online_signin_notifier_ =
std::make_unique<UserOnlineSigninNotifier>(user_manager->GetUsers());
user_online_signin_notifier_->AddObserver(
mock_online_signin_notifier_observer_.get());
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account1_id_))
.Times(0);
EXPECT_CALL(*mock_online_signin_notifier_observer_,
OnOnlineSigninEnforced(gaia_login_account1_id_))
.Times(0);
user_online_signin_notifier()->CheckForPolicyEnforcedOnlineSignin();
EXPECT_FALSE(online_login_refresh_timer()->IsRunning());
}
} // namespace ash