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

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

Powered by Google App Engine
This is Rietveld 408576698