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..3445281637111b936e15c2d044bdac341fe158c7 100644 |
--- a/chrome/browser/apps/ephemeral_app_browsertest.cc |
+++ b/chrome/browser/apps/ephemeral_app_browsertest.cc |
@@ -2,45 +2,60 @@ |
// 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/scoped_observer.h" |
#include "base/stl_util.h" |
#include "chrome/browser/apps/app_browsertest_util.h" |
#include "chrome/browser/apps/ephemeral_app_service.h" |
#include "chrome/browser/extensions/api/file_system/file_system_api.h" |
+#include "chrome/browser/extensions/app_sync_data.h" |
#include "chrome/browser/extensions/extension_service.h" |
+#include "chrome/browser/extensions/extension_sync_service.h" |
#include "chrome/browser/extensions/extension_test_message_listener.h" |
#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 "sync/api/fake_sync_change_processor.h" |
+#include "sync/api/sync_change_processor_wrapper_for_test.h" |
+#include "sync/api/sync_error_factory_mock.h" |
#include "ui/message_center/message_center.h" |
#include "ui/message_center/notifier_settings.h" |
+using extensions::AppSyncData; |
using extensions::Event; |
using extensions::EventRouter; |
using extensions::Extension; |
using extensions::ExtensionInfo; |
using extensions::ExtensionPrefs; |
+using extensions::ExtensionRegistry; |
+using extensions::ExtensionRegistryObserver; |
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 +85,186 @@ 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 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) : registry_observer_(this) { |
+ registry_observer_.Add(ExtensionRegistry::Get(profile)); |
} |
- base::FilePath GetTestPath(const char* test_path) { |
- return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); |
- } |
+ virtual ~InstallObserver() {} |
- 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; |
+ std::vector<InstallParameters> install_params_; |
+ ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> |
+ registry_observer_; |
+}; |
+ |
+} // 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"); |
+ |
+ // 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); |
+} |
- LaunchPlatformApp(extension); |
- bool wait_result = launched_listener.WaitUntilSatisfied(); |
- EXPECT_TRUE(wait_result); |
- if (!wait_result) |
- return NULL; |
+const Extension* EphemeralAppTestBase::InstallEphemeralApp( |
+ const char* test_path, Manifest::Location manifest_location) { |
+ const Extension* extension = InstallEphemeralAppWithSourceAndFlags( |
+ GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS); |
+ EXPECT_TRUE(extension); |
+ if (extension) |
+ EXPECT_TRUE(extensions::util::IsEphemeralApp(extension->id(), profile())); |
+ return extension; |
+} |
+ |
+const Extension* EphemeralAppTestBase::InstallEphemeralApp( |
+ const char* test_path) { |
+ return InstallEphemeralApp(test_path, Manifest::INTERNAL); |
+} |
+ |
+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()); |
- return extension; |
+ 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::PromoteEphemeralApp( |
+ const extensions::Extension* app) { |
+ ExtensionService* extension_service = |
+ ExtensionSystem::Get(profile())->extension_service(); |
+ ASSERT_TRUE(extension_service); |
+ extension_service->PromoteEphemeralApp(app, false); |
+} |
+ |
+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 +283,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 +303,67 @@ 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 VerifyPromotedApp(const std::string& app_id, |
+ ExtensionRegistry::IncludeFlag expected_set) { |
+ const Extension* app = ExtensionRegistry::Get(profile())->GetExtensionById( |
+ app_id, expected_set); |
+ 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()); |
+ } |
+ |
+ void InitSyncService() { |
+ ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
+ sync_service->MergeDataAndStartSyncing( |
+ syncer::APPS, |
+ syncer::SyncDataList(), |
+ scoped_ptr<syncer::SyncChangeProcessor>( |
+ new syncer::SyncChangeProcessorWrapperForTest( |
+ &mock_sync_processor_)), |
+ scoped_ptr<syncer::SyncErrorFactory>( |
+ new syncer::SyncErrorFactoryMock())); |
+ } |
+ |
+ scoped_ptr<AppSyncData> GetFirstSyncChangeForApp(const std::string& id) { |
+ scoped_ptr<AppSyncData> sync_data; |
+ for (syncer::SyncChangeList::iterator it = |
+ mock_sync_processor_.changes().begin(); |
+ it != mock_sync_processor_.changes().end(); ++it) { |
+ sync_data.reset(new AppSyncData(*it)); |
+ if (sync_data->id() == id) |
+ return sync_data.Pass(); |
+ } |
+ |
+ return scoped_ptr<AppSyncData>(); |
+ } |
+ |
+ void VerifySyncChange(const AppSyncData* sync_change, bool expect_enabled) { |
+ ASSERT_TRUE(sync_change); |
+ EXPECT_TRUE(sync_change->page_ordinal().IsValid()); |
+ EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid()); |
+ EXPECT_FALSE(sync_change->uninstalled()); |
+ EXPECT_EQ(expect_enabled, sync_change->extension_sync_data().enabled()); |
+ } |
+ |
+ syncer::FakeSyncChangeProcessor mock_sync_processor_; |
}; |
// Verify that ephemeral apps can be launched and receive system events when |
@@ -203,7 +376,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); |
@@ -246,41 +419,24 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, ReceiveMessagesWhenLaunched) { |
IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { |
const Extension* app_v1 = InstallEphemeralApp(kMessagingReceiverApp); |
ASSERT_TRUE(app_v1); |
- ASSERT_TRUE(extensions::util::IsEphemeralApp(app_v1->id(), profile())); |
std::string app_id = app_v1->id(); |
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 +450,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 +532,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 +558,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 +570,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 +594,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 +612,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 +636,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 +668,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 +697,161 @@ IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, GarbageCollectData) { |
evict_app = InstallEphemeralApp(kRetainDataApp); |
ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "DataReset")) << message_; |
} |
+ |
+// Checks the process of installing and then promoting an ephemeral app. |
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralApp) { |
+ InitSyncService(); |
+ |
+ const Extension* app = InstallEphemeralApp(kRetainDataApp); |
+ ASSERT_TRUE(app); |
+ |
+ // Ephemeral apps should not be synced. |
+ scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
+ EXPECT_FALSE(sync_change.get()); |
+ |
+ // Promote the app to a regular installed app. |
+ InstallObserver installed_observer(profile()); |
+ PromoteEphemeralApp(app); |
+ VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); |
+ |
+ // 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); |
+ |
+ // The installation should now be synced. |
+ sync_change = GetFirstSyncChangeForApp(app->id()); |
+ VerifySyncChange(sync_change.get(), true); |
+} |
+ |
+// Verifies that promoting an ephemeral app will enable it. |
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppAndEnable) { |
+ InitSyncService(); |
+ |
+ 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)); |
+ |
+ // Promote to a regular installed app. It should be enabled. |
+ PromoteEphemeralApp(app); |
+ VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); |
+ |
+ scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
+ VerifySyncChange(sync_change.get(), true); |
+} |
+ |
+// Verifies that promoting an ephemeral app that has unsupported requirements |
+// will not enable it. |
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
+ PromoteUnsupportedEphemeralApp) { |
+ InitSyncService(); |
+ |
+ 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_UNSUPPORTED_REQUIREMENT); |
+ ASSERT_TRUE(ExtensionRegistry::Get(profile())-> |
+ GetExtensionById(app->id(), ExtensionRegistry::DISABLED)); |
+ |
+ // Promote to a regular installed app. It should remain disabled. |
+ PromoteEphemeralApp(app); |
+ VerifyPromotedApp(app->id(), ExtensionRegistry::DISABLED); |
+ |
+ scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
+ VerifySyncChange(sync_change.get(), false); |
+} |
+ |
+// Checks the process of promoting an ephemeral app from sync. |
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppFromSync) { |
+ InitSyncService(); |
+ |
+ const Extension* app = InstallEphemeralApp(kRetainDataApp); |
+ ASSERT_TRUE(app); |
+ std::string app_id = app->id(); |
+ |
+ // Simulate an install from sync. |
+ const syncer::StringOrdinal kAppLaunchOrdinal("x"); |
+ const syncer::StringOrdinal kPageOrdinal("y"); |
+ AppSyncData app_sync_data( |
+ *app, |
+ true /* enabled */, |
+ false /* incognito enabled */, |
+ false /* remote install */, |
+ kAppLaunchOrdinal, |
+ kPageOrdinal, |
+ extensions::LAUNCH_TYPE_REGULAR); |
+ |
+ ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
+ sync_service->ProcessAppSyncData(app_sync_data); |
+ |
+ // Verify the installation. |
+ VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
+ |
+ // The sort ordinals from sync should not be overridden. |
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
+ extensions::AppSorting* app_sorting = prefs->app_sorting(); |
+ EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).Equals( |
+ kAppLaunchOrdinal)); |
+ EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal)); |
+} |
+ |
+// In most cases, ExtensionService::PromoteEphemeralApp() 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 (due |
+// to race conditions). 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); |
+ VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
+ |
+ // 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(); |
+ VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
+ |
+ // 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); |
+} |