Home | History | Annotate | Download | only in apps
      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 }
   1043