Update mojo surfaces bindings and mojo/cc/ glue
[chromium-blink-merge.git] / chrome / browser / apps / ephemeral_app_browsertest.cc
blob86dc13d7b50171e6514e7d4a7f6272b0a9b8f7a9
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/app_sync_data.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_sync_service.h"
20 #include "chrome/browser/extensions/extension_test_message_listener.h"
21 #include "chrome/browser/extensions/extension_util.h"
22 #include "chrome/browser/notifications/desktop_notification_service.h"
23 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/extensions/api/alarms.h"
26 #include "content/public/browser/power_save_blocker.h"
27 #include "content/public/test/browser_test.h"
28 #include "content/public/test/test_utils.h"
29 #include "extensions/browser/api/power/power_api_manager.h"
30 #include "extensions/browser/app_sorting.h"
31 #include "extensions/browser/event_router.h"
32 #include "extensions/browser/extension_prefs.h"
33 #include "extensions/browser/extension_registry.h"
34 #include "extensions/browser/extension_registry_observer.h"
35 #include "extensions/browser/extension_system.h"
36 #include "extensions/browser/extension_util.h"
37 #include "extensions/browser/notification_types.h"
38 #include "extensions/browser/process_manager.h"
39 #include "extensions/browser/uninstall_reason.h"
40 #include "extensions/common/extension.h"
41 #include "extensions/common/switches.h"
42 #include "sync/api/fake_sync_change_processor.h"
43 #include "sync/api/sync_change_processor_wrapper_for_test.h"
44 #include "sync/api/sync_error_factory_mock.h"
45 #include "ui/message_center/message_center.h"
46 #include "ui/message_center/notifier_settings.h"
48 using extensions::AppSyncData;
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::ExtensionSystem;
56 using extensions::Manifest;
58 namespace {
60 namespace alarms = extensions::api::alarms;
62 const char kPowerTestApp[] = "ephemeral_apps/power";
64 typedef std::vector<message_center::Notifier*> NotifierList;
66 bool IsNotifierInList(const message_center::NotifierId& notifier_id,
67 const NotifierList& notifiers) {
68 for (NotifierList::const_iterator it = notifiers.begin();
69 it != notifiers.end(); ++it) {
70 const message_center::Notifier* notifier = *it;
71 if (notifier->notifier_id == notifier_id)
72 return true;
75 return false;
78 // Saves some parameters from the extension installed notification in order
79 // to verify them in tests.
80 class InstallObserver : public ExtensionRegistryObserver {
81 public:
82 struct InstallParameters {
83 std::string id;
84 bool is_update;
85 bool from_ephemeral;
87 InstallParameters(
88 const std::string& id,
89 bool is_update,
90 bool from_ephemeral)
91 : id(id), is_update(is_update), from_ephemeral(from_ephemeral) {}
94 explicit InstallObserver(Profile* profile) : registry_observer_(this) {
95 registry_observer_.Add(ExtensionRegistry::Get(profile));
98 virtual ~InstallObserver() {}
100 const InstallParameters& Last() {
101 CHECK(!install_params_.empty());
102 return install_params_.back();
105 private:
106 virtual void OnExtensionWillBeInstalled(
107 content::BrowserContext* browser_context,
108 const Extension* extension,
109 bool is_update,
110 bool from_ephemeral,
111 const std::string& old_name) OVERRIDE {
112 install_params_.push_back(
113 InstallParameters(extension->id(), is_update, from_ephemeral));
116 std::vector<InstallParameters> install_params_;
117 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
118 registry_observer_;
121 // Instead of actually changing the system power settings, tests will just
122 // issue requests to this mock.
123 class PowerSettingsMock {
124 public:
125 PowerSettingsMock() : keep_awake_count_(0) {}
127 void request_keep_awake() { ++keep_awake_count_; }
129 void release_keep_awake() {
130 --keep_awake_count_;
131 ASSERT_GE(keep_awake_count_, 0);
134 int keep_awake_count() const { return keep_awake_count_; }
136 private:
137 int keep_awake_count_;
139 DISALLOW_COPY_AND_ASSIGN(PowerSettingsMock);
142 // Stub implementation of content::PowerSaveBlocker that updates the
143 // PowerSettingsMock.
144 class PowerSaveBlockerStub : public content::PowerSaveBlocker {
145 public:
146 explicit PowerSaveBlockerStub(PowerSettingsMock* power_settings)
147 : power_settings_(power_settings) {
148 power_settings_->request_keep_awake();
151 virtual ~PowerSaveBlockerStub() { power_settings_->release_keep_awake(); }
153 static scoped_ptr<PowerSaveBlocker> Create(PowerSettingsMock* power_settings,
154 PowerSaveBlockerType type,
155 const std::string& reason) {
156 return scoped_ptr<PowerSaveBlocker>(
157 new PowerSaveBlockerStub(power_settings));
160 private:
161 PowerSettingsMock* power_settings_; // Not owned.
163 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub);
166 } // namespace
169 // EphemeralAppTestBase:
171 const char EphemeralAppTestBase::kMessagingReceiverApp[] =
172 "ephemeral_apps/messaging_receiver";
173 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] =
174 "ephemeral_apps/messaging_receiver2";
175 const char EphemeralAppTestBase::kDispatchEventTestApp[] =
176 "ephemeral_apps/dispatch_event";
177 const char EphemeralAppTestBase::kNotificationsTestApp[] =
178 "ephemeral_apps/notification_settings";
179 const char EphemeralAppTestBase::kFileSystemTestApp[] =
180 "ephemeral_apps/filesystem_retain_entries";
182 EphemeralAppTestBase::EphemeralAppTestBase() {}
184 EphemeralAppTestBase::~EphemeralAppTestBase() {}
186 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) {
187 // Skip PlatformAppBrowserTest, which sets different values for the switches
188 // below.
189 ExtensionBrowserTest::SetUpCommandLine(command_line);
191 // Make event pages get suspended immediately.
192 command_line->AppendSwitchASCII(
193 extensions::switches::kEventPageIdleTime, "10");
194 command_line->AppendSwitchASCII(
195 extensions::switches::kEventPageSuspendingTime, "10");
197 // Enable ephemeral apps flag.
198 command_line->AppendSwitch(switches::kEnableEphemeralApps);
201 void EphemeralAppTestBase::SetUpOnMainThread() {
202 PlatformAppBrowserTest::SetUpOnMainThread();
204 // Disable ephemeral apps immediately after they stop running in tests.
205 EphemeralAppService::Get(profile())->set_disable_delay_for_test(0);
208 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) {
209 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path);
212 const Extension* EphemeralAppTestBase::InstallEphemeralApp(
213 const char* test_path, Manifest::Location manifest_location) {
214 const Extension* extension = InstallEphemeralAppWithSourceAndFlags(
215 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS);
216 EXPECT_TRUE(extension);
217 if (extension)
218 EXPECT_TRUE(extensions::util::IsEphemeralApp(extension->id(), profile()));
219 return extension;
222 const Extension* EphemeralAppTestBase::InstallEphemeralApp(
223 const char* test_path) {
224 return InstallEphemeralApp(test_path, Manifest::INTERNAL);
227 const Extension* EphemeralAppTestBase::InstallAndLaunchEphemeralApp(
228 const char* test_path) {
229 ExtensionTestMessageListener launched_listener("launched", false);
230 const Extension* extension = InstallEphemeralApp(test_path);
231 EXPECT_TRUE(extension);
232 if (!extension)
233 return NULL;
235 LaunchPlatformApp(extension);
236 bool wait_result = launched_listener.WaitUntilSatisfied();
237 EXPECT_TRUE(wait_result);
238 if (!wait_result)
239 return NULL;
241 return extension;
244 const Extension* EphemeralAppTestBase::UpdateEphemeralApp(
245 const std::string& app_id,
246 const base::FilePath& test_dir,
247 const base::FilePath& pem_path) {
248 // Pack a new version of the app.
249 base::ScopedTempDir temp_dir;
250 EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
252 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx");
253 if (!base::DeleteFile(crx_path, false)) {
254 ADD_FAILURE() << "Failed to delete existing crx: " << crx_path.value();
255 return NULL;
258 base::FilePath app_v2_path = PackExtensionWithOptions(
259 test_dir, crx_path, pem_path, base::FilePath());
260 EXPECT_FALSE(app_v2_path.empty());
262 // Update the ephemeral app and wait for the update to finish.
263 extensions::CrxInstaller* crx_installer = NULL;
264 content::WindowedNotificationObserver windowed_observer(
265 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
266 content::Source<extensions::CrxInstaller>(crx_installer));
267 ExtensionService* service =
268 ExtensionSystem::Get(profile())->extension_service();
269 EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true,
270 &crx_installer));
271 windowed_observer.Wait();
273 return ExtensionRegistry::Get(profile())
274 ->GetExtensionById(app_id, ExtensionRegistry::EVERYTHING);
277 void EphemeralAppTestBase::PromoteEphemeralApp(
278 const extensions::Extension* app) {
279 ExtensionService* extension_service =
280 ExtensionSystem::Get(profile())->extension_service();
281 ASSERT_TRUE(extension_service);
282 extension_service->PromoteEphemeralApp(app, false);
285 void EphemeralAppTestBase::DisableEphemeralApp(
286 const Extension* app,
287 Extension::DisableReason disable_reason) {
288 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
290 // Disabling due to a permissions increase also involves setting the
291 // DidExtensionEscalatePermissions flag.
292 if (disable_reason == Extension::DISABLE_PERMISSIONS_INCREASE)
293 prefs->SetDidExtensionEscalatePermissions(app, true);
295 ExtensionSystem::Get(profile())->extension_service()->DisableExtension(
296 app->id(), disable_reason);
298 ASSERT_TRUE(ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
299 app->id()));
302 void EphemeralAppTestBase::CloseApp(const std::string& app_id) {
303 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id));
304 apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id);
305 ASSERT_TRUE(app_window);
306 CloseAppWindow(app_window);
309 void EphemeralAppTestBase::CloseAppWaitForUnload(const std::string& app_id) {
310 // Ephemeral apps are unloaded from extension system after they stop running.
311 content::WindowedNotificationObserver unloaded_signal(
312 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
313 content::Source<Profile>(profile()));
314 CloseApp(app_id);
315 unloaded_signal.Wait();
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 content::WindowedNotificationObserver uninstalled_signal(
322 extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED,
323 content::Source<Profile>(profile()));
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);
334 uninstalled_signal.Wait();
337 // EphemeralAppBrowserTest:
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());
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;
355 ResultCatcher catcher;
356 launched_listener.Reply(test_name);
358 bool result = catcher.GetNextResult();
359 message_ = catcher.message();
361 CloseAppWaitForUnload(app->id());
362 return result;
365 // Verify that the event page of the app has not been loaded.
366 void VerifyAppNotLoaded(const std::string& app_id) {
367 EXPECT_FALSE(ExtensionSystem::Get(profile())->
368 process_manager()->GetBackgroundHostForExtension(app_id));
371 // Verify properties of ephemeral apps.
372 void VerifyEphemeralApp(const std::string& app_id) {
373 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_id, profile()));
375 // Ephemeral apps should not be synced.
376 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app_id);
377 EXPECT_FALSE(sync_change.get());
379 // Ephemeral apps should not be assigned ordinals.
380 extensions::AppSorting* app_sorting =
381 ExtensionPrefs::Get(profile())->app_sorting();
382 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid());
383 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_id).IsValid());
386 // Verify that after ephemeral apps stop running, they reside in extension
387 // system in a disabled and unloaded state.
388 void VerifyInactiveEphemeralApp(const std::string& app_id) {
389 EXPECT_TRUE(
390 ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
391 app_id));
393 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
394 EXPECT_TRUE(prefs->IsExtensionDisabled(app_id));
395 EXPECT_NE(0,
396 prefs->GetDisableReasons(app_id) &
397 Extension::DISABLE_INACTIVE_EPHEMERAL_APP);
400 // Verify the state of an app that has been promoted from an ephemeral to a
401 // fully installed app.
402 void VerifyPromotedApp(const std::string& app_id,
403 ExtensionRegistry::IncludeFlag expected_set) {
404 const Extension* app = ExtensionRegistry::Get(profile())
405 ->GetExtensionById(app_id, expected_set);
406 ASSERT_TRUE(app) << "App not found in expected set: " << expected_set;
408 // The app should not be ephemeral.
409 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
410 ASSERT_TRUE(prefs);
411 EXPECT_FALSE(prefs->IsEphemeralApp(app_id));
412 EXPECT_EQ(0,
413 prefs->GetDisableReasons(app_id) &
414 Extension::DISABLE_INACTIVE_EPHEMERAL_APP);
416 // Check sort ordinals.
417 extensions::AppSorting* app_sorting = prefs->app_sorting();
418 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid());
419 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid());
422 // Dispatch a fake alarm event to the app.
423 void DispatchAlarmEvent(EventRouter* event_router,
424 const std::string& app_id) {
425 alarms::Alarm dummy_alarm;
426 dummy_alarm.name = "test_alarm";
428 scoped_ptr<base::ListValue> args(new base::ListValue());
429 args->Append(dummy_alarm.ToValue().release());
430 scoped_ptr<Event> event(new Event(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<AppSyncData> sync_change = GetLastSyncChangeForApp(app->id());
453 EXPECT_FALSE(sync_change.get());
455 // Promote the app to a regular installed app.
456 InstallObserver installed_observer(profile());
457 PromoteEphemeralApp(app);
458 VerifyPromotedApp(app->id(), expected_set);
460 // Check the notification parameters.
461 const InstallObserver::InstallParameters& params =
462 installed_observer.Last();
463 EXPECT_EQ(app->id(), params.id);
464 EXPECT_TRUE(params.is_update);
465 EXPECT_TRUE(params.from_ephemeral);
467 // The installation should now be synced.
468 sync_change = GetLastSyncChangeForApp(app->id());
469 VerifySyncChange(sync_change.get(),
470 expected_set == ExtensionRegistry::ENABLED);
473 void PromoteEphemeralAppFromSyncAndVerify(
474 const Extension* app,
475 bool enable_from_sync,
476 ExtensionRegistry::IncludeFlag expected_set) {
477 ASSERT_TRUE(app);
479 // Simulate an install from sync.
480 const syncer::StringOrdinal kAppLaunchOrdinal("x");
481 const syncer::StringOrdinal kPageOrdinal("y");
482 AppSyncData app_sync_data(*app,
483 enable_from_sync,
484 false /* incognito enabled */,
485 false /* remote install */,
486 kAppLaunchOrdinal,
487 kPageOrdinal,
488 extensions::LAUNCH_TYPE_REGULAR);
490 std::string app_id = app->id();
491 app = NULL;
493 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile());
494 sync_service->ProcessAppSyncData(app_sync_data);
496 // Verify the installation.
497 VerifyPromotedApp(app_id, expected_set);
499 // The sort ordinals from sync should not be overridden.
500 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
501 extensions::AppSorting* app_sorting = prefs->app_sorting();
502 EXPECT_TRUE(
503 app_sorting->GetAppLaunchOrdinal(app_id).Equals(kAppLaunchOrdinal));
504 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal));
507 void InitSyncService() {
508 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile());
509 sync_service->MergeDataAndStartSyncing(
510 syncer::APPS,
511 syncer::SyncDataList(),
512 scoped_ptr<syncer::SyncChangeProcessor>(
513 new syncer::SyncChangeProcessorWrapperForTest(
514 &mock_sync_processor_)),
515 scoped_ptr<syncer::SyncErrorFactory>(
516 new syncer::SyncErrorFactoryMock()));
519 scoped_ptr<AppSyncData> GetLastSyncChangeForApp(const std::string& id) {
520 scoped_ptr<AppSyncData> sync_data;
521 for (syncer::SyncChangeList::iterator it =
522 mock_sync_processor_.changes().begin();
523 it != mock_sync_processor_.changes().end(); ++it) {
524 scoped_ptr<AppSyncData> data(new AppSyncData(*it));
525 if (data->id() == id)
526 sync_data.reset(data.release());
529 return sync_data.Pass();
532 void VerifySyncChange(const AppSyncData* sync_change, bool expect_enabled) {
533 ASSERT_TRUE(sync_change);
534 EXPECT_TRUE(sync_change->page_ordinal().IsValid());
535 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid());
536 EXPECT_FALSE(sync_change->uninstalled());
537 EXPECT_EQ(expect_enabled, sync_change->extension_sync_data().enabled());
540 void TestInstallEvent(bool close_app) {
541 ExtensionTestMessageListener first_msg_listener(false);
542 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
543 ASSERT_TRUE(app);
545 // When an ephemeral app is first added, it should not receive the
546 // onInstalled event, hence the first message received from the test should
547 // be "launched" and not "installed".
548 ASSERT_TRUE(first_msg_listener.WaitUntilSatisfied());
549 EXPECT_EQ(std::string("launched"), first_msg_listener.message());
551 if (close_app)
552 CloseAppWaitForUnload(app->id());
554 // When installed permanently, the app should receive the onInstalled event.
555 ExtensionTestMessageListener install_listener("installed", false);
556 PromoteEphemeralApp(app);
557 ASSERT_TRUE(install_listener.WaitUntilSatisfied());
560 private:
561 syncer::FakeSyncChangeProcessor mock_sync_processor_;
564 // Verify that ephemeral apps can be launched and receive system events when
565 // they are running. Once they are inactive they should not receive system
566 // events.
567 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) {
568 const Extension* extension =
569 InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
570 ASSERT_TRUE(extension);
572 // Send a fake alarm event to the app and verify that a response is
573 // received.
574 EventRouter* event_router = EventRouter::Get(profile());
575 ASSERT_TRUE(event_router);
577 ExtensionTestMessageListener alarm_received_listener("alarm_received", false);
578 DispatchAlarmEvent(event_router, extension->id());
579 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied());
581 CloseAppWaitForUnload(extension->id());
583 // Dispatch the alarm event again and verify that the event page did not get
584 // loaded for the app.
585 DispatchAlarmEvent(event_router, extension->id());
586 VerifyAppNotLoaded(extension->id());
589 // Verify that ephemeral apps will receive messages while they are running.
590 // Flaky test: crbug.com/394426
591 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
592 DISABLED_ReceiveMessagesWhenLaunched) {
593 const Extension* receiver =
594 InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
595 ASSERT_TRUE(receiver);
597 // Verify that messages are received while the app is running.
598 ExtensionApiTest::ResultCatcher result_catcher;
599 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success",
600 "Launched");
601 EXPECT_TRUE(result_catcher.GetNextResult());
603 CloseAppWaitForUnload(receiver->id());
605 // Verify that messages are not received while the app is inactive.
606 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail", "Launched");
607 EXPECT_TRUE(result_catcher.GetNextResult());
610 // Verifies that the chrome.runtime.onInstalled() event is received by a running
611 // ephemeral app only when it is promoted.
612 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
613 InstallEventReceivedWhileRunning) {
614 TestInstallEvent(false /* close app */);
617 // Verifies that when an idle ephemeral app is promoted, it will be loaded to
618 // receive the chrome.runtime.onInstalled() event.
619 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEventReceivedWhileIdle) {
620 TestInstallEvent(true /* close app */);
623 // Verifies that the chrome.runtime.onRestarted() event is received by an
624 // ephemeral app.
625 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RestartEventReceived) {
626 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp);
627 ASSERT_TRUE(app);
628 CloseAppWaitForUnload(app->id());
630 // Fake ephemeral app running before restart.
631 ExtensionSystem::Get(profile())->extension_service()->EnableExtension(
632 app->id());
633 ASSERT_TRUE(ExtensionRegistry::Get(profile())->enabled_extensions().Contains(
634 app->id()));
635 ExtensionPrefs::Get(profile())->SetExtensionRunning(app->id(), true);
637 ExtensionTestMessageListener restart_listener("restarted", false);
638 apps::AppRestoreService::Get(profile())->HandleStartup(true);
639 EXPECT_TRUE(restart_listener.WaitUntilSatisfied());
642 // Verify that an updated ephemeral app will still have its ephemeral flag
643 // enabled.
644 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) {
645 InitSyncService();
647 const Extension* app_v1 = InstallAndLaunchEphemeralApp(kMessagingReceiverApp);
648 ASSERT_TRUE(app_v1);
649 VerifyEphemeralApp(app_v1->id());
650 CloseAppWaitForUnload(app_v1->id());
651 VerifyInactiveEphemeralApp(app_v1->id());
653 std::string app_id = app_v1->id();
654 base::Version app_original_version = *app_v1->version();
656 // Update to version 2 of the app.
657 app_v1 = NULL; // The extension object will be destroyed during update.
658 InstallObserver installed_observer(profile());
659 const Extension* app_v2 =
660 UpdateEphemeralApp(app_id,
661 GetTestPath(kMessagingReceiverAppV2),
662 GetTestPath(kMessagingReceiverApp)
663 .ReplaceExtension(FILE_PATH_LITERAL(".pem")));
665 // Check the notification parameters.
666 const InstallObserver::InstallParameters& params = installed_observer.Last();
667 EXPECT_EQ(app_id, params.id);
668 EXPECT_TRUE(params.is_update);
669 EXPECT_FALSE(params.from_ephemeral);
671 // The ephemeral flag should still be set.
672 ASSERT_TRUE(app_v2);
673 EXPECT_GT(app_v2->version()->CompareTo(app_original_version), 0);
674 VerifyEphemeralApp(app_id);
676 // The app should still be disabled in extension system.
677 VerifyInactiveEphemeralApp(app_id);
680 // Verify that if notifications have been disabled for an ephemeral app, it will
681 // remain disabled even after being evicted from the cache.
682 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) {
683 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
684 ASSERT_TRUE(app);
686 // Disable notifications for this app.
687 DesktopNotificationService* notification_service =
688 DesktopNotificationServiceFactory::GetForProfile(profile());
689 ASSERT_TRUE(notification_service);
691 message_center::NotifierId notifier_id(
692 message_center::NotifierId::APPLICATION, app->id());
693 EXPECT_TRUE(notification_service->IsNotifierEnabled(notifier_id));
694 notification_service->SetNotifierEnabled(notifier_id, false);
695 EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id));
697 // Remove the app.
698 CloseAppWaitForUnload(app->id());
699 EvictApp(app->id());
701 // Reinstall the ephemeral app and verify that notifications remain disabled.
702 app = InstallEphemeralApp(kNotificationsTestApp);
703 ASSERT_TRUE(app);
704 message_center::NotifierId reinstalled_notifier_id(
705 message_center::NotifierId::APPLICATION, app->id());
706 EXPECT_FALSE(notification_service->IsNotifierEnabled(
707 reinstalled_notifier_id));
710 // Verify that only running ephemeral apps will appear in the Notification
711 // Settings UI. Inactive, cached ephemeral apps should not appear.
712 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
713 IncludeRunningEphemeralAppsInNotifiers) {
714 message_center::NotifierSettingsProvider* settings_provider =
715 message_center::MessageCenter::Get()->GetNotifierSettingsProvider();
716 DCHECK(settings_provider);
718 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
719 ASSERT_TRUE(app);
720 message_center::NotifierId notifier_id(
721 message_center::NotifierId::APPLICATION, app->id());
723 // Since the ephemeral app is running, it should be included in the list
724 // of notifiers to show in the UI.
725 NotifierList notifiers;
726 STLElementDeleter<NotifierList> notifier_deleter(&notifiers);
728 settings_provider->GetNotifierList(&notifiers);
729 EXPECT_TRUE(IsNotifierInList(notifier_id, notifiers));
730 STLDeleteElements(&notifiers);
732 // Close the ephemeral app.
733 CloseAppWaitForUnload(app->id());
735 // Inactive ephemeral apps should not be included in the list of notifiers to
736 // show in the UI.
737 settings_provider->GetNotifierList(&notifiers);
738 EXPECT_FALSE(IsNotifierInList(notifier_id, notifiers));
741 // Verify that ephemeral apps will have no ability to retain file entries after
742 // close. Normal retainEntry behavior for installed apps is tested in
743 // FileSystemApiTest.
744 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
745 DisableRetainFileSystemEntries) {
746 // Create a dummy file that we can just return to the test.
747 base::ScopedTempDir temp_dir;
748 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
749 base::FilePath temp_file;
750 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file));
752 using extensions::FileSystemChooseEntryFunction;
753 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
754 &temp_file);
755 // The temporary file needs to be registered for the tests to pass on
756 // ChromeOS.
757 FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
758 "temp", temp_dir.path());
760 // The first test opens the file and writes the file handle to local storage.
761 const Extension* app = InstallEphemeralApp(kFileSystemTestApp,
762 Manifest::UNPACKED);
763 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_;
765 // Verify that after the app has been closed, all retained entries are
766 // flushed.
767 std::vector<apps::SavedFileEntry> file_entries =
768 apps::SavedFilesService::Get(profile())
769 ->GetAllFileEntries(app->id());
770 EXPECT_TRUE(file_entries.empty());
772 // The second test verifies that the file cannot be reopened.
773 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_;
776 // Checks the process of launching an ephemeral app and then promoting the app
777 // while it is running.
778 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileRunning) {
779 InitSyncService();
781 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
782 ASSERT_TRUE(app);
784 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
786 // Ensure that the app is not unloaded and disabled after it is closed.
787 CloseApp(app->id());
788 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED);
791 // Checks the process of launching an ephemeral app and then promoting the app
792 // while it is idle.
793 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileIdle) {
794 InitSyncService();
796 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
797 ASSERT_TRUE(app);
798 CloseAppWaitForUnload(app->id());
799 VerifyInactiveEphemeralApp(app->id());
801 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
804 // Verifies that promoting an ephemeral app that was disabled due to a
805 // permissions increase will enable it.
806 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppAndGrantPermissions) {
807 InitSyncService();
809 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
810 ASSERT_TRUE(app);
811 CloseAppWaitForUnload(app->id());
812 DisableEphemeralApp(app, Extension::DISABLE_PERMISSIONS_INCREASE);
814 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED);
815 EXPECT_FALSE(ExtensionPrefs::Get(profile())
816 ->DidExtensionEscalatePermissions(app->id()));
819 // Verifies that promoting an ephemeral app that has unsupported requirements
820 // will not enable it.
821 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
822 PromoteUnsupportedEphemeralApp) {
823 InitSyncService();
825 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
826 ASSERT_TRUE(app);
827 CloseAppWaitForUnload(app->id());
828 DisableEphemeralApp(app, Extension::DISABLE_UNSUPPORTED_REQUIREMENT);
830 // When promoted to a regular installed app, it should remain disabled.
831 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::DISABLED);
834 // Verifies that promoting an ephemeral app that is blacklisted will not enable
835 // it.
836 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
837 PromoteBlacklistedEphemeralApp) {
838 InitSyncService();
840 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
841 ASSERT_TRUE(app);
842 CloseAppWaitForUnload(app->id());
844 ExtensionService* service =
845 ExtensionSystem::Get(profile())->extension_service();
846 service->BlacklistExtensionForTest(app->id());
847 ASSERT_TRUE(
848 ExtensionRegistry::Get(profile())->blacklisted_extensions().Contains(
849 app->id()));
851 // When promoted to a regular installed app, it should remain blacklisted.
852 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::BLACKLISTED);
854 // The app should be synced, but disabled.
855 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app->id());
856 VerifySyncChange(sync_change.get(), false);
859 // Checks the process of promoting an ephemeral app from sync while the app is
860 // running.
861 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
862 PromoteAppFromSyncWhileRunning) {
863 InitSyncService();
865 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
866 ASSERT_TRUE(app);
868 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED);
870 // Ensure that the app is not unloaded and disabled after it is closed.
871 CloseApp(app->id());
872 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED);
875 // Checks the process of promoting an ephemeral app from sync while the app is
876 // idle.
877 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppFromSyncWhileIdle) {
878 InitSyncService();
880 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
881 ASSERT_TRUE(app);
882 CloseAppWaitForUnload(app->id());
883 VerifyInactiveEphemeralApp(app->id());
885 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED);
888 // Checks the process of promoting an ephemeral app from sync, where the app
889 // from sync is disabled, and the ephemeral app is running.
890 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
891 PromoteDisabledAppFromSyncWhileRunning) {
892 InitSyncService();
894 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
895 ASSERT_TRUE(app);
897 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED);
900 // Checks the process of promoting an ephemeral app from sync, where the app
901 // from sync is disabled, and the ephemeral app is idle.
902 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
903 PromoteDisabledAppFromSyncWhileIdle) {
904 InitSyncService();
906 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
907 ASSERT_TRUE(app);
908 CloseAppWaitForUnload(app->id());
909 VerifyInactiveEphemeralApp(app->id());
911 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED);
914 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to
915 // permanently install an ephemeral app. However, there may be cases where an
916 // install occurs through the usual route of installing from the Web Store (due
917 // to race conditions). Ensure that the app is still installed correctly.
918 #if defined(OS_WIN)
919 // Disabled on Windows due to failures. See crbug.com/401028
920 #define MAYBE_ReplaceEphemeralAppWithInstalledApp \
921 DISABLED_ReplaceEphemeralAppWithInstalledApp
922 #else
923 #define MAYBE_ReplaceEphemeralAppWithInstalledApp \
924 ReplaceEphemeralAppWithInstalledApp
925 #endif
926 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
927 MAYBE_ReplaceEphemeralAppWithInstalledApp) {
928 InitSyncService();
930 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp);
931 ASSERT_TRUE(app);
932 CloseAppWaitForUnload(app->id());
933 std::string app_id = app->id();
934 app = NULL;
936 InstallObserver installed_observer(profile());
937 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 1);
938 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED);
940 // Check the notification parameters.
941 const InstallObserver::InstallParameters& params = installed_observer.Last();
942 EXPECT_EQ(app_id, params.id);
943 EXPECT_TRUE(params.is_update);
944 EXPECT_TRUE(params.from_ephemeral);
947 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will
948 // be delayed until the app is idle.
949 #if defined(OS_WIN)
950 // Disabled on Windows due to failures. See crbug.com/401028
951 #define MAYBE_ReplaceEphemeralAppWithDelayedInstalledApp \
952 DISABLED_ReplaceEphemeralAppWithDelayedInstalledApp
953 #else
954 #define MAYBE_ReplaceEphemeralAppWithDelayedInstalledApp \
955 ReplaceEphemeralAppWithDelayedInstalledApp
956 #endif
957 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
958 MAYBE_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 content::WindowedNotificationObserver installed_signal(
970 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
971 content::Source<Profile>(profile()));
972 InstallObserver installed_observer(profile());
973 CloseAppWaitForUnload(app_id);
974 installed_signal.Wait();
975 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED);
977 // Check the notification parameters.
978 const InstallObserver::InstallParameters& params = installed_observer.Last();
979 EXPECT_EQ(app_id, params.id);
980 EXPECT_TRUE(params.is_update);
981 EXPECT_TRUE(params.from_ephemeral);
984 // Verifies that an installed app cannot turn into an ephemeral app as result of
985 // race conditions, i.e. an ephemeral app can be promoted to an installed app,
986 // but not vice versa.
987 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
988 ReplaceInstalledAppWithEphemeralApp) {
989 const Extension* app = InstallPlatformApp(kNotificationsTestApp);
990 ASSERT_TRUE(app);
991 std::string app_id = app->id();
992 app = NULL;
994 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile()));
995 app =
996 InstallEphemeralAppWithSourceAndFlags(GetTestPath(kNotificationsTestApp),
998 Manifest::INTERNAL,
999 Extension::NO_FLAGS);
1000 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile()));
1003 // Ephemerality was previously encoded by the Extension::IS_EPHEMERAL creation
1004 // flag. This was changed to an "ephemeral_app" property. Check that the prefs
1005 // are handled correctly.
1006 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
1007 ExtensionPrefBackcompatibility) {
1008 // Ensure that apps with the old prefs are recognized as ephemeral.
1009 const Extension* app =
1010 InstallExtensionWithSourceAndFlags(GetTestPath(kNotificationsTestApp),
1012 Manifest::INTERNAL,
1013 Extension::IS_EPHEMERAL);
1014 ASSERT_TRUE(app);
1015 EXPECT_TRUE(extensions::util::IsEphemeralApp(app->id(), profile()));
1017 // Ensure that when the app is promoted to an installed app, the bit in the
1018 // creation flags is cleared.
1019 PromoteEphemeralApp(app);
1020 EXPECT_FALSE(extensions::util::IsEphemeralApp(app->id(), profile()));
1022 int creation_flags =
1023 ExtensionPrefs::Get(profile())->GetCreationFlags(app->id());
1024 EXPECT_EQ(0, creation_flags & Extension::IS_EPHEMERAL);
1027 // Verifies that the power keep awake will be automatically released for
1028 // ephemeral apps that stop running. Well behaved apps should actually call
1029 // chrome.power.releaseKeepAwake() themselves.
1030 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, ReleasePowerKeepAwake) {
1031 PowerSettingsMock power_settings;
1032 extensions::PowerApiManager* power_manager =
1033 extensions::PowerApiManager::Get(profile());
1034 power_manager->SetCreateBlockerFunctionForTesting(
1035 base::Bind(&PowerSaveBlockerStub::Create, &power_settings));
1037 const Extension* app = InstallAndLaunchEphemeralApp(kPowerTestApp);
1038 ASSERT_TRUE(app);
1039 EXPECT_EQ(1, power_settings.keep_awake_count());
1041 CloseAppWaitForUnload(app->id());
1043 EXPECT_EQ(0, power_settings.keep_awake_count());