Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / background / background_application_list_model_unittest.cc
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   ~BackgroundApplicationListModelTest() override {}
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 }