Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / apps / ephemeral_app_browsertest.cc
blob61144b0700f4fc0c6ce501ed3fa13f95cfa66024
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.
5 #include "chrome/browser/apps/ephemeral_app_browsertest.h"
7 #include <vector>
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"
48 using extensions::Event;
49 using extensions::EventRouter;
50 using extensions::Extension;
51 using extensions::ExtensionPrefs;
52 using extensions::ExtensionRegistry;
53 using extensions::ExtensionRegistryObserver;
54 using extensions::ExtensionSyncData;
55 using extensions::ExtensionSystem;
56 using extensions::Manifest;
57 using extensions::ResultCatcher;
59 namespace {
61 namespace alarms = extensions::api::alarms;
63 const char kPowerTestApp[] = "ephemeral_apps/power";
65 // Enabling sync causes these tests to be flaky on Windows. Disable sync so that
66 // everything else can be tested. See crbug.com/401028
67 #if defined(OS_WIN)
68 const bool kEnableSync = false;
69 #else
70 const bool kEnableSync = true;
71 #endif
73 typedef std::vector<message_center::Notifier*> NotifierList;
75 bool IsNotifierInList(const message_center::NotifierId& notifier_id,
76 const NotifierList& notifiers) {
77 for (NotifierList::const_iterator it = notifiers.begin();
78 it != notifiers.end(); ++it) {
79 const message_center::Notifier* notifier = *it;
80 if (notifier->notifier_id == notifier_id)
81 return true;
84 return false;
87 // Saves some parameters from the extension installed notification in order
88 // to verify them in tests.
89 class InstallObserver : public ExtensionRegistryObserver {
90 public:
91 struct InstallParameters {
92 std::string id;
93 bool is_update;
94 bool from_ephemeral;
96 InstallParameters(
97 const std::string& id,
98 bool is_update,
99 bool from_ephemeral)
100 : id(id), is_update(is_update), from_ephemeral(from_ephemeral) {}
103 explicit InstallObserver(Profile* profile) : registry_observer_(this) {
104 registry_observer_.Add(ExtensionRegistry::Get(profile));
107 ~InstallObserver() override {}
109 const InstallParameters& Last() {
110 CHECK(!install_params_.empty());
111 return install_params_.back();
114 private:
115 void OnExtensionWillBeInstalled(content::BrowserContext* browser_context,
116 const Extension* extension,
117 bool is_update,
118 bool from_ephemeral,
119 const std::string& old_name) override {
120 install_params_.push_back(
121 InstallParameters(extension->id(), is_update, from_ephemeral));
124 std::vector<InstallParameters> install_params_;
125 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
126 registry_observer_;
129 // Instead of actually changing the system power settings, tests will just
130 // issue requests to this mock.
131 class PowerSettingsMock {
132 public:
133 PowerSettingsMock() : keep_awake_count_(0) {}
135 void request_keep_awake() { ++keep_awake_count_; }
137 void release_keep_awake() {
138 --keep_awake_count_;
139 ASSERT_GE(keep_awake_count_, 0);
142 int keep_awake_count() const { return keep_awake_count_; }
144 private:
145 int keep_awake_count_;
147 DISALLOW_COPY_AND_ASSIGN(PowerSettingsMock);
150 // Stub implementation of content::PowerSaveBlocker that updates the
151 // PowerSettingsMock.
152 class PowerSaveBlockerStub : public content::PowerSaveBlocker {
153 public:
154 explicit PowerSaveBlockerStub(PowerSettingsMock* power_settings)
155 : power_settings_(power_settings) {
156 power_settings_->request_keep_awake();
159 ~PowerSaveBlockerStub() override { power_settings_->release_keep_awake(); }
161 static scoped_ptr<PowerSaveBlocker> Create(PowerSettingsMock* power_settings,
162 PowerSaveBlockerType type,
163 Reason reason,
164 const std::string& description) {
165 return scoped_ptr<PowerSaveBlocker>(
166 new PowerSaveBlockerStub(power_settings));
169 private:
170 PowerSettingsMock* power_settings_; // Not owned.
172 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub);
175 } // namespace
178 // EphemeralAppTestBase:
180 const char EphemeralAppTestBase::kMessagingReceiverApp[] =
181 "ephemeral_apps/messaging_receiver";
182 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] =
183 "ephemeral_apps/messaging_receiver2";
184 const char EphemeralAppTestBase::kDispatchEventTestApp[] =
185 "ephemeral_apps/dispatch_event";
186 const char EphemeralAppTestBase::kNotificationsTestApp[] =
187 "ephemeral_apps/notification_settings";
188 const char EphemeralAppTestBase::kFileSystemTestApp[] =
189 "ephemeral_apps/filesystem_retain_entries";
191 EphemeralAppTestBase::EphemeralAppTestBase() {}
193 EphemeralAppTestBase::~EphemeralAppTestBase() {}
195 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) {
196 // Skip PlatformAppBrowserTest, which sets different values for the switches
197 // below.
198 ExtensionBrowserTest::SetUpCommandLine(command_line);
200 // Make event pages get suspended immediately.
201 extensions::ProcessManager::SetEventPageIdleTimeForTesting(1);
202 extensions::ProcessManager::SetEventPageSuspendingTimeForTesting(1);
204 // Enable ephemeral apps, which are gated by the experimental app launcher
205 // flag.
206 command_line->AppendSwitch(app_list::switches::kEnableExperimentalAppList);
209 void EphemeralAppTestBase::SetUpOnMainThread() {
210 PlatformAppBrowserTest::SetUpOnMainThread();
212 // Disable ephemeral apps immediately after they stop running in tests.
213 EphemeralAppService::Get(profile())->set_disable_delay_for_test(0);
216 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) {
217 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path);
220 const Extension* EphemeralAppTestBase::InstallEphemeralApp(
221 const char* test_path, Manifest::Location manifest_location) {
222 const Extension* extension = InstallEphemeralAppWithSourceAndFlags(
223 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS);
224 EXPECT_TRUE(extension);
225 if (extension)
226 EXPECT_TRUE(extensions::util::IsEphemeralApp(extension->id(), profile()));
227 return extension;
230 const Extension* EphemeralAppTestBase::InstallEphemeralApp(
231 const char* test_path) {
232 return InstallEphemeralApp(test_path, Manifest::INTERNAL);
235 const Extension* EphemeralAppTestBase::InstallAndLaunchEphemeralApp(
236 const char* test_path) {
237 ExtensionTestMessageListener launched_listener("launched", false);
238 const Extension* extension = InstallEphemeralApp(test_path);
239 EXPECT_TRUE(extension);
240 if (!extension)
241 return NULL;
243 LaunchPlatformApp(extension);
244 bool wait_result = launched_listener.WaitUntilSatisfied();
245 EXPECT_TRUE(wait_result);
246 if (!wait_result)
247 return NULL;
249 return extension;
252 const Extension* EphemeralAppTestBase::UpdateEphemeralApp(
253 const std::string& app_id,
254 const base::FilePath& test_dir,
255 const base::FilePath& pem_path) {
256 // Pack a new version of the app.
257 base::ScopedTempDir temp_dir;
258 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
260 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx");
261 if (!base::DeleteFile(crx_path, false)) {
262 ADD_FAILURE() << "Failed to delete existing crx: " << crx_path.value();
263 return NULL;
266 base::FilePath app_v2_path = PackExtensionWithOptions(
267 test_dir, crx_path, pem_path, base::FilePath());
268 EXPECT_FALSE(app_v2_path.empty());
270 // Update the ephemeral app and wait for the update to finish.
271 extensions::CrxInstaller* crx_installer = NULL;
272 content::WindowedNotificationObserver windowed_observer(
273 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
274 content::Source<extensions::CrxInstaller>(crx_installer));
275 ExtensionService* service =
276 ExtensionSystem::Get(profile())->extension_service();
277 EXPECT_TRUE(service->UpdateExtension(
278 extensions::CRXFileInfo(app_id, app_v2_path), true, &crx_installer));
279 windowed_observer.Wait();
281 return ExtensionRegistry::Get(profile())
282 ->GetExtensionById(app_id, ExtensionRegistry::EVERYTHING);
285 void EphemeralAppTestBase::PromoteEphemeralApp(
286 const extensions::Extension* app) {
287 ExtensionService* extension_service =
288 ExtensionSystem::Get(profile())->extension_service();
289 ASSERT_TRUE(extension_service);
290 extension_service->PromoteEphemeralApp(app, false);
293 void EphemeralAppTestBase::DisableEphemeralApp(
294 const Extension* app,
295 Extension::DisableReason disable_reason) {
296 ExtensionSystem::Get(profile())->extension_service()->DisableExtension(
297 app->id(), disable_reason);
299 ASSERT_TRUE(ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
300 app->id()));
303 void EphemeralAppTestBase::CloseApp(const std::string& app_id) {
304 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id));
305 extensions::AppWindow* app_window = GetFirstAppWindowForApp(app_id);
306 ASSERT_TRUE(app_window);
307 CloseAppWindow(app_window);
310 void EphemeralAppTestBase::CloseAppWaitForUnload(const std::string& app_id) {
311 // Ephemeral apps are unloaded from extension system after they stop running.
312 extensions::TestExtensionRegistryObserver observer(
313 ExtensionRegistry::Get(profile()), app_id);
314 CloseApp(app_id);
315 observer.WaitForExtensionUnloaded();
318 void EphemeralAppTestBase::EvictApp(const std::string& app_id) {
319 // Uninstall the app, which is what happens when ephemeral apps get evicted
320 // from the cache.
321 extensions::TestExtensionRegistryObserver observer(
322 ExtensionRegistry::Get(profile()), app_id);
324 ExtensionService* service =
325 ExtensionSystem::Get(profile())->extension_service();
326 ASSERT_TRUE(service);
327 service->UninstallExtension(
328 app_id,
329 extensions::UNINSTALL_REASON_ORPHANED_EPHEMERAL_EXTENSION,
330 base::Bind(&base::DoNothing),
331 NULL);
333 observer.WaitForExtensionUninstalled();
336 // EphemeralAppBrowserTest:
338 class EphemeralAppBrowserTest : public EphemeralAppTestBase {
339 protected:
340 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) {
341 // Ephemeral apps are unloaded after they are closed. Ensure they are
342 // enabled before launch.
343 ExtensionService* service =
344 ExtensionSystem::Get(profile())->extension_service();
345 service->EnableExtension(app->id());
347 ExtensionTestMessageListener launched_listener("launched", true);
348 LaunchPlatformApp(app);
349 if (!launched_listener.WaitUntilSatisfied()) {
350 message_ = "Failed to receive launched message from test";
351 return false;
354 ResultCatcher catcher;
355 launched_listener.Reply(test_name);
357 bool result = catcher.GetNextResult();
358 message_ = catcher.message();
360 CloseAppWaitForUnload(app->id());
361 return result;
364 // Verify that the event page of the app has not been loaded.
365 void VerifyAppNotLoaded(const std::string& app_id) {
366 EXPECT_FALSE(extensions::ProcessManager::Get(profile())
367 ->GetBackgroundHostForExtension(app_id));
370 // Verify properties of ephemeral apps.
371 void VerifyEphemeralApp(const std::string& app_id) {
372 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_id, profile()));
374 // Ephemeral apps should not be synced.
375 scoped_ptr<ExtensionSyncData> sync_change = GetLastSyncChangeForApp(app_id);
376 EXPECT_FALSE(sync_change.get());
378 // Ephemeral apps should not be assigned ordinals.
379 extensions::AppSorting* app_sorting =
380 ExtensionPrefs::Get(profile())->app_sorting();
381 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid());
382 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_id).IsValid());
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));
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);
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;
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);
415 // Check sort ordinals.
416 extensions::AppSorting* app_sorting = prefs->app_sorting();
417 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid());
418 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid());
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";
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()));
433 event_router->DispatchEventToExtension(app_id, event.Pass());
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);
446 void PromoteEphemeralAppAndVerify(
447 const Extension* app,
448 ExtensionRegistry::IncludeFlag expected_set) {
449 ASSERT_TRUE(app);
451 // Ephemeral apps should not be synced.
452 scoped_ptr<ExtensionSyncData> sync_change =
453 GetLastSyncChangeForApp(app->id());
454 EXPECT_FALSE(sync_change.get());
456 // Promote the app to a regular installed app.
457 InstallObserver installed_observer(profile());
458 PromoteEphemeralApp(app);
459 VerifyPromotedApp(app->id(), expected_set);
461 // Check the notification parameters.
462 const InstallObserver::InstallParameters& params =
463 installed_observer.Last();
464 EXPECT_EQ(app->id(), params.id);
465 EXPECT_TRUE(params.is_update);
466 EXPECT_TRUE(params.from_ephemeral);
468 // The installation should now be synced.
469 sync_change = GetLastSyncChangeForApp(app->id());
470 VerifySyncChange(sync_change.get(),
471 expected_set == ExtensionRegistry::ENABLED);
474 void PromoteEphemeralAppFromSyncAndVerify(
475 const Extension* app,
476 bool enable_from_sync,
477 ExtensionRegistry::IncludeFlag expected_set) {
478 ASSERT_TRUE(app);
480 // Simulate an install from sync.
481 int disable_reasons = enable_from_sync ? 0 : Extension::DISABLE_USER_ACTION;
482 const syncer::StringOrdinal kAppLaunchOrdinal("x");
483 const syncer::StringOrdinal kPageOrdinal("y");
484 ExtensionSyncData app_sync_data(
485 *app,
486 enable_from_sync,
487 disable_reasons,
488 false /* incognito enabled */,
489 false /* remote install */,
490 extensions::ExtensionSyncData::BOOLEAN_UNSET,
491 kAppLaunchOrdinal,
492 kPageOrdinal,
493 extensions::LAUNCH_TYPE_REGULAR);
495 std::string app_id = app->id();
496 app = NULL;
498 ExtensionSyncService::Get(profile())->ProcessSyncChanges(
499 FROM_HERE,
500 syncer::SyncChangeList(
501 1, app_sync_data.GetSyncChange(syncer::SyncChange::ACTION_ADD)));
503 // Verify the installation.
504 VerifyPromotedApp(app_id, expected_set);
506 // The sort ordinals from sync should not be overridden.
507 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
508 extensions::AppSorting* app_sorting = prefs->app_sorting();
509 EXPECT_TRUE(
510 app_sorting->GetAppLaunchOrdinal(app_id).Equals(kAppLaunchOrdinal));
511 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal));
514 void InitSyncService() {
515 if (!kEnableSync)
516 return;
518 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile());
519 sync_service->MergeDataAndStartSyncing(
520 syncer::APPS,
521 syncer::SyncDataList(),
522 scoped_ptr<syncer::SyncChangeProcessor>(
523 new syncer::SyncChangeProcessorWrapperForTest(
524 &mock_sync_processor_)),
525 scoped_ptr<syncer::SyncErrorFactory>(
526 new syncer::SyncErrorFactoryMock()));
529 scoped_ptr<ExtensionSyncData> GetLastSyncChangeForApp(const std::string& id) {
530 scoped_ptr<ExtensionSyncData> sync_data;
531 for (syncer::SyncChangeList::iterator it =
532 mock_sync_processor_.changes().begin();
533 it != mock_sync_processor_.changes().end(); ++it) {
534 scoped_ptr<ExtensionSyncData> data(
535 ExtensionSyncData::CreateFromSyncChange(*it));
536 if (data.get() && data->id() == id)
537 sync_data.reset(data.release());
540 return sync_data.Pass();
543 void VerifySyncChange(const ExtensionSyncData* sync_change,
544 bool expect_enabled) {
545 if (!kEnableSync)
546 return;
548 ASSERT_TRUE(sync_change);
549 EXPECT_TRUE(sync_change->page_ordinal().IsValid());
550 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid());
551 EXPECT_FALSE(sync_change->uninstalled());
552 EXPECT_EQ(expect_enabled, sync_change->enabled());
555 void TestInstallEvent(bool close_app) {
556 ExtensionTestMessageListener first_msg_listener(false);
557 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
558 ASSERT_TRUE(app);
560 // When an ephemeral app is first added, it should not receive the
561 // onInstalled event, hence the first message received from the test should
562 // be "launched" and not "installed".
563 ASSERT_TRUE(first_msg_listener.WaitUntilSatisfied());
564 EXPECT_EQ(std::string("launched"), first_msg_listener.message());
566 if (close_app)
567 CloseAppWaitForUnload(app->id());
569 // When installed permanently, the app should receive the onInstalled event.
570 ExtensionTestMessageListener install_listener("installed", false);
571 PromoteEphemeralApp(app);
572 ASSERT_TRUE(install_listener.WaitUntilSatisfied());
575 private:
576 syncer::FakeSyncChangeProcessor mock_sync_processor_;
579 // Verify that ephemeral apps can be launched and receive system events when
580 // they are running. Once they are inactive they should not receive system
581 // events.
582 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) {
583 const Extension* extension =
584 InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
585 ASSERT_TRUE(extension);
587 // Send a fake alarm event to the app and verify that a response is
588 // received.
589 EventRouter* event_router = EventRouter::Get(profile());
590 ASSERT_TRUE(event_router);
592 ExtensionTestMessageListener alarm_received_listener("alarm_received", false);
593 DispatchAlarmEvent(event_router, extension->id());
594 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied());
596 CloseAppWaitForUnload(extension->id());
598 // Dispatch the alarm event again and verify that the event page did not get
599 // loaded for the app.
600 DispatchAlarmEvent(event_router, extension->id());
601 VerifyAppNotLoaded(extension->id());
604 // Verify that ephemeral apps will receive messages while they are running.
605 // Flaky test: crbug.com/394426
606 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
607 DISABLED_ReceiveMessagesWhenLaunched) {
608 const Extension* receiver =
609 InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
610 ASSERT_TRUE(receiver);
612 // Verify that messages are received while the app is running.
613 ResultCatcher result_catcher;
614 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success",
615 "Launched");
616 EXPECT_TRUE(result_catcher.GetNextResult());
618 CloseAppWaitForUnload(receiver->id());
620 // Verify that messages are not received while the app is inactive.
621 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail", "Launched");
622 EXPECT_TRUE(result_catcher.GetNextResult());
625 // Verifies that the chrome.runtime.onInstalled() event is received by a running
626 // ephemeral app only when it is promoted.
627 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
628 InstallEventReceivedWhileRunning) {
629 TestInstallEvent(false /* close app */);
632 // Verifies that when an idle ephemeral app is promoted, it will be loaded to
633 // receive the chrome.runtime.onInstalled() event.
634 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEventReceivedWhileIdle) {
635 TestInstallEvent(true /* close app */);
638 // Verifies that the chrome.runtime.onRestarted() event is received by an
639 // ephemeral app.
640 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RestartEventReceived) {
641 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
642 ASSERT_TRUE(app);
643 CloseAppWaitForUnload(app->id());
645 // Fake ephemeral app running before restart.
646 ExtensionSystem::Get(profile())->extension_service()->EnableExtension(
647 app->id());
648 ASSERT_TRUE(ExtensionRegistry::Get(profile())->enabled_extensions().Contains(
649 app->id()));
650 ExtensionPrefs::Get(profile())->SetExtensionRunning(app->id(), true);
652 ExtensionTestMessageListener restart_listener("restarted", false);
653 apps::AppRestoreService::Get(profile())->HandleStartup(true);
654 EXPECT_TRUE(restart_listener.WaitUntilSatisfied());
657 // Verify that an updated ephemeral app will still have its ephemeral flag
658 // enabled.
659 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) {
660 InitSyncService();
662 const Extension* app_v1 = InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
663 ASSERT_TRUE(app_v1);
664 VerifyEphemeralApp(app_v1->id());
665 CloseAppWaitForUnload(app_v1->id());
666 VerifyInactiveEphemeralApp(app_v1->id());
668 std::string app_id = app_v1->id();
669 base::Version app_original_version = *app_v1->version();
671 // Update to version 2 of the app.
672 app_v1 = NULL; // The extension object will be destroyed during update.
673 InstallObserver installed_observer(profile());
674 const Extension* app_v2 =
675 UpdateEphemeralApp(app_id,
676 GetTestPath(kMessagingReceiverAppV2),
677 GetTestPath(kMessagingReceiverApp)
678 .ReplaceExtension(FILE_PATH_LITERAL(".pem")));
680 // Check the notification parameters.
681 const InstallObserver::InstallParameters& params = installed_observer.Last();
682 EXPECT_EQ(app_id, params.id);
683 EXPECT_TRUE(params.is_update);
684 EXPECT_FALSE(params.from_ephemeral);
686 // The ephemeral flag should still be set.
687 ASSERT_TRUE(app_v2);
688 EXPECT_GT(app_v2->version()->CompareTo(app_original_version), 0);
689 VerifyEphemeralApp(app_id);
691 // The app should still be disabled in extension system.
692 VerifyInactiveEphemeralApp(app_id);
695 // Verify that if notifications have been disabled for an ephemeral app, it will
696 // remain disabled even after being evicted from the cache.
697 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) {
698 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
699 ASSERT_TRUE(app);
701 // Disable notifications for this app.
702 NotifierStateTracker* notifier_state_tracker =
703 NotifierStateTrackerFactory::GetForProfile(profile());
704 ASSERT_TRUE(notifier_state_tracker);
706 message_center::NotifierId notifier_id(
707 message_center::NotifierId::APPLICATION, app->id());
708 EXPECT_TRUE(notifier_state_tracker->IsNotifierEnabled(notifier_id));
709 notifier_state_tracker->SetNotifierEnabled(notifier_id, false);
710 EXPECT_FALSE(notifier_state_tracker->IsNotifierEnabled(notifier_id));
712 // Remove the app.
713 CloseAppWaitForUnload(app->id());
714 EvictApp(app->id());
716 // Reinstall the ephemeral app and verify that notifications remain disabled.
717 app = InstallEphemeralApp(kNotificationsTestApp);
718 ASSERT_TRUE(app);
719 message_center::NotifierId reinstalled_notifier_id(
720 message_center::NotifierId::APPLICATION, app->id());
721 EXPECT_FALSE(notifier_state_tracker->IsNotifierEnabled(
722 reinstalled_notifier_id));
725 // Verify that only running ephemeral apps will appear in the Notification
726 // Settings UI. Inactive, cached ephemeral apps should not appear.
727 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
728 IncludeRunningEphemeralAppsInNotifiers) {
729 message_center::NotifierSettingsProvider* settings_provider =
730 message_center::MessageCenter::Get()->GetNotifierSettingsProvider();
731 DCHECK(settings_provider);
733 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
734 ASSERT_TRUE(app);
735 message_center::NotifierId notifier_id(
736 message_center::NotifierId::APPLICATION, app->id());
738 // Since the ephemeral app is running, it should be included in the list
739 // of notifiers to show in the UI.
740 NotifierList notifiers;
741 STLElementDeleter<NotifierList> notifier_deleter(&notifiers);
743 settings_provider->GetNotifierList(&notifiers);
744 EXPECT_TRUE(IsNotifierInList(notifier_id, notifiers));
745 STLDeleteElements(&notifiers);
747 // Close the ephemeral app.
748 CloseAppWaitForUnload(app->id());
750 // Inactive ephemeral apps should not be included in the list of notifiers to
751 // show in the UI.
752 settings_provider->GetNotifierList(&notifiers);
753 EXPECT_FALSE(IsNotifierInList(notifier_id, notifiers));
756 // Verify that ephemeral apps will have no ability to retain file entries after
757 // close. Normal retainEntry behavior for installed apps is tested in
758 // FileSystemApiTest.
759 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
760 DisableRetainFileSystemEntries) {
761 // Create a dummy file that we can just return to the test.
762 base::ScopedTempDir temp_dir;
763 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
764 base::FilePath temp_file;
765 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file));
767 using extensions::FileSystemChooseEntryFunction;
768 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
769 &temp_file);
770 // The temporary file needs to be registered for the tests to pass on
771 // ChromeOS.
772 FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
773 "temp", temp_dir.path());
775 // The first test opens the file and writes the file handle to local storage.
776 const Extension* app = InstallEphemeralApp(kFileSystemTestApp,
777 Manifest::UNPACKED);
778 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_;
780 // Verify that after the app has been closed, all retained entries are
781 // flushed.
782 std::vector<apps::SavedFileEntry> file_entries =
783 apps::SavedFilesService::Get(profile())
784 ->GetAllFileEntries(app->id());
785 EXPECT_TRUE(file_entries.empty());
787 // The second test verifies that the file cannot be reopened.
788 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_;
791 // Checks the process of launching an ephemeral app and then promoting the app
792 // while it is running.
793 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileRunning) {
794 InitSyncService();
796 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
797 ASSERT_TRUE(app);
799 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
801 // Ensure that the app is not unloaded and disabled after it is closed.
802 CloseApp(app->id());
803 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED);
806 // Checks the process of launching an ephemeral app and then promoting the app
807 // while it is idle.
808 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileIdle) {
809 InitSyncService();
811 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
812 ASSERT_TRUE(app);
813 CloseAppWaitForUnload(app->id());
814 VerifyInactiveEphemeralApp(app->id());
816 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
819 // Verifies that promoting an ephemeral app that was disabled due to a
820 // permissions increase will enable it.
821 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppAndGrantPermissions) {
822 InitSyncService();
824 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
825 ASSERT_TRUE(app);
826 CloseAppWaitForUnload(app->id());
827 DisableEphemeralApp(app, Extension::DISABLE_PERMISSIONS_INCREASE);
829 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
830 EXPECT_FALSE(ExtensionPrefs::Get(profile())
831 ->DidExtensionEscalatePermissions(app->id()));
834 // Verifies that promoting an ephemeral app that has unsupported requirements
835 // will not enable it.
836 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
837 PromoteUnsupportedEphemeralApp) {
838 InitSyncService();
840 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
841 ASSERT_TRUE(app);
842 CloseAppWaitForUnload(app->id());
843 DisableEphemeralApp(app, Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
845 // When promoted to a regular installed app, it should remain disabled.
846 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::DISABLED);
849 // Verifies that promoting an ephemeral app that is blacklisted will not enable
850 // it.
851 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
852 PromoteBlacklistedEphemeralApp) {
853 InitSyncService();
855 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
856 ASSERT_TRUE(app);
857 CloseAppWaitForUnload(app->id());
859 ExtensionService* service =
860 ExtensionSystem::Get(profile())->extension_service();
861 service->BlacklistExtensionForTest(app->id());
862 ASSERT_TRUE(
863 ExtensionRegistry::Get(profile())->blacklisted_extensions().Contains(
864 app->id()));
866 // When promoted to a regular installed app, it should remain blacklisted.
867 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::BLACKLISTED);
869 // The app should be synced, but disabled.
870 scoped_ptr<ExtensionSyncData> sync_change =
871 GetLastSyncChangeForApp(app->id());
872 VerifySyncChange(sync_change.get(), false);
875 // Checks the process of promoting an ephemeral app from sync while the app is
876 // running.
877 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
878 PromoteAppFromSyncWhileRunning) {
879 InitSyncService();
881 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
882 ASSERT_TRUE(app);
884 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED);
886 // Ensure that the app is not unloaded and disabled after it is closed.
887 CloseApp(app->id());
888 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED);
891 // Checks the process of promoting an ephemeral app from sync while the app is
892 // idle.
893 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppFromSyncWhileIdle) {
894 InitSyncService();
896 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
897 ASSERT_TRUE(app);
898 CloseAppWaitForUnload(app->id());
899 VerifyInactiveEphemeralApp(app->id());
901 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED);
904 // Checks the process of promoting an ephemeral app from sync, where the app
905 // from sync is disabled, and the ephemeral app is running.
906 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
907 PromoteDisabledAppFromSyncWhileRunning) {
908 InitSyncService();
910 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
911 ASSERT_TRUE(app);
913 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED);
916 // Checks the process of promoting an ephemeral app from sync, where the app
917 // from sync is disabled, and the ephemeral app is idle.
918 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
919 PromoteDisabledAppFromSyncWhileIdle) {
920 InitSyncService();
922 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
923 ASSERT_TRUE(app);
924 CloseAppWaitForUnload(app->id());
925 VerifyInactiveEphemeralApp(app->id());
927 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED);
930 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to
931 // permanently install an ephemeral app. However, there may be cases where an
932 // install occurs through the usual route of installing from the Web Store (due
933 // to race conditions). Ensure that the app is still installed correctly.
934 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
935 ReplaceEphemeralAppWithInstalledApp) {
936 InitSyncService();
938 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
939 ASSERT_TRUE(app);
940 CloseAppWaitForUnload(app->id());
941 std::string app_id = app->id();
942 app = NULL;
944 InstallObserver installed_observer(profile());
945 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 1);
946 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED);
948 // Check the notification parameters.
949 const InstallObserver::InstallParameters& params = installed_observer.Last();
950 EXPECT_EQ(app_id, params.id);
951 EXPECT_TRUE(params.is_update);
952 EXPECT_TRUE(params.from_ephemeral);
955 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will
956 // be delayed until the app is idle.
957 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
958 ReplaceEphemeralAppWithDelayedInstalledApp) {
959 InitSyncService();
960 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
961 ASSERT_TRUE(app);
962 std::string app_id = app->id();
963 app = NULL;
965 // Initiate install.
966 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 0);
968 // The delayed installation will occur when the ephemeral app is closed.
969 extensions::TestExtensionRegistryObserver observer(
970 ExtensionRegistry::Get(profile()), app_id);
971 InstallObserver installed_observer(profile());
972 CloseAppWaitForUnload(app_id);
973 observer.WaitForExtensionWillBeInstalled();
974 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED);
976 // Check the notification parameters.
977 const InstallObserver::InstallParameters& params = installed_observer.Last();
978 EXPECT_EQ(app_id, params.id);
979 EXPECT_TRUE(params.is_update);
980 EXPECT_TRUE(params.from_ephemeral);
983 // Verifies that an installed app cannot turn into an ephemeral app as result of
984 // race conditions, i.e. an ephemeral app can be promoted to an installed app,
985 // but not vice versa.
986 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
987 ReplaceInstalledAppWithEphemeralApp) {
988 const Extension* app = InstallPlatformApp(kNotificationsTestApp);
989 ASSERT_TRUE(app);
990 std::string app_id = app->id();
991 app = NULL;
993 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile()));
994 app =
995 InstallEphemeralAppWithSourceAndFlags(GetTestPath(kNotificationsTestApp),
997 Manifest::INTERNAL,
998 Extension::NO_FLAGS);
999 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile()));
1002 // Ephemerality was previously encoded by the Extension::IS_EPHEMERAL creation
1003 // flag. This was changed to an "ephemeral_app" property. Check that the prefs
1004 // are handled correctly.
1005 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
1006 ExtensionPrefBackcompatibility) {
1007 // Ensure that apps with the old prefs are recognized as ephemeral.
1008 const Extension* app =
1009 InstallExtensionWithSourceAndFlags(GetTestPath(kNotificationsTestApp),
1011 Manifest::INTERNAL,
1012 Extension::IS_EPHEMERAL);
1013 ASSERT_TRUE(app);
1014 EXPECT_TRUE(extensions::util::IsEphemeralApp(app->id(), profile()));
1016 // Ensure that when the app is promoted to an installed app, the bit in the
1017 // creation flags is cleared.
1018 PromoteEphemeralApp(app);
1019 EXPECT_FALSE(extensions::util::IsEphemeralApp(app->id(), profile()));
1021 int creation_flags =
1022 ExtensionPrefs::Get(profile())->GetCreationFlags(app->id());
1023 EXPECT_EQ(0, creation_flags & Extension::IS_EPHEMERAL);
1026 // Verifies that the power keep awake will be automatically released for
1027 // ephemeral apps that stop running. Well behaved apps should actually call
1028 // chrome.power.releaseKeepAwake() themselves.
1029 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, ReleasePowerKeepAwake) {
1030 PowerSettingsMock power_settings;
1031 extensions::PowerAPI::Get(profile())->SetCreateBlockerFunctionForTesting(
1032 base::Bind(&PowerSaveBlockerStub::Create, &power_settings));
1034 const Extension* app = InstallAndLaunchEphemeralApp(kPowerTestApp);
1035 ASSERT_TRUE(app);
1036 EXPECT_EQ(1, power_settings.keep_awake_count());
1038 CloseAppWaitForUnload(app->id());
1040 EXPECT_EQ(0, power_settings.keep_awake_count());