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

Side by Side Diff: chrome/browser/apps/ephemeral_app_launcher_browsertest.cc

Issue 339103002: Update the EphemeralAppLauncher for use by the webstorePrivate API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Self nit Created 6 years, 6 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
OLDNEW
(Empty)
1 // Copyright 2014 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/message_loop/message_loop_proxy.h"
6 #include "chrome/browser/apps/ephemeral_app_launcher.h"
7 #include "chrome/browser/extensions/extension_install_checker.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_test_message_listener.h"
10 #include "chrome/browser/extensions/test_blacklist.h"
11 #include "chrome/browser/extensions/webstore_installer_test.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "content/public/test/test_utils.h"
14 #include "extensions/browser/extension_prefs.h"
15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/browser/extension_system.h"
17 #include "extensions/browser/extension_util.h"
18 #include "extensions/browser/management_policy.h"
19
20 using extensions::Extension;
21 using extensions::ExtensionPrefs;
22 using extensions::ExtensionRegistry;
23 using extensions::ExtensionSystem;
24
25 namespace {
26
27 const char kWebstoreDomain[] = "cws.com";
28 const char kAppDomain[] = "app.com";
29 const char kNonAppDomain[] = "nonapp.com";
30 const char kTestDataPath[] = "extensions/platform_apps/ephemeral_launcher";
31
32 const char kExtensionId[] = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeid";
33 const char kExtensionTestPath[] = "extension";
34 const char kNonExistentId[] = "baaaaaaaaaaaaaaaaaaaaaaaaaaaadid";
35 const char kDefaultAppId[] = "kbiancnbopdghkfedjhfdoegjadfjeal";
36 const char kDefaultAppCrxFilename[] = "app.crx";
37 const char kDefaultAppTestPath[] = "app";
38 const char kAppWithPermissionsId[] = "mbfcnecjknjpipkfkoangpfnhhlpamki";
39 const char kAppWithPermissionsFilename[] = "app_with_permissions.crx";
40
41 class ExtensionInstallCheckerMock : public extensions::ExtensionInstallChecker {
42 public:
43 ExtensionInstallCheckerMock(Profile* profile,
44 const std::string& requirements_error)
45 : extensions::ExtensionInstallChecker(profile),
46 requirements_error_(requirements_error) {}
47
48 virtual ~ExtensionInstallCheckerMock() {}
49
50 private:
51 virtual void CheckRequirements() OVERRIDE {
52 // Simulate an asynchronous operation.
53 base::MessageLoopProxy::current()->PostTask(
54 FROM_HERE,
55 base::Bind(&ExtensionInstallCheckerMock::RequirementsErrorCheckDone,
56 base::Unretained(this)));
57 }
58
59 void RequirementsErrorCheckDone() {
60 std::vector<std::string> errors;
61 errors.push_back(requirements_error_);
62 OnRequirementsCheckDone(errors);
63 }
64
65 std::string requirements_error_;
66 };
67
68 class EphemeralAppLauncherForTest : public EphemeralAppLauncher {
69 public:
70 EphemeralAppLauncherForTest(const std::string& id, Profile* profile)
71 : EphemeralAppLauncher(id, profile, NULL, LaunchCallback()),
72 install_initiated_(false),
73 install_prompt_created_(false) {}
74
75 bool install_initiated() const { return install_initiated_; }
76 bool install_prompt_created() const { return install_prompt_created_; }
77
78 void set_requirements_error(const std::string& error) {
79 requirements_check_error_ = error;
80 }
81
82 private:
83 // Override necessary functions for testing.
84
85 virtual scoped_ptr<extensions::ExtensionInstallChecker> CreateInstallChecker()
86 OVERRIDE {
87 if (requirements_check_error_.empty()) {
88 return EphemeralAppLauncher::CreateInstallChecker();
89 } else {
90 return scoped_ptr<extensions::ExtensionInstallChecker>(
91 new ExtensionInstallCheckerMock(profile(),
92 requirements_check_error_));
93 }
94 }
95
96 virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI() OVERRIDE {
97 install_prompt_created_ = true;
98 return EphemeralAppLauncher::CreateInstallUI();
99 }
100
101 virtual scoped_ptr<extensions::WebstoreInstaller::Approval> CreateApproval()
102 const OVERRIDE {
103 install_initiated_ = true;
104 return EphemeralAppLauncher::CreateApproval();
105 }
106
107 private:
108 virtual ~EphemeralAppLauncherForTest() {}
109 friend class base::RefCountedThreadSafe<EphemeralAppLauncherForTest>;
110
111 mutable bool install_initiated_;
112 std::string requirements_check_error_;
113 bool install_prompt_created_;
114 };
115
116 class LaunchObserver {
117 public:
118 LaunchObserver()
119 : done_(false),
120 waiting_(false),
121 result_(EphemeralAppLauncher::LAUNCH_UNKNOWN_ERROR) {}
122
123 EphemeralAppLauncher::LaunchResult result() const { return result_; }
124 const std::string& error() const { return error_; }
125
126 void OnLaunchCallback(EphemeralAppLauncher::LaunchResult result,
127 const std::string& error) {
128 result_ = result;
129 error_ = error;
130 done_ = true;
131 if (waiting_) {
132 waiting_ = false;
133 base::MessageLoopForUI::current()->Quit();
134 }
135 }
136
137 void Wait() {
138 if (done_)
139 return;
140
141 waiting_ = true;
142 content::RunMessageLoop();
143 }
144
145 private:
146 bool done_;
147 bool waiting_;
148 EphemeralAppLauncher::LaunchResult result_;
149 std::string error_;
150 };
151
152 class ManagementPolicyMock : public extensions::ManagementPolicy::Provider {
153 public:
154 ManagementPolicyMock() {}
155
156 virtual std::string GetDebugPolicyProviderName() const OVERRIDE {
157 return "ManagementPolicyMock";
158 }
159
160 virtual bool UserMayLoad(const Extension* extension,
161 base::string16* error) const OVERRIDE {
162 return false;
163 }
164 };
165
166 } // namespace
167
168 class EphemeralAppLauncherTest : public WebstoreInstallerTest {
169 public:
170 EphemeralAppLauncherTest()
171 : WebstoreInstallerTest(kWebstoreDomain,
172 kTestDataPath,
173 kDefaultAppCrxFilename,
174 kAppDomain,
175 kNonAppDomain) {}
176
177 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
178 WebstoreInstallerTest::SetUpCommandLine(command_line);
179
180 // Enable ephemeral apps flag.
181 command_line->AppendSwitch(switches::kEnableEphemeralApps);
182 }
183
184 base::FilePath GetTestPath(const char* test_name) {
185 return test_data_dir_.AppendASCII("platform_apps/ephemeral_launcher")
186 .AppendASCII(test_name);
187 }
188
189 const Extension* GetInstalledExtension(const std::string& id) {
190 return ExtensionRegistry::Get(profile())
191 ->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
192 }
193
194 void SetCrxFilename(const std::string& filename) {
195 GURL crx_url = GenerateTestServerUrl(kWebstoreDomain, filename);
196 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
197 switches::kAppsGalleryUpdateURL, crx_url.spec());
198 }
199
200 void StartLauncherAndCheckResult(
201 EphemeralAppLauncherForTest* launcher,
202 EphemeralAppLauncher::LaunchResult expected_result,
203 bool expect_install_initiated) {
204 ExtensionTestMessageListener launched_listener("launched", false);
205 LaunchObserver launch_observer;
206
207 launcher->launch_callback_ = base::Bind(&LaunchObserver::OnLaunchCallback,
208 base::Unretained(&launch_observer));
209 launcher->Start();
210 launch_observer.Wait();
211
212 // Verify the launch result.
213 EXPECT_EQ(expected_result, launch_observer.result());
214 EXPECT_EQ(expect_install_initiated, launcher->install_initiated());
215
216 // Verify that the app was actually launched if the launcher succeeded.
217 if (launch_observer.result() == EphemeralAppLauncher::LAUNCH_SUCCESS)
218 EXPECT_TRUE(launched_listener.WaitUntilSatisfied());
219 else
220 EXPECT_FALSE(launched_listener.was_satisfied());
221
222 // Check the reference count to ensure the launcher instance will not be
223 // leaked.
224 EXPECT_TRUE(launcher->HasOneRef());
225 }
226
227 void RunLaunchTest(const std::string& id,
228 EphemeralAppLauncher::LaunchResult expected_result,
229 bool expect_install_initiated) {
230 scoped_refptr<EphemeralAppLauncherForTest> launcher(
231 new EphemeralAppLauncherForTest(id, profile()));
232 StartLauncherAndCheckResult(
233 launcher.get(), expected_result, expect_install_initiated);
234 }
235
236 void ValidateAppInstalledEphemerally(const std::string& id) {
237 EXPECT_TRUE(GetInstalledExtension(id));
238 EXPECT_TRUE(extensions::util::IsEphemeralApp(id, profile()));
239 }
240
241 const Extension* InstallAndDisableApp(
242 const char* test_path,
243 Extension::DisableReason disable_reason) {
244 const Extension* app = InstallExtension(GetTestPath(test_path), 1);
245 EXPECT_TRUE(app);
246 if (!app)
247 return NULL;
248
249 if (disable_reason == Extension::DISABLE_GREYLIST) {
250 ExtensionPrefs::Get(profile())->SetExtensionBlacklistState(
251 app->id(), extensions::BLACKLISTED_MALWARE);
252 }
253
254 ExtensionService* service =
255 ExtensionSystem::Get(profile())->extension_service();
256 service->DisableExtension(app->id(), disable_reason);
257
258 if (disable_reason == Extension::DISABLE_PERMISSIONS_INCREASE) {
259 // When an extension is disabled due to a permissions increase, this
260 // flag needs to be set too, for some reason.
261 ExtensionPrefs::Get(profile())
262 ->SetDidExtensionEscalatePermissions(app, true);
263 }
264
265 EXPECT_FALSE(
266 ExtensionRegistry::Get(profile())->enabled_extensions().Contains(
267 app->id()));
268 return app;
269 }
270 };
271
272 class EphemeralAppLauncherTestDisabled : public EphemeralAppLauncherTest {
273 public:
274 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
275 // Skip EphemeralAppLauncherTest as it enables the feature.
276 WebstoreInstallerTest::SetUpCommandLine(command_line);
277 }
278 };
279
280 // Verifies that an ephemeral app will not be installed and launched if the
281 // feature is disabled.
282 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTestDisabled, FeatureDisabled) {
283 RunLaunchTest(kDefaultAppCrxFilename,
284 EphemeralAppLauncher::LAUNCH_FEATURE_DISABLED,
285 false);
286 EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
287 }
288
289 // Verifies that an app with no permission warnings will be installed
290 // ephemerally and launched without prompting the user.
291 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
292 LaunchAppWithNoPermissionWarnings) {
293 scoped_refptr<EphemeralAppLauncherForTest> launcher(
294 new EphemeralAppLauncherForTest(kDefaultAppId, profile()));
295 StartLauncherAndCheckResult(
296 launcher.get(), EphemeralAppLauncher::LAUNCH_SUCCESS, true);
297 ValidateAppInstalledEphemerally(kDefaultAppId);
298
299 // Apps with no permission warnings should not result in a prompt.
300 EXPECT_FALSE(launcher->install_prompt_created());
301
302 // After an app has been installed ephemerally, it can be launched again
303 // without installing from the web store.
304 RunLaunchTest(kDefaultAppId, EphemeralAppLauncher::LAUNCH_SUCCESS, false);
305 }
306
307 // Verifies that an app with permission warnings will be installed
308 // ephemerally and launched if accepted by the user.
309 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
310 LaunchAppWithPermissionsWarnings) {
311 SetCrxFilename(kAppWithPermissionsFilename);
312 AutoAcceptInstall();
313
314 scoped_refptr<EphemeralAppLauncherForTest> launcher(
315 new EphemeralAppLauncherForTest(kAppWithPermissionsId, profile()));
316 StartLauncherAndCheckResult(
317 launcher.get(), EphemeralAppLauncher::LAUNCH_SUCCESS, true);
318 ValidateAppInstalledEphemerally(kAppWithPermissionsId);
319 EXPECT_TRUE(launcher->install_prompt_created());
320 }
321
322 // Verifies that an app with permission warnings will not be installed
323 // ephemerally if cancelled by the user.
324 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
325 CancelInstallAppWithPermissionWarnings) {
326 SetCrxFilename(kAppWithPermissionsFilename);
327 AutoCancelInstall();
328
329 scoped_refptr<EphemeralAppLauncherForTest> launcher(
330 new EphemeralAppLauncherForTest(kAppWithPermissionsId, profile()));
331 StartLauncherAndCheckResult(
332 launcher.get(), EphemeralAppLauncher::LAUNCH_USER_CANCELLED, false);
333 EXPECT_FALSE(GetInstalledExtension(kAppWithPermissionsId));
334 EXPECT_TRUE(launcher->install_prompt_created());
335 }
336
337 // Verifies that an extension will not be installed ephemerally.
338 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, InstallExtension) {
339 RunLaunchTest(kExtensionId,
340 EphemeralAppLauncher::LAUNCH_UNSUPPORTED_EXTENSION_TYPE,
341 false);
342 EXPECT_FALSE(GetInstalledExtension(kExtensionId));
343 }
344
345 // Verifies that an already installed extension will not be launched.
346 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchExtension) {
347 const Extension* extension =
348 InstallExtension(GetTestPath(kExtensionTestPath), 1);
349 ASSERT_TRUE(extension);
350 RunLaunchTest(extension->id(),
351 EphemeralAppLauncher::LAUNCH_UNSUPPORTED_EXTENSION_TYPE,
352 false);
353 }
354
355 // Verifies that the EphemeralAppLauncher handles non-existent extension ids.
356 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, NonExistentExtensionId) {
357 RunLaunchTest(
358 kNonExistentId, EphemeralAppLauncher::LAUNCH_INSTALL_ERROR, false);
359 EXPECT_FALSE(GetInstalledExtension(kNonExistentId));
360 }
361
362 // Verifies that an app blocked by management policy is not installed
363 // ephemerally.
364 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, BlockedByPolicy) {
365 // Register a provider that blocks the installation of all apps.
366 ManagementPolicyMock policy;
367 ExtensionSystem::Get(profile())->management_policy()->RegisterProvider(
368 &policy);
369
370 RunLaunchTest(
371 kDefaultAppId, EphemeralAppLauncher::LAUNCH_BLOCKED_BY_POLICY, false);
372 EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
373 }
374
375 // Verifies that an app blacklisted for malware is not installed ephemerally.
376 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, BlacklistedForMalware) {
377 // Mock a BLACKLISTED_MALWARE return status.
378 extensions::TestBlacklist blacklist_tester(
379 ExtensionSystem::Get(profile())->blacklist());
380 blacklist_tester.SetBlacklistState(
381 kDefaultAppId, extensions::BLACKLISTED_MALWARE, false);
382
383 RunLaunchTest(kDefaultAppId, EphemeralAppLauncher::LAUNCH_BLACKLISTED, false);
384 EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
385 }
386
387 // Verifies that an app with unknown blacklist status is installed ephemerally
388 // and launched.
389 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, BlacklistStateUnknown) {
390 // Mock a BLACKLISTED_MALWARE return status.
391 extensions::TestBlacklist blacklist_tester(
392 ExtensionSystem::Get(profile())->blacklist());
393 blacklist_tester.SetBlacklistState(
394 kDefaultAppId, extensions::BLACKLISTED_UNKNOWN, false);
395
396 RunLaunchTest(kDefaultAppId, EphemeralAppLauncher::LAUNCH_SUCCESS, true);
397 ValidateAppInstalledEphemerally(kDefaultAppId);
398 }
399
400 // Verifies that an app with unsupported requirements is not installed
401 // ephemerally.
402 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, UnsupportedRequirements) {
403 scoped_refptr<EphemeralAppLauncherForTest> launcher(
404 new EphemeralAppLauncherForTest(kDefaultAppId, profile()));
405 launcher->set_requirements_error("App has unsupported requirements");
406
407 StartLauncherAndCheckResult(
408 launcher.get(), EphemeralAppLauncher::LAUNCH_MISSING_DEPENDENCIES, false);
409 EXPECT_FALSE(GetInstalledExtension(kDefaultAppId));
410 }
411
412 // Verifies that an app disabled due to permissions increase can be enabled
413 // and launched.
414 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, EnableAndLaunchApp) {
415 const Extension* app = InstallAndDisableApp(
416 kDefaultAppTestPath, Extension::DISABLE_PERMISSIONS_INCREASE);
417 ASSERT_TRUE(app);
418
419 AutoAcceptInstall();
420 RunLaunchTest(app->id(), EphemeralAppLauncher::LAUNCH_SUCCESS, false);
421 }
422
423 // Verifies that if the user cancels the enable flow, the app will not be
424 // enabled and launched.
425 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, EnableCancelled) {
426 const Extension* app = InstallAndDisableApp(
427 kDefaultAppTestPath, Extension::DISABLE_PERMISSIONS_INCREASE);
428 ASSERT_TRUE(app);
429
430 AutoCancelInstall();
431 RunLaunchTest(app->id(), EphemeralAppLauncher::LAUNCH_USER_CANCELLED, false);
432 }
433
434 // Verifies that an installed app that had been blocked by policy cannot be
435 // launched.
436 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchAppBlockedByPolicy) {
437 const Extension* app = InstallExtension(GetTestPath(kDefaultAppTestPath), 1);
438 ASSERT_TRUE(app);
439
440 // Simulate blocking of the app after it has been installed.
441 ManagementPolicyMock policy;
442 ExtensionSystem::Get(profile())->management_policy()->RegisterProvider(
443 &policy);
444 ExtensionSystem::Get(profile())->extension_service()->CheckManagementPolicy();
445
446 RunLaunchTest(
447 app->id(), EphemeralAppLauncher::LAUNCH_BLOCKED_BY_POLICY, false);
448 }
449
450 // Verifies that an installed blacklisted app cannot be launched.
451 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest, LaunchBlacklistedApp) {
452 const Extension* app =
453 InstallAndDisableApp(kDefaultAppTestPath, Extension::DISABLE_GREYLIST);
454 ASSERT_TRUE(app);
455
456 RunLaunchTest(app->id(), EphemeralAppLauncher::LAUNCH_BLACKLISTED, false);
457 }
458
459 // Verifies that an installed app with unsupported requirements cannot be
460 // launched.
461 IN_PROC_BROWSER_TEST_F(EphemeralAppLauncherTest,
462 LaunchAppWithUnsupportedRequirements) {
463 const Extension* app = InstallAndDisableApp(
464 kDefaultAppTestPath, Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
465 ASSERT_TRUE(app);
466
467 RunLaunchTest(
468 app->id(), EphemeralAppLauncher::LAUNCH_MISSING_DEPENDENCIES, false);
469 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698