blob: 8338c95241fea00009be16c54d2f441345bd1998 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <memory>
#include <vector>
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/test/test_future.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/ash/extensions/users_private/users_private_delegate.h"
#include "chrome/browser/ash/extensions/users_private/users_private_delegate_factory.h"
#include "chrome/browser/ash/login/lock/screen_locker.h"
#include "chrome/browser/ash/login/lock/screen_locker_tester.h"
#include "chrome/browser/ash/login/test/device_state_mixin.h"
#include "chrome/browser/ash/login/test/oobe_base_test.h"
#include "chrome/browser/ash/ownership/owner_settings_service_ash.h"
#include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h"
#include "chrome/browser/extensions/api/settings_private/prefs_util.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/users_private.h"
#include "chromeos/ash/components/install_attributes/stub_install_attributes.h"
#include "chromeos/ash/components/policy/device_policy/cached_device_policy_updater.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/ownership/mock_owner_key_util.h"
#include "components/prefs/pref_service.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/api/test/test_api.h"
#include "extensions/common/switches.h"
namespace extensions {
namespace {
class TestPrefsUtil : public PrefsUtil {
public:
explicit TestPrefsUtil(Profile* profile) : PrefsUtil(profile) {}
std::optional<api::settings_private::PrefObject> GetPref(
const std::string& name) override {
if (name != "cros.accounts.users")
return PrefsUtil::GetPref(name);
api::settings_private::PrefObject pref_object;
pref_object.key = name;
pref_object.type = api::settings_private::PrefType::kList;
base::Value::List value;
for (auto& email : user_list_) {
value.Append(email);
}
pref_object.value = base::Value(std::move(value));
return pref_object;
}
bool AppendToListCrosSetting(const std::string& pref_name,
const base::Value& value) override {
std::string email;
if (value.is_string())
email = value.GetString();
for (auto& user : user_list_) {
if (email == user)
return false;
}
user_list_.push_back(email);
return true;
}
bool RemoveFromListCrosSetting(const std::string& pref_name,
const base::Value& value) override {
std::string email;
if (value.is_string())
email = value.GetString();
auto iter = std::ranges::find(user_list_, email);
if (iter != user_list_.end())
user_list_.erase(iter);
return true;
}
private:
std::vector<std::string> user_list_;
};
class TestDelegate : public UsersPrivateDelegate {
public:
explicit TestDelegate(Profile* profile) : UsersPrivateDelegate(profile) {
profile_ = profile;
prefs_util_ = nullptr;
}
TestDelegate(const TestDelegate&) = delete;
TestDelegate& operator=(const TestDelegate&) = delete;
~TestDelegate() override = default;
PrefsUtil* GetPrefsUtil() override {
if (!prefs_util_)
prefs_util_ = std::make_unique<TestPrefsUtil>(profile_);
return prefs_util_.get();
}
private:
raw_ptr<Profile, LeakedDanglingUntriaged> profile_; // weak
std::unique_ptr<TestPrefsUtil> prefs_util_;
};
class UsersPrivateApiTest
: public InProcessBrowserTestMixinHostSupport<ExtensionApiTest> {
public:
UsersPrivateApiTest() = default;
UsersPrivateApiTest(const UsersPrivateApiTest&) = delete;
UsersPrivateApiTest& operator=(const UsersPrivateApiTest&) = delete;
~UsersPrivateApiTest() override = default;
void SetUpInProcessBrowserTestFixture() override {
InProcessBrowserTestMixinHostSupport<
ExtensionApiTest>::SetUpInProcessBrowserTestFixture();
policy::CachedDevicePolicyUpdater updater;
updater.policy_data().set_username("testuser@gmail.com");
updater.policy_data().set_management_mode(
enterprise_management::PolicyData::LOCAL_OWNER);
updater.Commit();
}
void SetUpOnMainThread() override {
InProcessBrowserTestMixinHostSupport<ExtensionApiTest>::SetUpOnMainThread();
UsersPrivateDelegateFactory::GetInstance()->SetTestingFactory(
profile(), base::BindRepeating([](content::BrowserContext* context)
-> std::unique_ptr<KeyedService> {
return std::make_unique<TestDelegate>(
Profile::FromBrowserContext(context));
}));
content::RunAllPendingInMessageLoop();
auto* owner_settings_service =
ash::OwnerSettingsServiceAshFactory::GetForBrowserContext(profile());
base::test::TestFuture<bool> future;
owner_settings_service->IsOwnerAsync(future.GetCallback());
ASSERT_TRUE(future.Get());
}
protected:
bool RunSubtest(const std::string& subtest) {
const std::string extension_url = "main.html?" + subtest;
return RunExtensionTest("users_private",
{.extension_url = extension_url.c_str()},
{.load_as_component = true});
}
private:
ash::ScopedStubInstallAttributes scoped_stub_install_attributes_{
ash::StubInstallAttributes::CreateConsumerOwned()};
ash::DeviceStateMixin device_state_{
&mixin_host_,
ash::DeviceStateMixin::State::OOBE_COMPLETED_CONSUMER_OWNED};
};
class LoginStatusTestConfig {
public:
LoginStatusTestConfig() = default;
~LoginStatusTestConfig() = default;
void Init() {
extensions::TestGetConfigFunction::set_test_config_state(&test_config_);
}
void Reset() {
extensions::TestGetConfigFunction::set_test_config_state(nullptr);
}
void SetConfig(bool logged_in, bool screen_locked) {
test_config_.SetByDottedPath("loginStatus.isLoggedIn",
base::Value(logged_in));
test_config_.SetByDottedPath("loginStatus.isScreenLocked",
base::Value(screen_locked));
}
private:
base::Value::Dict test_config_;
};
class UsersPrivateApiLoginStatusTest : public ExtensionApiTest {
protected:
void SetUpOnMainThread() override {
ExtensionApiTest::SetUpOnMainThread();
test_config_.Init();
test_config_.SetConfig(true /*logged_in*/, false /*screen_locked*/);
}
void TearDownOnMainThread() override {
ExtensionApiTest::TearDownOnMainThread();
test_config_.Reset();
}
LoginStatusTestConfig test_config_;
};
class UsersPrivateApiLockStatusTest : public UsersPrivateApiLoginStatusTest {
protected:
void SetUpOnMainThread() override {
UsersPrivateApiLoginStatusTest::SetUpOnMainThread();
test_config_.SetConfig(true /*logged_in*/, true /*screen_locked*/);
}
};
} // namespace
IN_PROC_BROWSER_TEST_F(UsersPrivateApiTest, AddUser) {
EXPECT_TRUE(RunSubtest("addUser")) << message_;
}
IN_PROC_BROWSER_TEST_F(UsersPrivateApiTest, AddAndRemoveUsers) {
EXPECT_TRUE(RunSubtest("addAndRemoveUsers")) << message_;
}
IN_PROC_BROWSER_TEST_F(UsersPrivateApiTest, IsUserInList) {
EXPECT_TRUE(RunSubtest("isUserInList")) << message_;
}
IN_PROC_BROWSER_TEST_F(UsersPrivateApiTest, IsOwner) {
EXPECT_TRUE(RunSubtest("isOwner")) << message_;
}
// User profile - logged in, screen not locked.
IN_PROC_BROWSER_TEST_F(UsersPrivateApiLoginStatusTest, User) {
EXPECT_TRUE(RunExtensionTest("users_private",
{.extension_url = "main.html?getLoginStatus"},
{.load_as_component = true}))
<< message_;
}
// TODO(achuith): Signin profile - not logged in, screen not locked.
// Screenlock - logged in, screen locked.
IN_PROC_BROWSER_TEST_F(UsersPrivateApiLockStatusTest, ScreenLock) {
ash::ScreenLockerTester().Lock();
EXPECT_TRUE(RunExtensionTest("users_private",
{.extension_url = "main.html?getLoginStatus"},
{.load_as_component = true}))
<< message_;
}
} // namespace extensions