Commit 6a6a98aa authored by Maksim Ivanov's avatar Maksim Ivanov Committed by Commit Bot

Test sign-in screen extensions lifetime manager

Add browsertests for the LoginScreenExtensionsLifetimeManager class that
implements disabling/reenabling login-screen policy extensions when
switching to/from user sessions.

Also extend ExtensionForceInstallMixin to support setting policy via
DeviceStateMixin.

Bug: 1045740
Change-Id: I4ff3502cc571c396da74af76a7714d369a0b4f59
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2276412Reviewed-by: default avatarDenis Kuznetsov [CET] <antrim@chromium.org>
Reviewed-by: default avatarAlexander Hendrich <hendrich@chromium.org>
Commit-Queue: Maksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#788446}
parent 0e635f4a
// Copyright 2020 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/login/login_screen_extensions_lifetime_manager.h"
#include <string>
#include "base/command_line.h"
#include "base/path_service.h"
#include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
#include "chrome/browser/chromeos/login/test/device_state_mixin.h"
#include "chrome/browser/chromeos/login/test/login_manager_mixin.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/policy/extension_force_install_mixin.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/mixin_based_in_process_browser_test.h"
#include "chromeos/constants/chromeos_switches.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/test/browser_test.h"
#include "extensions/test/test_background_page_ready_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace {
constexpr char kAllowlistedAppId[] = "bjaiihebfngildkcjkjckolinodhliff";
constexpr char kAllowlistedAppCrxPath[] =
"extensions/signin_screen_manual_test_app/app_signed_by_webstore.crx";
Profile* GetInitialProfile() {
return chromeos::ProfileHelper::GetSigninProfile()->GetOriginalProfile();
}
} // namespace
class LoginScreenExtensionsLifetimeManagerTest
: public MixinBasedInProcessBrowserTest {
protected:
LoginScreenExtensionsLifetimeManagerTest() {
// Don't shut down when no browser is open, since it breaks the test and
// since it's not the real Chrome OS behavior.
set_exit_when_last_browser_closes(false);
}
LoginScreenExtensionsLifetimeManagerTest(
const LoginScreenExtensionsLifetimeManagerTest&) = delete;
LoginScreenExtensionsLifetimeManagerTest& operator=(
const LoginScreenExtensionsLifetimeManagerTest&) = delete;
~LoginScreenExtensionsLifetimeManagerTest() override = default;
void SetUpCommandLine(base::CommandLine* command_line) override {
// Skip showing post-login screens, as advancing through them isn't faked in
// the test.
command_line->AppendSwitch(switches::kOobeSkipPostLogin);
MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line);
}
void SetUpOnMainThread() override {
MixinBasedInProcessBrowserTest::SetUpOnMainThread();
extension_force_install_mixin_.InitWithDeviceStateMixin(
GetInitialProfile(), &device_state_mixin_);
}
void LogIn() {
login_manager_mixin_.LoginAsNewRegularUser();
login_manager_mixin_.WaitForActiveSession();
}
void LockSession() { ScreenLockerTester().Lock(); }
void UnlockSession() {
const std::string kPassword = "pass";
const AccountId account_id =
user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId();
ScreenLockerTester screen_locker_tester;
screen_locker_tester.SetUnlockPassword(account_id, kPassword);
screen_locker_tester.UnlockWithPassword(account_id, kPassword);
screen_locker_tester.WaitForUnlock();
}
ExtensionForceInstallMixin* extension_force_install_mixin() {
return &extension_force_install_mixin_;
}
bool IsExtensionInstalled(const std::string& extension_id) const {
return extension_force_install_mixin_.GetInstalledExtension(extension_id) !=
nullptr;
}
bool IsExtensionEnabled(const std::string& extension_id) const {
return extension_force_install_mixin_.GetEnabledExtension(extension_id) !=
nullptr;
}
bool IsExtensionBackgroundPageReady(const std::string& extension_id) const {
return extension_force_install_mixin_.IsExtensionBackgroundPageReady(
extension_id);
}
private:
DeviceStateMixin device_state_mixin_{
&mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED};
LoginManagerMixin login_manager_mixin_{&mixin_host_};
ExtensionForceInstallMixin extension_force_install_mixin_{&mixin_host_};
};
// Tests that an extension force-installed on the login/lock screen gets
// disabled during an active user session.
IN_PROC_BROWSER_TEST_F(LoginScreenExtensionsLifetimeManagerTest, Basic) {
// Force-install the app while on the login screen. The app gets loaded.
EXPECT_TRUE(extension_force_install_mixin()->ForceInstallFromCrx(
base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
.AppendASCII(kAllowlistedAppCrxPath),
ExtensionForceInstallMixin::WaitMode::kBackgroundPageReady));
ASSERT_TRUE(IsExtensionEnabled(kAllowlistedAppId));
EXPECT_TRUE(IsExtensionBackgroundPageReady(kAllowlistedAppId));
// The user logs in. The app gets disabled, although still installed.
LogIn();
EXPECT_TRUE(IsExtensionInstalled(kAllowlistedAppId));
EXPECT_FALSE(IsExtensionEnabled(kAllowlistedAppId));
// The user locks the session. The app gets enabled and the background page
// is loaded again.
extensions::ExtensionBackgroundPageReadyObserver page_observer(
GetInitialProfile(), kAllowlistedAppId);
LockSession();
page_observer.Wait();
ASSERT_TRUE(IsExtensionEnabled(kAllowlistedAppId));
// The user unlocks the session. The app gets disabled again.
UnlockSession();
EXPECT_TRUE(IsExtensionInstalled(kAllowlistedAppId));
EXPECT_FALSE(IsExtensionEnabled(kAllowlistedAppId));
}
// Tests that an extension force-installed into the login/lock screen when
// they're not active doesn't get launched.
IN_PROC_BROWSER_TEST_F(LoginScreenExtensionsLifetimeManagerTest,
InstalledDuringSession) {
// Force-install the app during an active user session. The app gets
// installed, but is immediately disabled.
LogIn();
EXPECT_TRUE(extension_force_install_mixin()->ForceInstallFromCrx(
base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
.AppendASCII(kAllowlistedAppCrxPath),
ExtensionForceInstallMixin::WaitMode::kLoad));
EXPECT_TRUE(IsExtensionInstalled(kAllowlistedAppId));
EXPECT_FALSE(IsExtensionEnabled(kAllowlistedAppId));
// The user locks the session. The app gets enabled and the background page is
// loaded again.
extensions::ExtensionBackgroundPageReadyObserver page_observer(
GetInitialProfile(), kAllowlistedAppId);
LockSession();
page_observer.Wait();
ASSERT_TRUE(IsExtensionEnabled(kAllowlistedAppId));
EXPECT_TRUE(IsExtensionBackgroundPageReady(kAllowlistedAppId));
}
} // namespace chromeos
......@@ -41,6 +41,7 @@
#include "url/gurl.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/test/device_state_mixin.h"
#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
#include "components/policy/proto/chrome_device_policy.pb.h"
#endif
......@@ -232,6 +233,17 @@ std::string MakeForceInstallPolicyItemValue(
update_manifest_url.spec().c_str());
}
void UpdatePolicyViaDeviceStateMixin(
const extensions::ExtensionId& extension_id,
const GURL& update_manifest_url,
chromeos::DeviceStateMixin* device_state_mixin) {
device_state_mixin->RequestDevicePolicyUpdate()
->policy_payload()
->mutable_device_login_screen_extensions()
->add_device_login_screen_extensions(
MakeForceInstallPolicyItemValue(extension_id, update_manifest_url));
}
void UpdatePolicyViaDevicePolicyCrosTestHelper(
const extensions::ExtensionId& extension_id,
const GURL& update_manifest_url,
......@@ -256,6 +268,17 @@ ExtensionForceInstallMixin::~ExtensionForceInstallMixin() = default;
#if defined(OS_CHROMEOS)
void ExtensionForceInstallMixin::InitWithDeviceStateMixin(
Profile* profile,
chromeos::DeviceStateMixin* device_state_mixin) {
DCHECK(profile);
DCHECK(device_state_mixin);
DCHECK(!profile_) << "Init already called";
DCHECK(!device_state_mixin_);
profile_ = profile;
device_state_mixin_ = device_state_mixin;
}
void ExtensionForceInstallMixin::InitWithDevicePolicyCrosTestHelper(
Profile* profile,
policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper) {
......@@ -472,6 +495,11 @@ bool ExtensionForceInstallMixin::UpdatePolicy(
DCHECK(profile_) << "Init not called";
#if defined(OS_CHROMEOS)
if (device_state_mixin_) {
UpdatePolicyViaDeviceStateMixin(extension_id, update_manifest_url,
device_state_mixin_);
return true;
}
if (device_policy_cros_test_helper_) {
UpdatePolicyViaDevicePolicyCrosTestHelper(extension_id, update_manifest_url,
device_policy_cros_test_helper_);
......
......@@ -27,6 +27,10 @@ class Extension;
#if defined(OS_CHROMEOS)
namespace chromeos {
class DeviceStateMixin;
} // namespace chromeos
namespace policy {
class DevicePolicyCrosTestHelper;
} // namespace policy
......@@ -85,6 +89,8 @@ class ExtensionForceInstallMixin final : public InProcessBrowserTestMixin {
// other method:
#if defined(OS_CHROMEOS)
void InitWithDeviceStateMixin(Profile* profile,
chromeos::DeviceStateMixin* device_state_mixin);
void InitWithDevicePolicyCrosTestHelper(
Profile* profile,
policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper);
......@@ -162,6 +168,7 @@ class ExtensionForceInstallMixin final : public InProcessBrowserTestMixin {
net::EmbeddedTestServer embedded_test_server_;
Profile* profile_ = nullptr;
#if defined(OS_CHROMEOS)
chromeos::DeviceStateMixin* device_state_mixin_ = nullptr;
policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper_ = nullptr;
#endif
};
......
......@@ -2244,6 +2244,7 @@ if (!is_android) {
"../browser/chromeos/login/login_browsertest.cc",
"../browser/chromeos/login/login_manager_test.cc",
"../browser/chromeos/login/login_manager_test.h",
"../browser/chromeos/login/login_screen_extensions_lifetime_manager_browsertest.cc",
"../browser/chromeos/login/login_screen_policy_browsertest.cc",
"../browser/chromeos/login/login_ui_browsertest.cc",
"../browser/chromeos/login/login_ui_hide_supervised_users_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