Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Unified Diff: chrome/browser/apps/ephemeral_app_browsertest.cc

Issue 297263003: Optimize promotion of ephemeral apps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/apps/ephemeral_app_browsertest.cc
diff --git a/chrome/browser/apps/ephemeral_app_browsertest.cc b/chrome/browser/apps/ephemeral_app_browsertest.cc
index 0ea00bc4db791e572b1e0759bf4d02206a052ecc..480d3c1403f4c5c26a3f51590f452c985577677d 100644
--- a/chrome/browser/apps/ephemeral_app_browsertest.cc
+++ b/chrome/browser/apps/ephemeral_app_browsertest.cc
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/browser/apps/ephemeral_app_browsertest.h"
+
+#include <vector>
+
#include "apps/saved_files_service.h"
#include "base/files/scoped_temp_dir.h"
#include "base/stl_util.h"
@@ -13,14 +17,19 @@
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/desktop_notification_service_factory.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/alarms.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
+#include "extensions/browser/app_sorting.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/process_manager.h"
+#include "extensions/common/extension.h"
#include "extensions/common/switches.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/notifier_settings.h"
@@ -30,17 +39,15 @@ using extensions::EventRouter;
using extensions::Extension;
using extensions::ExtensionInfo;
using extensions::ExtensionPrefs;
+using extensions::ExtensionRegistry;
using extensions::ExtensionSystem;
using extensions::Manifest;
-using extensions::PlatformAppBrowserTest;
namespace {
namespace alarms = extensions::api::alarms;
const char kDispatchEventTestApp[] = "ephemeral_apps/dispatch_event";
-const char kMessagingReceiverApp[] = "ephemeral_apps/messaging_receiver";
-const char kMessagingReceiverAppV2[] = "ephemeral_apps/messaging_receiver2";
const char kNotificationsTestApp[] = "ephemeral_apps/notification_settings";
const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries";
const char kRetainDataApp[] = "ephemeral_apps/retain_data";
@@ -70,57 +77,188 @@ bool IsAppInExtensionsInfo(const ExtensionPrefs::ExtensionsInfo& ext_info,
return false;
}
-} // namespace
-
-class EphemeralAppBrowserTest : public PlatformAppBrowserTest {
- protected:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- // Skip PlatformAppBrowserTest, which sets different values for the switches
- // below.
- ExtensionBrowserTest::SetUpCommandLine(command_line);
-
- // Make event pages get suspended immediately.
- command_line->AppendSwitchASCII(
- extensions::switches::kEventPageIdleTime, "10");
- command_line->AppendSwitchASCII(
- extensions::switches::kEventPageSuspendingTime, "10");
+// Saves some parameters from the extension installed notification in order
+// to verify them in tests.
+class InstallObserver : public extensions::ExtensionRegistryObserver {
+ public:
+ struct InstallParameters {
+ std::string id;
+ bool is_update;
+ bool from_ephemeral;
+
+ InstallParameters(
+ const std::string& id,
+ bool is_update,
+ bool from_ephemeral)
+ : id(id), is_update(is_update), from_ephemeral(from_ephemeral) {}
+ };
+
+ explicit InstallObserver(Profile* profile) : profile_(profile) {
+ ExtensionRegistry::Get(profile)->AddObserver(this);
}
- base::FilePath GetTestPath(const char* test_path) {
- return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path);
+ virtual ~InstallObserver() {
+ ExtensionRegistry::Get(profile_)->RemoveObserver(this);
}
- const Extension* InstallEphemeralApp(const char* test_path,
- Manifest::Location manifest_location) {
- const Extension* extension =
- InstallEphemeralAppWithSourceAndFlags(
- GetTestPath(test_path),
- 1,
- manifest_location,
- Extension::NO_FLAGS);
- return extension;
+ const InstallParameters& Last() {
+ CHECK(!install_params_.empty());
+ return install_params_.back();
}
- const Extension* InstallEphemeralApp(const char* test_path) {
- return InstallEphemeralApp(test_path, Manifest::INTERNAL);
+ private:
+ virtual void OnExtensionWillBeInstalled(
+ content::BrowserContext* browser_context,
+ const Extension* extension,
+ bool is_update,
+ bool from_ephemeral,
+ const std::string& old_name) OVERRIDE {
+ install_params_.push_back(
+ InstallParameters(extension->id(), is_update, from_ephemeral));
}
- const Extension* InstallAndLaunchEphemeralApp(const char* test_path) {
- ExtensionTestMessageListener launched_listener("launched", false);
- const Extension* extension = InstallEphemeralApp(test_path);
- EXPECT_TRUE(extension);
- if (!extension)
- return NULL;
+ Profile* profile_;
+ std::vector<InstallParameters> install_params_;
+};
+
+} // namespace
+
+
+// EphemeralAppTestBase:
+
+const char EphemeralAppTestBase::kMessagingReceiverApp[] =
+ "ephemeral_apps/messaging_receiver";
+const char EphemeralAppTestBase::kMessagingReceiverAppV2[] =
+ "ephemeral_apps/messaging_receiver2";
+
+EphemeralAppTestBase::EphemeralAppTestBase() {}
+
+EphemeralAppTestBase::~EphemeralAppTestBase() {}
+
+void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) {
+ // Skip PlatformAppBrowserTest, which sets different values for the switches
+ // below.
+ ExtensionBrowserTest::SetUpCommandLine(command_line);
+
+ // Make event pages get suspended immediately.
+ command_line->AppendSwitchASCII(
+ extensions::switches::kEventPageIdleTime, "10");
+ command_line->AppendSwitchASCII(
+ extensions::switches::kEventPageSuspendingTime, "10");
- LaunchPlatformApp(extension);
- bool wait_result = launched_listener.WaitUntilSatisfied();
- EXPECT_TRUE(wait_result);
- if (!wait_result)
- return NULL;
+ // Enable ephemeral apps flag.
+ command_line->AppendSwitch(switches::kEnableEphemeralApps);
+}
+
+base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) {
+ return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path);
+}
+
+const Extension* EphemeralAppTestBase::InstallEphemeralApp(
+ const char* test_path, Manifest::Location manifest_location) {
+ const Extension* extension =
+ InstallEphemeralAppWithSourceAndFlags(
benwells 2014/05/27 01:42:56 Is this git cl format? Looks like this line would
tmdiep 2014/05/27 07:46:05 Done
+ GetTestPath(test_path),
+ 1,
+ manifest_location,
+ Extension::NO_FLAGS);
+ return extension;
+}
+
+const Extension* EphemeralAppTestBase::InstallEphemeralApp(
+ const char* test_path) {
+ return InstallEphemeralApp(test_path, Manifest::INTERNAL);
+}
- return extension;
+const Extension* EphemeralAppTestBase::InstallAndLaunchEphemeralApp(
+ const char* test_path) {
+ ExtensionTestMessageListener launched_listener("launched", false);
+ const Extension* extension = InstallEphemeralApp(test_path);
+ EXPECT_TRUE(extension);
+ if (!extension)
+ return NULL;
+
+ LaunchPlatformApp(extension);
+ bool wait_result = launched_listener.WaitUntilSatisfied();
+ EXPECT_TRUE(wait_result);
+ if (!wait_result)
+ return NULL;
+
+ return extension;
+}
+
+const Extension* EphemeralAppTestBase::UpdateEphemeralApp(
+ const std::string& app_id,
+ const base::FilePath& test_dir,
+ const base::FilePath& pem_path) {
+ // Pack a new version of the app.
+ base::ScopedTempDir temp_dir;
+ EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx");
+ if (!base::DeleteFile(crx_path, false)) {
+ ADD_FAILURE() << "Failed to delete existing crx: " << crx_path.value();
+ return NULL;
}
+ base::FilePath app_v2_path = PackExtensionWithOptions(
+ test_dir, crx_path, pem_path, base::FilePath());
+ EXPECT_FALSE(app_v2_path.empty());
+
+ // Update the ephemeral app and wait for the update to finish.
+ extensions::CrxInstaller* crx_installer = NULL;
+ content::WindowedNotificationObserver windowed_observer(
+ chrome::NOTIFICATION_CRX_INSTALLER_DONE,
+ content::Source<extensions::CrxInstaller>(crx_installer));
+ ExtensionService* service =
+ ExtensionSystem::Get(profile())->extension_service();
+ EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true,
+ &crx_installer));
+ windowed_observer.Wait();
+
+ return service->GetExtensionById(app_id, false);
+}
+
+void EphemeralAppTestBase::InstallEphemeralAppPermanently(
+ const extensions::Extension* app) {
+ ExtensionService* extension_service =
+ ExtensionSystem::Get(profile())->extension_service();
+ ASSERT_TRUE(extension_service);
+ extension_service->InstallEphemeralApp(app, true);
+}
+
+void EphemeralAppTestBase::CloseApp(const std::string& app_id) {
+ content::WindowedNotificationObserver event_page_destroyed_signal(
+ chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+ content::Source<Profile>(profile()));
+
+ EXPECT_EQ(1U, GetAppWindowCountForApp(app_id));
+ apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id);
+ ASSERT_TRUE(app_window);
+ CloseAppWindow(app_window);
+
+ event_page_destroyed_signal.Wait();
+}
+
+void EphemeralAppTestBase::EvictApp(const std::string& app_id) {
+ // Uninstall the app, which is what happens when ephemeral apps get evicted
+ // from the cache.
+ content::WindowedNotificationObserver uninstalled_signal(
+ chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+ content::Source<Profile>(profile()));
+
+ ExtensionService* service =
+ ExtensionSystem::Get(profile())->extension_service();
+ ASSERT_TRUE(service);
+ service->UninstallExtension(app_id, false, NULL);
+
+ uninstalled_signal.Wait();
+}
+
+// EphemeralAppBrowserTest:
+
+class EphemeralAppBrowserTest : public EphemeralAppTestBase {
+ protected:
bool LaunchAppAndRunTest(const Extension* app, const char* test_name) {
ExtensionTestMessageListener launched_listener("launched", true);
LaunchPlatformApp(app);
@@ -139,36 +277,8 @@ class EphemeralAppBrowserTest : public PlatformAppBrowserTest {
return result;
}
- void CloseApp(const std::string& app_id) {
- content::WindowedNotificationObserver event_page_destroyed_signal(
- chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
- content::Source<Profile>(browser()->profile()));
-
- EXPECT_EQ(1U, GetAppWindowCountForApp(app_id));
- apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id);
- ASSERT_TRUE(app_window);
- CloseAppWindow(app_window);
-
- event_page_destroyed_signal.Wait();
- }
-
- void EvictApp(const std::string& app_id) {
- // Uninstall the app, which is what happens when ephemeral apps get evicted
- // from the cache.
- content::WindowedNotificationObserver uninstalled_signal(
- chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
- content::Source<Profile>(browser()->profile()));
-
- ExtensionService* service =
- ExtensionSystem::Get(browser()->profile())->extension_service();
- ASSERT_TRUE(service);
- service->UninstallExtension(app_id, false, NULL);
-
- uninstalled_signal.Wait();
- }
-
void VerifyAppNotLoaded(const std::string& app_id) {
- EXPECT_FALSE(ExtensionSystem::Get(browser()->profile())->
+ EXPECT_FALSE(ExtensionSystem::Get(profile())->
process_manager()->GetBackgroundHostForExtension(app_id));
}
@@ -187,10 +297,32 @@ class EphemeralAppBrowserTest : public PlatformAppBrowserTest {
void GarbageCollectData() {
EphemeralAppService* service =
- EphemeralAppService::Get(browser()->profile());
+ EphemeralAppService::Get(profile());
ASSERT_TRUE(service);
service->GarbageCollectData();
}
+
+ const Extension* ReplaceEphemeralApp(const std::string& app_id,
+ const char* test_path) {
+ return UpdateExtensionWaitForIdle(app_id, GetTestPath(test_path), 0);
+ }
+
+ void VerifyInstalledApp(const std::string& app_id) {
+ // The app should be loaded and enabled.
+ const Extension* app = ExtensionRegistry::Get(profile())->
+ GetExtensionById(app_id, ExtensionRegistry::ENABLED);
+ ASSERT_TRUE(app);
+
+ // The app should not be ephemeral.
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ ASSERT_TRUE(prefs);
+ EXPECT_FALSE(prefs->IsEphemeralApp(app_id));
+
+ // Check sort ordinals.
+ extensions::AppSorting* app_sorting = prefs->app_sorting();
+ EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid());
+ EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid());
+ }
};
// Verify that ephemeral apps can be launched and receive system events when
@@ -203,7 +335,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) {
// Send a fake alarm event to the app and verify that a response is
// received.
- EventRouter* event_router = EventRouter::Get(browser()->profile());
+ EventRouter* event_router = EventRouter::Get(profile());
ASSERT_TRUE(event_router);
ExtensionTestMessageListener alarm_received_listener("alarm_received", false);
@@ -251,36 +383,21 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) {
base::Version app_original_version = *app_v1->version();
app_v1 = NULL; // The extension object will be destroyed during update.
- // Pack version 2 of the app.
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx");
- if (!base::DeleteFile(crx_path, false)) {
- ADD_FAILURE() << "Failed to delete crx: " << crx_path.value();
- return;
- }
-
- base::FilePath app_v2_path = PackExtensionWithOptions(
- GetTestPath(kMessagingReceiverAppV2),
- crx_path,
+ // Update to version 2 of the app.
+ InstallObserver installed_observer(profile());
+ const Extension* app_v2 = UpdateEphemeralApp(
+ app_id, GetTestPath(kMessagingReceiverAppV2),
GetTestPath(kMessagingReceiverApp).ReplaceExtension(
- FILE_PATH_LITERAL(".pem")),
- base::FilePath());
- ASSERT_FALSE(app_v2_path.empty());
+ FILE_PATH_LITERAL(".pem")));
- // Update the ephemeral app and wait for the update to finish.
- extensions::CrxInstaller* crx_installer = NULL;
- content::WindowedNotificationObserver windowed_observer(
- chrome::NOTIFICATION_CRX_INSTALLER_DONE,
- content::Source<extensions::CrxInstaller>(crx_installer));
- ExtensionService* service =
- ExtensionSystem::Get(browser()->profile())->extension_service();
- EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true,
- &crx_installer));
- windowed_observer.Wait();
+ // Check the notification parameters.
+ const InstallObserver::InstallParameters& params =
+ installed_observer.Last();
+ EXPECT_EQ(app_id, params.id);
+ EXPECT_TRUE(params.is_update);
+ EXPECT_FALSE(params.from_ephemeral);
- const Extension* app_v2 = service->GetExtensionById(app_id, false);
+ // The ephemeral flag should still be enabled.
ASSERT_TRUE(app_v2);
EXPECT_TRUE(app_v2->version()->CompareTo(app_original_version) > 0);
EXPECT_TRUE(extensions::util::IsEphemeralApp(app_v2->id(), profile()));
@@ -294,7 +411,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) {
// Disable notifications for this app.
DesktopNotificationService* notification_service =
- DesktopNotificationServiceFactory::GetForProfile(browser()->profile());
+ DesktopNotificationServiceFactory::GetForProfile(profile());
ASSERT_TRUE(notification_service);
message_center::NotifierId notifier_id(
@@ -376,7 +493,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
// Verify that after the app has been closed, all retained entries are
// flushed.
std::vector<apps::SavedFileEntry> file_entries =
- apps::SavedFilesService::Get(browser()->profile())
+ apps::SavedFilesService::Get(profile())
->GetAllFileEntries(app->id());
EXPECT_TRUE(file_entries.empty());
@@ -402,7 +519,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) {
app = NULL;
// The app should be in the list of evicted apps.
- ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
ASSERT_TRUE(prefs);
scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
prefs->GetEvictedEphemeralAppsInfo());
@@ -414,14 +531,15 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) {
// The app should not be in the list of installed extensions.
extensions_info = prefs->GetInstalledExtensionsInfo();
EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id));
+ EXPECT_FALSE(prefs->IsEphemeralApp(app_id));
// Ensure the evicted app is considered to have isolated storage. This will
// prevent its data from getting garbage collected by
// ExtensionService::GarbageCollectIsolatedStorage().
GURL site_url = extensions::util::GetSiteForExtensionId(
- app_id, browser()->profile());
+ app_id, profile());
EXPECT_TRUE(extensions::util::SiteHasIsolatedStorage(
- site_url, browser()->profile()));
+ site_url, profile()));
// Phase 2 - Reinstall the ephemeral app and verify that data still exists
// in the storage.
@@ -437,6 +555,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) {
EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id));
single_extension_info = prefs->GetEvictedEphemeralAppInfo(app_id);
EXPECT_FALSE(single_extension_info.get());
+ EXPECT_TRUE(prefs->IsEphemeralApp(app_id));
}
// Verify that preferences are updated correctly when an evicted ephemeral app
@@ -454,7 +573,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEvictedEphemeralApp) {
ASSERT_TRUE(app);
// Verify that preferences are correct.
- ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
ASSERT_TRUE(prefs);
EXPECT_FALSE(prefs->IsEphemeralApp(app->id()));
@@ -478,7 +597,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RemoveInstalledData) {
app = NULL;
// The app should not be in the preferences.
- ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
ASSERT_TRUE(prefs);
scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
prefs->GetEvictedEphemeralAppsInfo());
@@ -510,7 +629,7 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, GarbageCollectData) {
EvictApp(retain_app_id);
retain_app = NULL;
- ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
ASSERT_TRUE(prefs);
// Both apps should be in the list of evicted apps.
@@ -539,3 +658,91 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, GarbageCollectData) {
evict_app = InstallEphemeralApp(kRetainDataApp);
ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "DataReset")) << message_;
}
+
+// Checks the process of installing an ephemeral app permanently.
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
+ InstallEphemeralAppPermanently) {
+ const Extension* app = InstallEphemeralApp(kRetainDataApp);
+ ASSERT_TRUE(app);
+
+ InstallObserver installed_observer(profile());
+ InstallEphemeralAppPermanently(app);
+ VerifyInstalledApp(app->id());
+
+ // Check the notification parameters.
+ const InstallObserver::InstallParameters& params =
+ installed_observer.Last();
+ EXPECT_EQ(app->id(), params.id);
+ EXPECT_TRUE(params.is_update);
+ EXPECT_TRUE(params.from_ephemeral);
+}
+
+// Verifies that installing an ephemeral app permanently will enable it.
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
+ InstallEphemeralAppPermanentlyAndEnable) {
+ const Extension* app = InstallEphemeralApp(kRetainDataApp);
+ ASSERT_TRUE(app);
+
+ // Disable the ephemeral app.
+ ExtensionService* service =
+ ExtensionSystem::Get(profile())->extension_service();
+ service->DisableExtension(app->id(), Extension::DISABLE_PERMISSIONS_INCREASE);
+ ASSERT_TRUE(ExtensionRegistry::Get(profile())->
+ GetExtensionById(app->id(), ExtensionRegistry::DISABLED));
+
+ // Install the app permanently.
+ InstallEphemeralAppPermanently(app);
+ VerifyInstalledApp(app->id());
+}
+
+// In most cases, ExtensionService::InstallEphemeralApp will be called to
+// permanently install an ephemeral app. However, there may be cases where an
+// install occurs through the usual route of installing from the Web Store.
+// Ensure that the app is still installed correctly.
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
+ ReplaceEphemeralAppWithInstalledApp) {
+ const Extension* app = InstallEphemeralApp(kRetainDataApp);
+ ASSERT_TRUE(app);
+ std::string app_id = app->id();
+ app = NULL;
+
+ InstallObserver installed_observer(profile());
+ ReplaceEphemeralApp(app_id, kRetainDataApp);
+ VerifyInstalledApp(app_id);
+
+ // Check the notification parameters.
+ const InstallObserver::InstallParameters& params =
+ installed_observer.Last();
+ EXPECT_EQ(app_id, params.id);
+ EXPECT_TRUE(params.is_update);
+ EXPECT_TRUE(params.from_ephemeral);
+}
+
+// This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will
+// be delayed until the app is idle.
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest,
+ ReplaceEphemeralAppWithDelayedInstalledApp) {
+ const Extension* app = InstallAndLaunchEphemeralApp(kRetainDataApp);
+ ASSERT_TRUE(app);
+ std::string app_id = app->id();
+ app = NULL;
+
+ // Initiate install.
+ ReplaceEphemeralApp(app_id, kRetainDataApp);
+
+ // The delayed installation will occur when the ephemeral app is closed.
+ content::WindowedNotificationObserver installed_signal(
+ chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
+ content::Source<Profile>(profile()));
+ InstallObserver installed_observer(profile());
+ CloseApp(app_id);
+ installed_signal.Wait();
+ VerifyInstalledApp(app_id);
+
+ // Check the notification parameters.
+ const InstallObserver::InstallParameters& params =
+ installed_observer.Last();
+ EXPECT_EQ(app_id, params.id);
+ EXPECT_TRUE(params.is_update);
+ EXPECT_TRUE(params.from_ephemeral);
+}

Powered by Google App Engine
This is Rietveld 408576698