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"
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_util.h"
21 #include "chrome/browser/notifications/desktop_notification_service.h"
22 #include "chrome/browser/notifications/desktop_notification_service_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::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
;
57 using extensions::ResultCatcher
;
61 namespace alarms
= extensions::core_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
68 const bool kEnableSync
= false;
70 const bool kEnableSync
= true;
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
)
87 // Saves some parameters from the extension installed notification in order
88 // to verify them in tests.
89 class InstallObserver
: public ExtensionRegistryObserver
{
91 struct InstallParameters
{
97 const std::string
& id
,
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();
115 void OnExtensionWillBeInstalled(content::BrowserContext
* browser_context
,
116 const Extension
* extension
,
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
>
129 // Instead of actually changing the system power settings, tests will just
130 // issue requests to this mock.
131 class PowerSettingsMock
{
133 PowerSettingsMock() : keep_awake_count_(0) {}
135 void request_keep_awake() { ++keep_awake_count_
; }
137 void release_keep_awake() {
139 ASSERT_GE(keep_awake_count_
, 0);
142 int keep_awake_count() const { return keep_awake_count_
; }
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
{
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
,
164 const std::string
& description
) {
165 return scoped_ptr
<PowerSaveBlocker
>(
166 new PowerSaveBlockerStub(power_settings
));
170 PowerSettingsMock
* power_settings_
; // Not owned.
172 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub
);
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
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
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
);
226 EXPECT_TRUE(extensions::util::IsEphemeralApp(extension
->id(), profile()));
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
);
243 LaunchPlatformApp(extension
);
244 bool wait_result
= launched_listener
.WaitUntilSatisfied();
245 EXPECT_TRUE(wait_result
);
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();
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 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(profile());
298 // Disabling due to a permissions increase also involves setting the
299 // DidExtensionEscalatePermissions flag.
300 if (disable_reason
== Extension::DISABLE_PERMISSIONS_INCREASE
)
301 prefs
->SetDidExtensionEscalatePermissions(app
, true);
303 ExtensionSystem::Get(profile())->extension_service()->DisableExtension(
304 app
->id(), disable_reason
);
306 ASSERT_TRUE(ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
310 void EphemeralAppTestBase::CloseApp(const std::string
& app_id
) {
311 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id
));
312 extensions::AppWindow
* app_window
= GetFirstAppWindowForApp(app_id
);
313 ASSERT_TRUE(app_window
);
314 CloseAppWindow(app_window
);
317 void EphemeralAppTestBase::CloseAppWaitForUnload(const std::string
& app_id
) {
318 // Ephemeral apps are unloaded from extension system after they stop running.
319 extensions::TestExtensionRegistryObserver
observer(
320 ExtensionRegistry::Get(profile()), app_id
);
322 observer
.WaitForExtensionUnloaded();
325 void EphemeralAppTestBase::EvictApp(const std::string
& app_id
) {
326 // Uninstall the app, which is what happens when ephemeral apps get evicted
328 extensions::TestExtensionRegistryObserver
observer(
329 ExtensionRegistry::Get(profile()), app_id
);
331 ExtensionService
* service
=
332 ExtensionSystem::Get(profile())->extension_service();
333 ASSERT_TRUE(service
);
334 service
->UninstallExtension(
336 extensions::UNINSTALL_REASON_ORPHANED_EPHEMERAL_EXTENSION
,
337 base::Bind(&base::DoNothing
),
340 observer
.WaitForExtensionUninstalled();
343 // EphemeralAppBrowserTest:
345 class EphemeralAppBrowserTest
: public EphemeralAppTestBase
{
347 bool LaunchAppAndRunTest(const Extension
* app
, const char* test_name
) {
348 // Ephemeral apps are unloaded after they are closed. Ensure they are
349 // enabled before launch.
350 ExtensionService
* service
=
351 ExtensionSystem::Get(profile())->extension_service();
352 service
->EnableExtension(app
->id());
354 ExtensionTestMessageListener
launched_listener("launched", true);
355 LaunchPlatformApp(app
);
356 if (!launched_listener
.WaitUntilSatisfied()) {
357 message_
= "Failed to receive launched message from test";
361 ResultCatcher catcher
;
362 launched_listener
.Reply(test_name
);
364 bool result
= catcher
.GetNextResult();
365 message_
= catcher
.message();
367 CloseAppWaitForUnload(app
->id());
371 // Verify that the event page of the app has not been loaded.
372 void VerifyAppNotLoaded(const std::string
& app_id
) {
373 EXPECT_FALSE(extensions::ProcessManager::Get(profile())
374 ->GetBackgroundHostForExtension(app_id
));
377 // Verify properties of ephemeral apps.
378 void VerifyEphemeralApp(const std::string
& app_id
) {
379 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_id
, profile()));
381 // Ephemeral apps should not be synced.
382 scoped_ptr
<AppSyncData
> sync_change
= GetLastSyncChangeForApp(app_id
);
383 EXPECT_FALSE(sync_change
.get());
385 // Ephemeral apps should not be assigned ordinals.
386 extensions::AppSorting
* app_sorting
=
387 ExtensionPrefs::Get(profile())->app_sorting();
388 EXPECT_FALSE(app_sorting
->GetAppLaunchOrdinal(app_id
).IsValid());
389 EXPECT_FALSE(app_sorting
->GetPageOrdinal(app_id
).IsValid());
392 // Verify that after ephemeral apps stop running, they reside in extension
393 // system in a disabled and unloaded state.
394 void VerifyInactiveEphemeralApp(const std::string
& app_id
) {
396 ExtensionRegistry::Get(profile())->disabled_extensions().Contains(
399 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(profile());
400 EXPECT_TRUE(prefs
->IsExtensionDisabled(app_id
));
402 prefs
->GetDisableReasons(app_id
) &
403 Extension::DISABLE_INACTIVE_EPHEMERAL_APP
);
406 // Verify the state of an app that has been promoted from an ephemeral to a
407 // fully installed app.
408 void VerifyPromotedApp(const std::string
& app_id
,
409 ExtensionRegistry::IncludeFlag expected_set
) {
410 const Extension
* app
= ExtensionRegistry::Get(profile())
411 ->GetExtensionById(app_id
, expected_set
);
412 ASSERT_TRUE(app
) << "App not found in expected set: " << expected_set
;
414 // The app should not be ephemeral.
415 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(profile());
417 EXPECT_FALSE(prefs
->IsEphemeralApp(app_id
));
419 prefs
->GetDisableReasons(app_id
) &
420 Extension::DISABLE_INACTIVE_EPHEMERAL_APP
);
422 // Check sort ordinals.
423 extensions::AppSorting
* app_sorting
= prefs
->app_sorting();
424 EXPECT_TRUE(app_sorting
->GetAppLaunchOrdinal(app_id
).IsValid());
425 EXPECT_TRUE(app_sorting
->GetPageOrdinal(app_id
).IsValid());
428 // Dispatch a fake alarm event to the app.
429 void DispatchAlarmEvent(EventRouter
* event_router
,
430 const std::string
& app_id
) {
431 alarms::Alarm dummy_alarm
;
432 dummy_alarm
.name
= "test_alarm";
434 scoped_ptr
<base::ListValue
> args(new base::ListValue());
435 args
->Append(dummy_alarm
.ToValue().release());
436 scoped_ptr
<Event
> event(new Event(alarms::OnAlarm::kEventName
,
439 event_router
->DispatchEventToExtension(app_id
, event
.Pass());
442 // Simulates the scenario where an app is installed, via the normal
443 // installation route, on top of an ephemeral app. This can occur due to race
445 const Extension
* ReplaceEphemeralApp(const std::string
& app_id
,
446 const char* test_path
,
447 int expected_enabled_change
) {
448 return UpdateExtensionWaitForIdle(
449 app_id
, GetTestPath(test_path
), expected_enabled_change
);
452 void PromoteEphemeralAppAndVerify(
453 const Extension
* app
,
454 ExtensionRegistry::IncludeFlag expected_set
) {
457 // Ephemeral apps should not be synced.
458 scoped_ptr
<AppSyncData
> sync_change
= GetLastSyncChangeForApp(app
->id());
459 EXPECT_FALSE(sync_change
.get());
461 // Promote the app to a regular installed app.
462 InstallObserver
installed_observer(profile());
463 PromoteEphemeralApp(app
);
464 VerifyPromotedApp(app
->id(), expected_set
);
466 // Check the notification parameters.
467 const InstallObserver::InstallParameters
& params
=
468 installed_observer
.Last();
469 EXPECT_EQ(app
->id(), params
.id
);
470 EXPECT_TRUE(params
.is_update
);
471 EXPECT_TRUE(params
.from_ephemeral
);
473 // The installation should now be synced.
474 sync_change
= GetLastSyncChangeForApp(app
->id());
475 VerifySyncChange(sync_change
.get(),
476 expected_set
== ExtensionRegistry::ENABLED
);
479 void PromoteEphemeralAppFromSyncAndVerify(
480 const Extension
* app
,
481 bool enable_from_sync
,
482 ExtensionRegistry::IncludeFlag expected_set
) {
485 // Simulate an install from sync.
486 const syncer::StringOrdinal
kAppLaunchOrdinal("x");
487 const syncer::StringOrdinal
kPageOrdinal("y");
488 AppSyncData
app_sync_data(*app
,
490 false /* incognito enabled */,
491 false /* remote install */,
492 extensions::ExtensionSyncData::BOOLEAN_UNSET
,
495 extensions::LAUNCH_TYPE_REGULAR
);
497 std::string app_id
= app
->id();
500 ExtensionSyncService
* sync_service
= ExtensionSyncService::Get(profile());
501 sync_service
->ProcessAppSyncData(app_sync_data
);
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();
510 app_sorting
->GetAppLaunchOrdinal(app_id
).Equals(kAppLaunchOrdinal
));
511 EXPECT_TRUE(app_sorting
->GetPageOrdinal(app_id
).Equals(kPageOrdinal
));
514 void InitSyncService() {
518 ExtensionSyncService
* sync_service
= ExtensionSyncService::Get(profile());
519 sync_service
->MergeDataAndStartSyncing(
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
<AppSyncData
> GetLastSyncChangeForApp(const std::string
& id
) {
530 scoped_ptr
<AppSyncData
> 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
<AppSyncData
> data(AppSyncData::CreateFromSyncChange(*it
));
535 if (data
.get() && data
->id() == id
)
536 sync_data
.reset(data
.release());
539 return sync_data
.Pass();
542 void VerifySyncChange(const AppSyncData
* sync_change
, bool expect_enabled
) {
546 ASSERT_TRUE(sync_change
);
547 EXPECT_TRUE(sync_change
->page_ordinal().IsValid());
548 EXPECT_TRUE(sync_change
->app_launch_ordinal().IsValid());
549 EXPECT_FALSE(sync_change
->uninstalled());
550 EXPECT_EQ(expect_enabled
, sync_change
->extension_sync_data().enabled());
553 void TestInstallEvent(bool close_app
) {
554 ExtensionTestMessageListener
first_msg_listener(false);
555 const Extension
* app
= InstallAndLaunchEphemeralApp(kDispatchEventTestApp
);
558 // When an ephemeral app is first added, it should not receive the
559 // onInstalled event, hence the first message received from the test should
560 // be "launched" and not "installed".
561 ASSERT_TRUE(first_msg_listener
.WaitUntilSatisfied());
562 EXPECT_EQ(std::string("launched"), first_msg_listener
.message());
565 CloseAppWaitForUnload(app
->id());
567 // When installed permanently, the app should receive the onInstalled event.
568 ExtensionTestMessageListener
install_listener("installed", false);
569 PromoteEphemeralApp(app
);
570 ASSERT_TRUE(install_listener
.WaitUntilSatisfied());
574 syncer::FakeSyncChangeProcessor mock_sync_processor_
;
577 // Verify that ephemeral apps can be launched and receive system events when
578 // they are running. Once they are inactive they should not receive system
580 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, EventDispatchWhenLaunched
) {
581 const Extension
* extension
=
582 InstallAndLaunchEphemeralApp(kDispatchEventTestApp
);
583 ASSERT_TRUE(extension
);
585 // Send a fake alarm event to the app and verify that a response is
587 EventRouter
* event_router
= EventRouter::Get(profile());
588 ASSERT_TRUE(event_router
);
590 ExtensionTestMessageListener
alarm_received_listener("alarm_received", false);
591 DispatchAlarmEvent(event_router
, extension
->id());
592 ASSERT_TRUE(alarm_received_listener
.WaitUntilSatisfied());
594 CloseAppWaitForUnload(extension
->id());
596 // Dispatch the alarm event again and verify that the event page did not get
597 // loaded for the app.
598 DispatchAlarmEvent(event_router
, extension
->id());
599 VerifyAppNotLoaded(extension
->id());
602 // Verify that ephemeral apps will receive messages while they are running.
603 // Flaky test: crbug.com/394426
604 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
605 DISABLED_ReceiveMessagesWhenLaunched
) {
606 const Extension
* receiver
=
607 InstallAndLaunchEphemeralApp(kMessagingReceiverApp
);
608 ASSERT_TRUE(receiver
);
610 // Verify that messages are received while the app is running.
611 ResultCatcher result_catcher
;
612 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success",
614 EXPECT_TRUE(result_catcher
.GetNextResult());
616 CloseAppWaitForUnload(receiver
->id());
618 // Verify that messages are not received while the app is inactive.
619 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail", "Launched");
620 EXPECT_TRUE(result_catcher
.GetNextResult());
623 // Verifies that the chrome.runtime.onInstalled() event is received by a running
624 // ephemeral app only when it is promoted.
625 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
626 InstallEventReceivedWhileRunning
) {
627 TestInstallEvent(false /* close app */);
630 // Verifies that when an idle ephemeral app is promoted, it will be loaded to
631 // receive the chrome.runtime.onInstalled() event.
632 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, InstallEventReceivedWhileIdle
) {
633 TestInstallEvent(true /* close app */);
636 // Verifies that the chrome.runtime.onRestarted() event is received by an
638 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, RestartEventReceived
) {
639 const Extension
* app
= InstallAndLaunchEphemeralApp(kDispatchEventTestApp
);
641 CloseAppWaitForUnload(app
->id());
643 // Fake ephemeral app running before restart.
644 ExtensionSystem::Get(profile())->extension_service()->EnableExtension(
646 ASSERT_TRUE(ExtensionRegistry::Get(profile())->enabled_extensions().Contains(
648 ExtensionPrefs::Get(profile())->SetExtensionRunning(app
->id(), true);
650 ExtensionTestMessageListener
restart_listener("restarted", false);
651 apps::AppRestoreService::Get(profile())->HandleStartup(true);
652 EXPECT_TRUE(restart_listener
.WaitUntilSatisfied());
655 // Verify that an updated ephemeral app will still have its ephemeral flag
657 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, UpdateEphemeralApp
) {
660 const Extension
* app_v1
= InstallAndLaunchEphemeralApp(kMessagingReceiverApp
);
662 VerifyEphemeralApp(app_v1
->id());
663 CloseAppWaitForUnload(app_v1
->id());
664 VerifyInactiveEphemeralApp(app_v1
->id());
666 std::string app_id
= app_v1
->id();
667 base::Version app_original_version
= *app_v1
->version();
669 // Update to version 2 of the app.
670 app_v1
= NULL
; // The extension object will be destroyed during update.
671 InstallObserver
installed_observer(profile());
672 const Extension
* app_v2
=
673 UpdateEphemeralApp(app_id
,
674 GetTestPath(kMessagingReceiverAppV2
),
675 GetTestPath(kMessagingReceiverApp
)
676 .ReplaceExtension(FILE_PATH_LITERAL(".pem")));
678 // Check the notification parameters.
679 const InstallObserver::InstallParameters
& params
= installed_observer
.Last();
680 EXPECT_EQ(app_id
, params
.id
);
681 EXPECT_TRUE(params
.is_update
);
682 EXPECT_FALSE(params
.from_ephemeral
);
684 // The ephemeral flag should still be set.
686 EXPECT_GT(app_v2
->version()->CompareTo(app_original_version
), 0);
687 VerifyEphemeralApp(app_id
);
689 // The app should still be disabled in extension system.
690 VerifyInactiveEphemeralApp(app_id
);
693 // Verify that if notifications have been disabled for an ephemeral app, it will
694 // remain disabled even after being evicted from the cache.
695 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, StickyNotificationSettings
) {
696 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
699 // Disable notifications for this app.
700 DesktopNotificationService
* notification_service
=
701 DesktopNotificationServiceFactory::GetForProfile(profile());
702 ASSERT_TRUE(notification_service
);
704 message_center::NotifierId
notifier_id(
705 message_center::NotifierId::APPLICATION
, app
->id());
706 EXPECT_TRUE(notification_service
->IsNotifierEnabled(notifier_id
));
707 notification_service
->SetNotifierEnabled(notifier_id
, false);
708 EXPECT_FALSE(notification_service
->IsNotifierEnabled(notifier_id
));
711 CloseAppWaitForUnload(app
->id());
714 // Reinstall the ephemeral app and verify that notifications remain disabled.
715 app
= InstallEphemeralApp(kNotificationsTestApp
);
717 message_center::NotifierId
reinstalled_notifier_id(
718 message_center::NotifierId::APPLICATION
, app
->id());
719 EXPECT_FALSE(notification_service
->IsNotifierEnabled(
720 reinstalled_notifier_id
));
723 // Verify that only running ephemeral apps will appear in the Notification
724 // Settings UI. Inactive, cached ephemeral apps should not appear.
725 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
726 IncludeRunningEphemeralAppsInNotifiers
) {
727 message_center::NotifierSettingsProvider
* settings_provider
=
728 message_center::MessageCenter::Get()->GetNotifierSettingsProvider();
729 DCHECK(settings_provider
);
731 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
733 message_center::NotifierId
notifier_id(
734 message_center::NotifierId::APPLICATION
, app
->id());
736 // Since the ephemeral app is running, it should be included in the list
737 // of notifiers to show in the UI.
738 NotifierList notifiers
;
739 STLElementDeleter
<NotifierList
> notifier_deleter(¬ifiers
);
741 settings_provider
->GetNotifierList(¬ifiers
);
742 EXPECT_TRUE(IsNotifierInList(notifier_id
, notifiers
));
743 STLDeleteElements(¬ifiers
);
745 // Close the ephemeral app.
746 CloseAppWaitForUnload(app
->id());
748 // Inactive ephemeral apps should not be included in the list of notifiers to
750 settings_provider
->GetNotifierList(¬ifiers
);
751 EXPECT_FALSE(IsNotifierInList(notifier_id
, notifiers
));
754 // Verify that ephemeral apps will have no ability to retain file entries after
755 // close. Normal retainEntry behavior for installed apps is tested in
756 // FileSystemApiTest.
757 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
758 DisableRetainFileSystemEntries
) {
759 // Create a dummy file that we can just return to the test.
760 base::ScopedTempDir temp_dir
;
761 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
762 base::FilePath temp_file
;
763 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir
.path(), &temp_file
));
765 using extensions::FileSystemChooseEntryFunction
;
766 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
768 // The temporary file needs to be registered for the tests to pass on
770 FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest(
771 "temp", temp_dir
.path());
773 // The first test opens the file and writes the file handle to local storage.
774 const Extension
* app
= InstallEphemeralApp(kFileSystemTestApp
,
776 ASSERT_TRUE(LaunchAppAndRunTest(app
, "OpenAndRetainFile")) << message_
;
778 // Verify that after the app has been closed, all retained entries are
780 std::vector
<apps::SavedFileEntry
> file_entries
=
781 apps::SavedFilesService::Get(profile())
782 ->GetAllFileEntries(app
->id());
783 EXPECT_TRUE(file_entries
.empty());
785 // The second test verifies that the file cannot be reopened.
786 ASSERT_TRUE(LaunchAppAndRunTest(app
, "RestoreRetainedFile")) << message_
;
789 // Checks the process of launching an ephemeral app and then promoting the app
790 // while it is running.
791 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, PromoteAppWhileRunning
) {
794 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
797 PromoteEphemeralAppAndVerify(app
, ExtensionRegistry::ENABLED
);
799 // Ensure that the app is not unloaded and disabled after it is closed.
801 VerifyPromotedApp(app
->id(), ExtensionRegistry::ENABLED
);
804 // Checks the process of launching an ephemeral app and then promoting the app
806 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, PromoteAppWhileIdle
) {
809 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
811 CloseAppWaitForUnload(app
->id());
812 VerifyInactiveEphemeralApp(app
->id());
814 PromoteEphemeralAppAndVerify(app
, ExtensionRegistry::ENABLED
);
817 // Verifies that promoting an ephemeral app that was disabled due to a
818 // permissions increase will enable it.
819 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, PromoteAppAndGrantPermissions
) {
822 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
824 CloseAppWaitForUnload(app
->id());
825 DisableEphemeralApp(app
, Extension::DISABLE_PERMISSIONS_INCREASE
);
827 PromoteEphemeralAppAndVerify(app
, ExtensionRegistry::ENABLED
);
828 EXPECT_FALSE(ExtensionPrefs::Get(profile())
829 ->DidExtensionEscalatePermissions(app
->id()));
832 // Verifies that promoting an ephemeral app that has unsupported requirements
833 // will not enable it.
834 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
835 PromoteUnsupportedEphemeralApp
) {
838 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
840 CloseAppWaitForUnload(app
->id());
841 DisableEphemeralApp(app
, Extension::DISABLE_UNSUPPORTED_REQUIREMENT
);
843 // When promoted to a regular installed app, it should remain disabled.
844 PromoteEphemeralAppAndVerify(app
, ExtensionRegistry::DISABLED
);
847 // Verifies that promoting an ephemeral app that is blacklisted will not enable
849 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
850 PromoteBlacklistedEphemeralApp
) {
853 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
855 CloseAppWaitForUnload(app
->id());
857 ExtensionService
* service
=
858 ExtensionSystem::Get(profile())->extension_service();
859 service
->BlacklistExtensionForTest(app
->id());
861 ExtensionRegistry::Get(profile())->blacklisted_extensions().Contains(
864 // When promoted to a regular installed app, it should remain blacklisted.
865 PromoteEphemeralAppAndVerify(app
, ExtensionRegistry::BLACKLISTED
);
867 // The app should be synced, but disabled.
868 scoped_ptr
<AppSyncData
> sync_change
= GetLastSyncChangeForApp(app
->id());
869 VerifySyncChange(sync_change
.get(), false);
872 // Checks the process of promoting an ephemeral app from sync while the app is
874 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
875 PromoteAppFromSyncWhileRunning
) {
878 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
881 PromoteEphemeralAppFromSyncAndVerify(app
, true, ExtensionRegistry::ENABLED
);
883 // Ensure that the app is not unloaded and disabled after it is closed.
885 VerifyPromotedApp(app
->id(), ExtensionRegistry::ENABLED
);
888 // Checks the process of promoting an ephemeral app from sync while the app is
890 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, PromoteAppFromSyncWhileIdle
) {
893 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
895 CloseAppWaitForUnload(app
->id());
896 VerifyInactiveEphemeralApp(app
->id());
898 PromoteEphemeralAppFromSyncAndVerify(app
, true, ExtensionRegistry::ENABLED
);
901 // Checks the process of promoting an ephemeral app from sync, where the app
902 // from sync is disabled, and the ephemeral app is running.
903 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
904 PromoteDisabledAppFromSyncWhileRunning
) {
907 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
910 PromoteEphemeralAppFromSyncAndVerify(app
, false, ExtensionRegistry::DISABLED
);
913 // Checks the process of promoting an ephemeral app from sync, where the app
914 // from sync is disabled, and the ephemeral app is idle.
915 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
916 PromoteDisabledAppFromSyncWhileIdle
) {
919 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
921 CloseAppWaitForUnload(app
->id());
922 VerifyInactiveEphemeralApp(app
->id());
924 PromoteEphemeralAppFromSyncAndVerify(app
, false, ExtensionRegistry::DISABLED
);
927 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to
928 // permanently install an ephemeral app. However, there may be cases where an
929 // install occurs through the usual route of installing from the Web Store (due
930 // to race conditions). Ensure that the app is still installed correctly.
931 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
932 ReplaceEphemeralAppWithInstalledApp
) {
935 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
937 CloseAppWaitForUnload(app
->id());
938 std::string app_id
= app
->id();
941 InstallObserver
installed_observer(profile());
942 ReplaceEphemeralApp(app_id
, kNotificationsTestApp
, 1);
943 VerifyPromotedApp(app_id
, ExtensionRegistry::ENABLED
);
945 // Check the notification parameters.
946 const InstallObserver::InstallParameters
& params
= installed_observer
.Last();
947 EXPECT_EQ(app_id
, params
.id
);
948 EXPECT_TRUE(params
.is_update
);
949 EXPECT_TRUE(params
.from_ephemeral
);
952 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will
953 // be delayed until the app is idle.
954 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
955 ReplaceEphemeralAppWithDelayedInstalledApp
) {
957 const Extension
* app
= InstallAndLaunchEphemeralApp(kNotificationsTestApp
);
959 std::string app_id
= app
->id();
963 ReplaceEphemeralApp(app_id
, kNotificationsTestApp
, 0);
965 // The delayed installation will occur when the ephemeral app is closed.
966 extensions::TestExtensionRegistryObserver
observer(
967 ExtensionRegistry::Get(profile()), app_id
);
968 InstallObserver
installed_observer(profile());
969 CloseAppWaitForUnload(app_id
);
970 observer
.WaitForExtensionWillBeInstalled();
971 VerifyPromotedApp(app_id
, ExtensionRegistry::ENABLED
);
973 // Check the notification parameters.
974 const InstallObserver::InstallParameters
& params
= installed_observer
.Last();
975 EXPECT_EQ(app_id
, params
.id
);
976 EXPECT_TRUE(params
.is_update
);
977 EXPECT_TRUE(params
.from_ephemeral
);
980 // Verifies that an installed app cannot turn into an ephemeral app as result of
981 // race conditions, i.e. an ephemeral app can be promoted to an installed app,
982 // but not vice versa.
983 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
984 ReplaceInstalledAppWithEphemeralApp
) {
985 const Extension
* app
= InstallPlatformApp(kNotificationsTestApp
);
987 std::string app_id
= app
->id();
990 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id
, profile()));
992 InstallEphemeralAppWithSourceAndFlags(GetTestPath(kNotificationsTestApp
),
995 Extension::NO_FLAGS
);
996 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id
, profile()));
999 // Ephemerality was previously encoded by the Extension::IS_EPHEMERAL creation
1000 // flag. This was changed to an "ephemeral_app" property. Check that the prefs
1001 // are handled correctly.
1002 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
,
1003 ExtensionPrefBackcompatibility
) {
1004 // Ensure that apps with the old prefs are recognized as ephemeral.
1005 const Extension
* app
=
1006 InstallExtensionWithSourceAndFlags(GetTestPath(kNotificationsTestApp
),
1009 Extension::IS_EPHEMERAL
);
1011 EXPECT_TRUE(extensions::util::IsEphemeralApp(app
->id(), profile()));
1013 // Ensure that when the app is promoted to an installed app, the bit in the
1014 // creation flags is cleared.
1015 PromoteEphemeralApp(app
);
1016 EXPECT_FALSE(extensions::util::IsEphemeralApp(app
->id(), profile()));
1018 int creation_flags
=
1019 ExtensionPrefs::Get(profile())->GetCreationFlags(app
->id());
1020 EXPECT_EQ(0, creation_flags
& Extension::IS_EPHEMERAL
);
1023 // Verifies that the power keep awake will be automatically released for
1024 // ephemeral apps that stop running. Well behaved apps should actually call
1025 // chrome.power.releaseKeepAwake() themselves.
1026 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, ReleasePowerKeepAwake
) {
1027 PowerSettingsMock power_settings
;
1028 extensions::PowerAPI::Get(profile())->SetCreateBlockerFunctionForTesting(
1029 base::Bind(&PowerSaveBlockerStub::Create
, &power_settings
));
1031 const Extension
* app
= InstallAndLaunchEphemeralApp(kPowerTestApp
);
1033 EXPECT_EQ(1, power_settings
.keep_awake_count());
1035 CloseAppWaitForUnload(app
->id());
1037 EXPECT_EQ(0, power_settings
.keep_awake_count());