1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/files/file_path.h"
6 #include "base/test/scoped_feature_list.h"
7 #include "chrome/browser/extensions/extension_browsertest.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/supervised_user/logged_in_user_mixin.h"
10 #include "chrome/browser/supervised_user/supervised_user_features.h"
11 #include "chrome/browser/supervised_user/supervised_user_service.h"
12 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
13 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
14 #include "content/public/test/browser_test.h"
15 #include "content/public/test/test_launcher.h"
16 #include "extensions/browser/disable_reason.h"
17 #include "extensions/browser/extension_prefs.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/common/extension.h"
20
21 namespace {
22
23 constexpr char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
24
25 }
26
27 namespace extensions {
28
29 // Tests for the interaction between supervised users and extensions.
30 class SupervisedUserExtensionTest : public ExtensionBrowserTest {
31 public:
SupervisedUserExtensionTest()32 SupervisedUserExtensionTest() {
33 // Suppress regular user login to enable child user login.
34 set_chromeos_user_ = false;
35 }
36
37 // We have to essentially replicate what MixinBasedInProcessBrowserTest does
38 // here because ExtensionBrowserTest doesn't inherit from that class.
SetUp()39 void SetUp() override {
40 scoped_feature_list_.InitAndEnableFeature(
41 supervised_users::kSupervisedUserInitiatedExtensionInstall);
42 mixin_host_.SetUp();
43 ExtensionBrowserTest::SetUp();
44 }
45
SetUpCommandLine(base::CommandLine * command_line)46 void SetUpCommandLine(base::CommandLine* command_line) override {
47 mixin_host_.SetUpCommandLine(command_line);
48 ExtensionBrowserTest::SetUpCommandLine(command_line);
49 }
50
SetUpDefaultCommandLine(base::CommandLine * command_line)51 void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
52 mixin_host_.SetUpDefaultCommandLine(command_line);
53 ExtensionBrowserTest::SetUpDefaultCommandLine(command_line);
54 }
55
SetUpUserDataDirectory()56 bool SetUpUserDataDirectory() override {
57 return mixin_host_.SetUpUserDataDirectory() &&
58 ExtensionBrowserTest::SetUpUserDataDirectory();
59 }
60
SetUpInProcessBrowserTestFixture()61 void SetUpInProcessBrowserTestFixture() override {
62 mixin_host_.SetUpInProcessBrowserTestFixture();
63 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
64 }
65
CreatedBrowserMainParts(content::BrowserMainParts * browser_main_parts)66 void CreatedBrowserMainParts(
67 content::BrowserMainParts* browser_main_parts) override {
68 mixin_host_.CreatedBrowserMainParts(browser_main_parts);
69 ExtensionBrowserTest::CreatedBrowserMainParts(browser_main_parts);
70 }
71
SetUpOnMainThread()72 void SetUpOnMainThread() override {
73 mixin_host_.SetUpOnMainThread();
74 logged_in_user_mixin_.LogInUser();
75 ExtensionBrowserTest::SetUpOnMainThread();
76 }
77
TearDownOnMainThread()78 void TearDownOnMainThread() override {
79 mixin_host_.TearDownOnMainThread();
80 ExtensionBrowserTest::TearDownOnMainThread();
81 }
82
TearDownInProcessBrowserTestFixture()83 void TearDownInProcessBrowserTestFixture() override {
84 mixin_host_.TearDownInProcessBrowserTestFixture();
85 ExtensionBrowserTest::TearDownInProcessBrowserTestFixture();
86 }
87
TearDown()88 void TearDown() override {
89 mixin_host_.TearDown();
90 ExtensionBrowserTest::TearDown();
91 }
92
93 protected:
GetSupervisedUserService()94 SupervisedUserService* GetSupervisedUserService() {
95 return SupervisedUserServiceFactory::GetForProfile(profile());
96 }
97
SetSupervisedUserExtensionsMayRequestPermissionsPref(bool enabled)98 void SetSupervisedUserExtensionsMayRequestPermissionsPref(bool enabled) {
99 GetSupervisedUserService()
100 ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(
101 enabled);
102 }
103
IsDisabledForCustodianApproval(const std::string & extension_id)104 bool IsDisabledForCustodianApproval(const std::string& extension_id) {
105 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
106 return extension_prefs->HasDisableReason(
107 extension_id,
108 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
109 }
110
111 private:
112 InProcessBrowserTestMixinHost mixin_host_;
113
114 // We want to log in as child user for all of the PRE tests, and regular user
115 // otherwise.
116 chromeos::LoggedInUserMixin logged_in_user_mixin_{
117 &mixin_host_,
118 content::IsPreTest() ? chromeos::LoggedInUserMixin::LogInType::kChild
119 : chromeos::LoggedInUserMixin::LogInType::kRegular,
120 embedded_test_server(), this};
121
122 base::test::ScopedFeatureList scoped_feature_list_;
123 };
124
125 // Removing supervision should also remove associated disable reasons, such as
126 // DISABLE_CUSTODIAN_APPROVAL_REQUIRED. Extensions should become enabled again
127 // after removing supervision. Prevents a regression to crbug/1045625.
IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionTest,PRE_RemovingSupervisionCustodianApprovalRequired)128 IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionTest,
129 PRE_RemovingSupervisionCustodianApprovalRequired) {
130 SetSupervisedUserExtensionsMayRequestPermissionsPref(true);
131
132 EXPECT_TRUE(profile()->IsChild());
133
134 base::FilePath path = test_data_dir_.AppendASCII("good.crx");
135 EXPECT_FALSE(LoadExtensionWithFlags(path, kFlagNone));
136 const Extension* extension =
137 extension_registry()->GetInstalledExtension(kGoodCrxId);
138 EXPECT_TRUE(extension);
139
140 // This extension is a supervised user initiated install and should remain
141 // disabled.
142 EXPECT_TRUE(extension_registry()->disabled_extensions().Contains(kGoodCrxId));
143 EXPECT_TRUE(IsDisabledForCustodianApproval(kGoodCrxId));
144 }
145
IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionTest,RemovingSupervisionCustodianApprovalRequired)146 IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionTest,
147 RemovingSupervisionCustodianApprovalRequired) {
148 EXPECT_FALSE(profile()->IsChild());
149 // The extension should still be installed since we are sharing the same data
150 // directory as the PRE test.
151 const Extension* extension =
152 extension_registry()->GetInstalledExtension(kGoodCrxId);
153 EXPECT_TRUE(extension);
154 // The extension should be enabled now after removing supervision.
155 EXPECT_TRUE(extension_registry()->enabled_extensions().Contains(kGoodCrxId));
156 EXPECT_FALSE(IsDisabledForCustodianApproval(kGoodCrxId));
157 }
158
159 } // namespace extensions
160