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