Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / background / background_application_list_model_unittest.cc
blobb4bc0ccbade4a645c25875e21b41872d99da0df7
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_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_registry.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"
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)
37 using extensions::APIPermission;
38 using extensions::Extension;
39 using extensions::ExtensionRegistry;
41 // For ExtensionService interface when it requires a path that is not used.
42 base::FilePath bogus_file_pathname(const std::string& name) {
43 return base::FilePath(FILE_PATH_LITERAL("//foobar_nonexistent"))
44 .AppendASCII(name);
47 class BackgroundApplicationListModelTest
48 : public extensions::ExtensionServiceTestBase {
49 public:
50 BackgroundApplicationListModelTest() {}
51 ~BackgroundApplicationListModelTest() override {}
53 protected:
54 void InitializeAndLoadEmptyExtensionService() {
55 InitializeEmptyExtensionService();
56 service_->Init(); /* Sends EXTENSIONS_READY */
59 bool IsBackgroundApp(const Extension& app) {
60 return BackgroundApplicationListModel::IsBackgroundApp(app,
61 profile_.get());
65 enum PushMessagingOption {
66 NO_PUSH_MESSAGING,
67 PUSH_MESSAGING_PERMISSION,
68 PUSH_MESSAGING_BUT_NOT_BACKGROUND
71 // Returns a barebones test Extension object with the specified |name|. The
72 // returned extension will include background permission if
73 // |background_permission| is true.
74 static scoped_refptr<Extension> CreateExtension(
75 const std::string& name,
76 bool background_permission) {
77 base::DictionaryValue manifest;
78 manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0");
79 manifest.SetString(extensions::manifest_keys::kName, name);
80 base::ListValue* permissions = new base::ListValue();
81 manifest.Set(extensions::manifest_keys::kPermissions, permissions);
82 if (background_permission) {
83 permissions->Append(new base::StringValue("background"));
86 std::string error;
87 scoped_refptr<Extension> extension;
89 extension = Extension::Create(
90 bogus_file_pathname(name),
91 extensions::Manifest::INVALID_LOCATION,
92 manifest,
93 Extension::NO_FLAGS,
94 &error);
96 // Cannot ASSERT_* here because that attempts an illegitimate return.
97 // Cannot EXPECT_NE here because that assumes non-pointers unlike EXPECT_EQ
98 EXPECT_TRUE(extension.get() != NULL) << error;
99 return extension;
102 namespace {
103 std::string GenerateUniqueExtensionName() {
104 static int uniqueness = 0;
105 std::ostringstream output;
106 output << "Unique Named Extension " << uniqueness;
107 ++uniqueness;
108 return output.str();
111 void AddBackgroundPermission(ExtensionService* service,
112 Extension* extension) {
113 if (BackgroundApplicationListModel::IsBackgroundApp(*extension,
114 service->profile())) {
115 return;
118 scoped_refptr<Extension> temporary =
119 CreateExtension(GenerateUniqueExtensionName(), true);
120 scoped_refptr<const extensions::PermissionSet> permissions =
121 temporary->permissions_data()->active_permissions();
122 extensions::PermissionsUpdater(service->profile()).AddPermissions(
123 extension, permissions.get());
126 void RemoveBackgroundPermission(ExtensionService* service,
127 Extension* extension) {
128 if (!BackgroundApplicationListModel::IsBackgroundApp(*extension,
129 service->profile())) {
130 return;
132 extensions::PermissionsUpdater(service->profile()).RemovePermissions(
133 extension, extension->permissions_data()->active_permissions().get());
136 void AddEphemeralApp(const Extension* extension, ExtensionService* service) {
137 extensions::ExtensionPrefs* prefs =
138 extensions::ExtensionPrefs::Get(service->profile());
139 ASSERT_TRUE(prefs);
140 prefs->OnExtensionInstalled(extension,
141 extensions::Extension::ENABLED,
142 syncer::StringOrdinal(),
143 extensions::kInstallFlagIsEphemeral,
144 std::string());
146 service->AddExtension(extension);
149 } // namespace
151 // Crashes on Mac tryslaves.
152 // http://crbug.com/165458
153 #if defined(OS_MACOSX) || defined(OS_LINUX)
154 #define MAYBE_ExplicitTest DISABLED_ExplicitTest
155 #else
156 #define MAYBE_ExplicitTest ExplicitTest
157 #endif
158 // With minimal test logic, verifies behavior over an explicit set of
159 // extensions, of which some are Background Apps and others are not.
160 TEST_F(BackgroundApplicationListModelTest, MAYBE_ExplicitTest) {
161 InitializeAndLoadEmptyExtensionService();
162 ASSERT_TRUE(service()->is_ready());
163 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
164 scoped_ptr<BackgroundApplicationListModel> model(
165 new BackgroundApplicationListModel(profile_.get()));
166 ASSERT_EQ(0U, model->size());
168 scoped_refptr<Extension> ext1 = CreateExtension("alpha", false);
169 scoped_refptr<Extension> ext2 = CreateExtension("bravo", false);
170 scoped_refptr<Extension> ext3 = CreateExtension("charlie", false);
171 scoped_refptr<Extension> bgapp1 = CreateExtension("delta", true);
172 scoped_refptr<Extension> bgapp2 = CreateExtension("echo", true);
173 ASSERT_EQ(0U, registry()->enabled_extensions().size());
174 ASSERT_EQ(0U, model->size());
176 // Add alternating Extensions and Background Apps
177 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
178 service()->AddExtension(ext1.get());
179 ASSERT_EQ(1U, registry()->enabled_extensions().size());
180 ASSERT_EQ(0U, model->size());
181 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
182 service()->AddExtension(bgapp1.get());
183 ASSERT_EQ(2U, registry()->enabled_extensions().size());
184 ASSERT_EQ(1U, model->size());
185 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
186 service()->AddExtension(ext2.get());
187 ASSERT_EQ(3U, registry()->enabled_extensions().size());
188 ASSERT_EQ(1U, model->size());
189 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
190 service()->AddExtension(bgapp2.get());
191 ASSERT_EQ(4U, registry()->enabled_extensions().size());
192 ASSERT_EQ(2U, model->size());
193 ASSERT_FALSE(IsBackgroundApp(*ext3.get()));
194 service()->AddExtension(ext3.get());
195 ASSERT_EQ(5U, registry()->enabled_extensions().size());
196 ASSERT_EQ(2U, model->size());
198 // Remove in FIFO order.
199 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
200 service()->UninstallExtension(ext1->id(),
201 extensions::UNINSTALL_REASON_FOR_TESTING,
202 base::Bind(&base::DoNothing), NULL);
203 ASSERT_EQ(4U, registry()->enabled_extensions().size());
204 ASSERT_EQ(2U, model->size());
205 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
206 service()->UninstallExtension(bgapp1->id(),
207 extensions::UNINSTALL_REASON_FOR_TESTING,
208 base::Bind(&base::DoNothing), NULL);
209 ASSERT_EQ(3U, registry()->enabled_extensions().size());
210 ASSERT_EQ(1U, model->size());
211 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
212 service()->UninstallExtension(ext2->id(),
213 extensions::UNINSTALL_REASON_FOR_TESTING,
214 base::Bind(&base::DoNothing), NULL);
215 ASSERT_EQ(2U, registry()->enabled_extensions().size());
216 ASSERT_EQ(1U, model->size());
217 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
218 service()->UninstallExtension(bgapp2->id(),
219 extensions::UNINSTALL_REASON_FOR_TESTING,
220 base::Bind(&base::DoNothing), NULL);
221 ASSERT_EQ(1U, registry()->enabled_extensions().size());
222 ASSERT_EQ(0U, model->size());
223 ASSERT_FALSE(IsBackgroundApp(*ext3.get()));
224 service()->UninstallExtension(ext3->id(),
225 extensions::UNINSTALL_REASON_FOR_TESTING,
226 base::Bind(&base::DoNothing), NULL);
227 ASSERT_EQ(0U, registry()->enabled_extensions().size());
228 ASSERT_EQ(0U, model->size());
231 // Verifies that an ephemeral app cannot trigger background mode.
232 TEST_F(BackgroundApplicationListModelTest, EphemeralAppTest) {
233 InitializeAndLoadEmptyExtensionService();
234 ASSERT_TRUE(service()->is_ready());
235 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
236 scoped_ptr<BackgroundApplicationListModel> model(
237 new BackgroundApplicationListModel(profile_.get()));
238 ASSERT_EQ(0U, model->size());
240 scoped_refptr<Extension> background = CreateExtension("background", true);
242 // An ephemeral app with the background permission should not trigger
243 // background mode.
244 AddEphemeralApp(background.get(), service());
245 ASSERT_FALSE(IsBackgroundApp(*background.get()));
246 ASSERT_EQ(1U, registry()->enabled_extensions().size());
247 ASSERT_EQ(0U, model->size());
249 // If the ephemeral app becomes promoted to an installed app, it can now
250 // trigger background mode.
251 service()->PromoteEphemeralApp(background.get(), false /*from sync*/);
252 ASSERT_TRUE(IsBackgroundApp(*background.get()));
253 ASSERT_EQ(1U, registry()->enabled_extensions().size());
254 ASSERT_EQ(1U, model->size());
257 // With minimal test logic, verifies behavior with dynamic permissions.
258 TEST_F(BackgroundApplicationListModelTest, AddRemovePermissionsTest) {
259 InitializeAndLoadEmptyExtensionService();
260 ASSERT_TRUE(service()->is_ready());
261 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
262 scoped_ptr<BackgroundApplicationListModel> model(
263 new BackgroundApplicationListModel(profile_.get()));
264 ASSERT_EQ(0U, model->size());
266 scoped_refptr<Extension> ext = CreateExtension("extension", false);
267 ASSERT_FALSE(
268 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground));
269 scoped_refptr<Extension> bgapp = CreateExtension("application", true);
270 ASSERT_TRUE(
271 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground));
272 ASSERT_EQ(0U, registry()->enabled_extensions().size());
273 ASSERT_EQ(0U, model->size());
275 // Add one (non-background) extension and one background application
276 ASSERT_FALSE(IsBackgroundApp(*ext.get()));
277 service()->AddExtension(ext.get());
278 ASSERT_EQ(1U, registry()->enabled_extensions().size());
279 ASSERT_EQ(0U, model->size());
280 ASSERT_TRUE(IsBackgroundApp(*bgapp.get()));
281 service()->AddExtension(bgapp.get());
282 ASSERT_EQ(2U, registry()->enabled_extensions().size());
283 ASSERT_EQ(1U, model->size());
285 // Change permissions back and forth
286 AddBackgroundPermission(service(), ext.get());
287 ASSERT_TRUE(
288 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground));
289 ASSERT_EQ(2U, registry()->enabled_extensions().size());
290 ASSERT_EQ(2U, model->size());
291 RemoveBackgroundPermission(service(), bgapp.get());
292 ASSERT_FALSE(
293 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground));
294 ASSERT_EQ(2U, registry()->enabled_extensions().size());
295 ASSERT_EQ(1U, model->size());
296 RemoveBackgroundPermission(service(), ext.get());
297 ASSERT_FALSE(
298 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground));
299 ASSERT_EQ(2U, registry()->enabled_extensions().size());
300 ASSERT_EQ(0U, model->size());
301 AddBackgroundPermission(service(), bgapp.get());
302 ASSERT_TRUE(
303 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground));
304 ASSERT_EQ(2U, registry()->enabled_extensions().size());
305 ASSERT_EQ(1U, model->size());
308 typedef std::set<scoped_refptr<Extension> > ExtensionCollection;
310 namespace {
311 void AddExtension(ExtensionService* service,
312 ExtensionCollection* extensions,
313 BackgroundApplicationListModel* model,
314 size_t* expected,
315 size_t* count) {
316 ExtensionRegistry* registry = ExtensionRegistry::Get(service->profile());
317 bool create_background = false;
318 if (rand() % 2) {
319 create_background = true;
320 ++*expected;
322 scoped_refptr<Extension> extension =
323 CreateExtension(GenerateUniqueExtensionName(), create_background);
324 ASSERT_EQ(BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
325 service->profile()),
326 create_background);
327 extensions->insert(extension);
328 ++*count;
329 ASSERT_EQ(*count, extensions->size());
330 service->AddExtension(extension.get());
331 ASSERT_EQ(*count, registry->enabled_extensions().size());
332 ASSERT_EQ(*expected, model->size());
335 void RemoveExtension(ExtensionService* service,
336 ExtensionCollection* extensions,
337 BackgroundApplicationListModel* model,
338 size_t* expected,
339 size_t* count) { // Maybe remove an extension.
340 ExtensionRegistry* registry = ExtensionRegistry::Get(service->profile());
341 ExtensionCollection::iterator cursor = extensions->begin();
342 if (cursor == extensions->end()) {
343 // Nothing to remove. Just verify accounting.
344 ASSERT_EQ(0U, *count);
345 ASSERT_EQ(0U, *expected);
346 ASSERT_EQ(0U, registry->enabled_extensions().size());
347 ASSERT_EQ(0U, model->size());
348 } else {
349 // Randomly select which extension to remove
350 if (extensions->size() > 1) {
351 int offset = rand() % (extensions->size() - 1);
352 for (int index = 0; index < offset; ++index)
353 ++cursor;
355 scoped_refptr<Extension> extension = cursor->get();
356 std::string id = extension->id();
357 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
358 service->profile())) {
359 --*expected;
361 extensions->erase(cursor);
362 --*count;
363 ASSERT_EQ(*count, extensions->size());
364 service->UninstallExtension(extension->id(),
365 extensions::UNINSTALL_REASON_FOR_TESTING,
366 base::Bind(&base::DoNothing), NULL);
367 ASSERT_EQ(*count, registry->enabled_extensions().size());
368 ASSERT_EQ(*expected, model->size());
372 void TogglePermission(ExtensionService* service,
373 ExtensionCollection* extensions,
374 BackgroundApplicationListModel* model,
375 size_t* expected,
376 size_t* count) {
377 ExtensionRegistry* registry = ExtensionRegistry::Get(service->profile());
378 ExtensionCollection::iterator cursor = extensions->begin();
379 if (cursor == extensions->end()) {
380 // Nothing to toggle. Just verify accounting.
381 ASSERT_EQ(0U, *count);
382 ASSERT_EQ(0U, *expected);
383 ASSERT_EQ(0U, registry->enabled_extensions().size());
384 ASSERT_EQ(0U, model->size());
385 } else {
386 // Randomly select which extension to toggle.
387 if (extensions->size() > 1) {
388 int offset = rand() % (extensions->size() - 1);
389 for (int index = 0; index < offset; ++index)
390 ++cursor;
392 scoped_refptr<Extension> extension = cursor->get();
393 std::string id = extension->id();
394 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
395 service->profile())) {
396 --*expected;
397 ASSERT_EQ(*count, extensions->size());
398 RemoveBackgroundPermission(service, extension.get());
399 ASSERT_EQ(*count, registry->enabled_extensions().size());
400 ASSERT_EQ(*expected, model->size());
401 } else {
402 ++*expected;
403 ASSERT_EQ(*count, extensions->size());
404 AddBackgroundPermission(service, extension.get());
405 ASSERT_EQ(*count, registry->enabled_extensions().size());
406 ASSERT_EQ(*expected, model->size());
410 } // namespace
412 // Verifies behavior with a pseudo-randomly generated set of actions: Adding and
413 // removing extensions, of which some are Background Apps and others are not.
414 TEST_F(BackgroundApplicationListModelTest, RandomTest) {
415 InitializeAndLoadEmptyExtensionService();
416 ASSERT_TRUE(service()->is_ready());
417 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
418 scoped_ptr<BackgroundApplicationListModel> model(
419 new BackgroundApplicationListModel(profile_.get()));
420 ASSERT_EQ(0U, model->size());
422 static const int kIterations = 20;
423 ExtensionCollection extensions;
424 size_t count = 0;
425 size_t expected = 0;
426 srand(RANDOM_SEED);
427 for (int index = 0; index < kIterations; ++index) {
428 switch (rand() % 3) {
429 case 0:
430 AddExtension(service(), &extensions, model.get(), &expected, &count);
431 break;
432 case 1:
433 RemoveExtension(service(), &extensions, model.get(), &expected, &count);
434 break;
435 case 2:
436 TogglePermission(service(), &extensions, model.get(), &expected,
437 &count);
438 break;
439 default:
440 NOTREACHED();
441 break;