| 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" | 5 #include "chrome/browser/apps/ephemeral_app_browsertest.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "apps/app_restore_service.h" |
| 9 #include "apps/saved_files_service.h" | 10 #include "apps/saved_files_service.h" |
| 10 #include "base/files/scoped_temp_dir.h" | 11 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/scoped_observer.h" | 12 #include "base/scoped_observer.h" |
| 12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 13 #include "chrome/browser/apps/app_browsertest_util.h" | 14 #include "chrome/browser/apps/app_browsertest_util.h" |
| 15 #include "chrome/browser/apps/ephemeral_app_service.h" |
| 14 #include "chrome/browser/extensions/api/file_system/file_system_api.h" | 16 #include "chrome/browser/extensions/api/file_system/file_system_api.h" |
| 15 #include "chrome/browser/extensions/app_sync_data.h" | 17 #include "chrome/browser/extensions/app_sync_data.h" |
| 16 #include "chrome/browser/extensions/extension_service.h" | 18 #include "chrome/browser/extensions/extension_service.h" |
| 17 #include "chrome/browser/extensions/extension_sync_service.h" | 19 #include "chrome/browser/extensions/extension_sync_service.h" |
| 18 #include "chrome/browser/extensions/extension_test_message_listener.h" | 20 #include "chrome/browser/extensions/extension_test_message_listener.h" |
| 19 #include "chrome/browser/extensions/extension_util.h" | 21 #include "chrome/browser/extensions/extension_util.h" |
| 20 #include "chrome/browser/notifications/desktop_notification_service.h" | 22 #include "chrome/browser/notifications/desktop_notification_service.h" |
| 21 #include "chrome/browser/notifications/desktop_notification_service_factory.h" | 23 #include "chrome/browser/notifications/desktop_notification_service_factory.h" |
| 22 #include "chrome/common/chrome_switches.h" | 24 #include "chrome/common/chrome_switches.h" |
| 23 #include "chrome/common/extensions/api/alarms.h" | 25 #include "chrome/common/extensions/api/alarms.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 47 using extensions::ExtensionPrefs; | 49 using extensions::ExtensionPrefs; |
| 48 using extensions::ExtensionRegistry; | 50 using extensions::ExtensionRegistry; |
| 49 using extensions::ExtensionRegistryObserver; | 51 using extensions::ExtensionRegistryObserver; |
| 50 using extensions::ExtensionSystem; | 52 using extensions::ExtensionSystem; |
| 51 using extensions::Manifest; | 53 using extensions::Manifest; |
| 52 | 54 |
| 53 namespace { | 55 namespace { |
| 54 | 56 |
| 55 namespace alarms = extensions::api::alarms; | 57 namespace alarms = extensions::api::alarms; |
| 56 | 58 |
| 57 const char kNotificationsTestApp[] = "ephemeral_apps/notification_settings"; | |
| 58 const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries"; | 59 const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries"; |
| 59 | 60 |
| 60 typedef std::vector<message_center::Notifier*> NotifierList; | 61 typedef std::vector<message_center::Notifier*> NotifierList; |
| 61 | 62 |
| 62 bool IsNotifierInList(const message_center::NotifierId& notifier_id, | 63 bool IsNotifierInList(const message_center::NotifierId& notifier_id, |
| 63 const NotifierList& notifiers) { | 64 const NotifierList& notifiers) { |
| 64 for (NotifierList::const_iterator it = notifiers.begin(); | 65 for (NotifierList::const_iterator it = notifiers.begin(); |
| 65 it != notifiers.end(); ++it) { | 66 it != notifiers.end(); ++it) { |
| 66 const message_center::Notifier* notifier = *it; | 67 const message_center::Notifier* notifier = *it; |
| 67 if (notifier->notifier_id == notifier_id) | 68 if (notifier->notifier_id == notifier_id) |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 119 |
| 119 | 120 |
| 120 // EphemeralAppTestBase: | 121 // EphemeralAppTestBase: |
| 121 | 122 |
| 122 const char EphemeralAppTestBase::kMessagingReceiverApp[] = | 123 const char EphemeralAppTestBase::kMessagingReceiverApp[] = |
| 123 "ephemeral_apps/messaging_receiver"; | 124 "ephemeral_apps/messaging_receiver"; |
| 124 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] = | 125 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] = |
| 125 "ephemeral_apps/messaging_receiver2"; | 126 "ephemeral_apps/messaging_receiver2"; |
| 126 const char EphemeralAppTestBase::kDispatchEventTestApp[] = | 127 const char EphemeralAppTestBase::kDispatchEventTestApp[] = |
| 127 "ephemeral_apps/dispatch_event"; | 128 "ephemeral_apps/dispatch_event"; |
| 129 const char EphemeralAppTestBase::kNotificationsTestApp[] = |
| 130 "ephemeral_apps/notification_settings"; |
| 128 | 131 |
| 129 EphemeralAppTestBase::EphemeralAppTestBase() {} | 132 EphemeralAppTestBase::EphemeralAppTestBase() {} |
| 130 | 133 |
| 131 EphemeralAppTestBase::~EphemeralAppTestBase() {} | 134 EphemeralAppTestBase::~EphemeralAppTestBase() {} |
| 132 | 135 |
| 133 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) { | 136 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) { |
| 134 // Skip PlatformAppBrowserTest, which sets different values for the switches | 137 // Skip PlatformAppBrowserTest, which sets different values for the switches |
| 135 // below. | 138 // below. |
| 136 ExtensionBrowserTest::SetUpCommandLine(command_line); | 139 ExtensionBrowserTest::SetUpCommandLine(command_line); |
| 137 | 140 |
| 138 // Make event pages get suspended immediately. | 141 // Make event pages get suspended immediately. |
| 139 command_line->AppendSwitchASCII( | 142 command_line->AppendSwitchASCII( |
| 140 extensions::switches::kEventPageIdleTime, "10"); | 143 extensions::switches::kEventPageIdleTime, "10"); |
| 141 command_line->AppendSwitchASCII( | 144 command_line->AppendSwitchASCII( |
| 142 extensions::switches::kEventPageSuspendingTime, "10"); | 145 extensions::switches::kEventPageSuspendingTime, "10"); |
| 143 | 146 |
| 144 // Enable ephemeral apps flag. | 147 // Enable ephemeral apps flag. |
| 145 command_line->AppendSwitch(switches::kEnableEphemeralApps); | 148 command_line->AppendSwitch(switches::kEnableEphemeralApps); |
| 146 } | 149 } |
| 147 | 150 |
| 151 void EphemeralAppTestBase::SetUpOnMainThread() { |
| 152 PlatformAppBrowserTest::SetUpOnMainThread(); |
| 153 |
| 154 // Unload ephemeral apps immediately after they stop running in tests. |
| 155 EphemeralAppService::Get(profile())->set_unload_delay_for_test(0); |
| 156 } |
| 157 |
| 148 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) { | 158 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) { |
| 149 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); | 159 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); |
| 150 } | 160 } |
| 151 | 161 |
| 152 const Extension* EphemeralAppTestBase::InstallEphemeralApp( | 162 const Extension* EphemeralAppTestBase::InstallEphemeralApp( |
| 153 const char* test_path, Manifest::Location manifest_location) { | 163 const char* test_path, Manifest::Location manifest_location) { |
| 154 const Extension* extension = InstallEphemeralAppWithSourceAndFlags( | 164 const Extension* extension = InstallEphemeralAppWithSourceAndFlags( |
| 155 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS); | 165 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS); |
| 156 EXPECT_TRUE(extension); | 166 EXPECT_TRUE(extension); |
| 157 if (extension) | 167 if (extension) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 extensions::CrxInstaller* crx_installer = NULL; | 213 extensions::CrxInstaller* crx_installer = NULL; |
| 204 content::WindowedNotificationObserver windowed_observer( | 214 content::WindowedNotificationObserver windowed_observer( |
| 205 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 215 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
| 206 content::Source<extensions::CrxInstaller>(crx_installer)); | 216 content::Source<extensions::CrxInstaller>(crx_installer)); |
| 207 ExtensionService* service = | 217 ExtensionService* service = |
| 208 ExtensionSystem::Get(profile())->extension_service(); | 218 ExtensionSystem::Get(profile())->extension_service(); |
| 209 EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true, | 219 EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true, |
| 210 &crx_installer)); | 220 &crx_installer)); |
| 211 windowed_observer.Wait(); | 221 windowed_observer.Wait(); |
| 212 | 222 |
| 213 return service->GetExtensionById(app_id, false); | 223 return ExtensionRegistry::Get(profile()) |
| 224 ->GetExtensionById(app_id, ExtensionRegistry::EVERYTHING); |
| 214 } | 225 } |
| 215 | 226 |
| 216 void EphemeralAppTestBase::PromoteEphemeralApp( | 227 void EphemeralAppTestBase::PromoteEphemeralApp( |
| 217 const extensions::Extension* app) { | 228 const extensions::Extension* app) { |
| 218 ExtensionService* extension_service = | 229 ExtensionService* extension_service = |
| 219 ExtensionSystem::Get(profile())->extension_service(); | 230 ExtensionSystem::Get(profile())->extension_service(); |
| 220 ASSERT_TRUE(extension_service); | 231 ASSERT_TRUE(extension_service); |
| 221 extension_service->PromoteEphemeralApp(app, false); | 232 extension_service->PromoteEphemeralApp(app, false); |
| 222 } | 233 } |
| 223 | 234 |
| 224 void EphemeralAppTestBase::CloseApp(const std::string& app_id) { | 235 void EphemeralAppTestBase::CloseApp(const std::string& app_id) { |
| 225 content::WindowedNotificationObserver event_page_destroyed_signal( | |
| 226 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | |
| 227 content::Source<Profile>(profile())); | |
| 228 | |
| 229 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id)); | 236 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id)); |
| 230 apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id); | 237 apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id); |
| 231 ASSERT_TRUE(app_window); | 238 ASSERT_TRUE(app_window); |
| 232 CloseAppWindow(app_window); | 239 CloseAppWindow(app_window); |
| 240 } |
| 233 | 241 |
| 234 event_page_destroyed_signal.Wait(); | 242 void EphemeralAppTestBase::CloseAppWaitForUnload(const std::string& app_id) { |
| 243 // Ephemeral apps are unloaded from extension system after they stop running. |
| 244 content::WindowedNotificationObserver unloaded_signal( |
| 245 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, |
| 246 content::Source<Profile>(profile())); |
| 247 CloseApp(app_id); |
| 248 unloaded_signal.Wait(); |
| 235 } | 249 } |
| 236 | 250 |
| 237 void EphemeralAppTestBase::EvictApp(const std::string& app_id) { | 251 void EphemeralAppTestBase::EvictApp(const std::string& app_id) { |
| 238 // Uninstall the app, which is what happens when ephemeral apps get evicted | 252 // Uninstall the app, which is what happens when ephemeral apps get evicted |
| 239 // from the cache. | 253 // from the cache. |
| 240 content::WindowedNotificationObserver uninstalled_signal( | 254 content::WindowedNotificationObserver uninstalled_signal( |
| 241 chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED, | 255 chrome::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED, |
| 242 content::Source<Profile>(profile())); | 256 content::Source<Profile>(profile())); |
| 243 | 257 |
| 244 ExtensionService* service = | 258 ExtensionService* service = |
| 245 ExtensionSystem::Get(profile())->extension_service(); | 259 ExtensionSystem::Get(profile())->extension_service(); |
| 246 ASSERT_TRUE(service); | 260 ASSERT_TRUE(service); |
| 247 service->UninstallExtension( | 261 service->UninstallExtension( |
| 248 app_id, extensions::UNINSTALL_REASON_ORPHANED_EPHEMERAL_EXTENSION, NULL); | 262 app_id, extensions::UNINSTALL_REASON_ORPHANED_EPHEMERAL_EXTENSION, NULL); |
| 249 | 263 |
| 250 uninstalled_signal.Wait(); | 264 uninstalled_signal.Wait(); |
| 251 } | 265 } |
| 252 | 266 |
| 253 // EphemeralAppBrowserTest: | 267 // EphemeralAppBrowserTest: |
| 254 | 268 |
| 255 class EphemeralAppBrowserTest : public EphemeralAppTestBase { | 269 class EphemeralAppBrowserTest : public EphemeralAppTestBase { |
| 256 protected: | 270 protected: |
| 257 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) { | 271 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) { |
| 272 // Ephemeral apps are unloaded after they are closed. Ensure they are |
| 273 // enabled before launch. |
| 274 ExtensionService* service = |
| 275 ExtensionSystem::Get(profile())->extension_service(); |
| 276 service->EnableExtension(app->id()); |
| 277 |
| 258 ExtensionTestMessageListener launched_listener("launched", true); | 278 ExtensionTestMessageListener launched_listener("launched", true); |
| 259 LaunchPlatformApp(app); | 279 LaunchPlatformApp(app); |
| 260 if (!launched_listener.WaitUntilSatisfied()) { | 280 if (!launched_listener.WaitUntilSatisfied()) { |
| 261 message_ = "Failed to receive launched message from test"; | 281 message_ = "Failed to receive launched message from test"; |
| 262 return false; | 282 return false; |
| 263 } | 283 } |
| 264 | 284 |
| 265 ResultCatcher catcher; | 285 ResultCatcher catcher; |
| 266 launched_listener.Reply(test_name); | 286 launched_listener.Reply(test_name); |
| 267 | 287 |
| 268 bool result = catcher.GetNextResult(); | 288 bool result = catcher.GetNextResult(); |
| 269 message_ = catcher.message(); | 289 message_ = catcher.message(); |
| 270 | 290 |
| 271 CloseApp(app->id()); | 291 CloseAppWaitForUnload(app->id()); |
| 272 return result; | 292 return result; |
| 273 } | 293 } |
| 274 | 294 |
| 295 // Verify that the event page of the app has not been loaded. |
| 275 void VerifyAppNotLoaded(const std::string& app_id) { | 296 void VerifyAppNotLoaded(const std::string& app_id) { |
| 276 EXPECT_FALSE(ExtensionSystem::Get(profile())-> | 297 EXPECT_FALSE(ExtensionSystem::Get(profile())-> |
| 277 process_manager()->GetBackgroundHostForExtension(app_id)); | 298 process_manager()->GetBackgroundHostForExtension(app_id)); |
| 278 } | 299 } |
| 279 | 300 |
| 280 // Verify properties of ephemeral apps. | 301 // Verify properties of ephemeral apps. |
| 281 void VerifyEphemeralApp(const std::string& app_id) { | 302 void VerifyEphemeralApp(const std::string& app_id) { |
| 282 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_id, profile())); | 303 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_id, profile())); |
| 283 | 304 |
| 284 // Ephemeral apps should not be synced. | 305 // Ephemeral apps should not be synced. |
| 285 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app_id); | 306 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app_id); |
| 286 EXPECT_FALSE(sync_change.get()); | 307 EXPECT_FALSE(sync_change.get()); |
| 287 | 308 |
| 288 // Ephemeral apps should not be assigned ordinals. | 309 // Ephemeral apps should not be assigned ordinals. |
| 289 extensions::AppSorting* app_sorting = | 310 extensions::AppSorting* app_sorting = |
| 290 ExtensionPrefs::Get(profile())->app_sorting(); | 311 ExtensionPrefs::Get(profile())->app_sorting(); |
| 291 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); | 312 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); |
| 292 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_id).IsValid()); | 313 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_id).IsValid()); |
| 293 } | 314 } |
| 294 | 315 |
| 316 // Verify that after ephemeral apps stop running, they reside in extension |
| 317 // system in a disabled and unloaded state. |
| 318 void VerifyInactiveEphemeralApp(const std::string& app_id) { |
| 319 EXPECT_TRUE( |
| 320 ExtensionRegistry::Get(profile())->disabled_extensions().Contains( |
| 321 app_id)); |
| 322 |
| 323 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 324 EXPECT_TRUE(prefs->IsExtensionDisabled(app_id)); |
| 325 EXPECT_NE(0, |
| 326 prefs->GetDisableReasons(app_id) & |
| 327 Extension::DISABLE_INACTIVE_EPHEMERAL_APP); |
| 328 } |
| 329 |
| 330 // Verify the state of an app that has been promoted from an ephemeral to a |
| 331 // fully installed app. |
| 332 void VerifyPromotedApp(const std::string& app_id, |
| 333 ExtensionRegistry::IncludeFlag expected_set) { |
| 334 const Extension* app = ExtensionRegistry::Get(profile()) |
| 335 ->GetExtensionById(app_id, expected_set); |
| 336 ASSERT_TRUE(app) << "App not found in expected set: " << expected_set; |
| 337 |
| 338 // The app should not be ephemeral. |
| 339 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 340 ASSERT_TRUE(prefs); |
| 341 EXPECT_FALSE(prefs->IsEphemeralApp(app_id)); |
| 342 EXPECT_EQ(0, |
| 343 prefs->GetDisableReasons(app_id) & |
| 344 Extension::DISABLE_INACTIVE_EPHEMERAL_APP); |
| 345 |
| 346 // Check sort ordinals. |
| 347 extensions::AppSorting* app_sorting = prefs->app_sorting(); |
| 348 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); |
| 349 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid()); |
| 350 } |
| 351 |
| 295 // Dispatch a fake alarm event to the app. | 352 // Dispatch a fake alarm event to the app. |
| 296 void DispatchAlarmEvent(EventRouter* event_router, | 353 void DispatchAlarmEvent(EventRouter* event_router, |
| 297 const std::string& app_id) { | 354 const std::string& app_id) { |
| 298 alarms::Alarm dummy_alarm; | 355 alarms::Alarm dummy_alarm; |
| 299 dummy_alarm.name = "test_alarm"; | 356 dummy_alarm.name = "test_alarm"; |
| 300 | 357 |
| 301 scoped_ptr<base::ListValue> args(new base::ListValue()); | 358 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 302 args->Append(dummy_alarm.ToValue().release()); | 359 args->Append(dummy_alarm.ToValue().release()); |
| 303 scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, | 360 scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, |
| 304 args.Pass())); | 361 args.Pass())); |
| 305 | 362 |
| 306 event_router->DispatchEventToExtension(app_id, event.Pass()); | 363 event_router->DispatchEventToExtension(app_id, event.Pass()); |
| 307 } | 364 } |
| 308 | 365 |
| 366 // Simulates the scenario where an app is installed, via the normal |
| 367 // installation route, on top of an ephemeral app. This can occur due to race |
| 368 // conditions. |
| 309 const Extension* ReplaceEphemeralApp(const std::string& app_id, | 369 const Extension* ReplaceEphemeralApp(const std::string& app_id, |
| 310 const char* test_path) { | 370 const char* test_path, |
| 311 return UpdateExtensionWaitForIdle(app_id, GetTestPath(test_path), 0); | 371 int expected_enabled_change) { |
| 372 return UpdateExtensionWaitForIdle( |
| 373 app_id, GetTestPath(test_path), expected_enabled_change); |
| 312 } | 374 } |
| 313 | 375 |
| 314 void VerifyPromotedApp(const std::string& app_id, | 376 void DisableEphemeralApp(const Extension* app, |
| 315 ExtensionRegistry::IncludeFlag expected_set) { | 377 Extension::DisableReason disable_reason) { |
| 316 const Extension* app = ExtensionRegistry::Get(profile())->GetExtensionById( | 378 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 317 app_id, expected_set); | 379 |
| 380 // Disabling due to a permissions increase also involves setting the |
| 381 // DidExtensionEscalatePermissions flag. |
| 382 if (disable_reason == Extension::DISABLE_PERMISSIONS_INCREASE) |
| 383 prefs->SetDidExtensionEscalatePermissions(app, true); |
| 384 |
| 385 ExtensionSystem::Get(profile())->extension_service()->DisableExtension( |
| 386 app->id(), disable_reason); |
| 387 |
| 388 ASSERT_TRUE( |
| 389 ExtensionRegistry::Get(profile())->disabled_extensions().Contains( |
| 390 app->id())); |
| 391 } |
| 392 |
| 393 void PromoteEphemeralAppAndVerify( |
| 394 const Extension* app, |
| 395 ExtensionRegistry::IncludeFlag expected_set) { |
| 318 ASSERT_TRUE(app); | 396 ASSERT_TRUE(app); |
| 319 | 397 |
| 320 // The app should not be ephemeral. | 398 // Ephemeral apps should not be synced. |
| 399 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app->id()); |
| 400 EXPECT_FALSE(sync_change.get()); |
| 401 |
| 402 // Promote the app to a regular installed app. |
| 403 InstallObserver installed_observer(profile()); |
| 404 PromoteEphemeralApp(app); |
| 405 VerifyPromotedApp(app->id(), expected_set); |
| 406 |
| 407 // Check the notification parameters. |
| 408 const InstallObserver::InstallParameters& params = |
| 409 installed_observer.Last(); |
| 410 EXPECT_EQ(app->id(), params.id); |
| 411 EXPECT_TRUE(params.is_update); |
| 412 EXPECT_TRUE(params.from_ephemeral); |
| 413 |
| 414 // The installation should now be synced. |
| 415 sync_change = GetLastSyncChangeForApp(app->id()); |
| 416 VerifySyncChange(sync_change.get(), |
| 417 expected_set == ExtensionRegistry::ENABLED); |
| 418 } |
| 419 |
| 420 void PromoteEphemeralAppFromSyncAndVerify( |
| 421 const Extension* app, |
| 422 bool enable_from_sync, |
| 423 ExtensionRegistry::IncludeFlag expected_set) { |
| 424 ASSERT_TRUE(app); |
| 425 |
| 426 // Simulate an install from sync. |
| 427 const syncer::StringOrdinal kAppLaunchOrdinal("x"); |
| 428 const syncer::StringOrdinal kPageOrdinal("y"); |
| 429 AppSyncData app_sync_data(*app, |
| 430 enable_from_sync, |
| 431 false /* incognito enabled */, |
| 432 false /* remote install */, |
| 433 kAppLaunchOrdinal, |
| 434 kPageOrdinal, |
| 435 extensions::LAUNCH_TYPE_REGULAR); |
| 436 |
| 437 std::string app_id = app->id(); |
| 438 app = NULL; |
| 439 |
| 440 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
| 441 sync_service->ProcessAppSyncData(app_sync_data); |
| 442 |
| 443 // Verify the installation. |
| 444 VerifyPromotedApp(app_id, expected_set); |
| 445 |
| 446 // The sort ordinals from sync should not be overridden. |
| 321 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | 447 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 322 ASSERT_TRUE(prefs); | |
| 323 EXPECT_FALSE(prefs->IsEphemeralApp(app_id)); | |
| 324 | |
| 325 // Check sort ordinals. | |
| 326 extensions::AppSorting* app_sorting = prefs->app_sorting(); | 448 extensions::AppSorting* app_sorting = prefs->app_sorting(); |
| 327 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); | 449 EXPECT_TRUE( |
| 328 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid()); | 450 app_sorting->GetAppLaunchOrdinal(app_id).Equals(kAppLaunchOrdinal)); |
| 451 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal)); |
| 329 } | 452 } |
| 330 | 453 |
| 331 void InitSyncService() { | 454 void InitSyncService() { |
| 332 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); | 455 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
| 333 sync_service->MergeDataAndStartSyncing( | 456 sync_service->MergeDataAndStartSyncing( |
| 334 syncer::APPS, | 457 syncer::APPS, |
| 335 syncer::SyncDataList(), | 458 syncer::SyncDataList(), |
| 336 scoped_ptr<syncer::SyncChangeProcessor>( | 459 scoped_ptr<syncer::SyncChangeProcessor>( |
| 337 new syncer::SyncChangeProcessorWrapperForTest( | 460 new syncer::SyncChangeProcessorWrapperForTest( |
| 338 &mock_sync_processor_)), | 461 &mock_sync_processor_)), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 354 } | 477 } |
| 355 | 478 |
| 356 void VerifySyncChange(const AppSyncData* sync_change, bool expect_enabled) { | 479 void VerifySyncChange(const AppSyncData* sync_change, bool expect_enabled) { |
| 357 ASSERT_TRUE(sync_change); | 480 ASSERT_TRUE(sync_change); |
| 358 EXPECT_TRUE(sync_change->page_ordinal().IsValid()); | 481 EXPECT_TRUE(sync_change->page_ordinal().IsValid()); |
| 359 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid()); | 482 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid()); |
| 360 EXPECT_FALSE(sync_change->uninstalled()); | 483 EXPECT_FALSE(sync_change->uninstalled()); |
| 361 EXPECT_EQ(expect_enabled, sync_change->extension_sync_data().enabled()); | 484 EXPECT_EQ(expect_enabled, sync_change->extension_sync_data().enabled()); |
| 362 } | 485 } |
| 363 | 486 |
| 487 void TestInstallEvent(bool close_app) { |
| 488 ExtensionTestMessageListener first_msg_listener(false); |
| 489 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp); |
| 490 ASSERT_TRUE(app); |
| 491 |
| 492 // When an ephemeral app is first added, it should not receive the |
| 493 // onInstalled event, hence the first message received from the test should |
| 494 // be "launched" and not "installed". |
| 495 ASSERT_TRUE(first_msg_listener.WaitUntilSatisfied()); |
| 496 EXPECT_EQ(std::string("launched"), first_msg_listener.message()); |
| 497 |
| 498 if (close_app) |
| 499 CloseAppWaitForUnload(app->id()); |
| 500 |
| 501 // When installed permanently, the app should receive the onInstalled event. |
| 502 ExtensionTestMessageListener install_listener("installed", false); |
| 503 PromoteEphemeralApp(app); |
| 504 ASSERT_TRUE(install_listener.WaitUntilSatisfied()); |
| 505 } |
| 506 |
| 507 private: |
| 364 syncer::FakeSyncChangeProcessor mock_sync_processor_; | 508 syncer::FakeSyncChangeProcessor mock_sync_processor_; |
| 365 }; | 509 }; |
| 366 | 510 |
| 367 // Verify that ephemeral apps can be launched and receive system events when | 511 // Verify that ephemeral apps can be launched and receive system events when |
| 368 // they are running. Once they are inactive they should not receive system | 512 // they are running. Once they are inactive they should not receive system |
| 369 // events. | 513 // events. |
| 370 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) { | 514 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) { |
| 371 const Extension* extension = | 515 const Extension* extension = |
| 372 InstallAndLaunchEphemeralApp(kDispatchEventTestApp); | 516 InstallAndLaunchEphemeralApp(kDispatchEventTestApp); |
| 373 ASSERT_TRUE(extension); | 517 ASSERT_TRUE(extension); |
| 374 | 518 |
| 375 // Send a fake alarm event to the app and verify that a response is | 519 // Send a fake alarm event to the app and verify that a response is |
| 376 // received. | 520 // received. |
| 377 EventRouter* event_router = EventRouter::Get(profile()); | 521 EventRouter* event_router = EventRouter::Get(profile()); |
| 378 ASSERT_TRUE(event_router); | 522 ASSERT_TRUE(event_router); |
| 379 | 523 |
| 380 ExtensionTestMessageListener alarm_received_listener("alarm_received", false); | 524 ExtensionTestMessageListener alarm_received_listener("alarm_received", false); |
| 381 DispatchAlarmEvent(event_router, extension->id()); | 525 DispatchAlarmEvent(event_router, extension->id()); |
| 382 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied()); | 526 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied()); |
| 383 | 527 |
| 384 CloseApp(extension->id()); | 528 CloseAppWaitForUnload(extension->id()); |
| 385 | |
| 386 // The app needs to be launched once in order to have the onAlarm() event | |
| 387 // registered. | |
| 388 ASSERT_TRUE(event_router->ExtensionHasEventListener( | |
| 389 extension->id(), alarms::OnAlarm::kEventName)); | |
| 390 | 529 |
| 391 // Dispatch the alarm event again and verify that the event page did not get | 530 // Dispatch the alarm event again and verify that the event page did not get |
| 392 // loaded for the app. | 531 // loaded for the app. |
| 393 DispatchAlarmEvent(event_router, extension->id()); | 532 DispatchAlarmEvent(event_router, extension->id()); |
| 394 VerifyAppNotLoaded(extension->id()); | 533 VerifyAppNotLoaded(extension->id()); |
| 395 } | 534 } |
| 396 | 535 |
| 397 // Verify that ephemeral apps will receive messages while they are running. | 536 // Verify that ephemeral apps will receive messages while they are running. |
| 398 // Flaky test: crbug.com/394426 | 537 // Flaky test: crbug.com/394426 |
| 399 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | 538 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 400 DISABLED_ReceiveMessagesWhenLaunched) { | 539 DISABLED_ReceiveMessagesWhenLaunched) { |
| 401 const Extension* receiver = | 540 const Extension* receiver = |
| 402 InstallAndLaunchEphemeralApp(kMessagingReceiverApp); | 541 InstallAndLaunchEphemeralApp(kMessagingReceiverApp); |
| 403 ASSERT_TRUE(receiver); | 542 ASSERT_TRUE(receiver); |
| 404 | 543 |
| 405 // Verify that messages are received while the app is running. | 544 // Verify that messages are received while the app is running. |
| 406 ExtensionApiTest::ResultCatcher result_catcher; | 545 ExtensionApiTest::ResultCatcher result_catcher; |
| 407 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success", | 546 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success", |
| 408 "Launched"); | 547 "Launched"); |
| 409 EXPECT_TRUE(result_catcher.GetNextResult()); | 548 EXPECT_TRUE(result_catcher.GetNextResult()); |
| 410 | 549 |
| 411 CloseApp(receiver->id()); | 550 CloseAppWaitForUnload(receiver->id()); |
| 412 | 551 |
| 413 // Verify that messages are not received while the app is inactive. | 552 // Verify that messages are not received while the app is inactive. |
| 414 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail", "Launched"); | 553 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail", "Launched"); |
| 415 EXPECT_TRUE(result_catcher.GetNextResult()); | 554 EXPECT_TRUE(result_catcher.GetNextResult()); |
| 416 } | 555 } |
| 417 | 556 |
| 557 // Verifies that the chrome.runtime.onInstalled() event is received by a running |
| 558 // ephemeral app only when it is promoted. |
| 559 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 560 InstallEventReceivedWhileRunning) { |
| 561 TestInstallEvent(false /* close app */); |
| 562 } |
| 563 |
| 564 // Verifies that when an idle ephemeral app is promoted, it will be loaded to |
| 565 // receive the chrome.runtime.onInstalled() event. |
| 566 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEventReceivedWhileIdle) { |
| 567 TestInstallEvent(true /* close app */); |
| 568 } |
| 569 |
| 570 // Verifies that the chrome.runtime.onRestarted() event is received by an |
| 571 // ephemeral app. |
| 572 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RestartEventReceived) { |
| 573 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp); |
| 574 ASSERT_TRUE(app); |
| 575 CloseAppWaitForUnload(app->id()); |
| 576 |
| 577 // Fake ephemeral app running before restart. |
| 578 ExtensionSystem::Get(profile())->extension_service()->EnableExtension( |
| 579 app->id()); |
| 580 ASSERT_TRUE(ExtensionRegistry::Get(profile())->enabled_extensions().Contains( |
| 581 app->id())); |
| 582 ExtensionPrefs::Get(profile())->SetExtensionRunning(app->id(), true); |
| 583 |
| 584 ExtensionTestMessageListener restart_listener("restarted", false); |
| 585 apps::AppRestoreService::Get(profile())->HandleStartup(true); |
| 586 EXPECT_TRUE(restart_listener.WaitUntilSatisfied()); |
| 587 } |
| 588 |
| 418 // Verify that an updated ephemeral app will still have its ephemeral flag | 589 // Verify that an updated ephemeral app will still have its ephemeral flag |
| 419 // enabled. | 590 // enabled. |
| 420 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { | 591 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { |
| 421 InitSyncService(); | 592 InitSyncService(); |
| 422 | 593 |
| 423 const Extension* app_v1 = InstallAndLaunchEphemeralApp(kMessagingReceiverApp); | 594 const Extension* app_v1 = InstallAndLaunchEphemeralApp(kMessagingReceiverApp); |
| 424 ASSERT_TRUE(app_v1); | 595 ASSERT_TRUE(app_v1); |
| 596 VerifyEphemeralApp(app_v1->id()); |
| 597 CloseAppWaitForUnload(app_v1->id()); |
| 598 VerifyInactiveEphemeralApp(app_v1->id()); |
| 599 |
| 425 std::string app_id = app_v1->id(); | 600 std::string app_id = app_v1->id(); |
| 426 base::Version app_original_version = *app_v1->version(); | 601 base::Version app_original_version = *app_v1->version(); |
| 427 | 602 |
| 428 VerifyEphemeralApp(app_id); | |
| 429 CloseApp(app_id); | |
| 430 | |
| 431 // Update to version 2 of the app. | 603 // Update to version 2 of the app. |
| 432 app_v1 = NULL; // The extension object will be destroyed during update. | 604 app_v1 = NULL; // The extension object will be destroyed during update. |
| 433 InstallObserver installed_observer(profile()); | 605 InstallObserver installed_observer(profile()); |
| 434 const Extension* app_v2 = UpdateEphemeralApp( | 606 const Extension* app_v2 = |
| 435 app_id, GetTestPath(kMessagingReceiverAppV2), | 607 UpdateEphemeralApp(app_id, |
| 436 GetTestPath(kMessagingReceiverApp).ReplaceExtension( | 608 GetTestPath(kMessagingReceiverAppV2), |
| 437 FILE_PATH_LITERAL(".pem"))); | 609 GetTestPath(kMessagingReceiverApp) |
| 610 .ReplaceExtension(FILE_PATH_LITERAL(".pem"))); |
| 438 | 611 |
| 439 // Check the notification parameters. | 612 // Check the notification parameters. |
| 440 const InstallObserver::InstallParameters& params = installed_observer.Last(); | 613 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 441 EXPECT_EQ(app_id, params.id); | 614 EXPECT_EQ(app_id, params.id); |
| 442 EXPECT_TRUE(params.is_update); | 615 EXPECT_TRUE(params.is_update); |
| 443 EXPECT_FALSE(params.from_ephemeral); | 616 EXPECT_FALSE(params.from_ephemeral); |
| 444 | 617 |
| 445 // The ephemeral flag should still be enabled. | 618 // The ephemeral flag should still be set. |
| 446 ASSERT_TRUE(app_v2); | 619 ASSERT_TRUE(app_v2); |
| 447 EXPECT_GT(app_v2->version()->CompareTo(app_original_version), 0); | 620 EXPECT_GT(app_v2->version()->CompareTo(app_original_version), 0); |
| 448 VerifyEphemeralApp(app_id); | 621 VerifyEphemeralApp(app_id); |
| 622 |
| 623 // The app should still be disabled in extension system. |
| 624 VerifyInactiveEphemeralApp(app_id); |
| 449 } | 625 } |
| 450 | 626 |
| 451 // Verify that if notifications have been disabled for an ephemeral app, it will | 627 // Verify that if notifications have been disabled for an ephemeral app, it will |
| 452 // remain disabled even after being evicted from the cache. | 628 // remain disabled even after being evicted from the cache. |
| 453 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) { | 629 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) { |
| 454 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 630 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 455 ASSERT_TRUE(app); | 631 ASSERT_TRUE(app); |
| 456 | 632 |
| 457 // Disable notifications for this app. | 633 // Disable notifications for this app. |
| 458 DesktopNotificationService* notification_service = | 634 DesktopNotificationService* notification_service = |
| 459 DesktopNotificationServiceFactory::GetForProfile(profile()); | 635 DesktopNotificationServiceFactory::GetForProfile(profile()); |
| 460 ASSERT_TRUE(notification_service); | 636 ASSERT_TRUE(notification_service); |
| 461 | 637 |
| 462 message_center::NotifierId notifier_id( | 638 message_center::NotifierId notifier_id( |
| 463 message_center::NotifierId::APPLICATION, app->id()); | 639 message_center::NotifierId::APPLICATION, app->id()); |
| 464 EXPECT_TRUE(notification_service->IsNotifierEnabled(notifier_id)); | 640 EXPECT_TRUE(notification_service->IsNotifierEnabled(notifier_id)); |
| 465 notification_service->SetNotifierEnabled(notifier_id, false); | 641 notification_service->SetNotifierEnabled(notifier_id, false); |
| 466 EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id)); | 642 EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id)); |
| 467 | 643 |
| 468 // Remove the app. | 644 // Remove the app. |
| 645 CloseAppWaitForUnload(app->id()); |
| 469 EvictApp(app->id()); | 646 EvictApp(app->id()); |
| 470 | 647 |
| 471 // Reinstall the ephemeral app and verify that notifications remain disabled. | 648 // Reinstall the ephemeral app and verify that notifications remain disabled. |
| 472 app = InstallEphemeralApp(kNotificationsTestApp); | 649 app = InstallEphemeralApp(kNotificationsTestApp); |
| 473 ASSERT_TRUE(app); | 650 ASSERT_TRUE(app); |
| 474 message_center::NotifierId reinstalled_notifier_id( | 651 message_center::NotifierId reinstalled_notifier_id( |
| 475 message_center::NotifierId::APPLICATION, app->id()); | 652 message_center::NotifierId::APPLICATION, app->id()); |
| 476 EXPECT_FALSE(notification_service->IsNotifierEnabled( | 653 EXPECT_FALSE(notification_service->IsNotifierEnabled( |
| 477 reinstalled_notifier_id)); | 654 reinstalled_notifier_id)); |
| 478 } | 655 } |
| 479 | 656 |
| 480 // Verify that only running ephemeral apps will appear in the Notification | 657 // Verify that only running ephemeral apps will appear in the Notification |
| 481 // Settings UI. Inactive, cached ephemeral apps should not appear. | 658 // Settings UI. Inactive, cached ephemeral apps should not appear. |
| 482 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | 659 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 483 IncludeRunningEphemeralAppsInNotifiers) { | 660 IncludeRunningEphemeralAppsInNotifiers) { |
| 484 message_center::NotifierSettingsProvider* settings_provider = | 661 message_center::NotifierSettingsProvider* settings_provider = |
| 485 message_center::MessageCenter::Get()->GetNotifierSettingsProvider(); | 662 message_center::MessageCenter::Get()->GetNotifierSettingsProvider(); |
| 486 // TODO(tmdiep): Remove once notifications settings are supported across | 663 DCHECK(settings_provider); |
| 487 // all platforms. This test will fail for Linux GTK. | |
| 488 if (!settings_provider) | |
| 489 return; | |
| 490 | 664 |
| 491 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | 665 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 492 ASSERT_TRUE(app); | 666 ASSERT_TRUE(app); |
| 493 message_center::NotifierId notifier_id( | 667 message_center::NotifierId notifier_id( |
| 494 message_center::NotifierId::APPLICATION, app->id()); | 668 message_center::NotifierId::APPLICATION, app->id()); |
| 495 | 669 |
| 496 // Since the ephemeral app is running, it should be included in the list | 670 // Since the ephemeral app is running, it should be included in the list |
| 497 // of notifiers to show in the UI. | 671 // of notifiers to show in the UI. |
| 498 NotifierList notifiers; | 672 NotifierList notifiers; |
| 499 STLElementDeleter<NotifierList> notifier_deleter(¬ifiers); | 673 STLElementDeleter<NotifierList> notifier_deleter(¬ifiers); |
| 500 | 674 |
| 501 settings_provider->GetNotifierList(¬ifiers); | 675 settings_provider->GetNotifierList(¬ifiers); |
| 502 EXPECT_TRUE(IsNotifierInList(notifier_id, notifiers)); | 676 EXPECT_TRUE(IsNotifierInList(notifier_id, notifiers)); |
| 503 STLDeleteElements(¬ifiers); | 677 STLDeleteElements(¬ifiers); |
| 504 | 678 |
| 505 // Close the ephemeral app. | 679 // Close the ephemeral app. |
| 506 CloseApp(app->id()); | 680 CloseAppWaitForUnload(app->id()); |
| 507 | 681 |
| 508 // Inactive ephemeral apps should not be included in the list of notifiers to | 682 // Inactive ephemeral apps should not be included in the list of notifiers to |
| 509 // show in the UI. | 683 // show in the UI. |
| 510 settings_provider->GetNotifierList(¬ifiers); | 684 settings_provider->GetNotifierList(¬ifiers); |
| 511 EXPECT_FALSE(IsNotifierInList(notifier_id, notifiers)); | 685 EXPECT_FALSE(IsNotifierInList(notifier_id, notifiers)); |
| 512 } | 686 } |
| 513 | 687 |
| 514 // Verify that ephemeral apps will have no ability to retain file entries after | 688 // Verify that ephemeral apps will have no ability to retain file entries after |
| 515 // close. Normal retainEntry behavior for installed apps is tested in | 689 // close. Normal retainEntry behavior for installed apps is tested in |
| 516 // FileSystemApiTest. | 690 // FileSystemApiTest. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 539 // flushed. | 713 // flushed. |
| 540 std::vector<apps::SavedFileEntry> file_entries = | 714 std::vector<apps::SavedFileEntry> file_entries = |
| 541 apps::SavedFilesService::Get(profile()) | 715 apps::SavedFilesService::Get(profile()) |
| 542 ->GetAllFileEntries(app->id()); | 716 ->GetAllFileEntries(app->id()); |
| 543 EXPECT_TRUE(file_entries.empty()); | 717 EXPECT_TRUE(file_entries.empty()); |
| 544 | 718 |
| 545 // The second test verifies that the file cannot be reopened. | 719 // The second test verifies that the file cannot be reopened. |
| 546 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_; | 720 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_; |
| 547 } | 721 } |
| 548 | 722 |
| 549 // Checks the process of installing and then promoting an ephemeral app. | 723 // Checks the process of launching an ephemeral app and then promoting the app |
| 550 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralApp) { | 724 // while it is running. |
| 725 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileRunning) { |
| 551 InitSyncService(); | 726 InitSyncService(); |
| 552 | 727 |
| 553 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 728 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 554 ASSERT_TRUE(app); | 729 ASSERT_TRUE(app); |
| 555 | 730 |
| 556 // Ephemeral apps should not be synced. | 731 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED); |
| 557 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app->id()); | |
| 558 EXPECT_FALSE(sync_change.get()); | |
| 559 | 732 |
| 560 // Promote the app to a regular installed app. | 733 // Ensure that the app is not unloaded and disabled after it is closed. |
| 561 InstallObserver installed_observer(profile()); | 734 CloseApp(app->id()); |
| 562 PromoteEphemeralApp(app); | |
| 563 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); | 735 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); |
| 564 | |
| 565 // Check the notification parameters. | |
| 566 const InstallObserver::InstallParameters& params = installed_observer.Last(); | |
| 567 EXPECT_EQ(app->id(), params.id); | |
| 568 EXPECT_TRUE(params.is_update); | |
| 569 EXPECT_TRUE(params.from_ephemeral); | |
| 570 | |
| 571 // The installation should now be synced. | |
| 572 sync_change = GetLastSyncChangeForApp(app->id()); | |
| 573 VerifySyncChange(sync_change.get(), true); | |
| 574 } | 736 } |
| 575 | 737 |
| 576 // Verifies that promoting an ephemeral app will enable it. | 738 // Checks the process of launching an ephemeral app and then promoting the app |
| 577 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppAndEnable) { | 739 // while it is idle. |
| 740 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileIdle) { |
| 578 InitSyncService(); | 741 InitSyncService(); |
| 579 | 742 |
| 580 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 743 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 581 ASSERT_TRUE(app); | 744 ASSERT_TRUE(app); |
| 745 CloseAppWaitForUnload(app->id()); |
| 746 VerifyInactiveEphemeralApp(app->id()); |
| 582 | 747 |
| 583 // Disable the ephemeral app due to a permissions increase. This also involves | 748 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED); |
| 584 // setting the DidExtensionEscalatePermissions flag. | 749 } |
| 585 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | |
| 586 prefs->SetDidExtensionEscalatePermissions(app, true); | |
| 587 ExtensionService* service = | |
| 588 ExtensionSystem::Get(profile())->extension_service(); | |
| 589 service->DisableExtension(app->id(), Extension::DISABLE_PERMISSIONS_INCREASE); | |
| 590 ASSERT_TRUE(ExtensionRegistry::Get(profile())-> | |
| 591 GetExtensionById(app->id(), ExtensionRegistry::DISABLED)); | |
| 592 | 750 |
| 593 // Promote to a regular installed app. It should be enabled. | 751 // Verifies that promoting an ephemeral app that was disabled due to a |
| 594 PromoteEphemeralApp(app); | 752 // permissions increase will enable it. |
| 595 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); | 753 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppAndGrantPermissions) { |
| 596 EXPECT_FALSE(prefs->DidExtensionEscalatePermissions(app->id())); | 754 InitSyncService(); |
| 597 | 755 |
| 598 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app->id()); | 756 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 599 VerifySyncChange(sync_change.get(), true); | 757 ASSERT_TRUE(app); |
| 758 CloseAppWaitForUnload(app->id()); |
| 759 DisableEphemeralApp(app, Extension::DISABLE_PERMISSIONS_INCREASE); |
| 760 |
| 761 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED); |
| 762 EXPECT_FALSE(ExtensionPrefs::Get(profile()) |
| 763 ->DidExtensionEscalatePermissions(app->id())); |
| 600 } | 764 } |
| 601 | 765 |
| 602 // Verifies that promoting an ephemeral app that has unsupported requirements | 766 // Verifies that promoting an ephemeral app that has unsupported requirements |
| 603 // will not enable it. | 767 // will not enable it. |
| 604 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | 768 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 605 PromoteUnsupportedEphemeralApp) { | 769 PromoteUnsupportedEphemeralApp) { |
| 606 InitSyncService(); | 770 InitSyncService(); |
| 607 | 771 |
| 608 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 772 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 609 ASSERT_TRUE(app); | 773 ASSERT_TRUE(app); |
| 774 CloseAppWaitForUnload(app->id()); |
| 775 DisableEphemeralApp(app, Extension::DISABLE_UNSUPPORTED_REQUIREMENT); |
| 610 | 776 |
| 611 // Disable the ephemeral app. | 777 // When promoted to a regular installed app, it should remain disabled. |
| 778 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::DISABLED); |
| 779 } |
| 780 |
| 781 // Verifies that promoting an ephemeral app that is blacklisted will not enable |
| 782 // it. |
| 783 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 784 PromoteBlacklistedEphemeralApp) { |
| 785 InitSyncService(); |
| 786 |
| 787 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 788 ASSERT_TRUE(app); |
| 789 CloseAppWaitForUnload(app->id()); |
| 790 |
| 612 ExtensionService* service = | 791 ExtensionService* service = |
| 613 ExtensionSystem::Get(profile())->extension_service(); | 792 ExtensionSystem::Get(profile())->extension_service(); |
| 614 service->DisableExtension( | 793 service->BlacklistExtensionForTest(app->id()); |
| 615 app->id(), Extension::DISABLE_UNSUPPORTED_REQUIREMENT); | 794 ASSERT_TRUE( |
| 616 ASSERT_TRUE(ExtensionRegistry::Get(profile())-> | 795 ExtensionRegistry::Get(profile())->blacklisted_extensions().Contains( |
| 617 GetExtensionById(app->id(), ExtensionRegistry::DISABLED)); | 796 app->id())); |
| 618 | 797 |
| 619 // Promote to a regular installed app. It should remain disabled. | 798 // When promoted to a regular installed app, it should remain blacklisted. |
| 620 PromoteEphemeralApp(app); | 799 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::BLACKLISTED); |
| 621 VerifyPromotedApp(app->id(), ExtensionRegistry::DISABLED); | |
| 622 | 800 |
| 801 // The app should be synced, but disabled. |
| 623 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app->id()); | 802 scoped_ptr<AppSyncData> sync_change = GetLastSyncChangeForApp(app->id()); |
| 624 VerifySyncChange(sync_change.get(), false); | 803 VerifySyncChange(sync_change.get(), false); |
| 625 } | 804 } |
| 626 | 805 |
| 627 // Checks the process of promoting an ephemeral app from sync. | 806 // Checks the process of promoting an ephemeral app from sync while the app is |
| 628 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppFromSync) { | 807 // running. |
| 808 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 809 PromoteAppFromSyncWhileRunning) { |
| 629 InitSyncService(); | 810 InitSyncService(); |
| 630 | 811 |
| 631 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 812 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 632 ASSERT_TRUE(app); | 813 ASSERT_TRUE(app); |
| 633 std::string app_id = app->id(); | |
| 634 | 814 |
| 635 // Simulate an install from sync. | 815 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED); |
| 636 const syncer::StringOrdinal kAppLaunchOrdinal("x"); | |
| 637 const syncer::StringOrdinal kPageOrdinal("y"); | |
| 638 AppSyncData app_sync_data( | |
| 639 *app, | |
| 640 true /* enabled */, | |
| 641 false /* incognito enabled */, | |
| 642 false /* remote install */, | |
| 643 kAppLaunchOrdinal, | |
| 644 kPageOrdinal, | |
| 645 extensions::LAUNCH_TYPE_REGULAR); | |
| 646 | 816 |
| 647 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); | 817 // Ensure that the app is not unloaded and disabled after it is closed. |
| 648 sync_service->ProcessAppSyncData(app_sync_data); | 818 CloseApp(app->id()); |
| 819 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); |
| 820 } |
| 649 | 821 |
| 650 // Verify the installation. | 822 // Checks the process of promoting an ephemeral app from sync while the app is |
| 651 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); | 823 // idle. |
| 824 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppFromSyncWhileIdle) { |
| 825 InitSyncService(); |
| 652 | 826 |
| 653 // The sort ordinals from sync should not be overridden. | 827 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 654 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | 828 ASSERT_TRUE(app); |
| 655 extensions::AppSorting* app_sorting = prefs->app_sorting(); | 829 CloseAppWaitForUnload(app->id()); |
| 656 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).Equals( | 830 VerifyInactiveEphemeralApp(app->id()); |
| 657 kAppLaunchOrdinal)); | 831 |
| 658 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal)); | 832 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED); |
| 833 } |
| 834 |
| 835 // Checks the process of promoting an ephemeral app from sync, where the app |
| 836 // from sync is disabled, and the ephemeral app is running. |
| 837 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 838 PromoteDisabledAppFromSyncWhileRunning) { |
| 839 InitSyncService(); |
| 840 |
| 841 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 842 ASSERT_TRUE(app); |
| 843 |
| 844 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED); |
| 845 } |
| 846 |
| 847 // Checks the process of promoting an ephemeral app from sync, where the app |
| 848 // from sync is disabled, and the ephemeral app is idle. |
| 849 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 850 PromoteDisabledAppFromSyncWhileIdle) { |
| 851 InitSyncService(); |
| 852 |
| 853 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 854 ASSERT_TRUE(app); |
| 855 CloseAppWaitForUnload(app->id()); |
| 856 VerifyInactiveEphemeralApp(app->id()); |
| 857 |
| 858 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED); |
| 659 } | 859 } |
| 660 | 860 |
| 661 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to | 861 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to |
| 662 // permanently install an ephemeral app. However, there may be cases where an | 862 // permanently install an ephemeral app. However, there may be cases where an |
| 663 // install occurs through the usual route of installing from the Web Store (due | 863 // install occurs through the usual route of installing from the Web Store (due |
| 664 // to race conditions). Ensure that the app is still installed correctly. | 864 // to race conditions). Ensure that the app is still installed correctly. |
| 665 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | 865 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 666 ReplaceEphemeralAppWithInstalledApp) { | 866 ReplaceEphemeralAppWithInstalledApp) { |
| 667 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 867 InitSyncService(); |
| 868 |
| 869 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 668 ASSERT_TRUE(app); | 870 ASSERT_TRUE(app); |
| 871 CloseAppWaitForUnload(app->id()); |
| 669 std::string app_id = app->id(); | 872 std::string app_id = app->id(); |
| 670 app = NULL; | 873 app = NULL; |
| 671 | 874 |
| 672 InstallObserver installed_observer(profile()); | 875 InstallObserver installed_observer(profile()); |
| 673 ReplaceEphemeralApp(app_id, kNotificationsTestApp); | 876 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 1); |
| 674 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); | 877 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
| 675 | 878 |
| 676 // Check the notification parameters. | 879 // Check the notification parameters. |
| 677 const InstallObserver::InstallParameters& params = installed_observer.Last(); | 880 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 678 EXPECT_EQ(app_id, params.id); | 881 EXPECT_EQ(app_id, params.id); |
| 679 EXPECT_TRUE(params.is_update); | 882 EXPECT_TRUE(params.is_update); |
| 680 EXPECT_TRUE(params.from_ephemeral); | 883 EXPECT_TRUE(params.from_ephemeral); |
| 681 } | 884 } |
| 682 | 885 |
| 683 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will | 886 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will |
| 684 // be delayed until the app is idle. | 887 // be delayed until the app is idle. |
| 685 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | 888 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 686 ReplaceEphemeralAppWithDelayedInstalledApp) { | 889 ReplaceEphemeralAppWithDelayedInstalledApp) { |
| 890 InitSyncService(); |
| 891 |
| 687 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | 892 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); |
| 688 ASSERT_TRUE(app); | 893 ASSERT_TRUE(app); |
| 689 std::string app_id = app->id(); | 894 std::string app_id = app->id(); |
| 690 app = NULL; | 895 app = NULL; |
| 691 | 896 |
| 692 // Initiate install. | 897 // Initiate install. |
| 693 ReplaceEphemeralApp(app_id, kNotificationsTestApp); | 898 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 0); |
| 694 | 899 |
| 695 // The delayed installation will occur when the ephemeral app is closed. | 900 // The delayed installation will occur when the ephemeral app is closed. |
| 696 content::WindowedNotificationObserver installed_signal( | 901 content::WindowedNotificationObserver installed_signal( |
| 697 chrome::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, | 902 chrome::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED, |
| 698 content::Source<Profile>(profile())); | 903 content::Source<Profile>(profile())); |
| 699 InstallObserver installed_observer(profile()); | 904 InstallObserver installed_observer(profile()); |
| 700 CloseApp(app_id); | 905 CloseAppWaitForUnload(app_id); |
| 701 installed_signal.Wait(); | 906 installed_signal.Wait(); |
| 702 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); | 907 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
| 703 | 908 |
| 704 // Check the notification parameters. | 909 // Check the notification parameters. |
| 705 const InstallObserver::InstallParameters& params = installed_observer.Last(); | 910 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 706 EXPECT_EQ(app_id, params.id); | 911 EXPECT_EQ(app_id, params.id); |
| 707 EXPECT_TRUE(params.is_update); | 912 EXPECT_TRUE(params.is_update); |
| 708 EXPECT_TRUE(params.from_ephemeral); | 913 EXPECT_TRUE(params.from_ephemeral); |
| 709 } | 914 } |
| 710 | 915 |
| 916 // Verifies that an installed app cannot turn into an ephemeral app as result of |
| 917 // race conditions, i.e. an ephemeral app can be promoted to an installed app, |
| 918 // but not vice versa. |
| 919 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 920 ReplaceInstalledAppWithEphemeralApp) { |
| 921 const Extension* app = InstallPlatformApp(kNotificationsTestApp); |
| 922 ASSERT_TRUE(app); |
| 923 std::string app_id = app->id(); |
| 924 app = NULL; |
| 925 |
| 926 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile())); |
| 927 app = |
| 928 InstallEphemeralAppWithSourceAndFlags(GetTestPath(kNotificationsTestApp), |
| 929 0, |
| 930 Manifest::INTERNAL, |
| 931 Extension::NO_FLAGS); |
| 932 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile())); |
| 933 } |
| 934 |
| 711 // Ephemerality was previously encoded by the Extension::IS_EPHEMERAL creation | 935 // Ephemerality was previously encoded by the Extension::IS_EPHEMERAL creation |
| 712 // flag. This was changed to an "ephemeral_app" property. Check that the prefs | 936 // flag. This was changed to an "ephemeral_app" property. Check that the prefs |
| 713 // are handled correctly. | 937 // are handled correctly. |
| 714 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | 938 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 715 ExtensionPrefBackcompatibility) { | 939 ExtensionPrefBackcompatibility) { |
| 716 // Ensure that apps with the old prefs are recognized as ephemeral. | 940 // Ensure that apps with the old prefs are recognized as ephemeral. |
| 717 const Extension* app = | 941 const Extension* app = |
| 718 InstallExtensionWithSourceAndFlags(GetTestPath(kNotificationsTestApp), | 942 InstallExtensionWithSourceAndFlags(GetTestPath(kNotificationsTestApp), |
| 719 1, | 943 1, |
| 720 Manifest::INTERNAL, | 944 Manifest::INTERNAL, |
| 721 Extension::IS_EPHEMERAL); | 945 Extension::IS_EPHEMERAL); |
| 722 ASSERT_TRUE(app); | 946 ASSERT_TRUE(app); |
| 723 EXPECT_TRUE(extensions::util::IsEphemeralApp(app->id(), profile())); | 947 EXPECT_TRUE(extensions::util::IsEphemeralApp(app->id(), profile())); |
| 724 | 948 |
| 725 // Ensure that when the app is promoted to an installed app, the bit in the | 949 // Ensure that when the app is promoted to an installed app, the bit in the |
| 726 // creation flags is cleared. | 950 // creation flags is cleared. |
| 727 PromoteEphemeralApp(app); | 951 PromoteEphemeralApp(app); |
| 728 EXPECT_FALSE(extensions::util::IsEphemeralApp(app->id(), profile())); | 952 EXPECT_FALSE(extensions::util::IsEphemeralApp(app->id(), profile())); |
| 729 | 953 |
| 730 int creation_flags = | 954 int creation_flags = |
| 731 ExtensionPrefs::Get(profile())->GetCreationFlags(app->id()); | 955 ExtensionPrefs::Get(profile())->GetCreationFlags(app->id()); |
| 732 EXPECT_EQ(0, creation_flags & Extension::IS_EPHEMERAL); | 956 EXPECT_EQ(0, creation_flags & Extension::IS_EPHEMERAL); |
| 733 } | 957 } |
| OLD | NEW |