| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/apps/ephemeral_app_browsertest.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 5 #include "apps/saved_files_service.h" | 9 #include "apps/saved_files_service.h" |
| 6 #include "base/files/scoped_temp_dir.h" | 10 #include "base/files/scoped_temp_dir.h" |
| 7 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 8 #include "chrome/browser/apps/app_browsertest_util.h" | 12 #include "chrome/browser/apps/app_browsertest_util.h" |
| 9 #include "chrome/browser/apps/ephemeral_app_service.h" | 13 #include "chrome/browser/apps/ephemeral_app_service.h" |
| 10 #include "chrome/browser/extensions/api/file_system/file_system_api.h" | 14 #include "chrome/browser/extensions/api/file_system/file_system_api.h" |
| 15 #include "chrome/browser/extensions/app_sync_data.h" |
| 11 #include "chrome/browser/extensions/extension_service.h" | 16 #include "chrome/browser/extensions/extension_service.h" |
| 17 #include "chrome/browser/extensions/extension_sync_service.h" |
| 12 #include "chrome/browser/extensions/extension_test_message_listener.h" | 18 #include "chrome/browser/extensions/extension_test_message_listener.h" |
| 13 #include "chrome/browser/extensions/extension_util.h" | 19 #include "chrome/browser/extensions/extension_util.h" |
| 14 #include "chrome/browser/notifications/desktop_notification_service.h" | 20 #include "chrome/browser/notifications/desktop_notification_service.h" |
| 15 #include "chrome/browser/notifications/desktop_notification_service_factory.h" | 21 #include "chrome/browser/notifications/desktop_notification_service_factory.h" |
| 22 #include "chrome/common/chrome_switches.h" |
| 16 #include "chrome/common/extensions/api/alarms.h" | 23 #include "chrome/common/extensions/api/alarms.h" |
| 17 #include "content/public/test/browser_test.h" | 24 #include "content/public/test/browser_test.h" |
| 18 #include "content/public/test/test_utils.h" | 25 #include "content/public/test/test_utils.h" |
| 26 #include "extensions/browser/app_sorting.h" |
| 19 #include "extensions/browser/event_router.h" | 27 #include "extensions/browser/event_router.h" |
| 20 #include "extensions/browser/extension_prefs.h" | 28 #include "extensions/browser/extension_prefs.h" |
| 29 #include "extensions/browser/extension_registry.h" |
| 30 #include "extensions/browser/extension_registry_observer.h" |
| 21 #include "extensions/browser/extension_system.h" | 31 #include "extensions/browser/extension_system.h" |
| 22 #include "extensions/browser/extension_util.h" | 32 #include "extensions/browser/extension_util.h" |
| 23 #include "extensions/browser/process_manager.h" | 33 #include "extensions/browser/process_manager.h" |
| 34 #include "extensions/common/extension.h" |
| 24 #include "extensions/common/switches.h" | 35 #include "extensions/common/switches.h" |
| 36 #include "sync/api/fake_sync_change_processor.h" |
| 37 #include "sync/api/sync_change_processor_wrapper_for_test.h" |
| 38 #include "sync/api/sync_error_factory_mock.h" |
| 25 #include "ui/message_center/message_center.h" | 39 #include "ui/message_center/message_center.h" |
| 26 #include "ui/message_center/notifier_settings.h" | 40 #include "ui/message_center/notifier_settings.h" |
| 27 | 41 |
| 42 using extensions::AppSyncData; |
| 28 using extensions::Event; | 43 using extensions::Event; |
| 29 using extensions::EventRouter; | 44 using extensions::EventRouter; |
| 30 using extensions::Extension; | 45 using extensions::Extension; |
| 31 using extensions::ExtensionInfo; | 46 using extensions::ExtensionInfo; |
| 32 using extensions::ExtensionPrefs; | 47 using extensions::ExtensionPrefs; |
| 48 using extensions::ExtensionRegistry; |
| 33 using extensions::ExtensionSystem; | 49 using extensions::ExtensionSystem; |
| 34 using extensions::Manifest; | 50 using extensions::Manifest; |
| 35 using extensions::PlatformAppBrowserTest; | |
| 36 | 51 |
| 37 namespace { | 52 namespace { |
| 38 | 53 |
| 39 namespace alarms = extensions::api::alarms; | 54 namespace alarms = extensions::api::alarms; |
| 40 | 55 |
| 41 const char kDispatchEventTestApp[] = "ephemeral_apps/dispatch_event"; | 56 const char kDispatchEventTestApp[] = "ephemeral_apps/dispatch_event"; |
| 42 const char kMessagingReceiverApp[] = "ephemeral_apps/messaging_receiver"; | |
| 43 const char kMessagingReceiverAppV2[] = "ephemeral_apps/messaging_receiver2"; | |
| 44 const char kNotificationsTestApp[] = "ephemeral_apps/notification_settings"; | 57 const char kNotificationsTestApp[] = "ephemeral_apps/notification_settings"; |
| 45 const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries"; | 58 const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries"; |
| 46 const char kRetainDataApp[] = "ephemeral_apps/retain_data"; | 59 const char kRetainDataApp[] = "ephemeral_apps/retain_data"; |
| 47 | 60 |
| 48 typedef std::vector<message_center::Notifier*> NotifierList; | 61 typedef std::vector<message_center::Notifier*> NotifierList; |
| 49 | 62 |
| 50 bool IsNotifierInList(const message_center::NotifierId& notifier_id, | 63 bool IsNotifierInList(const message_center::NotifierId& notifier_id, |
| 51 const NotifierList& notifiers) { | 64 const NotifierList& notifiers) { |
| 52 for (NotifierList::const_iterator it = notifiers.begin(); | 65 for (NotifierList::const_iterator it = notifiers.begin(); |
| 53 it != notifiers.end(); ++it) { | 66 it != notifiers.end(); ++it) { |
| 54 const message_center::Notifier* notifier = *it; | 67 const message_center::Notifier* notifier = *it; |
| 55 if (notifier->notifier_id == notifier_id) | 68 if (notifier->notifier_id == notifier_id) |
| 56 return true; | 69 return true; |
| 57 } | 70 } |
| 58 | 71 |
| 59 return false; | 72 return false; |
| 60 } | 73 } |
| 61 | 74 |
| 62 bool IsAppInExtensionsInfo(const ExtensionPrefs::ExtensionsInfo& ext_info, | 75 bool IsAppInExtensionsInfo(const ExtensionPrefs::ExtensionsInfo& ext_info, |
| 63 const std::string& extension_id) { | 76 const std::string& extension_id) { |
| 64 for (size_t i = 0; i < ext_info.size(); ++i) { | 77 for (size_t i = 0; i < ext_info.size(); ++i) { |
| 65 ExtensionInfo* info = ext_info.at(i).get(); | 78 ExtensionInfo* info = ext_info.at(i).get(); |
| 66 if (info->extension_id == extension_id) | 79 if (info->extension_id == extension_id) |
| 67 return true; | 80 return true; |
| 68 } | 81 } |
| 69 | 82 |
| 70 return false; | 83 return false; |
| 71 } | 84 } |
| 72 | 85 |
| 86 // Saves some parameters from the extension installed notification in order |
| 87 // to verify them in tests. |
| 88 class InstallObserver : public extensions::ExtensionRegistryObserver { |
| 89 public: |
| 90 struct InstallParameters { |
| 91 std::string id; |
| 92 bool is_update; |
| 93 bool from_ephemeral; |
| 94 |
| 95 InstallParameters( |
| 96 const std::string& id, |
| 97 bool is_update, |
| 98 bool from_ephemeral) |
| 99 : id(id), is_update(is_update), from_ephemeral(from_ephemeral) {} |
| 100 }; |
| 101 |
| 102 explicit InstallObserver(Profile* profile) : profile_(profile) { |
| 103 ExtensionRegistry::Get(profile)->AddObserver(this); |
| 104 } |
| 105 |
| 106 virtual ~InstallObserver() { |
| 107 ExtensionRegistry::Get(profile_)->RemoveObserver(this); |
| 108 } |
| 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 Profile* profile_; |
| 127 std::vector<InstallParameters> install_params_; |
| 128 }; |
| 129 |
| 73 } // namespace | 130 } // namespace |
| 74 | 131 |
| 75 class EphemeralAppBrowserTest : public PlatformAppBrowserTest { | |
| 76 protected: | |
| 77 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
| 78 // Skip PlatformAppBrowserTest, which sets different values for the switches | |
| 79 // below. | |
| 80 ExtensionBrowserTest::SetUpCommandLine(command_line); | |
| 81 | 132 |
| 82 // Make event pages get suspended immediately. | 133 // EphemeralAppTestBase: |
| 83 command_line->AppendSwitchASCII( | 134 |
| 84 extensions::switches::kEventPageIdleTime, "10"); | 135 const char EphemeralAppTestBase::kMessagingReceiverApp[] = |
| 85 command_line->AppendSwitchASCII( | 136 "ephemeral_apps/messaging_receiver"; |
| 86 extensions::switches::kEventPageSuspendingTime, "10"); | 137 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] = |
| 138 "ephemeral_apps/messaging_receiver2"; |
| 139 |
| 140 EphemeralAppTestBase::EphemeralAppTestBase() {} |
| 141 |
| 142 EphemeralAppTestBase::~EphemeralAppTestBase() {} |
| 143 |
| 144 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) { |
| 145 // Skip PlatformAppBrowserTest, which sets different values for the switches |
| 146 // below. |
| 147 ExtensionBrowserTest::SetUpCommandLine(command_line); |
| 148 |
| 149 // Make event pages get suspended immediately. |
| 150 command_line->AppendSwitchASCII( |
| 151 extensions::switches::kEventPageIdleTime, "10"); |
| 152 command_line->AppendSwitchASCII( |
| 153 extensions::switches::kEventPageSuspendingTime, "10"); |
| 154 |
| 155 // Enable ephemeral apps flag. |
| 156 command_line->AppendSwitch(switches::kEnableEphemeralApps); |
| 157 } |
| 158 |
| 159 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) { |
| 160 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); |
| 161 } |
| 162 |
| 163 const Extension* EphemeralAppTestBase::InstallEphemeralApp( |
| 164 const char* test_path, Manifest::Location manifest_location) { |
| 165 const Extension* extension = InstallEphemeralAppWithSourceAndFlags( |
| 166 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS); |
| 167 return extension; |
| 168 } |
| 169 |
| 170 const Extension* EphemeralAppTestBase::InstallEphemeralApp( |
| 171 const char* test_path) { |
| 172 return InstallEphemeralApp(test_path, Manifest::INTERNAL); |
| 173 } |
| 174 |
| 175 const Extension* EphemeralAppTestBase::InstallAndLaunchEphemeralApp( |
| 176 const char* test_path) { |
| 177 ExtensionTestMessageListener launched_listener("launched", false); |
| 178 const Extension* extension = InstallEphemeralApp(test_path); |
| 179 EXPECT_TRUE(extension); |
| 180 if (!extension) |
| 181 return NULL; |
| 182 |
| 183 LaunchPlatformApp(extension); |
| 184 bool wait_result = launched_listener.WaitUntilSatisfied(); |
| 185 EXPECT_TRUE(wait_result); |
| 186 if (!wait_result) |
| 187 return NULL; |
| 188 |
| 189 return extension; |
| 190 } |
| 191 |
| 192 const Extension* EphemeralAppTestBase::UpdateEphemeralApp( |
| 193 const std::string& app_id, |
| 194 const base::FilePath& test_dir, |
| 195 const base::FilePath& pem_path) { |
| 196 // Pack a new version of the app. |
| 197 base::ScopedTempDir temp_dir; |
| 198 EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 199 |
| 200 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx"); |
| 201 if (!base::DeleteFile(crx_path, false)) { |
| 202 ADD_FAILURE() << "Failed to delete existing crx: " << crx_path.value(); |
| 203 return NULL; |
| 87 } | 204 } |
| 88 | 205 |
| 89 base::FilePath GetTestPath(const char* test_path) { | 206 base::FilePath app_v2_path = PackExtensionWithOptions( |
| 90 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); | 207 test_dir, crx_path, pem_path, base::FilePath()); |
| 91 } | 208 EXPECT_FALSE(app_v2_path.empty()); |
| 92 | 209 |
| 93 const Extension* InstallEphemeralApp(const char* test_path, | 210 // Update the ephemeral app and wait for the update to finish. |
| 94 Manifest::Location manifest_location) { | 211 extensions::CrxInstaller* crx_installer = NULL; |
| 95 const Extension* extension = | 212 content::WindowedNotificationObserver windowed_observer( |
| 96 InstallEphemeralAppWithSourceAndFlags( | 213 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
| 97 GetTestPath(test_path), | 214 content::Source<extensions::CrxInstaller>(crx_installer)); |
| 98 1, | 215 ExtensionService* service = |
| 99 manifest_location, | 216 ExtensionSystem::Get(profile())->extension_service(); |
| 100 Extension::NO_FLAGS); | 217 EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true, |
| 101 return extension; | 218 &crx_installer)); |
| 102 } | 219 windowed_observer.Wait(); |
| 103 | 220 |
| 104 const Extension* InstallEphemeralApp(const char* test_path) { | 221 return service->GetExtensionById(app_id, false); |
| 105 return InstallEphemeralApp(test_path, Manifest::INTERNAL); | 222 } |
| 106 } | |
| 107 | 223 |
| 108 const Extension* InstallAndLaunchEphemeralApp(const char* test_path) { | 224 void EphemeralAppTestBase::PromoteEphemeralApp( |
| 109 ExtensionTestMessageListener launched_listener("launched", false); | 225 const extensions::Extension* app) { |
| 110 const Extension* extension = InstallEphemeralApp(test_path); | 226 ExtensionService* extension_service = |
| 111 EXPECT_TRUE(extension); | 227 ExtensionSystem::Get(profile())->extension_service(); |
| 112 if (!extension) | 228 ASSERT_TRUE(extension_service); |
| 113 return NULL; | 229 extension_service->PromoteEphemeralApp(app, false); |
| 230 } |
| 114 | 231 |
| 115 LaunchPlatformApp(extension); | 232 void EphemeralAppTestBase::CloseApp(const std::string& app_id) { |
| 116 bool wait_result = launched_listener.WaitUntilSatisfied(); | 233 content::WindowedNotificationObserver event_page_destroyed_signal( |
| 117 EXPECT_TRUE(wait_result); | 234 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
| 118 if (!wait_result) | 235 content::Source<Profile>(profile())); |
| 119 return NULL; | |
| 120 | 236 |
| 121 return extension; | 237 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id)); |
| 122 } | 238 apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id); |
| 239 ASSERT_TRUE(app_window); |
| 240 CloseAppWindow(app_window); |
| 123 | 241 |
| 242 event_page_destroyed_signal.Wait(); |
| 243 } |
| 244 |
| 245 void EphemeralAppTestBase::EvictApp(const std::string& app_id) { |
| 246 // Uninstall the app, which is what happens when ephemeral apps get evicted |
| 247 // from the cache. |
| 248 content::WindowedNotificationObserver uninstalled_signal( |
| 249 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
| 250 content::Source<Profile>(profile())); |
| 251 |
| 252 ExtensionService* service = |
| 253 ExtensionSystem::Get(profile())->extension_service(); |
| 254 ASSERT_TRUE(service); |
| 255 service->UninstallExtension(app_id, false, NULL); |
| 256 |
| 257 uninstalled_signal.Wait(); |
| 258 } |
| 259 |
| 260 // EphemeralAppBrowserTest: |
| 261 |
| 262 class EphemeralAppBrowserTest : public EphemeralAppTestBase { |
| 263 protected: |
| 124 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) { | 264 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) { |
| 125 ExtensionTestMessageListener launched_listener("launched", true); | 265 ExtensionTestMessageListener launched_listener("launched", true); |
| 126 LaunchPlatformApp(app); | 266 LaunchPlatformApp(app); |
| 127 if (!launched_listener.WaitUntilSatisfied()) { | 267 if (!launched_listener.WaitUntilSatisfied()) { |
| 128 message_ = "Failed to receive launched message from test"; | 268 message_ = "Failed to receive launched message from test"; |
| 129 return false; | 269 return false; |
| 130 } | 270 } |
| 131 | 271 |
| 132 ResultCatcher catcher; | 272 ResultCatcher catcher; |
| 133 launched_listener.Reply(test_name); | 273 launched_listener.Reply(test_name); |
| 134 | 274 |
| 135 bool result = catcher.GetNextResult(); | 275 bool result = catcher.GetNextResult(); |
| 136 message_ = catcher.message(); | 276 message_ = catcher.message(); |
| 137 | 277 |
| 138 CloseApp(app->id()); | 278 CloseApp(app->id()); |
| 139 return result; | 279 return result; |
| 140 } | 280 } |
| 141 | 281 |
| 142 void CloseApp(const std::string& app_id) { | |
| 143 content::WindowedNotificationObserver event_page_destroyed_signal( | |
| 144 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | |
| 145 content::Source<Profile>(browser()->profile())); | |
| 146 | |
| 147 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id)); | |
| 148 apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id); | |
| 149 ASSERT_TRUE(app_window); | |
| 150 CloseAppWindow(app_window); | |
| 151 | |
| 152 event_page_destroyed_signal.Wait(); | |
| 153 } | |
| 154 | |
| 155 void EvictApp(const std::string& app_id) { | |
| 156 // Uninstall the app, which is what happens when ephemeral apps get evicted | |
| 157 // from the cache. | |
| 158 content::WindowedNotificationObserver uninstalled_signal( | |
| 159 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | |
| 160 content::Source<Profile>(browser()->profile())); | |
| 161 | |
| 162 ExtensionService* service = | |
| 163 ExtensionSystem::Get(browser()->profile())->extension_service(); | |
| 164 ASSERT_TRUE(service); | |
| 165 service->UninstallExtension(app_id, false, NULL); | |
| 166 | |
| 167 uninstalled_signal.Wait(); | |
| 168 } | |
| 169 | |
| 170 void VerifyAppNotLoaded(const std::string& app_id) { | 282 void VerifyAppNotLoaded(const std::string& app_id) { |
| 171 EXPECT_FALSE(ExtensionSystem::Get(browser()->profile())-> | 283 EXPECT_FALSE(ExtensionSystem::Get(profile())-> |
| 172 process_manager()->GetBackgroundHostForExtension(app_id)); | 284 process_manager()->GetBackgroundHostForExtension(app_id)); |
| 173 } | 285 } |
| 174 | 286 |
| 175 void DispatchAlarmEvent(EventRouter* event_router, | 287 void DispatchAlarmEvent(EventRouter* event_router, |
| 176 const std::string& app_id) { | 288 const std::string& app_id) { |
| 177 alarms::Alarm dummy_alarm; | 289 alarms::Alarm dummy_alarm; |
| 178 dummy_alarm.name = "test_alarm"; | 290 dummy_alarm.name = "test_alarm"; |
| 179 | 291 |
| 180 scoped_ptr<base::ListValue> args(new base::ListValue()); | 292 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 181 args->Append(dummy_alarm.ToValue().release()); | 293 args->Append(dummy_alarm.ToValue().release()); |
| 182 scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, | 294 scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, |
| 183 args.Pass())); | 295 args.Pass())); |
| 184 | 296 |
| 185 event_router->DispatchEventToExtension(app_id, event.Pass()); | 297 event_router->DispatchEventToExtension(app_id, event.Pass()); |
| 186 } | 298 } |
| 187 | 299 |
| 188 void GarbageCollectData() { | 300 void GarbageCollectData() { |
| 189 EphemeralAppService* service = | 301 EphemeralAppService* service = |
| 190 EphemeralAppService::Get(browser()->profile()); | 302 EphemeralAppService::Get(profile()); |
| 191 ASSERT_TRUE(service); | 303 ASSERT_TRUE(service); |
| 192 service->GarbageCollectData(); | 304 service->GarbageCollectData(); |
| 193 } | 305 } |
| 306 |
| 307 const Extension* ReplaceEphemeralApp(const std::string& app_id, |
| 308 const char* test_path) { |
| 309 return UpdateExtensionWaitForIdle(app_id, GetTestPath(test_path), 0); |
| 310 } |
| 311 |
| 312 void VerifyInstalledApp(const std::string& app_id, |
| 313 ExtensionRegistry::IncludeFlag expected_set) { |
| 314 const Extension* app = ExtensionRegistry::Get(profile())->GetExtensionById( |
| 315 app_id, expected_set); |
| 316 ASSERT_TRUE(app); |
| 317 |
| 318 // The app should not be ephemeral. |
| 319 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 320 ASSERT_TRUE(prefs); |
| 321 EXPECT_FALSE(prefs->IsEphemeralApp(app_id)); |
| 322 |
| 323 // Check sort ordinals. |
| 324 extensions::AppSorting* app_sorting = prefs->app_sorting(); |
| 325 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); |
| 326 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid()); |
| 327 } |
| 328 |
| 329 void InitSyncService() { |
| 330 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
| 331 sync_service->MergeDataAndStartSyncing( |
| 332 syncer::APPS, |
| 333 syncer::SyncDataList(), |
| 334 scoped_ptr<syncer::SyncChangeProcessor>( |
| 335 new syncer::SyncChangeProcessorWrapperForTest( |
| 336 &mock_sync_processor_)), |
| 337 scoped_ptr<syncer::SyncErrorFactory>( |
| 338 new syncer::SyncErrorFactoryMock())); |
| 339 } |
| 340 |
| 341 scoped_ptr<AppSyncData> GetFirstSyncChangeForApp(const std::string& id) { |
| 342 scoped_ptr<AppSyncData> sync_data; |
| 343 for (syncer::SyncChangeList::iterator it = |
| 344 mock_sync_processor_.changes().begin(); |
| 345 it != mock_sync_processor_.changes().end(); ++it) { |
| 346 sync_data.reset(new AppSyncData(*it)); |
| 347 if (sync_data->id() == id) |
| 348 return sync_data.Pass(); |
| 349 } |
| 350 |
| 351 return scoped_ptr<AppSyncData>(); |
| 352 } |
| 353 |
| 354 void VerifySyncChange(const AppSyncData* sync_change, bool expect_enabled) { |
| 355 ASSERT_TRUE(sync_change); |
| 356 EXPECT_TRUE(sync_change->page_ordinal().IsValid()); |
| 357 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid()); |
| 358 EXPECT_FALSE(sync_change->uninstalled()); |
| 359 EXPECT_EQ(expect_enabled, sync_change->extension_sync_data().enabled()); |
| 360 } |
| 361 |
| 362 syncer::FakeSyncChangeProcessor mock_sync_processor_; |
| 194 }; | 363 }; |
| 195 | 364 |
| 196 // Verify that ephemeral apps can be launched and receive system events when | 365 // Verify that ephemeral apps can be launched and receive system events when |
| 197 // they are running. Once they are inactive they should not receive system | 366 // they are running. Once they are inactive they should not receive system |
| 198 // events. | 367 // events. |
| 199 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) { | 368 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) { |
| 200 const Extension* extension = | 369 const Extension* extension = |
| 201 InstallAndLaunchEphemeralApp(kDispatchEventTestApp); | 370 InstallAndLaunchEphemeralApp(kDispatchEventTestApp); |
| 202 ASSERT_TRUE(extension); | 371 ASSERT_TRUE(extension); |
| 203 | 372 |
| 204 // Send a fake alarm event to the app and verify that a response is | 373 // Send a fake alarm event to the app and verify that a response is |
| 205 // received. | 374 // received. |
| 206 EventRouter* event_router = EventRouter::Get(browser()->profile()); | 375 EventRouter* event_router = EventRouter::Get(profile()); |
| 207 ASSERT_TRUE(event_router); | 376 ASSERT_TRUE(event_router); |
| 208 | 377 |
| 209 ExtensionTestMessageListener alarm_received_listener("alarm_received", false); | 378 ExtensionTestMessageListener alarm_received_listener("alarm_received", false); |
| 210 DispatchAlarmEvent(event_router, extension->id()); | 379 DispatchAlarmEvent(event_router, extension->id()); |
| 211 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied()); | 380 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied()); |
| 212 | 381 |
| 213 CloseApp(extension->id()); | 382 CloseApp(extension->id()); |
| 214 | 383 |
| 215 // The app needs to be launched once in order to have the onAlarm() event | 384 // The app needs to be launched once in order to have the onAlarm() event |
| 216 // registered. | 385 // registered. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 244 // Verify that an updated ephemeral app will still have its ephemeral flag | 413 // Verify that an updated ephemeral app will still have its ephemeral flag |
| 245 // enabled. | 414 // enabled. |
| 246 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { | 415 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { |
| 247 const Extension* app_v1 = InstallEphemeralApp(kMessagingReceiverApp); | 416 const Extension* app_v1 = InstallEphemeralApp(kMessagingReceiverApp); |
| 248 ASSERT_TRUE(app_v1); | 417 ASSERT_TRUE(app_v1); |
| 249 ASSERT_TRUE(extensions::util::IsEphemeralApp(app_v1->id(), profile())); | 418 ASSERT_TRUE(extensions::util::IsEphemeralApp(app_v1->id(), profile())); |
| 250 std::string app_id = app_v1->id(); | 419 std::string app_id = app_v1->id(); |
| 251 base::Version app_original_version = *app_v1->version(); | 420 base::Version app_original_version = *app_v1->version(); |
| 252 app_v1 = NULL; // The extension object will be destroyed during update. | 421 app_v1 = NULL; // The extension object will be destroyed during update. |
| 253 | 422 |
| 254 // Pack version 2 of the app. | 423 // Update to version 2 of the app. |
| 255 base::ScopedTempDir temp_dir; | 424 InstallObserver installed_observer(profile()); |
| 256 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 425 const Extension* app_v2 = UpdateEphemeralApp( |
| 426 app_id, GetTestPath(kMessagingReceiverAppV2), |
| 427 GetTestPath(kMessagingReceiverApp).ReplaceExtension( |
| 428 FILE_PATH_LITERAL(".pem"))); |
| 257 | 429 |
| 258 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx"); | 430 // Check the notification parameters. |
| 259 if (!base::DeleteFile(crx_path, false)) { | 431 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 260 ADD_FAILURE() << "Failed to delete crx: " << crx_path.value(); | 432 EXPECT_EQ(app_id, params.id); |
| 261 return; | 433 EXPECT_TRUE(params.is_update); |
| 262 } | 434 EXPECT_FALSE(params.from_ephemeral); |
| 263 | 435 |
| 264 base::FilePath app_v2_path = PackExtensionWithOptions( | 436 // The ephemeral flag should still be enabled. |
| 265 GetTestPath(kMessagingReceiverAppV2), | |
| 266 crx_path, | |
| 267 GetTestPath(kMessagingReceiverApp).ReplaceExtension( | |
| 268 FILE_PATH_LITERAL(".pem")), | |
| 269 base::FilePath()); | |
| 270 ASSERT_FALSE(app_v2_path.empty()); | |
| 271 | |
| 272 // Update the ephemeral app and wait for the update to finish. | |
| 273 extensions::CrxInstaller* crx_installer = NULL; | |
| 274 content::WindowedNotificationObserver windowed_observer( | |
| 275 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | |
| 276 content::Source<extensions::CrxInstaller>(crx_installer)); | |
| 277 ExtensionService* service = | |
| 278 ExtensionSystem::Get(browser()->profile())->extension_service(); | |
| 279 EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true, | |
| 280 &crx_installer)); | |
| 281 windowed_observer.Wait(); | |
| 282 | |
| 283 const Extension* app_v2 = service->GetExtensionById(app_id, false); | |
| 284 ASSERT_TRUE(app_v2); | 437 ASSERT_TRUE(app_v2); |
| 285 EXPECT_TRUE(app_v2->version()->CompareTo(app_original_version) > 0); | 438 EXPECT_TRUE(app_v2->version()->CompareTo(app_original_version) > 0); |
| 286 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_v2->id(), profile())); | 439 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_v2->id(), profile())); |
| 287 } | 440 } |
| 288 | 441 |
| 289 // Verify that if notifications have been disabled for an ephemeral app, it will | 442 // Verify that if notifications have been disabled for an ephemeral app, it will |
| 290 // remain disabled even after being evicted from the cache. | 443 // remain disabled even after being evicted from the cache. |
| 291 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) { | 444 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) { |
| 292 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 445 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); |
| 293 ASSERT_TRUE(app); | 446 ASSERT_TRUE(app); |
| 294 | 447 |
| 295 // Disable notifications for this app. | 448 // Disable notifications for this app. |
| 296 DesktopNotificationService* notification_service = | 449 DesktopNotificationService* notification_service = |
| 297 DesktopNotificationServiceFactory::GetForProfile(browser()->profile()); | 450 DesktopNotificationServiceFactory::GetForProfile(profile()); |
| 298 ASSERT_TRUE(notification_service); | 451 ASSERT_TRUE(notification_service); |
| 299 | 452 |
| 300 message_center::NotifierId notifier_id( | 453 message_center::NotifierId notifier_id( |
| 301 message_center::NotifierId::APPLICATION, app->id()); | 454 message_center::NotifierId::APPLICATION, app->id()); |
| 302 EXPECT_TRUE(notification_service->IsNotifierEnabled(notifier_id)); | 455 EXPECT_TRUE(notification_service->IsNotifierEnabled(notifier_id)); |
| 303 notification_service->SetNotifierEnabled(notifier_id, false); | 456 notification_service->SetNotifierEnabled(notifier_id, false); |
| 304 EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id)); | 457 EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id)); |
| 305 | 458 |
| 306 // Remove the app. | 459 // Remove the app. |
| 307 EvictApp(app->id()); | 460 EvictApp(app->id()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 "temp", temp_dir.path()); | 522 "temp", temp_dir.path()); |
| 370 | 523 |
| 371 // The first test opens the file and writes the file handle to local storage. | 524 // The first test opens the file and writes the file handle to local storage. |
| 372 const Extension* app = InstallEphemeralApp(kFileSystemTestApp, | 525 const Extension* app = InstallEphemeralApp(kFileSystemTestApp, |
| 373 Manifest::UNPACKED); | 526 Manifest::UNPACKED); |
| 374 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_; | 527 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_; |
| 375 | 528 |
| 376 // Verify that after the app has been closed, all retained entries are | 529 // Verify that after the app has been closed, all retained entries are |
| 377 // flushed. | 530 // flushed. |
| 378 std::vector<apps::SavedFileEntry> file_entries = | 531 std::vector<apps::SavedFileEntry> file_entries = |
| 379 apps::SavedFilesService::Get(browser()->profile()) | 532 apps::SavedFilesService::Get(profile()) |
| 380 ->GetAllFileEntries(app->id()); | 533 ->GetAllFileEntries(app->id()); |
| 381 EXPECT_TRUE(file_entries.empty()); | 534 EXPECT_TRUE(file_entries.empty()); |
| 382 | 535 |
| 383 // The second test verifies that the file cannot be reopened. | 536 // The second test verifies that the file cannot be reopened. |
| 384 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_; | 537 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_; |
| 385 } | 538 } |
| 386 | 539 |
| 387 // Verify that once evicted from the cache, the data of ephemeral apps will not | 540 // Verify that once evicted from the cache, the data of ephemeral apps will not |
| 388 // be deleted. | 541 // be deleted. |
| 389 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) { | 542 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) { |
| 390 // Phase 1 - Install the ephemeral app and write data to various storage. | 543 // Phase 1 - Install the ephemeral app and write data to various storage. |
| 391 const Extension* app = InstallEphemeralApp(kRetainDataApp); | 544 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 392 ASSERT_TRUE(app); | 545 ASSERT_TRUE(app); |
| 393 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; | 546 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; |
| 394 | 547 |
| 395 // Sanity check to ensure that the ReadData tests should pass before the app | 548 // Sanity check to ensure that the ReadData tests should pass before the app |
| 396 // is removed. | 549 // is removed. |
| 397 ASSERT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; | 550 ASSERT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; |
| 398 | 551 |
| 399 // Remove the app. | 552 // Remove the app. |
| 400 const std::string app_id = app->id(); | 553 const std::string app_id = app->id(); |
| 401 EvictApp(app->id()); | 554 EvictApp(app->id()); |
| 402 app = NULL; | 555 app = NULL; |
| 403 | 556 |
| 404 // The app should be in the list of evicted apps. | 557 // The app should be in the list of evicted apps. |
| 405 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 558 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 406 ASSERT_TRUE(prefs); | 559 ASSERT_TRUE(prefs); |
| 407 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 560 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
| 408 prefs->GetEvictedEphemeralAppsInfo()); | 561 prefs->GetEvictedEphemeralAppsInfo()); |
| 409 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 562 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
| 410 scoped_ptr<ExtensionInfo> single_extension_info( | 563 scoped_ptr<ExtensionInfo> single_extension_info( |
| 411 prefs->GetEvictedEphemeralAppInfo(app_id)); | 564 prefs->GetEvictedEphemeralAppInfo(app_id)); |
| 412 EXPECT_TRUE(single_extension_info.get()); | 565 EXPECT_TRUE(single_extension_info.get()); |
| 413 | 566 |
| 414 // The app should not be in the list of installed extensions. | 567 // The app should not be in the list of installed extensions. |
| 415 extensions_info = prefs->GetInstalledExtensionsInfo(); | 568 extensions_info = prefs->GetInstalledExtensionsInfo(); |
| 416 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 569 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
| 570 EXPECT_FALSE(prefs->IsEphemeralApp(app_id)); |
| 417 | 571 |
| 418 // Ensure the evicted app is considered to have isolated storage. This will | 572 // Ensure the evicted app is considered to have isolated storage. This will |
| 419 // prevent its data from getting garbage collected by | 573 // prevent its data from getting garbage collected by |
| 420 // ExtensionService::GarbageCollectIsolatedStorage(). | 574 // ExtensionService::GarbageCollectIsolatedStorage(). |
| 421 GURL site_url = extensions::util::GetSiteForExtensionId( | 575 GURL site_url = extensions::util::GetSiteForExtensionId( |
| 422 app_id, browser()->profile()); | 576 app_id, profile()); |
| 423 EXPECT_TRUE(extensions::util::SiteHasIsolatedStorage( | 577 EXPECT_TRUE(extensions::util::SiteHasIsolatedStorage( |
| 424 site_url, browser()->profile())); | 578 site_url, profile())); |
| 425 | 579 |
| 426 // Phase 2 - Reinstall the ephemeral app and verify that data still exists | 580 // Phase 2 - Reinstall the ephemeral app and verify that data still exists |
| 427 // in the storage. | 581 // in the storage. |
| 428 app = InstallEphemeralApp(kRetainDataApp); | 582 app = InstallEphemeralApp(kRetainDataApp); |
| 429 ASSERT_TRUE(app); | 583 ASSERT_TRUE(app); |
| 430 EXPECT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; | 584 EXPECT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; |
| 431 | 585 |
| 432 // The app should now be in the list of installed extensions, but not in the | 586 // The app should now be in the list of installed extensions, but not in the |
| 433 // list of evicted apps. | 587 // list of evicted apps. |
| 434 extensions_info = prefs->GetInstalledExtensionsInfo(); | 588 extensions_info = prefs->GetInstalledExtensionsInfo(); |
| 435 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 589 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
| 436 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); | 590 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); |
| 437 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 591 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
| 438 single_extension_info = prefs->GetEvictedEphemeralAppInfo(app_id); | 592 single_extension_info = prefs->GetEvictedEphemeralAppInfo(app_id); |
| 439 EXPECT_FALSE(single_extension_info.get()); | 593 EXPECT_FALSE(single_extension_info.get()); |
| 594 EXPECT_TRUE(prefs->IsEphemeralApp(app_id)); |
| 440 } | 595 } |
| 441 | 596 |
| 442 // Verify that preferences are updated correctly when an evicted ephemeral app | 597 // Verify that preferences are updated correctly when an evicted ephemeral app |
| 443 // is re-installed permanently. | 598 // is re-installed permanently. |
| 444 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEvictedEphemeralApp) { | 599 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEvictedEphemeralApp) { |
| 445 const Extension* app = InstallEphemeralApp(kRetainDataApp); | 600 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 446 ASSERT_TRUE(app); | 601 ASSERT_TRUE(app); |
| 447 | 602 |
| 448 // Remove the app. | 603 // Remove the app. |
| 449 EvictApp(app->id()); | 604 EvictApp(app->id()); |
| 450 app = NULL; | 605 app = NULL; |
| 451 | 606 |
| 452 // Install the app permanently. | 607 // Install the app permanently. |
| 453 app = InstallPlatformApp(kRetainDataApp); | 608 app = InstallPlatformApp(kRetainDataApp); |
| 454 ASSERT_TRUE(app); | 609 ASSERT_TRUE(app); |
| 455 | 610 |
| 456 // Verify that preferences are correct. | 611 // Verify that preferences are correct. |
| 457 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 612 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 458 ASSERT_TRUE(prefs); | 613 ASSERT_TRUE(prefs); |
| 459 EXPECT_FALSE(prefs->IsEphemeralApp(app->id())); | 614 EXPECT_FALSE(prefs->IsEphemeralApp(app->id())); |
| 460 | 615 |
| 461 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 616 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
| 462 prefs->GetEvictedEphemeralAppsInfo()); | 617 prefs->GetEvictedEphemeralAppsInfo()); |
| 463 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app->id())); | 618 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app->id())); |
| 464 extensions_info = prefs->GetInstalledExtensionsInfo(); | 619 extensions_info = prefs->GetInstalledExtensionsInfo(); |
| 465 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app->id())); | 620 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app->id())); |
| 466 } | 621 } |
| 467 | 622 |
| 468 // Verify that the data of regular installed apps are deleted on uninstall. | 623 // Verify that the data of regular installed apps are deleted on uninstall. |
| 469 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RemoveInstalledData) { | 624 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RemoveInstalledData) { |
| 470 // Install the ephemeral app and write data to various storage. | 625 // Install the ephemeral app and write data to various storage. |
| 471 const Extension* app = InstallPlatformApp(kRetainDataApp); | 626 const Extension* app = InstallPlatformApp(kRetainDataApp); |
| 472 ASSERT_TRUE(app); | 627 ASSERT_TRUE(app); |
| 473 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; | 628 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; |
| 474 | 629 |
| 475 // Remove the app. | 630 // Remove the app. |
| 476 const std::string app_id = app->id(); | 631 const std::string app_id = app->id(); |
| 477 EvictApp(app->id()); | 632 EvictApp(app->id()); |
| 478 app = NULL; | 633 app = NULL; |
| 479 | 634 |
| 480 // The app should not be in the preferences. | 635 // The app should not be in the preferences. |
| 481 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 636 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 482 ASSERT_TRUE(prefs); | 637 ASSERT_TRUE(prefs); |
| 483 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 638 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
| 484 prefs->GetEvictedEphemeralAppsInfo()); | 639 prefs->GetEvictedEphemeralAppsInfo()); |
| 485 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 640 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
| 486 extensions_info = prefs->GetInstalledExtensionsInfo(); | 641 extensions_info = prefs->GetInstalledExtensionsInfo(); |
| 487 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 642 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
| 488 | 643 |
| 489 // Reinstall the app and verify that all data has been reset. | 644 // Reinstall the app and verify that all data has been reset. |
| 490 app = InstallPlatformApp(kRetainDataApp); | 645 app = InstallPlatformApp(kRetainDataApp); |
| 491 ASSERT_TRUE(LaunchAppAndRunTest(app, "DataReset")) << message_; | 646 ASSERT_TRUE(LaunchAppAndRunTest(app, "DataReset")) << message_; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 503 std::string evict_app_id = evict_app->id(); | 658 std::string evict_app_id = evict_app->id(); |
| 504 EvictApp(evict_app_id); | 659 EvictApp(evict_app_id); |
| 505 evict_app = NULL; | 660 evict_app = NULL; |
| 506 | 661 |
| 507 const Extension* retain_app = InstallEphemeralApp(kDispatchEventTestApp); | 662 const Extension* retain_app = InstallEphemeralApp(kDispatchEventTestApp); |
| 508 ASSERT_TRUE(retain_app); | 663 ASSERT_TRUE(retain_app); |
| 509 std::string retain_app_id = retain_app->id(); | 664 std::string retain_app_id = retain_app->id(); |
| 510 EvictApp(retain_app_id); | 665 EvictApp(retain_app_id); |
| 511 retain_app = NULL; | 666 retain_app = NULL; |
| 512 | 667 |
| 513 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 668 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 514 ASSERT_TRUE(prefs); | 669 ASSERT_TRUE(prefs); |
| 515 | 670 |
| 516 // Both apps should be in the list of evicted apps. | 671 // Both apps should be in the list of evicted apps. |
| 517 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 672 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
| 518 prefs->GetEvictedEphemeralAppsInfo()); | 673 prefs->GetEvictedEphemeralAppsInfo()); |
| 519 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); | 674 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); |
| 520 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); | 675 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); |
| 521 | 676 |
| 522 // Set a fake last launch time so that the ephemeral app's data will be | 677 // Set a fake last launch time so that the ephemeral app's data will be |
| 523 // garbage collected. | 678 // garbage collected. |
| 524 base::Time launch_time = | 679 base::Time launch_time = |
| 525 base::Time::Now() - base::TimeDelta::FromDays( | 680 base::Time::Now() - base::TimeDelta::FromDays( |
| 526 EphemeralAppService::kDataInactiveThreshold + 1); | 681 EphemeralAppService::kDataInactiveThreshold + 1); |
| 527 prefs->SetLastLaunchTime(evict_app_id, launch_time); | 682 prefs->SetLastLaunchTime(evict_app_id, launch_time); |
| 528 prefs->SetLastLaunchTime(retain_app_id, base::Time::Now()); | 683 prefs->SetLastLaunchTime(retain_app_id, base::Time::Now()); |
| 529 | 684 |
| 530 // Garbage collect data. | 685 // Garbage collect data. |
| 531 GarbageCollectData(); | 686 GarbageCollectData(); |
| 532 | 687 |
| 533 // The garbage collected app should no longer be in the preferences. | 688 // The garbage collected app should no longer be in the preferences. |
| 534 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); | 689 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); |
| 535 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); | 690 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); |
| 536 ASSERT_FALSE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); | 691 ASSERT_FALSE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); |
| 537 | 692 |
| 538 // Reinstall the app and verify that all data has been reset. | 693 // Reinstall the app and verify that all data has been reset. |
| 539 evict_app = InstallEphemeralApp(kRetainDataApp); | 694 evict_app = InstallEphemeralApp(kRetainDataApp); |
| 540 ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "DataReset")) << message_; | 695 ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "DataReset")) << message_; |
| 541 } | 696 } |
| 697 |
| 698 // Checks the process of installing and then promoting an ephemeral app. |
| 699 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralApp) { |
| 700 InitSyncService(); |
| 701 |
| 702 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 703 ASSERT_TRUE(app); |
| 704 |
| 705 // Ephemeral apps should not be synced. |
| 706 scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
| 707 EXPECT_FALSE(sync_change.get()); |
| 708 |
| 709 // Promote the app to a regular installed app. |
| 710 InstallObserver installed_observer(profile()); |
| 711 PromoteEphemeralApp(app); |
| 712 VerifyInstalledApp(app->id(), ExtensionRegistry::ENABLED); |
| 713 |
| 714 // Check the notification parameters. |
| 715 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 716 EXPECT_EQ(app->id(), params.id); |
| 717 EXPECT_TRUE(params.is_update); |
| 718 EXPECT_TRUE(params.from_ephemeral); |
| 719 |
| 720 // The installation should now be synced. |
| 721 sync_change = GetFirstSyncChangeForApp(app->id()); |
| 722 VerifySyncChange(sync_change.get(), true); |
| 723 } |
| 724 |
| 725 // Verifies that promoting an ephemeral app will enable it. |
| 726 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppAndEnable) { |
| 727 InitSyncService(); |
| 728 |
| 729 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 730 ASSERT_TRUE(app); |
| 731 |
| 732 // Disable the ephemeral app. |
| 733 ExtensionService* service = |
| 734 ExtensionSystem::Get(profile())->extension_service(); |
| 735 service->DisableExtension(app->id(), Extension::DISABLE_PERMISSIONS_INCREASE); |
| 736 ASSERT_TRUE(ExtensionRegistry::Get(profile())-> |
| 737 GetExtensionById(app->id(), ExtensionRegistry::DISABLED)); |
| 738 |
| 739 // Promote to a regular installed app. It should be enabled. |
| 740 PromoteEphemeralApp(app); |
| 741 VerifyInstalledApp(app->id(), ExtensionRegistry::ENABLED); |
| 742 |
| 743 scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
| 744 VerifySyncChange(sync_change.get(), true); |
| 745 } |
| 746 |
| 747 // Verifies that promoting an ephemeral app that has unsupported requirements |
| 748 // will not enable it. |
| 749 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 750 PromoteUnsupportedEphemeralApp) { |
| 751 InitSyncService(); |
| 752 |
| 753 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 754 ASSERT_TRUE(app); |
| 755 |
| 756 // Disable the ephemeral app. |
| 757 ExtensionService* service = |
| 758 ExtensionSystem::Get(profile())->extension_service(); |
| 759 service->DisableExtension( |
| 760 app->id(), Extension::DISABLE_UNSUPPORTED_REQUIREMENT); |
| 761 ASSERT_TRUE(ExtensionRegistry::Get(profile())-> |
| 762 GetExtensionById(app->id(), ExtensionRegistry::DISABLED)); |
| 763 |
| 764 // Promote to a regular installed app. It should remain disabled. |
| 765 PromoteEphemeralApp(app); |
| 766 VerifyInstalledApp(app->id(), ExtensionRegistry::DISABLED); |
| 767 |
| 768 scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
| 769 VerifySyncChange(sync_change.get(), false); |
| 770 } |
| 771 |
| 772 // Checks the process of promoting an ephemeral app from sync. |
| 773 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppFromSync) { |
| 774 InitSyncService(); |
| 775 |
| 776 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 777 ASSERT_TRUE(app); |
| 778 std::string app_id = app->id(); |
| 779 |
| 780 // Simulate an install from sync. |
| 781 const syncer::StringOrdinal kAppLaunchOrdinal("x"); |
| 782 const syncer::StringOrdinal kPageOrdinal("y"); |
| 783 AppSyncData app_sync_data( |
| 784 *app, |
| 785 true /* enabled */, |
| 786 false /* incognito enabled */, |
| 787 false /* remote install */, |
| 788 kAppLaunchOrdinal, |
| 789 kPageOrdinal, |
| 790 extensions::LAUNCH_TYPE_REGULAR); |
| 791 |
| 792 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
| 793 sync_service->ProcessAppSyncData(app_sync_data); |
| 794 |
| 795 // Verify the installation. |
| 796 VerifyInstalledApp(app_id, ExtensionRegistry::ENABLED); |
| 797 |
| 798 // The sort ordinals from sync should not be overridden. |
| 799 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 800 extensions::AppSorting* app_sorting = prefs->app_sorting(); |
| 801 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).Equals( |
| 802 kAppLaunchOrdinal)); |
| 803 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal)); |
| 804 } |
| 805 |
| 806 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to |
| 807 // permanently install an ephemeral app. However, there may be cases where an |
| 808 // install occurs through the usual route of installing from the Web Store (due |
| 809 // to race conditions). Ensure that the app is still installed correctly. |
| 810 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 811 ReplaceEphemeralAppWithInstalledApp) { |
| 812 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 813 ASSERT_TRUE(app); |
| 814 std::string app_id = app->id(); |
| 815 app = NULL; |
| 816 |
| 817 InstallObserver installed_observer(profile()); |
| 818 ReplaceEphemeralApp(app_id, kRetainDataApp); |
| 819 VerifyInstalledApp(app_id, ExtensionRegistry::ENABLED); |
| 820 |
| 821 // Check the notification parameters. |
| 822 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 823 EXPECT_EQ(app_id, params.id); |
| 824 EXPECT_TRUE(params.is_update); |
| 825 EXPECT_TRUE(params.from_ephemeral); |
| 826 } |
| 827 |
| 828 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will |
| 829 // be delayed until the app is idle. |
| 830 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 831 ReplaceEphemeralAppWithDelayedInstalledApp) { |
| 832 const Extension* app = InstallAndLaunchEphemeralApp(kRetainDataApp); |
| 833 ASSERT_TRUE(app); |
| 834 std::string app_id = app->id(); |
| 835 app = NULL; |
| 836 |
| 837 // Initiate install. |
| 838 ReplaceEphemeralApp(app_id, kRetainDataApp); |
| 839 |
| 840 // The delayed installation will occur when the ephemeral app is closed. |
| 841 content::WindowedNotificationObserver installed_signal( |
| 842 chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED, |
| 843 content::Source<Profile>(profile())); |
| 844 InstallObserver installed_observer(profile()); |
| 845 CloseApp(app_id); |
| 846 installed_signal.Wait(); |
| 847 VerifyInstalledApp(app_id, ExtensionRegistry::ENABLED); |
| 848 |
| 849 // Check the notification parameters. |
| 850 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 851 EXPECT_EQ(app_id, params.id); |
| 852 EXPECT_TRUE(params.is_update); |
| 853 EXPECT_TRUE(params.from_ephemeral); |
| 854 } |
| OLD | NEW |