1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // TODO(rickcam): Bug 73183: Add unit tests for image loading 6 7 #include <cstdlib> 8 #include <set> 9 10 #include "chrome/browser/background/background_application_list_model.h" 11 12 #include "base/command_line.h" 13 #include "base/files/file_path.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/stl_util.h" 17 #include "chrome/browser/extensions/extension_service.h" 18 #include "chrome/browser/extensions/extension_service_test_base.h" 19 #include "chrome/browser/extensions/permissions_updater.h" 20 #include "chrome/test/base/testing_profile.h" 21 #include "content/public/browser/notification_registrar.h" 22 #include "content/public/browser/notification_types.h" 23 #include "extensions/browser/extension_prefs.h" 24 #include "extensions/browser/extension_system.h" 25 #include "extensions/browser/uninstall_reason.h" 26 #include "extensions/common/extension.h" 27 #include "extensions/common/manifest_constants.h" 28 #include "extensions/common/permissions/api_permission.h" 29 #include "extensions/common/permissions/permission_set.h" 30 #include "extensions/common/permissions/permissions_data.h" 31 #include "testing/gtest/include/gtest/gtest.h" 32 33 // This value is used to seed the PRNG at the beginning of a sequence of 34 // operations to produce a repeatable sequence. 35 #define RANDOM_SEED (0x33F7A7A7) 36 37 using extensions::APIPermission; 38 using extensions::Extension; 39 40 // For ExtensionService interface when it requires a path that is not used. 41 base::FilePath bogus_file_pathname(const std::string& name) { 42 return base::FilePath(FILE_PATH_LITERAL("//foobar_nonexistent")) 43 .AppendASCII(name); 44 } 45 46 class BackgroundApplicationListModelTest 47 : public extensions::ExtensionServiceTestBase { 48 public: 49 BackgroundApplicationListModelTest() {} 50 virtual ~BackgroundApplicationListModelTest() {} 51 52 protected: 53 void InitializeAndLoadEmptyExtensionService() { 54 InitializeEmptyExtensionService(); 55 service_->Init(); /* Sends EXTENSIONS_READY */ 56 } 57 58 bool IsBackgroundApp(const Extension& app) { 59 return BackgroundApplicationListModel::IsBackgroundApp(app, 60 profile_.get()); 61 } 62 }; 63 64 enum PushMessagingOption { 65 NO_PUSH_MESSAGING, 66 PUSH_MESSAGING_PERMISSION, 67 PUSH_MESSAGING_BUT_NOT_BACKGROUND 68 }; 69 70 // Returns a barebones test Extension object with the specified |name|. The 71 // returned extension will include background permission iff 72 // |background_permission| is true and pushMessaging permission if requested 73 // by |push_messaging| value. Also the extension may have a specific id set 74 // to test the case when it has a pushMessaging permission but is not 75 // considered a background app based on a whitelist. 76 static scoped_refptr<Extension> CreateExtensionBase( 77 const std::string& name, 78 bool background_permission, 79 PushMessagingOption push_messaging) { 80 base::DictionaryValue manifest; 81 manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0"); 82 manifest.SetString(extensions::manifest_keys::kName, name); 83 base::ListValue* permissions = new base::ListValue(); 84 manifest.Set(extensions::manifest_keys::kPermissions, permissions); 85 if (background_permission) { 86 permissions->Append(new base::StringValue("background")); 87 } 88 if (push_messaging == PUSH_MESSAGING_PERMISSION || 89 push_messaging == PUSH_MESSAGING_BUT_NOT_BACKGROUND) { 90 permissions->Append(new base::StringValue("pushMessaging")); 91 } 92 93 std::string error; 94 scoped_refptr<Extension> extension; 95 96 // There is a whitelist for extensions that have pushMessaging permission but 97 // are not considered a background app. Create a test extension with a known 98 // test id if needed. 99 if (push_messaging == PUSH_MESSAGING_BUT_NOT_BACKGROUND) { 100 extension = Extension::Create( 101 bogus_file_pathname(name), 102 extensions::Manifest::INVALID_LOCATION, 103 manifest, 104 Extension::NO_FLAGS, 105 "aaaabbbbccccddddeeeeffffgggghhhh", 106 &error); 107 } else { 108 extension = Extension::Create( 109 bogus_file_pathname(name), 110 extensions::Manifest::INVALID_LOCATION, 111 manifest, 112 Extension::NO_FLAGS, 113 &error); 114 } 115 116 // Cannot ASSERT_* here because that attempts an illegitimate return. 117 // Cannot EXPECT_NE here because that assumes non-pointers unlike EXPECT_EQ 118 EXPECT_TRUE(extension.get() != NULL) << error; 119 return extension; 120 } 121 122 static scoped_refptr<Extension> CreateExtension(const std::string& name, 123 bool background_permission) { 124 return CreateExtensionBase(name, background_permission, NO_PUSH_MESSAGING); 125 } 126 127 namespace { 128 std::string GenerateUniqueExtensionName() { 129 static int uniqueness = 0; 130 std::ostringstream output; 131 output << "Unique Named Extension " << uniqueness; 132 ++uniqueness; 133 return output.str(); 134 } 135 136 void AddBackgroundPermission(ExtensionService* service, 137 Extension* extension) { 138 if (BackgroundApplicationListModel::IsBackgroundApp(*extension, 139 service->profile())) { 140 return; 141 } 142 143 scoped_refptr<Extension> temporary = 144 CreateExtension(GenerateUniqueExtensionName(), true); 145 scoped_refptr<const extensions::PermissionSet> permissions = 146 temporary->permissions_data()->active_permissions(); 147 extensions::PermissionsUpdater(service->profile()).AddPermissions( 148 extension, permissions.get()); 149 } 150 151 void RemoveBackgroundPermission(ExtensionService* service, 152 Extension* extension) { 153 if (!BackgroundApplicationListModel::IsBackgroundApp(*extension, 154 service->profile())) { 155 return; 156 } 157 extensions::PermissionsUpdater(service->profile()).RemovePermissions( 158 extension, extension->permissions_data()->active_permissions().get()); 159 } 160 161 void AddEphemeralApp(const Extension* extension, ExtensionService* service) { 162 extensions::ExtensionPrefs* prefs = 163 extensions::ExtensionPrefs::Get(service->profile()); 164 ASSERT_TRUE(prefs); 165 prefs->OnExtensionInstalled(extension, 166 extensions::Extension::ENABLED, 167 syncer::StringOrdinal(), 168 extensions::kInstallFlagIsEphemeral, 169 std::string()); 170 171 service->AddExtension(extension); 172 } 173 174 } // namespace 175 176 // Crashes on Mac tryslaves. 177 // http://crbug.com/165458 178 #if defined(OS_MACOSX) || defined(OS_LINUX) 179 #define MAYBE_ExplicitTest DISABLED_ExplicitTest 180 #else 181 #define MAYBE_ExplicitTest ExplicitTest 182 #endif 183 // With minimal test logic, verifies behavior over an explicit set of 184 // extensions, of which some are Background Apps and others are not. 185 TEST_F(BackgroundApplicationListModelTest, MAYBE_ExplicitTest) { 186 InitializeAndLoadEmptyExtensionService(); 187 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())-> 188 extension_service(); 189 ASSERT_TRUE(service); 190 ASSERT_TRUE(service->is_ready()); 191 ASSERT_TRUE(service->extensions()); 192 ASSERT_TRUE(service->extensions()->is_empty()); 193 scoped_ptr<BackgroundApplicationListModel> model( 194 new BackgroundApplicationListModel(profile_.get())); 195 ASSERT_EQ(0U, model->size()); 196 197 scoped_refptr<Extension> ext1 = CreateExtension("alpha", false); 198 scoped_refptr<Extension> ext2 = CreateExtension("bravo", false); 199 scoped_refptr<Extension> ext3 = CreateExtension("charlie", false); 200 scoped_refptr<Extension> bgapp1 = CreateExtension("delta", true); 201 scoped_refptr<Extension> bgapp2 = CreateExtension("echo", true); 202 ASSERT_TRUE(service->extensions() != NULL); 203 ASSERT_EQ(0U, service->extensions()->size()); 204 ASSERT_EQ(0U, model->size()); 205 206 // Add alternating Extensions and Background Apps 207 ASSERT_FALSE(IsBackgroundApp(*ext1.get())); 208 service->AddExtension(ext1.get()); 209 ASSERT_EQ(1U, service->extensions()->size()); 210 ASSERT_EQ(0U, model->size()); 211 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get())); 212 service->AddExtension(bgapp1.get()); 213 ASSERT_EQ(2U, service->extensions()->size()); 214 ASSERT_EQ(1U, model->size()); 215 ASSERT_FALSE(IsBackgroundApp(*ext2.get())); 216 service->AddExtension(ext2.get()); 217 ASSERT_EQ(3U, service->extensions()->size()); 218 ASSERT_EQ(1U, model->size()); 219 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get())); 220 service->AddExtension(bgapp2.get()); 221 ASSERT_EQ(4U, service->extensions()->size()); 222 ASSERT_EQ(2U, model->size()); 223 ASSERT_FALSE(IsBackgroundApp(*ext3.get())); 224 service->AddExtension(ext3.get()); 225 ASSERT_EQ(5U, service->extensions()->size()); 226 ASSERT_EQ(2U, model->size()); 227 228 // Remove in FIFO order. 229 ASSERT_FALSE(IsBackgroundApp(*ext1.get())); 230 service->UninstallExtension(ext1->id(), 231 extensions::UNINSTALL_REASON_FOR_TESTING, 232 base::Bind(&base::DoNothing), 233 NULL); 234 ASSERT_EQ(4U, service->extensions()->size()); 235 ASSERT_EQ(2U, model->size()); 236 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get())); 237 service->UninstallExtension(bgapp1->id(), 238 extensions::UNINSTALL_REASON_FOR_TESTING, 239 base::Bind(&base::DoNothing), 240 NULL); 241 ASSERT_EQ(3U, service->extensions()->size()); 242 ASSERT_EQ(1U, model->size()); 243 ASSERT_FALSE(IsBackgroundApp(*ext2.get())); 244 service->UninstallExtension(ext2->id(), 245 extensions::UNINSTALL_REASON_FOR_TESTING, 246 base::Bind(&base::DoNothing), 247 NULL); 248 ASSERT_EQ(2U, service->extensions()->size()); 249 ASSERT_EQ(1U, model->size()); 250 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get())); 251 service->UninstallExtension(bgapp2->id(), 252 extensions::UNINSTALL_REASON_FOR_TESTING, 253 base::Bind(&base::DoNothing), 254 NULL); 255 ASSERT_EQ(1U, service->extensions()->size()); 256 ASSERT_EQ(0U, model->size()); 257 ASSERT_FALSE(IsBackgroundApp(*ext3.get())); 258 service->UninstallExtension(ext3->id(), 259 extensions::UNINSTALL_REASON_FOR_TESTING, 260 base::Bind(&base::DoNothing), 261 NULL); 262 ASSERT_EQ(0U, service->extensions()->size()); 263 ASSERT_EQ(0U, model->size()); 264 } 265 266 // Verifies that pushMessaging also triggers background detection, except 267 // when extension is in a whitelist. 268 TEST_F(BackgroundApplicationListModelTest, PushMessagingTest) { 269 InitializeAndLoadEmptyExtensionService(); 270 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())-> 271 extension_service(); 272 ASSERT_TRUE(service); 273 ASSERT_TRUE(service->is_ready()); 274 ASSERT_TRUE(service->extensions()); 275 ASSERT_TRUE(service->extensions()->is_empty()); 276 scoped_ptr<BackgroundApplicationListModel> model( 277 new BackgroundApplicationListModel(profile_.get())); 278 ASSERT_EQ(0U, model->size()); 279 280 scoped_refptr<Extension> ext1 = CreateExtension("alpha", false); 281 scoped_refptr<Extension> ext2 = 282 CreateExtensionBase("charlie", false, PUSH_MESSAGING_BUT_NOT_BACKGROUND); 283 scoped_refptr<Extension> bgapp1 = 284 CreateExtensionBase("bravo", false, PUSH_MESSAGING_PERMISSION); 285 scoped_refptr<Extension> bgapp2 = 286 CreateExtensionBase("delta", true, PUSH_MESSAGING_PERMISSION); 287 scoped_refptr<Extension> bgapp3 = 288 CreateExtensionBase("echo", true, PUSH_MESSAGING_BUT_NOT_BACKGROUND); 289 ASSERT_TRUE(service->extensions() != NULL); 290 ASSERT_EQ(0U, service->extensions()->size()); 291 ASSERT_EQ(0U, model->size()); 292 293 // Add alternating Extensions and Background Apps 294 ASSERT_FALSE(IsBackgroundApp(*ext1.get())); 295 service->AddExtension(ext1.get()); 296 ASSERT_EQ(1U, service->extensions()->size()); 297 ASSERT_EQ(0U, model->size()); 298 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get())); 299 service->AddExtension(bgapp1.get()); 300 ASSERT_EQ(2U, service->extensions()->size()); 301 ASSERT_EQ(1U, model->size()); 302 ASSERT_FALSE(IsBackgroundApp(*ext2.get())); 303 service->AddExtension(ext2.get()); 304 ASSERT_EQ(3U, service->extensions()->size()); 305 ASSERT_EQ(1U, model->size()); 306 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get())); 307 service->AddExtension(bgapp2.get()); 308 ASSERT_EQ(4U, service->extensions()->size()); 309 ASSERT_EQ(2U, model->size()); 310 // Need to remove ext2 because it uses same id as bgapp3. 311 ASSERT_FALSE(IsBackgroundApp(*ext2.get())); 312 service->UninstallExtension(ext2->id(), 313 extensions::UNINSTALL_REASON_FOR_TESTING, 314 base::Bind(&base::DoNothing), 315 NULL); 316 ASSERT_EQ(3U, service->extensions()->size()); 317 ASSERT_EQ(2U, model->size()); 318 ASSERT_TRUE(IsBackgroundApp(*bgapp3.get())); 319 service->AddExtension(bgapp3.get()); 320 ASSERT_EQ(4U, service->extensions()->size()); 321 ASSERT_EQ(3U, model->size()); 322 323 // Remove in FIFO order. 324 ASSERT_FALSE(IsBackgroundApp(*ext1.get())); 325 service->UninstallExtension(ext1->id(), 326 extensions::UNINSTALL_REASON_FOR_TESTING, 327 base::Bind(&base::DoNothing), 328 NULL); 329 ASSERT_EQ(3U, service->extensions()->size()); 330 ASSERT_EQ(3U, model->size()); 331 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get())); 332 service->UninstallExtension(bgapp1->id(), 333 extensions::UNINSTALL_REASON_FOR_TESTING, 334 base::Bind(&base::DoNothing), 335 NULL); 336 ASSERT_EQ(2U, service->extensions()->size()); 337 ASSERT_EQ(2U, model->size()); 338 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get())); 339 service->UninstallExtension(bgapp2->id(), 340 extensions::UNINSTALL_REASON_FOR_TESTING, 341 base::Bind(&base::DoNothing), 342 NULL); 343 ASSERT_EQ(1U, service->extensions()->size()); 344 ASSERT_EQ(1U, model->size()); 345 ASSERT_TRUE(IsBackgroundApp(*bgapp3.get())); 346 service->UninstallExtension(bgapp3->id(), 347 extensions::UNINSTALL_REASON_FOR_TESTING, 348 base::Bind(&base::DoNothing), 349 NULL); 350 ASSERT_EQ(0U, service->extensions()->size()); 351 ASSERT_EQ(0U, model->size()); 352 } 353 354 // Verifies that an ephemeral app cannot trigger background mode. 355 TEST_F(BackgroundApplicationListModelTest, EphemeralAppTest) { 356 InitializeAndLoadEmptyExtensionService(); 357 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())-> 358 extension_service(); 359 ASSERT_TRUE(service); 360 ASSERT_TRUE(service->is_ready()); 361 ASSERT_TRUE(service->extensions()); 362 ASSERT_TRUE(service->extensions()->is_empty()); 363 scoped_ptr<BackgroundApplicationListModel> model( 364 new BackgroundApplicationListModel(profile_.get())); 365 ASSERT_EQ(0U, model->size()); 366 367 scoped_refptr<Extension> installed = 368 CreateExtensionBase("installed", false, PUSH_MESSAGING_PERMISSION); 369 scoped_refptr<Extension> ephemeral = 370 CreateExtensionBase("ephemeral", false, PUSH_MESSAGING_PERMISSION); 371 scoped_refptr<Extension> background = CreateExtension("background", true); 372 373 // Installed app with push messaging permissions can trigger background mode. 374 ASSERT_TRUE(IsBackgroundApp(*installed.get())); 375 service->AddExtension(installed.get()); 376 ASSERT_EQ(1U, service->extensions()->size()); 377 ASSERT_EQ(1U, model->size()); 378 // An ephemeral app with push messaging permissions should not trigger 379 // background mode. 380 AddEphemeralApp(ephemeral.get(), service); 381 ASSERT_FALSE(IsBackgroundApp(*ephemeral.get())); 382 ASSERT_EQ(2U, service->extensions()->size()); 383 ASSERT_EQ(1U, model->size()); 384 // An ephemeral app with the background permission should not trigger 385 // background mode. 386 AddEphemeralApp(background.get(), service); 387 ASSERT_FALSE(IsBackgroundApp(*background.get())); 388 ASSERT_EQ(3U, service->extensions()->size()); 389 ASSERT_EQ(1U, model->size()); 390 391 // If the ephemeral app becomes promoted to an installed app, it can now 392 // trigger background mode. 393 service->PromoteEphemeralApp(ephemeral.get(), false /*from sync*/); 394 ASSERT_TRUE(IsBackgroundApp(*ephemeral.get())); 395 ASSERT_EQ(3U, service->extensions()->size()); 396 ASSERT_EQ(2U, model->size()); 397 } 398 399 // With minimal test logic, verifies behavior with dynamic permissions. 400 TEST_F(BackgroundApplicationListModelTest, AddRemovePermissionsTest) { 401 InitializeAndLoadEmptyExtensionService(); 402 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())-> 403 extension_service(); 404 ASSERT_TRUE(service); 405 ASSERT_TRUE(service->is_ready()); 406 ASSERT_TRUE(service->extensions()); 407 ASSERT_TRUE(service->extensions()->is_empty()); 408 scoped_ptr<BackgroundApplicationListModel> model( 409 new BackgroundApplicationListModel(profile_.get())); 410 ASSERT_EQ(0U, model->size()); 411 412 scoped_refptr<Extension> ext = CreateExtension("extension", false); 413 ASSERT_FALSE( 414 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground)); 415 scoped_refptr<Extension> bgapp = CreateExtension("application", true); 416 ASSERT_TRUE( 417 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground)); 418 ASSERT_TRUE(service->extensions() != NULL); 419 ASSERT_EQ(0U, service->extensions()->size()); 420 ASSERT_EQ(0U, model->size()); 421 422 // Add one (non-background) extension and one background application 423 ASSERT_FALSE(IsBackgroundApp(*ext.get())); 424 service->AddExtension(ext.get()); 425 ASSERT_EQ(1U, service->extensions()->size()); 426 ASSERT_EQ(0U, model->size()); 427 ASSERT_TRUE(IsBackgroundApp(*bgapp.get())); 428 service->AddExtension(bgapp.get()); 429 ASSERT_EQ(2U, service->extensions()->size()); 430 ASSERT_EQ(1U, model->size()); 431 432 // Change permissions back and forth 433 AddBackgroundPermission(service, ext.get()); 434 ASSERT_TRUE( 435 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground)); 436 ASSERT_EQ(2U, service->extensions()->size()); 437 ASSERT_EQ(2U, model->size()); 438 RemoveBackgroundPermission(service, bgapp.get()); 439 ASSERT_FALSE( 440 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground)); 441 ASSERT_EQ(2U, service->extensions()->size()); 442 ASSERT_EQ(1U, model->size()); 443 RemoveBackgroundPermission(service, ext.get()); 444 ASSERT_FALSE( 445 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground)); 446 ASSERT_EQ(2U, service->extensions()->size()); 447 ASSERT_EQ(0U, model->size()); 448 AddBackgroundPermission(service, bgapp.get()); 449 ASSERT_TRUE( 450 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground)); 451 ASSERT_EQ(2U, service->extensions()->size()); 452 ASSERT_EQ(1U, model->size()); 453 } 454 455 typedef std::set<scoped_refptr<Extension> > ExtensionCollection; 456 457 namespace { 458 void AddExtension(ExtensionService* service, 459 ExtensionCollection* extensions, 460 BackgroundApplicationListModel* model, 461 size_t* expected, 462 size_t* count) { 463 bool create_background = false; 464 if (rand() % 2) { 465 create_background = true; 466 ++*expected; 467 } 468 scoped_refptr<Extension> extension = 469 CreateExtension(GenerateUniqueExtensionName(), create_background); 470 ASSERT_EQ(BackgroundApplicationListModel::IsBackgroundApp(*extension.get(), 471 service->profile()), 472 create_background); 473 extensions->insert(extension); 474 ++*count; 475 ASSERT_EQ(*count, extensions->size()); 476 service->AddExtension(extension.get()); 477 ASSERT_EQ(*count, service->extensions()->size()); 478 ASSERT_EQ(*expected, model->size()); 479 } 480 481 void RemoveExtension(ExtensionService* service, 482 ExtensionCollection* extensions, 483 BackgroundApplicationListModel* model, 484 size_t* expected, 485 size_t* count) { // Maybe remove an extension. 486 ExtensionCollection::iterator cursor = extensions->begin(); 487 if (cursor == extensions->end()) { 488 // Nothing to remove. Just verify accounting. 489 ASSERT_EQ(0U, *count); 490 ASSERT_EQ(0U, *expected); 491 ASSERT_EQ(0U, service->extensions()->size()); 492 ASSERT_EQ(0U, model->size()); 493 } else { 494 // Randomly select which extension to remove 495 if (extensions->size() > 1) { 496 int offset = rand() % (extensions->size() - 1); 497 for (int index = 0; index < offset; ++index) 498 ++cursor; 499 } 500 scoped_refptr<Extension> extension = cursor->get(); 501 std::string id = extension->id(); 502 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(), 503 service->profile())) { 504 --*expected; 505 } 506 extensions->erase(cursor); 507 --*count; 508 ASSERT_EQ(*count, extensions->size()); 509 service->UninstallExtension(extension->id(), 510 extensions::UNINSTALL_REASON_FOR_TESTING, 511 base::Bind(&base::DoNothing), 512 NULL); 513 ASSERT_EQ(*count, service->extensions()->size()); 514 ASSERT_EQ(*expected, model->size()); 515 } 516 } 517 518 void TogglePermission(ExtensionService* service, 519 ExtensionCollection* extensions, 520 BackgroundApplicationListModel* model, 521 size_t* expected, 522 size_t* count) { 523 ExtensionCollection::iterator cursor = extensions->begin(); 524 if (cursor == extensions->end()) { 525 // Nothing to toggle. Just verify accounting. 526 ASSERT_EQ(0U, *count); 527 ASSERT_EQ(0U, *expected); 528 ASSERT_EQ(0U, service->extensions()->size()); 529 ASSERT_EQ(0U, model->size()); 530 } else { 531 // Randomly select which extension to toggle. 532 if (extensions->size() > 1) { 533 int offset = rand() % (extensions->size() - 1); 534 for (int index = 0; index < offset; ++index) 535 ++cursor; 536 } 537 scoped_refptr<Extension> extension = cursor->get(); 538 std::string id = extension->id(); 539 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(), 540 service->profile())) { 541 --*expected; 542 ASSERT_EQ(*count, extensions->size()); 543 RemoveBackgroundPermission(service, extension.get()); 544 ASSERT_EQ(*count, service->extensions()->size()); 545 ASSERT_EQ(*expected, model->size()); 546 } else { 547 ++*expected; 548 ASSERT_EQ(*count, extensions->size()); 549 AddBackgroundPermission(service, extension.get()); 550 ASSERT_EQ(*count, service->extensions()->size()); 551 ASSERT_EQ(*expected, model->size()); 552 } 553 } 554 } 555 } // namespace 556 557 // Verifies behavior with a pseudo-randomly generated set of actions: Adding and 558 // removing extensions, of which some are Background Apps and others are not. 559 TEST_F(BackgroundApplicationListModelTest, RandomTest) { 560 InitializeAndLoadEmptyExtensionService(); 561 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())-> 562 extension_service(); 563 ASSERT_TRUE(service); 564 ASSERT_TRUE(service->is_ready()); 565 ASSERT_TRUE(service->extensions()); 566 ASSERT_TRUE(service->extensions()->is_empty()); 567 scoped_ptr<BackgroundApplicationListModel> model( 568 new BackgroundApplicationListModel(profile_.get())); 569 ASSERT_EQ(0U, model->size()); 570 571 static const int kIterations = 20; 572 ExtensionCollection extensions; 573 size_t count = 0; 574 size_t expected = 0; 575 srand(RANDOM_SEED); 576 for (int index = 0; index < kIterations; ++index) { 577 switch (rand() % 3) { 578 case 0: 579 AddExtension(service, &extensions, model.get(), &expected, &count); 580 break; 581 case 1: 582 RemoveExtension(service, &extensions, model.get(), &expected, &count); 583 break; 584 case 2: 585 TogglePermission(service, &extensions, model.get(), &expected, &count); 586 break; 587 default: 588 NOTREACHED(); 589 break; 590 } 591 } 592 } 593