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

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

Issue 1497193002: Remove all the ephemeral apps code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Self review, Devlin review. Created 5 years 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 "chrome/browser/apps/ephemeral_app_browsertest.h"
6
7 #include <vector>
8
9 #include "apps/app_restore_service.h"
10 #include "apps/saved_files_service.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/scoped_observer.h"
13 #include "base/stl_util.h"
14 #include "chrome/browser/apps/app_browsertest_util.h"
15 #include "chrome/browser/apps/ephemeral_app_service.h"
16 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_sync_data.h"
19 #include "chrome/browser/extensions/extension_sync_service.h"
20 #include "chrome/browser/extensions/extension_util.h"
21 #include "chrome/browser/notifications/notifier_state_tracker.h"
22 #include "chrome/browser/notifications/notifier_state_tracker_factory.h"
23 #include "content/public/browser/power_save_blocker.h"
24 #include "content/public/test/browser_test.h"
25 #include "content/public/test/test_utils.h"
26 #include "extensions/browser/api/power/power_api.h"
27 #include "extensions/browser/app_sorting.h"
28 #include "extensions/browser/event_router.h"
29 #include "extensions/browser/extension_prefs.h"
30 #include "extensions/browser/extension_registry.h"
31 #include "extensions/browser/extension_registry_observer.h"
32 #include "extensions/browser/extension_system.h"
33 #include "extensions/browser/extension_util.h"
34 #include "extensions/browser/process_manager.h"
35 #include "extensions/browser/test_extension_registry_observer.h"
36 #include "extensions/browser/uninstall_reason.h"
37 #include "extensions/common/api/alarms.h"
38 #include "extensions/common/extension.h"
39 #include "extensions/test/extension_test_message_listener.h"
40 #include "extensions/test/result_catcher.h"
41 #include "sync/api/fake_sync_change_processor.h"
42 #include "sync/api/sync_change_processor_wrapper_for_test.h"
43 #include "sync/api/sync_error_factory_mock.h"
44 #include "ui/app_list/app_list_switches.h"
45 #include "ui/message_center/message_center.h"
46 #include "ui/message_center/notifier_settings.h"
47
48 using extensions::AppSorting;
49 using extensions::Event;
50 using extensions::EventRouter;
51 using extensions::Extension;
52 using extensions::ExtensionPrefs;
53 using extensions::ExtensionRegistry;
54 using extensions::ExtensionRegistryObserver;
55 using extensions::ExtensionSyncData;
56 using extensions::ExtensionSystem;
57 using extensions::Manifest;
58 using extensions::ResultCatcher;
59
60 namespace {
61
62 namespace alarms = extensions::api::alarms;
63
64 const char kPowerTestApp[] = "ephemeral_apps/power";
65
66 // Enabling sync causes these tests to be flaky on Windows. Disable sync so that
67 // everything else can be tested. See crbug.com/401028
68 #if defined(OS_WIN)
69 const bool kEnableSync = false;
70 #else
71 const bool kEnableSync = true;
72 #endif
73
74 typedef std::vector<message_center::Notifier*> NotifierList;
75
76 bool IsNotifierInList(const message_center::NotifierId& notifier_id,
77 const NotifierList& notifiers) {
78 for (NotifierList::const_iterator it = notifiers.begin();
79 it != notifiers.end(); ++it) {
80 const message_center::Notifier* notifier = *it;
81 if (notifier->notifier_id == notifier_id)
82 return true;
83 }
84
85 return false;
86 }
87
88 // Saves some parameters from the extension installed notification in order
89 // to verify them in tests.
90 class InstallObserver : public ExtensionRegistryObserver {
91 public:
92 struct InstallParameters {
93 std::string id;
94 bool is_update;
95 bool from_ephemeral;
96
97 InstallParameters(
98 const std::string& id,
99 bool is_update,
100 bool from_ephemeral)
101 : id(id), is_update(is_update), from_ephemeral(from_ephemeral) {}
102 };
103
104 explicit InstallObserver(Profile* profile) : registry_observer_(this) {
105 registry_observer_.Add(ExtensionRegistry::Get(profile));
106 }
107
108 ~InstallObserver() override {}
109
110 const InstallParameters& Last() {
111 CHECK(!install_params_.empty());
112 return install_params_.back();
113 }
114
115 private:
116 void OnExtensionWillBeInstalled(content::BrowserContext* browser_context,
117 const Extension* extension,
118 bool is_update,
119 bool from_ephemeral,
120 const std::string& old_name) override {
121 install_params_.push_back(
122 InstallParameters(extension->id(), is_update, from_ephemeral));
123 }
124
125 std::vector<InstallParameters> install_params_;
126 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
127 registry_observer_;
128 };
129
130 // Instead of actually changing the system power settings, tests will just
131 // issue requests to this mock.
132 class PowerSettingsMock {
133 public:
134 PowerSettingsMock() : keep_awake_count_(0) {}
135
136 void request_keep_awake() { ++keep_awake_count_; }
137
138 void release_keep_awake() {
139 --keep_awake_count_;
140 ASSERT_GE(keep_awake_count_, 0);
141 }
142
143 int keep_awake_count() const { return keep_awake_count_; }
144
145 private:
146 int keep_awake_count_;
147
148 DISALLOW_COPY_AND_ASSIGN(PowerSettingsMock);
149 };
150
151 // Stub implementation of content::PowerSaveBlocker that updates the
152 // PowerSettingsMock.
153 class PowerSaveBlockerStub : public content::PowerSaveBlocker {
154 public:
155 explicit PowerSaveBlockerStub(PowerSettingsMock* power_settings)
156 : power_settings_(power_settings) {
157 power_settings_->request_keep_awake();
158 }
159
160 ~PowerSaveBlockerStub() override { power_settings_->release_keep_awake(); }
161
162 static scoped_ptr<PowerSaveBlocker> Create(PowerSettingsMock* power_settings,
163 PowerSaveBlockerType type,
164 Reason reason,
165 const std::string& description) {
166 return scoped_ptr<PowerSaveBlocker>(
167 new PowerSaveBlockerStub(power_settings));
168 }
169
170 private:
171 PowerSettingsMock* power_settings_; // Not owned.
172
173 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub);
174 };
175
176 } // namespace
177
178
179 // EphemeralAppTestBase:
180
181 const char EphemeralAppTestBase::kMessagingReceiverApp[] =
182 "ephemeral_apps/messaging_receiver";
183 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] =
184 "ephemeral_apps/messaging_receiver2";
185 const char EphemeralAppTestBase::kDispatchEventTestApp[] =
186 "ephemeral_apps/dispatch_event";
187 const char EphemeralAppTestBase::kNotificationsTestApp[] =
188 "ephemeral_apps/notification_settings";
189 const char EphemeralAppTestBase::kFileSystemTestApp[] =
190 "ephemeral_apps/filesystem_retain_entries";
191
192 EphemeralAppTestBase::EphemeralAppTestBase() {}
193
194 EphemeralAppTestBase::~EphemeralAppTestBase() {}
195
196 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) {
197 // Skip PlatformAppBrowserTest, which sets different values for the switches
198 // below.
199 ExtensionBrowserTest::SetUpCommandLine(command_line);
200
201 // Make event pages get suspended immediately.
202 extensions::ProcessManager::SetEventPageIdleTimeForTesting(1);
203 extensions::ProcessManager::SetEventPageSuspendingTimeForTesting(1);
204
205 // Enable ephemeral apps, which are gated by the experimental app launcher
206 // flag.
207 command_line->AppendSwitch(app_list::switches::kEnableExperimentalAppList);
208 }
209
210 void EphemeralAppTestBase::SetUpOnMainThread() {
211 PlatformAppBrowserTest::SetUpOnMainThread();
212
213 // Disable ephemeral apps immediately after they stop running in tests.
214 EphemeralAppService::Get(profile())->set_disable_delay_for_test(0);
215 }
216
217 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) {
218 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path);
219 }
220
221 const Extension* EphemeralAppTestBase::InstallEphemeralApp(
222 const char* test_path, Manifest::Location manifest_location) {
223 const Extension* extension = InstallEphemeralAppWithSourceAndFlags(
224 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS);
225 EXPECT_TRUE(extension);
226 if (extension)
227 EXPECT_TRUE(extensions::util::IsEphemeralApp(extension->id(), profile()));
228 return extension;
229 }
230
231 const Extension* EphemeralAppTestBase::InstallEphemeralApp(
232 const char* test_path) {
233 return InstallEphemeralApp(test_path, Manifest::INTERNAL);
234 }
235
236 const Extension* EphemeralAppTestBase::InstallAndLaunchEphemeralApp(
237 const char* test_path) {
238 ExtensionTestMessageListener launched_listener("launched", false);
239 const Extension* extension = InstallEphemeralApp(test_path);
240 EXPECT_TRUE(extension);
241 if (!extension)
242 return NULL;
243
244 LaunchPlatformApp(extension);
245 bool wait_result = launched_listener.WaitUntilSatisfied();
246 EXPECT_TRUE(wait_result);
247 if (!wait_result)
248 return NULL;
249
250 return extension;
251 }
252
253 const Extension* EphemeralAppTestBase::UpdateEphemeralApp(
254 const std::string& app_id,
255 const base::FilePath& test_dir,
256 const base::FilePath& pem_path) {
257 // Pack a new version of the app.
258 base::ScopedTempDir temp_dir;
259 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
260
261 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx");
262 if (!base::DeleteFile(crx_path, false)) {
263 ADD_FAILURE() << "Failed to delete existing crx: " << crx_path.value();
264 return NULL;
265 }
266
267 base::FilePath app_v2_path = PackExtensionWithOptions(
268 test_dir, crx_path, pem_path, base::FilePath());
269 EXPECT_FALSE(app_v2_path.empty());
270
271 // Update the ephemeral app and wait for the update to finish.
272 extensions::CrxInstaller* crx_installer = NULL;
273 content::WindowedNotificationObserver windowed_observer(
274 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
275 content::Source<extensions::CrxInstaller>(crx_installer));
276 ExtensionService* service =
277 ExtensionSystem::Get(profile())->extension_service();
278 EXPECT_TRUE(service->UpdateExtension(
279 extensions::CRXFileInfo(app_id, app_v2_path), true, &crx_installer));
280 windowed_observer.Wait();
281
282 return ExtensionRegistry::Get(profile())
283 ->GetExtensionById(app_id, ExtensionRegistry::EVERYTHING);
284 }
285
286 void EphemeralAppTestBase::PromoteEphemeralApp(
287 const extensions::Extension* app) {
288 ExtensionService* extension_service =
289 ExtensionSystem::Get(profile())->extension_service();
290 ASSERT_TRUE(extension_service);
291 extension_service->PromoteEphemeralApp(app, false);
292 }
293
294 void EphemeralAppTestBase::DisableEphemeralApp(
295 const Extension* app,
296 Extension::DisableReason disable_reason) {
297 ExtensionSystem::Get(profile())->extension_service()->DisableExtension(
298 app->id(), disable_reason);
299
300 ASSERT_TRUE(ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
301 app->id()));
302 }
303
304 void EphemeralAppTestBase::CloseApp(const std::string& app_id) {
305 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id));
306 extensions::AppWindow* app_window = GetFirstAppWindowForApp(app_id);
307 ASSERT_TRUE(app_window);
308 CloseAppWindow(app_window);
309 }
310
311 void EphemeralAppTestBase::CloseAppWaitForUnload(const std::string& app_id) {
312 // Ephemeral apps are unloaded from extension system after they stop running.
313 extensions::TestExtensionRegistryObserver observer(
314 ExtensionRegistry::Get(profile()), app_id);
315 CloseApp(app_id);
316 observer.WaitForExtensionUnloaded();
317 }
318
319 void EphemeralAppTestBase::EvictApp(const std::string& app_id) {
320 // Uninstall the app, which is what happens when ephemeral apps get evicted
321 // from the cache.
322 extensions::TestExtensionRegistryObserver observer(
323 ExtensionRegistry::Get(profile()), app_id);
324
325 ExtensionService* service =
326 ExtensionSystem::Get(profile())->extension_service();
327 ASSERT_TRUE(service);
328 service->UninstallExtension(
329 app_id,
330 extensions::UNINSTALL_REASON_ORPHANED_EPHEMERAL_EXTENSION,
331 base::Bind(&base::DoNothing),
332 NULL);
333
334 observer.WaitForExtensionUninstalled();
335 }
336
337 // EphemeralAppBrowserTest:
338
339 class EphemeralAppBrowserTest : public EphemeralAppTestBase {
340 protected:
341 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) {
342 // Ephemeral apps are unloaded after they are closed. Ensure they are
343 // enabled before launch.
344 ExtensionService* service =
345 ExtensionSystem::Get(profile())->extension_service();
346 service->EnableExtension(app->id());
347
348 ExtensionTestMessageListener launched_listener("launched", true);
349 LaunchPlatformApp(app);
350 if (!launched_listener.WaitUntilSatisfied()) {
351 message_ = "Failed to receive launched message from test";
352 return false;
353 }
354
355 ResultCatcher catcher;
356 launched_listener.Reply(test_name);
357
358 bool result = catcher.GetNextResult();
359 message_ = catcher.message();
360
361 CloseAppWaitForUnload(app->id());
362 return result;
363 }
364
365 // Verify that the event page of the app has not been loaded.
366 void VerifyAppNotLoaded(const std::string& app_id) {
367 EXPECT_FALSE(extensions::ProcessManager::Get(profile())
368 ->GetBackgroundHostForExtension(app_id));
369 }
370
371 // Verify properties of ephemeral apps.
372 void VerifyEphemeralApp(const std::string& app_id) {
373 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_id, profile()));
374
375 // Ephemeral apps should not be synced.
376 scoped_ptr<ExtensionSyncData> sync_change = GetLastSyncChangeForApp(app_id);
377 EXPECT_FALSE(sync_change.get());
378
379 // Ephemeral apps should not be assigned ordinals.
380 AppSorting* app_sorting = ExtensionSystem::Get(profile())->app_sorting();
381 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid());
382 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_id).IsValid());
383 }
384
385 // Verify that after ephemeral apps stop running, they reside in extension
386 // system in a disabled and unloaded state.
387 void VerifyInactiveEphemeralApp(const std::string& app_id) {
388 EXPECT_TRUE(
389 ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
390 app_id));
391
392 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
393 EXPECT_TRUE(prefs->IsExtensionDisabled(app_id));
394 EXPECT_NE(0,
395 prefs->GetDisableReasons(app_id) &
396 Extension::DISABLE_INACTIVE_EPHEMERAL_APP);
397 }
398
399 // Verify the state of an app that has been promoted from an ephemeral to a
400 // fully installed app.
401 void VerifyPromotedApp(const std::string& app_id,
402 ExtensionRegistry::IncludeFlag expected_set) {
403 const Extension* app = ExtensionRegistry::Get(profile())
404 ->GetExtensionById(app_id, expected_set);
405 ASSERT_TRUE(app) << "App not found in expected set: " << expected_set;
406
407 // The app should not be ephemeral.
408 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
409 ASSERT_TRUE(prefs);
410 EXPECT_FALSE(prefs->IsEphemeralApp(app_id));
411 EXPECT_EQ(0,
412 prefs->GetDisableReasons(app_id) &
413 Extension::DISABLE_INACTIVE_EPHEMERAL_APP);
414
415 // Check sort ordinals.
416 AppSorting* app_sorting = ExtensionSystem::Get(profile())->app_sorting();
417 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid());
418 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid());
419 }
420
421 // Dispatch a fake alarm event to the app.
422 void DispatchAlarmEvent(EventRouter* event_router,
423 const std::string& app_id) {
424 alarms::Alarm dummy_alarm;
425 dummy_alarm.name = "test_alarm";
426
427 scoped_ptr<base::ListValue> args(new base::ListValue());
428 args->Append(dummy_alarm.ToValue().release());
429 scoped_ptr<Event> event(new Event(extensions::events::ALARMS_ON_ALARM,
430 alarms::OnAlarm::kEventName,
431 args.Pass()));
432
433 event_router->DispatchEventToExtension(app_id, event.Pass());
434 }
435
436 // Simulates the scenario where an app is installed, via the normal
437 // installation route, on top of an ephemeral app. This can occur due to race
438 // conditions.
439 const Extension* ReplaceEphemeralApp(const std::string& app_id,
440 const char* test_path,
441 int expected_enabled_change) {
442 return UpdateExtensionWaitForIdle(
443 app_id, GetTestPath(test_path), expected_enabled_change);
444 }
445
446 void PromoteEphemeralAppAndVerify(
447 const Extension* app,
448 ExtensionRegistry::IncludeFlag expected_set,
449 bool expect_sync_enabled) {
450 ASSERT_TRUE(app);
451
452 // Ephemeral apps should not be synced.
453 scoped_ptr<ExtensionSyncData> sync_change =
454 GetLastSyncChangeForApp(app->id());
455 EXPECT_FALSE(sync_change.get());
456
457 // Promote the app to a regular installed app.
458 InstallObserver installed_observer(profile());
459 PromoteEphemeralApp(app);
460 VerifyPromotedApp(app->id(), expected_set);
461
462 // Check the notification parameters.
463 const InstallObserver::InstallParameters& params =
464 installed_observer.Last();
465 EXPECT_EQ(app->id(), params.id);
466 EXPECT_TRUE(params.is_update);
467 EXPECT_TRUE(params.from_ephemeral);
468
469 // The installation should now be synced.
470 sync_change = GetLastSyncChangeForApp(app->id());
471 VerifySyncChange(sync_change.get(), expect_sync_enabled);
472 }
473
474 void PromoteEphemeralAppAndVerify(
475 const Extension* app,
476 ExtensionRegistry::IncludeFlag expected_set) {
477 PromoteEphemeralAppAndVerify(app, expected_set,
478 expected_set == ExtensionRegistry::ENABLED);
479 }
480
481 void PromoteEphemeralAppFromSyncAndVerify(
482 const Extension* app,
483 bool enable_from_sync,
484 ExtensionRegistry::IncludeFlag expected_set) {
485 ASSERT_TRUE(app);
486
487 // Simulate an install from sync.
488 int disable_reasons = enable_from_sync ? 0 : Extension::DISABLE_USER_ACTION;
489 const syncer::StringOrdinal kAppLaunchOrdinal("x");
490 const syncer::StringOrdinal kPageOrdinal("y");
491 ExtensionSyncData app_sync_data(
492 *app,
493 enable_from_sync,
494 disable_reasons,
495 false /* incognito enabled */,
496 false /* remote install */,
497 extensions::ExtensionSyncData::BOOLEAN_UNSET,
498 kAppLaunchOrdinal,
499 kPageOrdinal,
500 extensions::LAUNCH_TYPE_REGULAR);
501
502 std::string app_id = app->id();
503 app = NULL;
504
505 ExtensionSyncService::Get(profile())->ProcessSyncChanges(
506 FROM_HERE,
507 syncer::SyncChangeList(
508 1, app_sync_data.GetSyncChange(syncer::SyncChange::ACTION_ADD)));
509
510 // Verify the installation.
511 VerifyPromotedApp(app_id, expected_set);
512
513 // The sort ordinals from sync should not be overridden.
514 AppSorting* app_sorting = ExtensionSystem::Get(profile())->app_sorting();
515 EXPECT_TRUE(
516 app_sorting->GetAppLaunchOrdinal(app_id).Equals(kAppLaunchOrdinal));
517 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal));
518 }
519
520 void InitSyncService() {
521 if (!kEnableSync)
522 return;
523
524 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile());
525 sync_service->MergeDataAndStartSyncing(
526 syncer::APPS,
527 syncer::SyncDataList(),
528 scoped_ptr<syncer::SyncChangeProcessor>(
529 new syncer::SyncChangeProcessorWrapperForTest(
530 &mock_sync_processor_)),
531 scoped_ptr<syncer::SyncErrorFactory>(
532 new syncer::SyncErrorFactoryMock()));
533 }
534
535 scoped_ptr<ExtensionSyncData> GetLastSyncChangeForApp(const std::string& id) {
536 scoped_ptr<ExtensionSyncData> sync_data;
537 for (syncer::SyncChangeList::iterator it =
538 mock_sync_processor_.changes().begin();
539 it != mock_sync_processor_.changes().end(); ++it) {
540 scoped_ptr<ExtensionSyncData> data(
541 ExtensionSyncData::CreateFromSyncChange(*it));
542 if (data.get() && data->id() == id)
543 sync_data.reset(data.release());
544 }
545
546 return sync_data.Pass();
547 }
548
549 void VerifySyncChange(const ExtensionSyncData* sync_change,
550 bool expect_enabled) {
551 if (!kEnableSync)
552 return;
553
554 ASSERT_TRUE(sync_change);
555 EXPECT_TRUE(sync_change->page_ordinal().IsValid());
556 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid());
557 EXPECT_FALSE(sync_change->uninstalled());
558 EXPECT_EQ(expect_enabled, sync_change->enabled());
559 }
560
561 void TestInstallEvent(bool close_app) {
562 ExtensionTestMessageListener first_msg_listener(false);
563 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
564 ASSERT_TRUE(app);
565
566 // When an ephemeral app is first added, it should not receive the
567 // onInstalled event, hence the first message received from the test should
568 // be "launched" and not "installed".
569 ASSERT_TRUE(first_msg_listener.WaitUntilSatisfied());
570 EXPECT_EQ(std::string("launched"), first_msg_listener.message());
571
572 if (close_app)
573 CloseAppWaitForUnload(app->id());
574
575 // When installed permanently, the app should receive the onInstalled event.
576 ExtensionTestMessageListener install_listener("installed", false);
577 PromoteEphemeralApp(app);
578 ASSERT_TRUE(install_listener.WaitUntilSatisfied());
579 }
580
581 private:
582 syncer::FakeSyncChangeProcessor mock_sync_processor_;
583 };
584
585 // Verify that ephemeral apps can be launched and receive system events when
586 // they are running. Once they are inactive they should not receive system
587 // events.
588 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) {
589 const Extension* extension =
590 InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
591 ASSERT_TRUE(extension);
592
593 // Send a fake alarm event to the app and verify that a response is
594 // received.
595 EventRouter* event_router = EventRouter::Get(profile());
596 ASSERT_TRUE(event_router);
597
598 ExtensionTestMessageListener alarm_received_listener("alarm_received", false);
599 DispatchAlarmEvent(event_router, extension->id());
600 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied());
601
602 CloseAppWaitForUnload(extension->id());
603
604 // Dispatch the alarm event again and verify that the event page did not get
605 // loaded for the app.
606 DispatchAlarmEvent(event_router, extension->id());
607 VerifyAppNotLoaded(extension->id());
608 }
609
610 // Verify that ephemeral apps will receive messages while they are running.
611 // Flaky test: crbug.com/394426
612 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
613 DISABLED_ReceiveMessagesWhenLaunched) {
614 const Extension* receiver =
615 InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
616 ASSERT_TRUE(receiver);
617
618 // Verify that messages are received while the app is running.
619 ResultCatcher result_catcher;
620 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success",
621 "Launched");
622 EXPECT_TRUE(result_catcher.GetNextResult());
623
624 CloseAppWaitForUnload(receiver->id());
625
626 // Verify that messages are not received while the app is inactive.
627 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail", "Launched");
628 EXPECT_TRUE(result_catcher.GetNextResult());
629 }
630
631 // Verifies that the chrome.runtime.onInstalled() event is received by a running
632 // ephemeral app only when it is promoted.
633 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
634 InstallEventReceivedWhileRunning) {
635 TestInstallEvent(false /* close app */);
636 }
637
638 // Verifies that when an idle ephemeral app is promoted, it will be loaded to
639 // receive the chrome.runtime.onInstalled() event.
640 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEventReceivedWhileIdle) {
641 TestInstallEvent(true /* close app */);
642 }
643
644 // Verifies that the chrome.runtime.onRestarted() event is received by an
645 // ephemeral app.
646 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RestartEventReceived) {
647 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
648 ASSERT_TRUE(app);
649 CloseAppWaitForUnload(app->id());
650
651 // Fake ephemeral app running before restart.
652 ExtensionSystem::Get(profile())->extension_service()->EnableExtension(
653 app->id());
654 ASSERT_TRUE(ExtensionRegistry::Get(profile())->enabled_extensions().Contains(
655 app->id()));
656 ExtensionPrefs::Get(profile())->SetExtensionRunning(app->id(), true);
657
658 ExtensionTestMessageListener restart_listener("restarted", false);
659 apps::AppRestoreService::Get(profile())->HandleStartup(true);
660 EXPECT_TRUE(restart_listener.WaitUntilSatisfied());
661 }
662
663 // Verify that an updated ephemeral app will still have its ephemeral flag
664 // enabled.
665 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) {
666 InitSyncService();
667
668 const Extension* app_v1 = InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
669 ASSERT_TRUE(app_v1);
670 VerifyEphemeralApp(app_v1->id());
671 CloseAppWaitForUnload(app_v1->id());
672 VerifyInactiveEphemeralApp(app_v1->id());
673
674 std::string app_id = app_v1->id();
675 base::Version app_original_version = *app_v1->version();
676
677 // Update to version 2 of the app.
678 app_v1 = NULL; // The extension object will be destroyed during update.
679 InstallObserver installed_observer(profile());
680 const Extension* app_v2 =
681 UpdateEphemeralApp(app_id,
682 GetTestPath(kMessagingReceiverAppV2),
683 GetTestPath(kMessagingReceiverApp)
684 .ReplaceExtension(FILE_PATH_LITERAL(".pem")));
685
686 // Check the notification parameters.
687 const InstallObserver::InstallParameters& params = installed_observer.Last();
688 EXPECT_EQ(app_id, params.id);
689 EXPECT_TRUE(params.is_update);
690 EXPECT_FALSE(params.from_ephemeral);
691
692 // The ephemeral flag should still be set.
693 ASSERT_TRUE(app_v2);
694 EXPECT_GT(app_v2->version()->CompareTo(app_original_version), 0);
695 VerifyEphemeralApp(app_id);
696
697 // The app should still be disabled in extension system.
698 VerifyInactiveEphemeralApp(app_id);
699 }
700
701 // Verify that if notifications have been disabled for an ephemeral app, it will
702 // remain disabled even after being evicted from the cache.
703 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) {
704 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
705 ASSERT_TRUE(app);
706
707 // Disable notifications for this app.
708 NotifierStateTracker* notifier_state_tracker =
709 NotifierStateTrackerFactory::GetForProfile(profile());
710 ASSERT_TRUE(notifier_state_tracker);
711
712 message_center::NotifierId notifier_id(
713 message_center::NotifierId::APPLICATION, app->id());
714 EXPECT_TRUE(notifier_state_tracker->IsNotifierEnabled(notifier_id));
715 notifier_state_tracker->SetNotifierEnabled(notifier_id, false);
716 EXPECT_FALSE(notifier_state_tracker->IsNotifierEnabled(notifier_id));
717
718 // Remove the app.
719 CloseAppWaitForUnload(app->id());
720 EvictApp(app->id());
721
722 // Reinstall the ephemeral app and verify that notifications remain disabled.
723 app = InstallEphemeralApp(kNotificationsTestApp);
724 ASSERT_TRUE(app);
725 message_center::NotifierId reinstalled_notifier_id(
726 message_center::NotifierId::APPLICATION, app->id());
727 EXPECT_FALSE(notifier_state_tracker->IsNotifierEnabled(
728 reinstalled_notifier_id));
729 }
730
731 // Verify that only running ephemeral apps will appear in the Notification
732 // Settings UI. Inactive, cached ephemeral apps should not appear.
733 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
734 IncludeRunningEphemeralAppsInNotifiers) {
735 message_center::NotifierSettingsProvider* settings_provider =
736 message_center::MessageCenter::Get()->GetNotifierSettingsProvider();
737 DCHECK(settings_provider);
738
739 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
740 ASSERT_TRUE(app);
741 message_center::NotifierId notifier_id(
742 message_center::NotifierId::APPLICATION, app->id());
743
744 // Since the ephemeral app is running, it should be included in the list
745 // of notifiers to show in the UI.
746 NotifierList notifiers;
747 STLElementDeleter<NotifierList> notifier_deleter(&notifiers);
748
749 settings_provider->GetNotifierList(&notifiers);
750 EXPECT_TRUE(IsNotifierInList(notifier_id, notifiers));
751 STLDeleteElements(&notifiers);
752
753 // Close the ephemeral app.
754 CloseAppWaitForUnload(app->id());
755
756 // Inactive ephemeral apps should not be included in the list of notifiers to
757 // show in the UI.
758 settings_provider->GetNotifierList(&notifiers);
759 EXPECT_FALSE(IsNotifierInList(notifier_id, notifiers));
760 }
761
762 // Verify that ephemeral apps will have no ability to retain file entries after
763 // close. Normal retainEntry behavior for installed apps is tested in
764 // FileSystemApiTest.
765 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
766 DisableRetainFileSystemEntries) {
767 // Create a dummy file that we can just return to the test.
768 base::ScopedTempDir temp_dir;
769 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
770 base::FilePath temp_file;
771 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file));
772
773 using extensions::FileSystemChooseEntryFunction;
774 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
775 &temp_file);
776 // The temporary file needs to be registered for the tests to pass on
777 // ChromeOS.
778 FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
779 "temp", temp_dir.path());
780
781 // The first test opens the file and writes the file handle to local storage.
782 const Extension* app = InstallEphemeralApp(kFileSystemTestApp,
783 Manifest::UNPACKED);
784 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_;
785
786 // Verify that after the app has been closed, all retained entries are
787 // flushed.
788 std::vector<apps::SavedFileEntry> file_entries =
789 apps::SavedFilesService::Get(profile())
790 ->GetAllFileEntries(app->id());
791 EXPECT_TRUE(file_entries.empty());
792
793 // The second test verifies that the file cannot be reopened.
794 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_;
795 }
796
797 // Checks the process of launching an ephemeral app and then promoting the app
798 // while it is running.
799 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileRunning) {
800 InitSyncService();
801
802 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
803 ASSERT_TRUE(app);
804
805 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
806
807 // Ensure that the app is not unloaded and disabled after it is closed.
808 CloseApp(app->id());
809 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED);
810 }
811
812 // Checks the process of launching an ephemeral app and then promoting the app
813 // while it is idle.
814 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileIdle) {
815 InitSyncService();
816
817 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
818 ASSERT_TRUE(app);
819 CloseAppWaitForUnload(app->id());
820 VerifyInactiveEphemeralApp(app->id());
821
822 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
823 }
824
825 // Verifies that promoting an ephemeral app that was disabled due to a
826 // permissions increase will enable it.
827 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppAndGrantPermissions) {
828 InitSyncService();
829
830 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
831 ASSERT_TRUE(app);
832 CloseAppWaitForUnload(app->id());
833 DisableEphemeralApp(app, Extension::DISABLE_PERMISSIONS_INCREASE);
834
835 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
836 EXPECT_FALSE(ExtensionPrefs::Get(profile())
837 ->DidExtensionEscalatePermissions(app->id()));
838 }
839
840 // Verifies that promoting an ephemeral app that has unsupported requirements
841 // will not enable it.
842 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
843 PromoteUnsupportedEphemeralApp) {
844 InitSyncService();
845
846 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
847 ASSERT_TRUE(app);
848 CloseAppWaitForUnload(app->id());
849 DisableEphemeralApp(app, Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
850
851 // When promoted to a regular installed app, it should remain disabled.
852 // However, DISABLE_UNSUPPORTED_REQUIREMENT is not a syncable disable reason,
853 // so sync should still say "enabled".
854 bool expect_sync_enabled = true;
855 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::DISABLED,
856 expect_sync_enabled);
857 }
858
859 // Verifies that promoting an ephemeral app that is blacklisted will not enable
860 // it.
861 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
862 PromoteBlacklistedEphemeralApp) {
863 InitSyncService();
864
865 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
866 ASSERT_TRUE(app);
867 CloseAppWaitForUnload(app->id());
868
869 ExtensionService* service =
870 ExtensionSystem::Get(profile())->extension_service();
871 service->BlacklistExtensionForTest(app->id());
872 ASSERT_TRUE(
873 ExtensionRegistry::Get(profile())->blacklisted_extensions().Contains(
874 app->id()));
875
876 // When promoted to a regular installed app, it should remain blacklisted.
877 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::BLACKLISTED);
878
879 // The app should be synced, but disabled.
880 scoped_ptr<ExtensionSyncData> sync_change =
881 GetLastSyncChangeForApp(app->id());
882 VerifySyncChange(sync_change.get(), false);
883 }
884
885 // Checks the process of promoting an ephemeral app from sync while the app is
886 // running.
887 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
888 PromoteAppFromSyncWhileRunning) {
889 InitSyncService();
890
891 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
892 ASSERT_TRUE(app);
893
894 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED);
895
896 // Ensure that the app is not unloaded and disabled after it is closed.
897 CloseApp(app->id());
898 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED);
899 }
900
901 // Checks the process of promoting an ephemeral app from sync while the app is
902 // idle.
903 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppFromSyncWhileIdle) {
904 InitSyncService();
905
906 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
907 ASSERT_TRUE(app);
908 CloseAppWaitForUnload(app->id());
909 VerifyInactiveEphemeralApp(app->id());
910
911 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED);
912 }
913
914 // Checks the process of promoting an ephemeral app from sync, where the app
915 // from sync is disabled, and the ephemeral app is running.
916 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
917 PromoteDisabledAppFromSyncWhileRunning) {
918 InitSyncService();
919
920 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
921 ASSERT_TRUE(app);
922
923 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED);
924 }
925
926 // Checks the process of promoting an ephemeral app from sync, where the app
927 // from sync is disabled, and the ephemeral app is idle.
928 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
929 PromoteDisabledAppFromSyncWhileIdle) {
930 InitSyncService();
931
932 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
933 ASSERT_TRUE(app);
934 CloseAppWaitForUnload(app->id());
935 VerifyInactiveEphemeralApp(app->id());
936
937 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED);
938 }
939
940 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to
941 // permanently install an ephemeral app. However, there may be cases where an
942 // install occurs through the usual route of installing from the Web Store (due
943 // to race conditions). Ensure that the app is still installed correctly.
944 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
945 ReplaceEphemeralAppWithInstalledApp) {
946 InitSyncService();
947
948 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
949 ASSERT_TRUE(app);
950 CloseAppWaitForUnload(app->id());
951 std::string app_id = app->id();
952 app = NULL;
953
954 InstallObserver installed_observer(profile());
955 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 1);
956 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED);
957
958 // Check the notification parameters.
959 const InstallObserver::InstallParameters& params = installed_observer.Last();
960 EXPECT_EQ(app_id, params.id);
961 EXPECT_TRUE(params.is_update);
962 EXPECT_TRUE(params.from_ephemeral);
963 }
964
965 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will
966 // be delayed until the app is idle.
967 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
968 ReplaceEphemeralAppWithDelayedInstalledApp) {
969 InitSyncService();
970 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
971 ASSERT_TRUE(app);
972 std::string app_id = app->id();
973 app = NULL;
974
975 // Initiate install.
976 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 0);
977
978 // The delayed installation will occur when the ephemeral app is closed.
979 extensions::TestExtensionRegistryObserver observer(
980 ExtensionRegistry::Get(profile()), app_id);
981 InstallObserver installed_observer(profile());
982 CloseAppWaitForUnload(app_id);
983 observer.WaitForExtensionWillBeInstalled();
984 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED);
985
986 // Check the notification parameters.
987 const InstallObserver::InstallParameters& params = installed_observer.Last();
988 EXPECT_EQ(app_id, params.id);
989 EXPECT_TRUE(params.is_update);
990 EXPECT_TRUE(params.from_ephemeral);
991 }
992
993 // Verifies that an installed app cannot turn into an ephemeral app as result of
994 // race conditions, i.e. an ephemeral app can be promoted to an installed app,
995 // but not vice versa.
996 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
997 ReplaceInstalledAppWithEphemeralApp) {
998 const Extension* app = InstallPlatformApp(kNotificationsTestApp);
999 ASSERT_TRUE(app);
1000 std::string app_id = app->id();
1001 app = NULL;
1002
1003 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile()));
1004 app =
1005 InstallEphemeralAppWithSourceAndFlags(GetTestPath(kNotificationsTestApp),
1006 0,
1007 Manifest::INTERNAL,
1008 Extension::NO_FLAGS);
1009 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile()));
1010 }
1011
1012 // Ephemerality was previously encoded by the Extension::IS_EPHEMERAL creation
1013 // flag. This was changed to an "ephemeral_app" property. Check that the prefs
1014 // are handled correctly.
1015 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
1016 ExtensionPrefBackcompatibility) {
1017 // Ensure that apps with the old prefs are recognized as ephemeral.
1018 const Extension* app =
1019 InstallExtensionWithSourceAndFlags(GetTestPath(kNotificationsTestApp),
1020 1,
1021 Manifest::INTERNAL,
1022 Extension::IS_EPHEMERAL);
1023 ASSERT_TRUE(app);
1024 EXPECT_TRUE(extensions::util::IsEphemeralApp(app->id(), profile()));
1025
1026 // Ensure that when the app is promoted to an installed app, the bit in the
1027 // creation flags is cleared.
1028 PromoteEphemeralApp(app);
1029 EXPECT_FALSE(extensions::util::IsEphemeralApp(app->id(), profile()));
1030
1031 int creation_flags =
1032 ExtensionPrefs::Get(profile())->GetCreationFlags(app->id());
1033 EXPECT_EQ(0, creation_flags & Extension::IS_EPHEMERAL);
1034 }
1035
1036 // Verifies that the power keep awake will be automatically released for
1037 // ephemeral apps that stop running. Well behaved apps should actually call
1038 // chrome.power.releaseKeepAwake() themselves.
1039 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, ReleasePowerKeepAwake) {
1040 PowerSettingsMock power_settings;
1041 extensions::PowerAPI::Get(profile())->SetCreateBlockerFunctionForTesting(
1042 base::Bind(&PowerSaveBlockerStub::Create, &power_settings));
1043
1044 const Extension* app = InstallAndLaunchEphemeralApp(kPowerTestApp);
1045 ASSERT_TRUE(app);
1046 EXPECT_EQ(1, power_settings.keep_awake_count());
1047
1048 CloseAppWaitForUnload(app->id());
1049
1050 EXPECT_EQ(0, power_settings.keep_awake_count());
1051 }
OLDNEW
« no previous file with comments | « chrome/browser/apps/ephemeral_app_browsertest.h ('k') | chrome/browser/apps/ephemeral_app_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698