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