Commit c2b5474c authored by Michael Giuffrida's avatar Michael Giuffrida Committed by Commit Bot

Time Limits browser test

Simple browser test for time limits that signs in a child user, sets a
LOCK override, and verifies that the screen becomes locked.

Adds test clocks to ScreenTimeController so browser tests can trigger
a variety of scenarios in a deterministic way.

Follow-up tests should expand on this, adding common test helpers to
child_account_test_utils.h.

Bug: 895816
Change-Id: Ibbfff2c20cb8829138fad7a94f7db922742d6b56
Reviewed-on: https://chromium-review.googlesource.com/c/1352031
Commit-Queue: Michael Giuffrida <michaelpg@chromium.org>
Reviewed-by: default avatarJacob Dufault <jdufault@chromium.org>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612381}
parent 8dfddfcc
// 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 "chrome/browser/chromeos/child_accounts/child_account_test_utils.h"
#include "base/base64.h"
#include "base/strings/stringprintf.h"
namespace chromeos {
namespace test {
const char kChildAccountServiceFlags[] = R"(["uca"])";
std::string GetChildAccountOAuthIdToken() {
std::string encoded;
base::Base64Encode(R"({ "services": ["uca"] })", &encoded);
return base::StringPrintf("dummy-header.%s.dummy-signature", encoded.c_str());
}
} // namespace test
} // namespace chromeos
// 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.
#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
#include <string>
namespace chromeos {
namespace test {
// JSON array of service flags for logging in a child account.
extern const char kChildAccountServiceFlags[];
// Returns a base64-encoded dummy token for child log-in.
std::string GetChildAccountOAuthIdToken();
} // namespace test
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_CHILD_ACCOUNT_TEST_UTILS_H_
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h" #include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/timer/timer.h"
#include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h" #include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h"
#include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service_factory.h" #include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service_factory.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
...@@ -44,6 +47,8 @@ void ScreenTimeController::RegisterProfilePrefs(PrefRegistrySimple* registry) { ...@@ -44,6 +47,8 @@ void ScreenTimeController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
ScreenTimeController::ScreenTimeController(content::BrowserContext* context) ScreenTimeController::ScreenTimeController(content::BrowserContext* context)
: context_(context), : context_(context),
pref_service_(Profile::FromBrowserContext(context)->GetPrefs()), pref_service_(Profile::FromBrowserContext(context)->GetPrefs()),
clock_(base::DefaultClock::GetInstance()),
next_state_timer_(std::make_unique<base::OneShotTimer>()),
time_limit_notifier_(context) { time_limit_notifier_(context) {
session_manager::SessionManager::Get()->AddObserver(this); session_manager::SessionManager::Get()->AddObserver(this);
system::TimezoneSettings::GetInstance()->AddObserver(this); system::TimezoneSettings::GetInstance()->AddObserver(this);
...@@ -67,6 +72,13 @@ base::TimeDelta ScreenTimeController::GetScreenTimeDuration() { ...@@ -67,6 +72,13 @@ base::TimeDelta ScreenTimeController::GetScreenTimeDuration() {
->GetChildScreenTime(); ->GetChildScreenTime();
} }
void ScreenTimeController::SetClocksForTesting(
const base::Clock* clock,
const base::TickClock* tick_clock) {
clock_ = clock;
next_state_timer_ = std::make_unique<base::OneShotTimer>(tick_clock);
}
void ScreenTimeController::CheckTimeLimit(const std::string& source) { void ScreenTimeController::CheckTimeLimit(const std::string& source) {
VLOG(1) << "Checking time limits (source=" << source << ")"; VLOG(1) << "Checking time limits (source=" << source << ")";
...@@ -74,7 +86,7 @@ void ScreenTimeController::CheckTimeLimit(const std::string& source) { ...@@ -74,7 +86,7 @@ void ScreenTimeController::CheckTimeLimit(const std::string& source) {
ResetStateTimers(); ResetStateTimers();
ResetInSessionTimers(); ResetInSessionTimers();
base::Time now = base::Time::Now(); base::Time now = clock_->Now();
const icu::TimeZone& time_zone = const icu::TimeZone& time_zone =
system::TimezoneSettings::GetInstance()->GetTimezone(); system::TimezoneSettings::GetInstance()->GetTimezone();
base::Optional<usage_time_limit::State> last_state = GetLastStateFromPref(); base::Optional<usage_time_limit::State> last_state = GetLastStateFromPref();
...@@ -132,7 +144,7 @@ void ScreenTimeController::CheckTimeLimit(const std::string& source) { ...@@ -132,7 +144,7 @@ void ScreenTimeController::CheckTimeLimit(const std::string& source) {
if (!next_get_state_time.is_null()) { if (!next_get_state_time.is_null()) {
VLOG(1) << "Scheduling state change timer in " VLOG(1) << "Scheduling state change timer in "
<< state.next_state_change_time - now; << state.next_state_change_time - now;
next_state_timer_.Start( next_state_timer_->Start(
FROM_HERE, next_get_state_time - now, FROM_HERE, next_get_state_time - now,
base::BindRepeating(&ScreenTimeController::CheckTimeLimit, base::BindRepeating(&ScreenTimeController::CheckTimeLimit,
base::Unretained(this), "next_state_timer_")); base::Unretained(this), "next_state_timer_"));
...@@ -172,7 +184,7 @@ void ScreenTimeController::OnPolicyChanged() { ...@@ -172,7 +184,7 @@ void ScreenTimeController::OnPolicyChanged() {
void ScreenTimeController::ResetStateTimers() { void ScreenTimeController::ResetStateTimers() {
VLOG(1) << "Stopping state timers"; VLOG(1) << "Stopping state timers";
next_state_timer_.Stop(); next_state_timer_->Stop();
} }
void ScreenTimeController::ResetInSessionTimers() { void ScreenTimeController::ResetInSessionTimers() {
......
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_ #ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_ #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_SCREEN_TIME_CONTROLLER_H_
#include <memory>
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/chromeos/child_accounts/time_limit_notifier.h" #include "chrome/browser/chromeos/child_accounts/time_limit_notifier.h"
#include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h" #include "chrome/browser/chromeos/child_accounts/usage_time_limit_processor.h"
#include "chromeos/dbus/system_clock_client.h" #include "chromeos/dbus/system_clock_client.h"
...@@ -17,6 +18,12 @@ ...@@ -17,6 +18,12 @@
class PrefRegistrySimple; class PrefRegistrySimple;
class PrefService; class PrefService;
namespace base {
class Clock;
class TickClock;
class OneShotTimer;
} // namespace base
namespace content { namespace content {
class BrowserContext; class BrowserContext;
} }
...@@ -42,6 +49,9 @@ class ScreenTimeController : public KeyedService, ...@@ -42,6 +49,9 @@ class ScreenTimeController : public KeyedService,
// used the device today (since the last reset). // used the device today (since the last reset).
base::TimeDelta GetScreenTimeDuration(); base::TimeDelta GetScreenTimeDuration();
void SetClocksForTesting(const base::Clock* clock,
const base::TickClock* tick_clock);
private: private:
// Call time limit processor for new state. // Call time limit processor for new state.
void CheckTimeLimit(const std::string& source); void CheckTimeLimit(const std::string& source);
...@@ -86,9 +96,12 @@ class ScreenTimeController : public KeyedService, ...@@ -86,9 +96,12 @@ class ScreenTimeController : public KeyedService,
content::BrowserContext* context_; content::BrowserContext* context_;
PrefService* pref_service_; PrefService* pref_service_;
// Points to the base::DefaultClock by default.
const base::Clock* clock_;
// Timer scheduled for when the next lock screen state change event is // Timer scheduled for when the next lock screen state change event is
// expected to happen, e.g. when bedtime is over or the usage limit ends. // expected to happen, e.g. when bedtime is over or the usage limit ends.
base::OneShotTimer next_state_timer_; std::unique_ptr<base::OneShotTimer> next_state_timer_;
// Used to set up timers when a time limit is approaching. // Used to set up timers when a time limit is approaching.
TimeLimitNotifier time_limit_notifier_; TimeLimitNotifier time_limit_notifier_;
......
// 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 "chrome/browser/chromeos/policy/login_policy_test_base.h"
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "base/strings/stringprintf.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/child_accounts/child_account_test_utils.h"
#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h"
#include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/session_manager/core/session_manager.h"
#include "content/public/browser/notification_service.h"
namespace chromeos {
namespace {
void WaitForScreenLock() {
content::WindowedNotificationObserver lock_state_observer(
chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
content::NotificationService::AllSources());
lock_state_observer.Wait();
}
} // namespace
class ScreenTimeControllerTest : public policy::LoginPolicyTestBase {
public:
ScreenTimeControllerTest() {
base::Time start_time;
EXPECT_TRUE(base::Time::FromUTCString("1 Jan 2018 10:00:00", &start_time));
task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
start_time, base::TimeTicks::UnixEpoch());
}
~ScreenTimeControllerTest() override = default;
// policy::LoginPolicyTestBase:
void SetUp() override {
// Recognize example.com (used by LoginPolicyTestBase) as non-enterprise
// account.
policy::BrowserPolicyConnector::SetNonEnterpriseDomainForTesting(
"example.com");
policy::LoginPolicyTestBase::SetUp();
}
void SetUpOnMainThread() override {
policy::LoginPolicyTestBase::SetUpOnMainThread();
SkipToLoginScreen();
LogIn(kAccountId, kAccountPassword, test::kChildAccountServiceFlags);
const user_manager::UserManager* const user_manager =
user_manager::UserManager::Get();
EXPECT_EQ(user_manager->GetActiveUser()->GetType(),
user_manager::USER_TYPE_CHILD);
child_profile_ =
ProfileHelper::Get()->GetProfileByUser(user_manager->GetActiveUser());
// Mock time for ScreenTimeController.
ScreenTimeControllerFactory::GetForBrowserContext(child_profile_)
->SetClocksForTesting(task_runner_->GetMockClock(),
task_runner_->GetMockTickClock());
}
void GetMandatoryPoliciesValue(base::DictionaryValue* policy) const override {
// A basic starting policy.
constexpr char kUsageTimeLimit[] = R"({
"time_usage_limit": {
"reset_at": {
"hour": 6, "minute": 0
}
}
})";
policy->SetKey("UsageTimeLimit", base::Value(kUsageTimeLimit));
}
std::string GetIdToken() const override {
return test::GetChildAccountOAuthIdToken();
}
protected:
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
Profile* child_profile_ = nullptr;
private:
DISALLOW_COPY_AND_ASSIGN(ScreenTimeControllerTest);
};
// Tests a simple lock override.
IN_PROC_BROWSER_TEST_F(ScreenTimeControllerTest, LockOverride) {
// Verify screen is unlocked.
EXPECT_FALSE(session_manager::SessionManager::Get()->IsScreenLocked());
// Wait one hour.
task_runner_->FastForwardBy(base::TimeDelta::FromHours(1));
EXPECT_FALSE(session_manager::SessionManager::Get()->IsScreenLocked());
// Set new policy.
int64_t created_at_millis =
(task_runner_->Now() - base::Time::UnixEpoch()).InMilliseconds();
std::string policy_value = base::StringPrintf(
R"(
{
"time_usage_limit": {
"reset_at": {
"hour": 6, "minute": 0
}
},
"overrides": [{
"action": "LOCK",
"created_at_millis": "%ld"
}]
})",
created_at_millis);
auto policy = std::make_unique<base::DictionaryValue>();
policy->SetKey("UsageTimeLimit", base::Value(policy_value));
user_policy_helper()->UpdatePolicy(*policy, base::DictionaryValue(),
child_profile_);
WaitForScreenLock();
EXPECT_TRUE(session_manager::SessionManager::Get()->IsScreenLocked());
}
} // namespace chromeos
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/child_accounts/child_account_test_utils.h"
#include "chrome/browser/chromeos/login/screens/gaia_view.h" #include "chrome/browser/chromeos/login/screens/gaia_view.h"
#include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h"
#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
...@@ -39,15 +40,6 @@ namespace { ...@@ -39,15 +40,6 @@ namespace {
// The Gaia ID supplied by FakeGaia for our mocked-out signin. // The Gaia ID supplied by FakeGaia for our mocked-out signin.
const char kTestGaiaId[] = "12345"; const char kTestGaiaId[] = "12345";
const char kIdTokenChildAccount[] =
"dummy-header."
// base64 encoded: { "services": ["uca"] }
"eyAic2VydmljZXMiOiBbInVjYSJdIH0="
".dummy-signature";
// Services list for the child user. (This must be a correct JSON array.)
const char kChildServices[] = "[\"uca\"]";
// Helper class that counts the number of notifications of the specified // Helper class that counts the number of notifications of the specified
// type that have been received. // type that have been received.
class CountNotificationObserver : public content::NotificationObserver { class CountNotificationObserver : public content::NotificationObserver {
...@@ -293,7 +285,9 @@ class UserCloudPolicyManagerChildTest ...@@ -293,7 +285,9 @@ class UserCloudPolicyManagerChildTest
~UserCloudPolicyManagerChildTest() override = default; ~UserCloudPolicyManagerChildTest() override = default;
// LoginPolicyTestBase: // LoginPolicyTestBase:
std::string GetIdToken() const override { return kIdTokenChildAccount; } std::string GetIdToken() const override {
return chromeos::test::GetChildAccountOAuthIdToken();
}
// UserCloudPolicyManagerNonEnterpriseTest: // UserCloudPolicyManagerNonEnterpriseTest:
void SetUp() override { void SetUp() override {
...@@ -319,7 +313,8 @@ IN_PROC_BROWSER_TEST_F(UserCloudPolicyManagerChildTest, PolicyForChildUser) { ...@@ -319,7 +313,8 @@ IN_PROC_BROWSER_TEST_F(UserCloudPolicyManagerChildTest, PolicyForChildUser) {
user_manager::known_user::GetProfileRequiresPolicy(account_id)); user_manager::known_user::GetProfileRequiresPolicy(account_id));
SkipToLoginScreen(); SkipToLoginScreen();
LogIn(GetAccount(), kAccountPassword, kChildServices); LogIn(GetAccount(), kAccountPassword,
chromeos::test::kChildAccountServiceFlags);
// User should be marked as having a valid OAuth token. // User should be marked as having a valid OAuth token.
const user_manager::UserManager* const user_manager = const user_manager::UserManager* const user_manager =
......
...@@ -1633,6 +1633,9 @@ test("browser_tests") { ...@@ -1633,6 +1633,9 @@ test("browser_tests") {
"../browser/chromeos/arc/user_session/arc_user_session_service_browsertest.cc", "../browser/chromeos/arc/user_session/arc_user_session_service_browsertest.cc",
"../browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc", "../browser/chromeos/arc/voice_interaction/arc_voice_interaction_arc_home_service_browsertest.cc",
"../browser/chromeos/attestation/attestation_policy_browsertest.cc", "../browser/chromeos/attestation/attestation_policy_browsertest.cc",
"../browser/chromeos/child_accounts/child_account_test_utils.cc",
"../browser/chromeos/child_accounts/child_account_test_utils.h",
"../browser/chromeos/child_accounts/screen_time_controller_browsertest.cc",
"../browser/chromeos/customization/customization_document_browsertest.cc", "../browser/chromeos/customization/customization_document_browsertest.cc",
"../browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc", "../browser/chromeos/customization/customization_wallpaper_downloader_browsertest.cc",
"../browser/chromeos/display/display_prefs_browsertest.cc", "../browser/chromeos/display/display_prefs_browsertest.cc",
......
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