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