Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: chrome/browser/chromeos/policy/signin_profile_apps_policy_browsertest.cc

Issue 2865063003: Add an end-to-end test for sign-in profile apps installation (Closed)
Patch Set: Remove dependency on http://crrev.com/2854293003 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/test/data/extensions/signin_screen_test_app/README » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <string>
6
7 #include "base/bind.h"
5 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/location.h"
11 #include "base/logging.h"
6 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/strings/string_util.h"
7 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
16 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
17 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
8 #include "chrome/browser/chromeos/profiles/profile_helper.h" 18 #include "chrome/browser/chromeos/profiles/profile_helper.h"
19 #include "chrome/browser/extensions/crx_installer.h"
9 #include "chrome/browser/extensions/extension_service.h" 20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/net/url_request_mock_util.h"
10 #include "chrome/browser/profiles/profile_manager.h" 22 #include "chrome/browser/profiles/profile_manager.h"
11 #include "chrome/common/chrome_switches.h" 23 #include "chrome/common/chrome_switches.h"
12 #include "chrome/test/base/in_process_browser_test.h" 24 #include "chrome/test/base/in_process_browser_test.h"
25 #include "chromeos/chromeos_switches.h"
26 #include "chromeos/dbus/fake_session_manager_client.h"
27 #include "components/version_info/channel.h"
28 #include "components/version_info/version_info.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/notification_source.h"
13 #include "content/public/test/browser_test.h" 31 #include "content/public/test/browser_test.h"
32 #include "content/public/test/test_utils.h"
33 #include "extensions/browser/extension_registry.h"
14 #include "extensions/browser/extension_system.h" 34 #include "extensions/browser/extension_system.h"
35 #include "extensions/browser/notification_types.h"
36 #include "extensions/browser/test_extension_registry_observer.h"
37 #include "extensions/common/extension.h"
38 #include "extensions/common/extension_set.h"
39 #include "extensions/common/features/feature_channel.h"
40 #include "net/test/url_request/url_request_mock_http_job.h"
15 #include "testing/gtest/include/gtest/gtest.h" 41 #include "testing/gtest/include/gtest/gtest.h"
42 #include "url/gurl.h"
16 43
17 namespace policy { 44 namespace policy {
18 45
19 namespace { 46 namespace {
20 47
48 // Parameters for the several extensions and apps that are used by the tests in
49 // this file (note that the paths are given relative to the src/chrome/test/data
50 // directory):
51 // * The test app which is whitelisted for running in the sign-in profile:
52 const char kTestAppId[] = "bjaiihebfngildkcjkjckolinodhliff";
53 const char kTestAppUpdateManifestPath[] =
54 "extensions/signin_screen_test_app/update_manifest.xml";
55 // * A trivial test app which is NOT whitelisted for running in the sign-in
56 // profile:
57 const char kTrivialAppId[] = "mockapnacjbcdncmpkjngjalkhphojek";
58 const char kTrivialAppUpdateManifestPath[] =
59 "extensions/trivial_platform_app/update_manifest.xml";
60 // * A trivial test extension (note that extensions cannot be whitelisted for
61 // running in the sign-in profile):
62 const char kTrivialExtensionId[] = "mockepjebcnmhmhcahfddgfcdgkdifnc";
63 const char kTrivialExtensionUpdateManifestPath[] =
64 "extensions/trivial_extension/update_manifest.xml";
65
66 // Observer that allows waiting for an installation failure of a specific
67 // extension/app.
68 // TODO(emaxx): Extract this into a more generic helper class for using in other
69 // tests.
70 class ExtensionInstallErrorObserver final {
71 public:
72 ExtensionInstallErrorObserver(const Profile* profile,
73 const std::string& extension_id)
74 : profile_(profile),
75 extension_id_(extension_id),
76 notification_observer_(
77 extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
78 base::Bind(&ExtensionInstallErrorObserver::IsNotificationRelevant,
79 base::Unretained(this))) {}
80
81 void Wait() { notification_observer_.Wait(); }
82
83 private:
84 // Callback which is used for |WindowedNotificationObserver| for checking
85 // whether the condition being awaited is met.
86 bool IsNotificationRelevant(
87 const content::NotificationSource& source,
88 const content::NotificationDetails& details) const {
89 extensions::CrxInstaller* const crx_installer =
90 content::Source<extensions::CrxInstaller>(source).ptr();
91 return crx_installer->profile() == profile_ &&
92 crx_installer->extension()->id() == extension_id_;
93 }
94
95 const Profile* const profile_;
96 const std::string extension_id_;
97 content::WindowedNotificationObserver notification_observer_;
98
99 DISALLOW_COPY_AND_ASSIGN(ExtensionInstallErrorObserver);
100 };
101
102 // Observer that allows waiting until the background page of the specified
103 // extension/app loads.
104 // TODO(emaxx): Extract this into a more generic helper class for using in other
105 // tests.
106 class ExtensionBackgroundPageReadyObserver final {
107 public:
108 explicit ExtensionBackgroundPageReadyObserver(const std::string& extension_id)
109 : extension_id_(extension_id),
110 notification_observer_(
111 extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
112 base::Bind(
113 &ExtensionBackgroundPageReadyObserver::IsNotificationRelevant,
114 base::Unretained(this))) {}
115
116 void Wait() { notification_observer_.Wait(); }
117
118 private:
119 // Callback which is used for |WindowedNotificationObserver| for checking
120 // whether the condition being awaited is met.
121 bool IsNotificationRelevant(
122 const content::NotificationSource& source,
123 const content::NotificationDetails& details) const {
124 return content::Source<const extensions::Extension>(source)->id() ==
125 extension_id_;
126 }
127
128 const std::string extension_id_;
129 content::WindowedNotificationObserver notification_observer_;
130
131 DISALLOW_COPY_AND_ASSIGN(ExtensionBackgroundPageReadyObserver);
132 };
133
134 // Returns the initial profile, which is the original profile of the sign-in
135 // profile. The apps specified in the policy will be installed into the initial
136 // profile, and then become available in both.
137 Profile* GetProfile() {
138 // Intentionally not using the |chromeos::ProfileHelper::GetSigninProfile|
139 // method here, as it performs the lazy construction of the profile, while for
140 // the testing purposes it's better to assert that it has been created before.
141 Profile* const profile =
142 g_browser_process->profile_manager()->GetProfileByPath(
143 chromeos::ProfileHelper::GetSigninProfileDir());
144 DCHECK(profile);
145 return profile;
146 }
147
21 // Tests for the sign-in profile apps being enabled via the command line flag. 148 // Tests for the sign-in profile apps being enabled via the command line flag.
22 // TODO(emaxx): Remove this smoke test once it's investigated whether just 149 // TODO(emaxx): Remove this smoke test once it's investigated whether just
23 // specifying this command line flag leads to tests being timed out. 150 // specifying this command line flag leads to tests being timed out.
24 class SigninProfileAppsEnabledViaCommandLineTest : public InProcessBrowserTest { 151 class SigninProfileAppsEnabledViaCommandLineTest : public InProcessBrowserTest {
25 protected: 152 protected:
26 SigninProfileAppsEnabledViaCommandLineTest() {} 153 SigninProfileAppsEnabledViaCommandLineTest() {}
27 154
28 void SetUpCommandLine(base::CommandLine* command_line) override { 155 void SetUpCommandLine(base::CommandLine* command_line) override {
29 InProcessBrowserTest::SetUpCommandLine(command_line); 156 InProcessBrowserTest::SetUpCommandLine(command_line);
30 command_line->AppendSwitch(switches::kEnableLoginScreenApps); 157 command_line->AppendSwitch(switches::kEnableLoginScreenApps);
31 } 158 }
32 159
33 private: 160 private:
34 DISALLOW_COPY_AND_ASSIGN(SigninProfileAppsEnabledViaCommandLineTest); 161 DISALLOW_COPY_AND_ASSIGN(SigninProfileAppsEnabledViaCommandLineTest);
35 }; 162 };
36 163
37 } // namespace 164 } // namespace
38 165
39 IN_PROC_BROWSER_TEST_F(SigninProfileAppsEnabledViaCommandLineTest, 166 IN_PROC_BROWSER_TEST_F(SigninProfileAppsEnabledViaCommandLineTest,
40 NoExtensions) { 167 NoExtensions) {
41 Profile* const initial_profile = 168 EXPECT_TRUE(extensions::ExtensionSystem::Get(GetProfile())
42 g_browser_process->profile_manager()->GetProfileByPath(
43 chromeos::ProfileHelper::GetSigninProfileDir());
44 ASSERT_TRUE(initial_profile);
45 EXPECT_TRUE(extensions::ExtensionSystem::Get(initial_profile)
46 ->extension_service() 169 ->extension_service()
47 ->extensions_enabled()); 170 ->extensions_enabled());
48 } 171 }
49 172
173 namespace {
174
175 // Base class for testing sign-in profile apps that are installed via the device
176 // policy.
177 class SigninProfileAppsPolicyTestBase : public DevicePolicyCrosBrowserTest {
178 protected:
179 explicit SigninProfileAppsPolicyTestBase(version_info::Channel channel)
180 : channel_(channel), scoped_current_channel_(channel) {}
181
182 void SetUpCommandLine(base::CommandLine* command_line) override {
183 DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
184 command_line->AppendSwitch(chromeos::switches::kLoginManager);
185 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
186 command_line->AppendSwitch(switches::kEnableLoginScreenApps);
187 }
188
189 void SetUpInProcessBrowserTestFixture() override {
190 DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
191 InstallOwnerKey();
192 MarkAsEnterpriseOwned();
193 }
194
195 void SetUpOnMainThread() override {
196 EnableUrlRequestMocks();
197 DevicePolicyCrosBrowserTest::SetUpOnMainThread();
198 }
199
200 void AddExtensionForForceInstallation(
201 const std::string& extension_id,
202 const base::FilePath& update_manifest_relative_path) {
203 const GURL update_manifest_url = net::URLRequestMockHTTPJob::GetMockUrl(
204 update_manifest_relative_path.MaybeAsASCII());
205 const std::string policy_item_value = base::ReplaceStringPlaceholders(
206 "$1;$2", {extension_id, update_manifest_url.spec()}, nullptr);
207 device_policy()
208 ->payload()
209 .mutable_device_login_screen_app_install_list()
210 ->add_device_login_screen_app_install_list(policy_item_value);
211 RefreshDevicePolicy();
212 }
213
214 const version_info::Channel channel_;
215
216 private:
217 // Enables URL request mocks for making the test data files (extensions'
218 // update manifests and packages) available under corresponding URLs.
219 static void EnableUrlRequestMocks() {
220 content::BrowserThread::PostTask(
221 content::BrowserThread::IO, FROM_HERE,
222 base::BindOnce(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
223 }
224
225 const extensions::ScopedCurrentChannel scoped_current_channel_;
226
227 DISALLOW_COPY_AND_ASSIGN(SigninProfileAppsPolicyTestBase);
228 };
229
230 // Class for testing sign-in profile apps under different browser channels.
231 class SigninProfileAppsPolicyPerChannelTest
232 : public SigninProfileAppsPolicyTestBase,
233 public testing::WithParamInterface<version_info::Channel> {
234 protected:
235 SigninProfileAppsPolicyPerChannelTest()
236 : SigninProfileAppsPolicyTestBase(GetParam()) {}
237
238 private:
239 DISALLOW_COPY_AND_ASSIGN(SigninProfileAppsPolicyPerChannelTest);
240 };
241
242 } // namespace
243
244 // Tests that a whitelisted app gets installed on any browser channel.
245 IN_PROC_BROWSER_TEST_P(SigninProfileAppsPolicyPerChannelTest,
246 WhitelistedAppInstallation) {
247 extensions::TestExtensionRegistryObserver registry_observer(
248 extensions::ExtensionRegistry::Get(GetProfile()), kTestAppId);
249
250 AddExtensionForForceInstallation(kTestAppId,
251 base::FilePath(kTestAppUpdateManifestPath));
252
253 registry_observer.WaitForExtensionLoaded();
254 EXPECT_TRUE(extensions::ExtensionRegistry::Get(GetProfile())
255 ->enabled_extensions()
256 .Contains(kTestAppId));
257 }
258
259 // Tests that a non-whitelisted app is installed only when on Dev, Canary or
260 // "unknown" (trunk) channels, but not on Beta or Stable channels.
261 IN_PROC_BROWSER_TEST_P(SigninProfileAppsPolicyPerChannelTest,
262 NotWhitelistedAppInstallation) {
263 extensions::TestExtensionRegistryObserver registry_observer(
264 extensions::ExtensionRegistry::Get(GetProfile()), kTrivialAppId);
265 ExtensionInstallErrorObserver install_error_observer(GetProfile(),
266 kTrivialAppId);
267
268 AddExtensionForForceInstallation(
269 kTrivialAppId, base::FilePath(kTrivialAppUpdateManifestPath));
270
271 switch (channel_) {
272 case version_info::Channel::UNKNOWN:
273 case version_info::Channel::CANARY:
274 case version_info::Channel::DEV:
275 registry_observer.WaitForExtensionLoaded();
276 EXPECT_TRUE(extensions::ExtensionRegistry::Get(GetProfile())
277 ->enabled_extensions()
278 .Contains(kTrivialAppId));
279 break;
280 case version_info::Channel::BETA:
281 case version_info::Channel::STABLE:
282 install_error_observer.Wait();
283 EXPECT_FALSE(extensions::ExtensionRegistry::Get(GetProfile())
284 ->GetInstalledExtension(kTrivialAppId));
285 break;
286 }
287 }
288
289 // Tests that an extension (as opposed to an app) is forbidden from installation
290 // regardless of the browser channel.
291 IN_PROC_BROWSER_TEST_P(SigninProfileAppsPolicyPerChannelTest,
292 ExtensionInstallation) {
293 ExtensionInstallErrorObserver install_error_observer(GetProfile(),
294 kTrivialExtensionId);
295
296 AddExtensionForForceInstallation(
297 kTrivialExtensionId, base::FilePath(kTrivialExtensionUpdateManifestPath));
298
299 install_error_observer.Wait();
300 EXPECT_FALSE(extensions::ExtensionRegistry::Get(GetProfile())
301 ->GetInstalledExtension(kTrivialExtensionId));
302 }
303
304 // TODO(emaxx): Add the STABLE option once the scoped feature channel bug is
305 // fixed (https://crrev.com/2854293003).
306 INSTANTIATE_TEST_CASE_P(,
307 SigninProfileAppsPolicyPerChannelTest,
308 testing::Values(version_info::Channel::UNKNOWN,
309 version_info::Channel::CANARY,
310 version_info::Channel::DEV,
311 version_info::Channel::BETA));
312
313 namespace {
314
315 // Class for testing sign-in profile apps under the "unknown" browser channel,
316 // which allows to bypass the troublesome whitelist checks.
317 class SigninProfileAppsPolicyTest : public SigninProfileAppsPolicyTestBase {
318 protected:
319 SigninProfileAppsPolicyTest()
320 : SigninProfileAppsPolicyTestBase(version_info::Channel::UNKNOWN) {}
321
322 private:
323 DISALLOW_COPY_AND_ASSIGN(SigninProfileAppsPolicyTest);
324 };
325
326 } // namespace
327
328 // Tests that a background page is created for the installed sign-in profile
329 // app.
330 IN_PROC_BROWSER_TEST_F(SigninProfileAppsPolicyTest, BackgroundPage) {
331 ExtensionBackgroundPageReadyObserver page_observer(kTrivialAppId);
332 AddExtensionForForceInstallation(
333 kTrivialAppId, base::FilePath(kTrivialAppUpdateManifestPath));
334 page_observer.Wait();
335 }
336
337 // Tests installation of multiple sign-in profile apps.
338 IN_PROC_BROWSER_TEST_F(SigninProfileAppsPolicyTest, MultipleApps) {
339 extensions::TestExtensionRegistryObserver registry_observer1(
340 extensions::ExtensionRegistry::Get(GetProfile()), kTestAppId);
341 extensions::TestExtensionRegistryObserver registry_observer2(
342 extensions::ExtensionRegistry::Get(GetProfile()), kTrivialAppId);
343
344 AddExtensionForForceInstallation(kTestAppId,
345 base::FilePath(kTestAppUpdateManifestPath));
346 AddExtensionForForceInstallation(
347 kTrivialAppId, base::FilePath(kTrivialAppUpdateManifestPath));
348
349 registry_observer1.WaitForExtensionLoaded();
350 registry_observer2.WaitForExtensionLoaded();
351 }
352
50 } // namespace policy 353 } // namespace policy
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/extensions/signin_screen_test_app/README » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698