| // 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 |