Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / background / background_application_list_model_unittest.cc
blobd52ed8a2a9239a110298d6fbbf9d3729861baa53
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.
5 // TODO(rickcam): Bug 73183: Add unit tests for image loading
7 #include <cstdlib>
8 #include <set>
10 #include "chrome/browser/background/background_application_list_model.h"
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_unittest.h"
19 #include "chrome/browser/extensions/extension_system.h"
20 #include "chrome/browser/extensions/permissions_updater.h"
21 #include "chrome/test/base/testing_profile.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "content/public/browser/notification_types.h"
24 #include "extensions/common/extension.h"
25 #include "extensions/common/manifest_constants.h"
26 #include "extensions/common/permissions/api_permission.h"
27 #include "extensions/common/permissions/permission_set.h"
28 #include "testing/gtest/include/gtest/gtest.h"
30 // This value is used to seed the PRNG at the beginning of a sequence of
31 // operations to produce a repeatable sequence.
32 #define RANDOM_SEED (0x33F7A7A7)
34 using extensions::APIPermission;
35 using extensions::Extension;
37 // For ExtensionService interface when it requires a path that is not used.
38 base::FilePath bogus_file_pathname(const std::string& name) {
39 return base::FilePath(FILE_PATH_LITERAL("//foobar_nonexistent"))
40 .AppendASCII(name);
43 class BackgroundApplicationListModelTest : public ExtensionServiceTestBase {
44 public:
45 BackgroundApplicationListModelTest() {}
46 virtual ~BackgroundApplicationListModelTest() {}
48 protected:
49 void InitializeAndLoadEmptyExtensionService() {
50 InitializeEmptyExtensionService();
51 service_->Init(); /* Sends EXTENSIONS_READY */
54 bool IsBackgroundApp(const Extension& app) {
55 return BackgroundApplicationListModel::IsBackgroundApp(app,
56 profile_.get());
60 enum PushMessagingOption {
61 NO_PUSH_MESSAGING,
62 PUSH_MESSAGING_PERMISSION,
63 PUSH_MESSAGING_BUT_NOT_BACKGROUND
66 // Returns a barebones test Extension object with the specified |name|. The
67 // returned extension will include background permission iff
68 // |background_permission| is true and pushMessaging permission if requested
69 // by |push_messaging| value. Also the extension may have a specific id set
70 // to test the case when it has a pushMessaging permission but is not
71 // considered a background app based on a whitelist.
72 static scoped_refptr<Extension> CreateExtensionBase(
73 const std::string& name,
74 bool background_permission,
75 PushMessagingOption push_messaging) {
76 base::DictionaryValue manifest;
77 manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
78 manifest.SetString(extensions::manifest_keys::kName, name);
79 base::ListValue* permissions = new base::ListValue();
80 manifest.Set(extensions::manifest_keys::kPermissions, permissions);
81 if (background_permission) {
82 permissions->Append(base::Value::CreateStringValue("background"));
84 if (push_messaging == PUSH_MESSAGING_PERMISSION ||
85 push_messaging == PUSH_MESSAGING_BUT_NOT_BACKGROUND) {
86 permissions->Append(base::Value::CreateStringValue("pushMessaging"));
89 std::string error;
90 scoped_refptr<Extension> extension;
92 // There is a whitelist for extensions that have pushMessaging permission but
93 // are not considered a background app. Create a test extension with a known
94 // test id if needed.
95 if (push_messaging == PUSH_MESSAGING_BUT_NOT_BACKGROUND) {
96 extension = Extension::Create(
97 bogus_file_pathname(name),
98 extensions::Manifest::INVALID_LOCATION,
99 manifest,
100 Extension::NO_FLAGS,
101 "aaaabbbbccccddddeeeeffffgggghhhh",
102 &error);
103 } else {
104 extension = Extension::Create(
105 bogus_file_pathname(name),
106 extensions::Manifest::INVALID_LOCATION,
107 manifest,
108 Extension::NO_FLAGS,
109 &error);
112 // Cannot ASSERT_* here because that attempts an illegitimate return.
113 // Cannot EXPECT_NE here because that assumes non-pointers unlike EXPECT_EQ
114 EXPECT_TRUE(extension.get() != NULL) << error;
115 return extension;
118 static scoped_refptr<Extension> CreateExtension(const std::string& name,
119 bool background_permission) {
120 return CreateExtensionBase(name, background_permission, NO_PUSH_MESSAGING);
123 namespace {
124 std::string GenerateUniqueExtensionName() {
125 static int uniqueness = 0;
126 std::ostringstream output;
127 output << "Unique Named Extension " << uniqueness;
128 ++uniqueness;
129 return output.str();
132 void AddBackgroundPermission(ExtensionService* service,
133 Extension* extension) {
134 if (BackgroundApplicationListModel::IsBackgroundApp(*extension,
135 service->profile())) {
136 return;
139 scoped_refptr<Extension> temporary =
140 CreateExtension(GenerateUniqueExtensionName(), true);
141 scoped_refptr<const extensions::PermissionSet> permissions =
142 temporary->GetActivePermissions();
143 extensions::PermissionsUpdater(service->profile()).AddPermissions(
144 extension, permissions.get());
147 void RemoveBackgroundPermission(ExtensionService* service,
148 Extension* extension) {
149 if (!BackgroundApplicationListModel::IsBackgroundApp(*extension,
150 service->profile())) {
151 return;
153 extensions::PermissionsUpdater(service->profile())
154 .RemovePermissions(extension, extension->GetActivePermissions().get());
156 } // namespace
158 // Crashes on Mac tryslaves.
159 // http://crbug.com/165458
160 #if defined(OS_MACOSX) || defined(OS_LINUX)
161 #define MAYBE_ExplicitTest DISABLED_ExplicitTest
162 #else
163 #define MAYBE_ExplicitTest ExplicitTest
164 #endif
165 // With minimal test logic, verifies behavior over an explicit set of
166 // extensions, of which some are Background Apps and others are not.
167 TEST_F(BackgroundApplicationListModelTest, MAYBE_ExplicitTest) {
168 InitializeAndLoadEmptyExtensionService();
169 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())->
170 extension_service();
171 ASSERT_TRUE(service);
172 ASSERT_TRUE(service->is_ready());
173 ASSERT_TRUE(service->extensions());
174 ASSERT_TRUE(service->extensions()->is_empty());
175 scoped_ptr<BackgroundApplicationListModel> model(
176 new BackgroundApplicationListModel(profile_.get()));
177 ASSERT_EQ(0U, model->size());
179 scoped_refptr<Extension> ext1 = CreateExtension("alpha", false);
180 scoped_refptr<Extension> ext2 = CreateExtension("bravo", false);
181 scoped_refptr<Extension> ext3 = CreateExtension("charlie", false);
182 scoped_refptr<Extension> bgapp1 = CreateExtension("delta", true);
183 scoped_refptr<Extension> bgapp2 = CreateExtension("echo", true);
184 ASSERT_TRUE(service->extensions() != NULL);
185 ASSERT_EQ(0U, service->extensions()->size());
186 ASSERT_EQ(0U, model->size());
188 // Add alternating Extensions and Background Apps
189 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
190 service->AddExtension(ext1.get());
191 ASSERT_EQ(1U, service->extensions()->size());
192 ASSERT_EQ(0U, model->size());
193 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
194 service->AddExtension(bgapp1.get());
195 ASSERT_EQ(2U, service->extensions()->size());
196 ASSERT_EQ(1U, model->size());
197 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
198 service->AddExtension(ext2.get());
199 ASSERT_EQ(3U, service->extensions()->size());
200 ASSERT_EQ(1U, model->size());
201 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
202 service->AddExtension(bgapp2.get());
203 ASSERT_EQ(4U, service->extensions()->size());
204 ASSERT_EQ(2U, model->size());
205 ASSERT_FALSE(IsBackgroundApp(*ext3.get()));
206 service->AddExtension(ext3.get());
207 ASSERT_EQ(5U, service->extensions()->size());
208 ASSERT_EQ(2U, model->size());
210 // Remove in FIFO order.
211 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
212 service->UninstallExtension(ext1->id(), false, NULL);
213 ASSERT_EQ(4U, service->extensions()->size());
214 ASSERT_EQ(2U, model->size());
215 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
216 service->UninstallExtension(bgapp1->id(), false, NULL);
217 ASSERT_EQ(3U, service->extensions()->size());
218 ASSERT_EQ(1U, model->size());
219 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
220 service->UninstallExtension(ext2->id(), false, NULL);
221 ASSERT_EQ(2U, service->extensions()->size());
222 ASSERT_EQ(1U, model->size());
223 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
224 service->UninstallExtension(bgapp2->id(), false, NULL);
225 ASSERT_EQ(1U, service->extensions()->size());
226 ASSERT_EQ(0U, model->size());
227 ASSERT_FALSE(IsBackgroundApp(*ext3.get()));
228 service->UninstallExtension(ext3->id(), false, NULL);
229 ASSERT_EQ(0U, service->extensions()->size());
230 ASSERT_EQ(0U, model->size());
233 // Verifies that pushMessaging also triggers background detection, except
234 // when extension is in a whitelist.
235 TEST_F(BackgroundApplicationListModelTest, PushMessagingTest) {
236 InitializeAndLoadEmptyExtensionService();
237 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())->
238 extension_service();
239 ASSERT_TRUE(service);
240 ASSERT_TRUE(service->is_ready());
241 ASSERT_TRUE(service->extensions());
242 ASSERT_TRUE(service->extensions()->is_empty());
243 scoped_ptr<BackgroundApplicationListModel> model(
244 new BackgroundApplicationListModel(profile_.get()));
245 ASSERT_EQ(0U, model->size());
247 scoped_refptr<Extension> ext1 = CreateExtension("alpha", false);
248 scoped_refptr<Extension> ext2 =
249 CreateExtensionBase("charlie", false, PUSH_MESSAGING_BUT_NOT_BACKGROUND);
250 scoped_refptr<Extension> bgapp1 =
251 CreateExtensionBase("bravo", false, PUSH_MESSAGING_PERMISSION);
252 scoped_refptr<Extension> bgapp2 =
253 CreateExtensionBase("delta", true, PUSH_MESSAGING_PERMISSION);
254 scoped_refptr<Extension> bgapp3 =
255 CreateExtensionBase("echo", true, PUSH_MESSAGING_BUT_NOT_BACKGROUND);
256 ASSERT_TRUE(service->extensions() != NULL);
257 ASSERT_EQ(0U, service->extensions()->size());
258 ASSERT_EQ(0U, model->size());
260 // Add alternating Extensions and Background Apps
261 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
262 service->AddExtension(ext1.get());
263 ASSERT_EQ(1U, service->extensions()->size());
264 ASSERT_EQ(0U, model->size());
265 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
266 service->AddExtension(bgapp1.get());
267 ASSERT_EQ(2U, service->extensions()->size());
268 ASSERT_EQ(1U, model->size());
269 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
270 service->AddExtension(ext2.get());
271 ASSERT_EQ(3U, service->extensions()->size());
272 ASSERT_EQ(1U, model->size());
273 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
274 service->AddExtension(bgapp2.get());
275 ASSERT_EQ(4U, service->extensions()->size());
276 ASSERT_EQ(2U, model->size());
277 // Need to remove ext2 because it uses same id as bgapp3.
278 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
279 service->UninstallExtension(ext2->id(), false, NULL);
280 ASSERT_EQ(3U, service->extensions()->size());
281 ASSERT_EQ(2U, model->size());
282 ASSERT_TRUE(IsBackgroundApp(*bgapp3.get()));
283 service->AddExtension(bgapp3.get());
284 ASSERT_EQ(4U, service->extensions()->size());
285 ASSERT_EQ(3U, model->size());
287 // Remove in FIFO order.
288 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
289 service->UninstallExtension(ext1->id(), false, NULL);
290 ASSERT_EQ(3U, service->extensions()->size());
291 ASSERT_EQ(3U, model->size());
292 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
293 service->UninstallExtension(bgapp1->id(), false, NULL);
294 ASSERT_EQ(2U, service->extensions()->size());
295 ASSERT_EQ(2U, model->size());
296 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
297 service->UninstallExtension(bgapp2->id(), false, NULL);
298 ASSERT_EQ(1U, service->extensions()->size());
299 ASSERT_EQ(1U, model->size());
300 ASSERT_TRUE(IsBackgroundApp(*bgapp3.get()));
301 service->UninstallExtension(bgapp3->id(), false, NULL);
302 ASSERT_EQ(0U, service->extensions()->size());
303 ASSERT_EQ(0U, model->size());
308 // With minimal test logic, verifies behavior with dynamic permissions.
309 TEST_F(BackgroundApplicationListModelTest, AddRemovePermissionsTest) {
310 InitializeAndLoadEmptyExtensionService();
311 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())->
312 extension_service();
313 ASSERT_TRUE(service);
314 ASSERT_TRUE(service->is_ready());
315 ASSERT_TRUE(service->extensions());
316 ASSERT_TRUE(service->extensions()->is_empty());
317 scoped_ptr<BackgroundApplicationListModel> model(
318 new BackgroundApplicationListModel(profile_.get()));
319 ASSERT_EQ(0U, model->size());
321 scoped_refptr<Extension> ext = CreateExtension("extension", false);
322 ASSERT_FALSE(ext->HasAPIPermission(APIPermission::kBackground));
323 scoped_refptr<Extension> bgapp = CreateExtension("application", true);
324 ASSERT_TRUE(bgapp->HasAPIPermission(APIPermission::kBackground));
325 ASSERT_TRUE(service->extensions() != NULL);
326 ASSERT_EQ(0U, service->extensions()->size());
327 ASSERT_EQ(0U, model->size());
329 // Add one (non-background) extension and one background application
330 ASSERT_FALSE(IsBackgroundApp(*ext.get()));
331 service->AddExtension(ext.get());
332 ASSERT_EQ(1U, service->extensions()->size());
333 ASSERT_EQ(0U, model->size());
334 ASSERT_TRUE(IsBackgroundApp(*bgapp.get()));
335 service->AddExtension(bgapp.get());
336 ASSERT_EQ(2U, service->extensions()->size());
337 ASSERT_EQ(1U, model->size());
339 // Change permissions back and forth
340 AddBackgroundPermission(service, ext.get());
341 ASSERT_TRUE(ext->HasAPIPermission(APIPermission::kBackground));
342 ASSERT_EQ(2U, service->extensions()->size());
343 ASSERT_EQ(2U, model->size());
344 RemoveBackgroundPermission(service, bgapp.get());
345 ASSERT_FALSE(bgapp->HasAPIPermission(APIPermission::kBackground));
346 ASSERT_EQ(2U, service->extensions()->size());
347 ASSERT_EQ(1U, model->size());
348 RemoveBackgroundPermission(service, ext.get());
349 ASSERT_FALSE(ext->HasAPIPermission(APIPermission::kBackground));
350 ASSERT_EQ(2U, service->extensions()->size());
351 ASSERT_EQ(0U, model->size());
352 AddBackgroundPermission(service, bgapp.get());
353 ASSERT_TRUE(bgapp->HasAPIPermission(APIPermission::kBackground));
354 ASSERT_EQ(2U, service->extensions()->size());
355 ASSERT_EQ(1U, model->size());
358 typedef std::set<scoped_refptr<Extension> > ExtensionCollection;
360 namespace {
361 void AddExtension(ExtensionService* service,
362 ExtensionCollection* extensions,
363 BackgroundApplicationListModel* model,
364 size_t* expected,
365 size_t* count) {
366 bool create_background = false;
367 if (rand() % 2) {
368 create_background = true;
369 ++*expected;
371 scoped_refptr<Extension> extension =
372 CreateExtension(GenerateUniqueExtensionName(), create_background);
373 ASSERT_EQ(BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
374 service->profile()),
375 create_background);
376 extensions->insert(extension);
377 ++*count;
378 ASSERT_EQ(*count, extensions->size());
379 service->AddExtension(extension.get());
380 ASSERT_EQ(*count, service->extensions()->size());
381 ASSERT_EQ(*expected, model->size());
384 void RemoveExtension(ExtensionService* service,
385 ExtensionCollection* extensions,
386 BackgroundApplicationListModel* model,
387 size_t* expected,
388 size_t* count) { // Maybe remove an extension.
389 ExtensionCollection::iterator cursor = extensions->begin();
390 if (cursor == extensions->end()) {
391 // Nothing to remove. Just verify accounting.
392 ASSERT_EQ(0U, *count);
393 ASSERT_EQ(0U, *expected);
394 ASSERT_EQ(0U, service->extensions()->size());
395 ASSERT_EQ(0U, model->size());
396 } else {
397 // Randomly select which extension to remove
398 if (extensions->size() > 1) {
399 int offset = rand() % (extensions->size() - 1);
400 for (int index = 0; index < offset; ++index)
401 ++cursor;
403 scoped_refptr<Extension> extension = cursor->get();
404 std::string id = extension->id();
405 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
406 service->profile())) {
407 --*expected;
409 extensions->erase(cursor);
410 --*count;
411 ASSERT_EQ(*count, extensions->size());
412 service->UninstallExtension(extension->id(), false, NULL);
413 ASSERT_EQ(*count, service->extensions()->size());
414 ASSERT_EQ(*expected, model->size());
418 void TogglePermission(ExtensionService* service,
419 ExtensionCollection* extensions,
420 BackgroundApplicationListModel* model,
421 size_t* expected,
422 size_t* count) {
423 ExtensionCollection::iterator cursor = extensions->begin();
424 if (cursor == extensions->end()) {
425 // Nothing to toggle. Just verify accounting.
426 ASSERT_EQ(0U, *count);
427 ASSERT_EQ(0U, *expected);
428 ASSERT_EQ(0U, service->extensions()->size());
429 ASSERT_EQ(0U, model->size());
430 } else {
431 // Randomly select which extension to toggle.
432 if (extensions->size() > 1) {
433 int offset = rand() % (extensions->size() - 1);
434 for (int index = 0; index < offset; ++index)
435 ++cursor;
437 scoped_refptr<Extension> extension = cursor->get();
438 std::string id = extension->id();
439 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
440 service->profile())) {
441 --*expected;
442 ASSERT_EQ(*count, extensions->size());
443 RemoveBackgroundPermission(service, extension.get());
444 ASSERT_EQ(*count, service->extensions()->size());
445 ASSERT_EQ(*expected, model->size());
446 } else {
447 ++*expected;
448 ASSERT_EQ(*count, extensions->size());
449 AddBackgroundPermission(service, extension.get());
450 ASSERT_EQ(*count, service->extensions()->size());
451 ASSERT_EQ(*expected, model->size());
455 } // namespace
457 // Verifies behavior with a pseudo-randomly generated set of actions: Adding and
458 // removing extensions, of which some are Background Apps and others are not.
459 TEST_F(BackgroundApplicationListModelTest, RandomTest) {
460 InitializeAndLoadEmptyExtensionService();
461 ExtensionService* service = extensions::ExtensionSystem::Get(profile_.get())->
462 extension_service();
463 ASSERT_TRUE(service);
464 ASSERT_TRUE(service->is_ready());
465 ASSERT_TRUE(service->extensions());
466 ASSERT_TRUE(service->extensions()->is_empty());
467 scoped_ptr<BackgroundApplicationListModel> model(
468 new BackgroundApplicationListModel(profile_.get()));
469 ASSERT_EQ(0U, model->size());
471 static const int kIterations = 20;
472 ExtensionCollection extensions;
473 size_t count = 0;
474 size_t expected = 0;
475 srand(RANDOM_SEED);
476 for (int index = 0; index < kIterations; ++index) {
477 switch (rand() % 3) {
478 case 0:
479 AddExtension(service, &extensions, model.get(), &expected, &count);
480 break;
481 case 1:
482 RemoveExtension(service, &extensions, model.get(), &expected, &count);
483 break;
484 case 2:
485 TogglePermission(service, &extensions, model.get(), &expected, &count);
486 break;
487 default:
488 NOTREACHED();
489 break;