Popular sites on the NTP: re-download popular suggestions once per Chrome run
[chromium-blink-merge.git] / chrome / browser / background / background_application_list_model_unittest.cc
blobfe92927d63b69f62a34257a4b95acdb33753bb06
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())
133 .RemovePermissionsUnsafe(
134 extension, extension->permissions_data()->active_permissions().get());
137 void AddEphemeralApp(const Extension* extension, ExtensionService* service) {
138 extensions::ExtensionPrefs* prefs =
139 extensions::ExtensionPrefs::Get(service->profile());
140 ASSERT_TRUE(prefs);
141 prefs->OnExtensionInstalled(extension,
142 extensions::Extension::ENABLED,
143 syncer::StringOrdinal(),
144 extensions::kInstallFlagIsEphemeral,
145 std::string());
147 service->AddExtension(extension);
150 } // namespace
152 // Crashes on Mac tryslaves.
153 // http://crbug.com/165458
154 #if defined(OS_MACOSX) || defined(OS_LINUX)
155 #define MAYBE_ExplicitTest DISABLED_ExplicitTest
156 #else
157 #define MAYBE_ExplicitTest ExplicitTest
158 #endif
159 // With minimal test logic, verifies behavior over an explicit set of
160 // extensions, of which some are Background Apps and others are not.
161 TEST_F(BackgroundApplicationListModelTest, MAYBE_ExplicitTest) {
162 InitializeAndLoadEmptyExtensionService();
163 ASSERT_TRUE(service()->is_ready());
164 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
165 scoped_ptr<BackgroundApplicationListModel> model(
166 new BackgroundApplicationListModel(profile_.get()));
167 ASSERT_EQ(0U, model->size());
169 scoped_refptr<Extension> ext1 = CreateExtension("alpha", false);
170 scoped_refptr<Extension> ext2 = CreateExtension("bravo", false);
171 scoped_refptr<Extension> ext3 = CreateExtension("charlie", false);
172 scoped_refptr<Extension> bgapp1 = CreateExtension("delta", true);
173 scoped_refptr<Extension> bgapp2 = CreateExtension("echo", true);
174 ASSERT_EQ(0U, registry()->enabled_extensions().size());
175 ASSERT_EQ(0U, model->size());
177 // Add alternating Extensions and Background Apps
178 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
179 service()->AddExtension(ext1.get());
180 ASSERT_EQ(1U, registry()->enabled_extensions().size());
181 ASSERT_EQ(0U, model->size());
182 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
183 service()->AddExtension(bgapp1.get());
184 ASSERT_EQ(2U, registry()->enabled_extensions().size());
185 ASSERT_EQ(1U, model->size());
186 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
187 service()->AddExtension(ext2.get());
188 ASSERT_EQ(3U, registry()->enabled_extensions().size());
189 ASSERT_EQ(1U, model->size());
190 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
191 service()->AddExtension(bgapp2.get());
192 ASSERT_EQ(4U, registry()->enabled_extensions().size());
193 ASSERT_EQ(2U, model->size());
194 ASSERT_FALSE(IsBackgroundApp(*ext3.get()));
195 service()->AddExtension(ext3.get());
196 ASSERT_EQ(5U, registry()->enabled_extensions().size());
197 ASSERT_EQ(2U, model->size());
199 // Remove in FIFO order.
200 ASSERT_FALSE(IsBackgroundApp(*ext1.get()));
201 service()->UninstallExtension(ext1->id(),
202 extensions::UNINSTALL_REASON_FOR_TESTING,
203 base::Bind(&base::DoNothing), NULL);
204 ASSERT_EQ(4U, registry()->enabled_extensions().size());
205 ASSERT_EQ(2U, model->size());
206 ASSERT_TRUE(IsBackgroundApp(*bgapp1.get()));
207 service()->UninstallExtension(bgapp1->id(),
208 extensions::UNINSTALL_REASON_FOR_TESTING,
209 base::Bind(&base::DoNothing), NULL);
210 ASSERT_EQ(3U, registry()->enabled_extensions().size());
211 ASSERT_EQ(1U, model->size());
212 ASSERT_FALSE(IsBackgroundApp(*ext2.get()));
213 service()->UninstallExtension(ext2->id(),
214 extensions::UNINSTALL_REASON_FOR_TESTING,
215 base::Bind(&base::DoNothing), NULL);
216 ASSERT_EQ(2U, registry()->enabled_extensions().size());
217 ASSERT_EQ(1U, model->size());
218 ASSERT_TRUE(IsBackgroundApp(*bgapp2.get()));
219 service()->UninstallExtension(bgapp2->id(),
220 extensions::UNINSTALL_REASON_FOR_TESTING,
221 base::Bind(&base::DoNothing), NULL);
222 ASSERT_EQ(1U, registry()->enabled_extensions().size());
223 ASSERT_EQ(0U, model->size());
224 ASSERT_FALSE(IsBackgroundApp(*ext3.get()));
225 service()->UninstallExtension(ext3->id(),
226 extensions::UNINSTALL_REASON_FOR_TESTING,
227 base::Bind(&base::DoNothing), NULL);
228 ASSERT_EQ(0U, registry()->enabled_extensions().size());
229 ASSERT_EQ(0U, model->size());
232 // Verifies that an ephemeral app cannot trigger background mode.
233 TEST_F(BackgroundApplicationListModelTest, EphemeralAppTest) {
234 InitializeAndLoadEmptyExtensionService();
235 ASSERT_TRUE(service()->is_ready());
236 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
237 scoped_ptr<BackgroundApplicationListModel> model(
238 new BackgroundApplicationListModel(profile_.get()));
239 ASSERT_EQ(0U, model->size());
241 scoped_refptr<Extension> background = CreateExtension("background", true);
243 // An ephemeral app with the background permission should not trigger
244 // background mode.
245 AddEphemeralApp(background.get(), service());
246 ASSERT_FALSE(IsBackgroundApp(*background.get()));
247 ASSERT_EQ(1U, registry()->enabled_extensions().size());
248 ASSERT_EQ(0U, model->size());
250 // If the ephemeral app becomes promoted to an installed app, it can now
251 // trigger background mode.
252 service()->PromoteEphemeralApp(background.get(), false /*from sync*/);
253 ASSERT_TRUE(IsBackgroundApp(*background.get()));
254 ASSERT_EQ(1U, registry()->enabled_extensions().size());
255 ASSERT_EQ(1U, model->size());
258 // With minimal test logic, verifies behavior with dynamic permissions.
259 TEST_F(BackgroundApplicationListModelTest, AddRemovePermissionsTest) {
260 InitializeAndLoadEmptyExtensionService();
261 ASSERT_TRUE(service()->is_ready());
262 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
263 scoped_ptr<BackgroundApplicationListModel> model(
264 new BackgroundApplicationListModel(profile_.get()));
265 ASSERT_EQ(0U, model->size());
267 scoped_refptr<Extension> ext = CreateExtension("extension", false);
268 ASSERT_FALSE(
269 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground));
270 scoped_refptr<Extension> bgapp = CreateExtension("application", true);
271 ASSERT_TRUE(
272 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground));
273 ASSERT_EQ(0U, registry()->enabled_extensions().size());
274 ASSERT_EQ(0U, model->size());
276 // Add one (non-background) extension and one background application
277 ASSERT_FALSE(IsBackgroundApp(*ext.get()));
278 service()->AddExtension(ext.get());
279 ASSERT_EQ(1U, registry()->enabled_extensions().size());
280 ASSERT_EQ(0U, model->size());
281 ASSERT_TRUE(IsBackgroundApp(*bgapp.get()));
282 service()->AddExtension(bgapp.get());
283 ASSERT_EQ(2U, registry()->enabled_extensions().size());
284 ASSERT_EQ(1U, model->size());
286 // Change permissions back and forth
287 AddBackgroundPermission(service(), ext.get());
288 ASSERT_TRUE(
289 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground));
290 ASSERT_EQ(2U, registry()->enabled_extensions().size());
291 ASSERT_EQ(2U, model->size());
292 RemoveBackgroundPermission(service(), bgapp.get());
293 ASSERT_FALSE(
294 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground));
295 ASSERT_EQ(2U, registry()->enabled_extensions().size());
296 ASSERT_EQ(1U, model->size());
297 RemoveBackgroundPermission(service(), ext.get());
298 ASSERT_FALSE(
299 ext->permissions_data()->HasAPIPermission(APIPermission::kBackground));
300 ASSERT_EQ(2U, registry()->enabled_extensions().size());
301 ASSERT_EQ(0U, model->size());
302 AddBackgroundPermission(service(), bgapp.get());
303 ASSERT_TRUE(
304 bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground));
305 ASSERT_EQ(2U, registry()->enabled_extensions().size());
306 ASSERT_EQ(1U, model->size());
309 typedef std::set<scoped_refptr<Extension> > ExtensionCollection;
311 namespace {
312 void AddExtension(ExtensionService* service,
313 ExtensionCollection* extensions,
314 BackgroundApplicationListModel* model,
315 size_t* expected,
316 size_t* count) {
317 ExtensionRegistry* registry = ExtensionRegistry::Get(service->profile());
318 bool create_background = false;
319 if (rand() % 2) {
320 create_background = true;
321 ++*expected;
323 scoped_refptr<Extension> extension =
324 CreateExtension(GenerateUniqueExtensionName(), create_background);
325 ASSERT_EQ(BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
326 service->profile()),
327 create_background);
328 extensions->insert(extension);
329 ++*count;
330 ASSERT_EQ(*count, extensions->size());
331 service->AddExtension(extension.get());
332 ASSERT_EQ(*count, registry->enabled_extensions().size());
333 ASSERT_EQ(*expected, model->size());
336 void RemoveExtension(ExtensionService* service,
337 ExtensionCollection* extensions,
338 BackgroundApplicationListModel* model,
339 size_t* expected,
340 size_t* count) { // Maybe remove an extension.
341 ExtensionRegistry* registry = ExtensionRegistry::Get(service->profile());
342 ExtensionCollection::iterator cursor = extensions->begin();
343 if (cursor == extensions->end()) {
344 // Nothing to remove. Just verify accounting.
345 ASSERT_EQ(0U, *count);
346 ASSERT_EQ(0U, *expected);
347 ASSERT_EQ(0U, registry->enabled_extensions().size());
348 ASSERT_EQ(0U, model->size());
349 } else {
350 // Randomly select which extension to remove
351 if (extensions->size() > 1) {
352 int offset = rand() % (extensions->size() - 1);
353 for (int index = 0; index < offset; ++index)
354 ++cursor;
356 scoped_refptr<Extension> extension = cursor->get();
357 std::string id = extension->id();
358 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
359 service->profile())) {
360 --*expected;
362 extensions->erase(cursor);
363 --*count;
364 ASSERT_EQ(*count, extensions->size());
365 service->UninstallExtension(extension->id(),
366 extensions::UNINSTALL_REASON_FOR_TESTING,
367 base::Bind(&base::DoNothing), NULL);
368 ASSERT_EQ(*count, registry->enabled_extensions().size());
369 ASSERT_EQ(*expected, model->size());
373 void TogglePermission(ExtensionService* service,
374 ExtensionCollection* extensions,
375 BackgroundApplicationListModel* model,
376 size_t* expected,
377 size_t* count) {
378 ExtensionRegistry* registry = ExtensionRegistry::Get(service->profile());
379 ExtensionCollection::iterator cursor = extensions->begin();
380 if (cursor == extensions->end()) {
381 // Nothing to toggle. Just verify accounting.
382 ASSERT_EQ(0U, *count);
383 ASSERT_EQ(0U, *expected);
384 ASSERT_EQ(0U, registry->enabled_extensions().size());
385 ASSERT_EQ(0U, model->size());
386 } else {
387 // Randomly select which extension to toggle.
388 if (extensions->size() > 1) {
389 int offset = rand() % (extensions->size() - 1);
390 for (int index = 0; index < offset; ++index)
391 ++cursor;
393 scoped_refptr<Extension> extension = cursor->get();
394 std::string id = extension->id();
395 if (BackgroundApplicationListModel::IsBackgroundApp(*extension.get(),
396 service->profile())) {
397 --*expected;
398 ASSERT_EQ(*count, extensions->size());
399 RemoveBackgroundPermission(service, extension.get());
400 ASSERT_EQ(*count, registry->enabled_extensions().size());
401 ASSERT_EQ(*expected, model->size());
402 } else {
403 ++*expected;
404 ASSERT_EQ(*count, extensions->size());
405 AddBackgroundPermission(service, extension.get());
406 ASSERT_EQ(*count, registry->enabled_extensions().size());
407 ASSERT_EQ(*expected, model->size());
411 } // namespace
413 // Verifies behavior with a pseudo-randomly generated set of actions: Adding and
414 // removing extensions, of which some are Background Apps and others are not.
415 TEST_F(BackgroundApplicationListModelTest, RandomTest) {
416 InitializeAndLoadEmptyExtensionService();
417 ASSERT_TRUE(service()->is_ready());
418 ASSERT_TRUE(registry()->enabled_extensions().is_empty());
419 scoped_ptr<BackgroundApplicationListModel> model(
420 new BackgroundApplicationListModel(profile_.get()));
421 ASSERT_EQ(0U, model->size());
423 static const int kIterations = 20;
424 ExtensionCollection extensions;
425 size_t count = 0;
426 size_t expected = 0;
427 srand(RANDOM_SEED);
428 for (int index = 0; index < kIterations; ++index) {
429 switch (rand() % 3) {
430 case 0:
431 AddExtension(service(), &extensions, model.get(), &expected, &count);
432 break;
433 case 1:
434 RemoveExtension(service(), &extensions, model.get(), &expected, &count);
435 break;
436 case 2:
437 TogglePermission(service(), &extensions, model.get(), &expected,
438 &count);
439 break;
440 default:
441 NOTREACHED();
442 break;