Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / extensions / chrome_app_sorting_unittest.cc
blobe121d0bd7410a03d1a58ea9a48dee6147e2480d2
1 // Copyright 2013 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 #include "chrome/browser/extensions/chrome_app_sorting.h"
7 #include "chrome/browser/extensions/extension_prefs_unittest.h"
8 #include "components/crx_file/id_util.h"
9 #include "extensions/common/constants.h"
10 #include "extensions/common/manifest_constants.h"
11 #include "sync/api/string_ordinal.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace extensions {
16 namespace keys = manifest_keys;
18 class ChromeAppSortingAppLocation : public ExtensionPrefsTest {
19 public:
20 void Initialize() override {
21 extension_ = prefs_.AddExtension("not_an_app");
22 // Non-apps should not have any app launch ordinal or page ordinal.
23 prefs()->OnExtensionInstalled(extension_.get(),
24 Extension::ENABLED,
25 syncer::StringOrdinal(),
26 std::string());
29 void Verify() override {
30 EXPECT_FALSE(
31 app_sorting()->GetAppLaunchOrdinal(extension_->id()).IsValid());
32 EXPECT_FALSE(app_sorting()->GetPageOrdinal(extension_->id()).IsValid());
35 private:
36 scoped_refptr<Extension> extension_;
38 TEST_F(ChromeAppSortingAppLocation, ChromeAppSortingAppLocation) {}
40 class ChromeAppSortingAppLaunchOrdinal : public ExtensionPrefsTest {
41 public:
42 void Initialize() override {
43 // No extensions yet.
44 syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
45 EXPECT_TRUE(syncer::StringOrdinal::CreateInitialOrdinal().Equals(
46 app_sorting()->CreateNextAppLaunchOrdinal(page)));
48 extension_ = prefs_.AddApp("on_extension_installed");
49 EXPECT_FALSE(prefs()->IsExtensionDisabled(extension_->id()));
50 prefs()->OnExtensionInstalled(extension_.get(),
51 Extension::ENABLED,
52 syncer::StringOrdinal(),
53 std::string());
56 void Verify() override {
57 syncer::StringOrdinal launch_ordinal =
58 app_sorting()->GetAppLaunchOrdinal(extension_->id());
59 syncer::StringOrdinal page_ordinal =
60 syncer::StringOrdinal::CreateInitialOrdinal();
62 // Extension should have been assigned a valid StringOrdinal.
63 EXPECT_TRUE(launch_ordinal.IsValid());
64 EXPECT_TRUE(launch_ordinal.LessThan(
65 app_sorting()->CreateNextAppLaunchOrdinal(page_ordinal)));
66 // Set a new launch ordinal of and verify it comes after.
67 app_sorting()->SetAppLaunchOrdinal(
68 extension_->id(),
69 app_sorting()->CreateNextAppLaunchOrdinal(page_ordinal));
70 syncer::StringOrdinal new_launch_ordinal =
71 app_sorting()->GetAppLaunchOrdinal(extension_->id());
72 EXPECT_TRUE(launch_ordinal.LessThan(new_launch_ordinal));
74 // This extension doesn't exist, so it should return an invalid
75 // StringOrdinal.
76 syncer::StringOrdinal invalid_app_launch_ordinal =
77 app_sorting()->GetAppLaunchOrdinal("foo");
78 EXPECT_FALSE(invalid_app_launch_ordinal.IsValid());
79 EXPECT_EQ(-1, app_sorting()->PageStringOrdinalAsInteger(
80 invalid_app_launch_ordinal));
82 // The second page doesn't have any apps so its next launch ordinal should
83 // be the first launch ordinal.
84 syncer::StringOrdinal next_page = page_ordinal.CreateAfter();
85 syncer::StringOrdinal next_page_app_launch_ordinal =
86 app_sorting()->CreateNextAppLaunchOrdinal(next_page);
87 EXPECT_TRUE(next_page_app_launch_ordinal.Equals(
88 app_sorting()->CreateFirstAppLaunchOrdinal(next_page)));
91 private:
92 scoped_refptr<Extension> extension_;
94 TEST_F(ChromeAppSortingAppLaunchOrdinal, ChromeAppSortingAppLaunchOrdinal) {}
96 class ChromeAppSortingPageOrdinal : public ExtensionPrefsTest {
97 public:
98 void Initialize() override {
99 extension_ = prefs_.AddApp("page_ordinal");
100 // Install with a page preference.
101 first_page_ = syncer::StringOrdinal::CreateInitialOrdinal();
102 prefs()->OnExtensionInstalled(extension_.get(),
103 Extension::ENABLED,
104 first_page_,
105 std::string());
106 EXPECT_TRUE(first_page_.Equals(
107 app_sorting()->GetPageOrdinal(extension_->id())));
108 EXPECT_EQ(0, app_sorting()->PageStringOrdinalAsInteger(first_page_));
110 scoped_refptr<Extension> extension2 = prefs_.AddApp("page_ordinal_2");
111 // Install without any page preference.
112 prefs()->OnExtensionInstalled(extension2.get(),
113 Extension::ENABLED,
114 syncer::StringOrdinal(),
115 std::string());
116 EXPECT_TRUE(first_page_.Equals(
117 app_sorting()->GetPageOrdinal(extension2->id())));
119 void Verify() override {
120 // Set the page ordinal.
121 syncer::StringOrdinal new_page = first_page_.CreateAfter();
122 app_sorting()->SetPageOrdinal(extension_->id(), new_page);
123 // Verify the page ordinal.
124 EXPECT_TRUE(
125 new_page.Equals(app_sorting()->GetPageOrdinal(extension_->id())));
126 EXPECT_EQ(1, app_sorting()->PageStringOrdinalAsInteger(new_page));
128 // This extension doesn't exist, so it should return an invalid
129 // StringOrdinal.
130 EXPECT_FALSE(app_sorting()->GetPageOrdinal("foo").IsValid());
133 private:
134 syncer::StringOrdinal first_page_;
135 scoped_refptr<Extension> extension_;
137 TEST_F(ChromeAppSortingPageOrdinal, ChromeAppSortingPageOrdinal) {}
139 // Ensure that ChromeAppSorting is able to properly initialize off a set
140 // of old page and app launch indices and properly convert them.
141 class ChromeAppSortingInitialize : public PrefsPrepopulatedTestBase {
142 public:
143 ChromeAppSortingInitialize() {}
144 ~ChromeAppSortingInitialize() override {}
146 void Initialize() override {
147 // A preference determining the order of which the apps appear on the NTP.
148 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
149 // A preference determining the page on which an app appears in the NTP.
150 const char kPrefPageIndexDeprecated[] = "page_index";
152 // Setup the deprecated preferences.
153 ExtensionScopedPrefs* scoped_prefs =
154 static_cast<ExtensionScopedPrefs*>(prefs());
155 scoped_prefs->UpdateExtensionPref(extension1()->id(),
156 kPrefAppLaunchIndexDeprecated,
157 new base::FundamentalValue(0));
158 scoped_prefs->UpdateExtensionPref(extension1()->id(),
159 kPrefPageIndexDeprecated,
160 new base::FundamentalValue(0));
162 scoped_prefs->UpdateExtensionPref(extension2()->id(),
163 kPrefAppLaunchIndexDeprecated,
164 new base::FundamentalValue(1));
165 scoped_prefs->UpdateExtensionPref(extension2()->id(),
166 kPrefPageIndexDeprecated,
167 new base::FundamentalValue(0));
169 scoped_prefs->UpdateExtensionPref(extension3()->id(),
170 kPrefAppLaunchIndexDeprecated,
171 new base::FundamentalValue(0));
172 scoped_prefs->UpdateExtensionPref(extension3()->id(),
173 kPrefPageIndexDeprecated,
174 new base::FundamentalValue(1));
176 // We insert the ids in reverse order so that we have to deal with the
177 // element on the 2nd page before the 1st page is seen.
178 ExtensionIdList ids;
179 ids.push_back(extension3()->id());
180 ids.push_back(extension2()->id());
181 ids.push_back(extension1()->id());
183 app_sorting()->MigrateAppIndex(ids);
185 void Verify() override {
186 syncer::StringOrdinal first_ordinal =
187 syncer::StringOrdinal::CreateInitialOrdinal();
189 EXPECT_TRUE(first_ordinal.Equals(
190 app_sorting()->GetAppLaunchOrdinal(extension1()->id())));
191 EXPECT_TRUE(first_ordinal.LessThan(
192 app_sorting()->GetAppLaunchOrdinal(extension2()->id())));
193 EXPECT_TRUE(first_ordinal.Equals(
194 app_sorting()->GetAppLaunchOrdinal(extension3()->id())));
196 EXPECT_TRUE(first_ordinal.Equals(
197 app_sorting()->GetPageOrdinal(extension1()->id())));
198 EXPECT_TRUE(first_ordinal.Equals(
199 app_sorting()->GetPageOrdinal(extension2()->id())));
200 EXPECT_TRUE(first_ordinal.LessThan(
201 app_sorting()->GetPageOrdinal(extension3()->id())));
204 TEST_F(ChromeAppSortingInitialize, ChromeAppSortingInitialize) {}
206 // Make sure that initialization still works when no extensions are present
207 // (i.e. make sure that the web store icon is still loaded into the map).
208 class ChromeAppSortingInitializeWithNoApps : public PrefsPrepopulatedTestBase {
209 public:
210 ChromeAppSortingInitializeWithNoApps() {}
211 ~ChromeAppSortingInitializeWithNoApps() override {}
213 void Initialize() override {
214 // Make sure that the web store has valid ordinals.
215 syncer::StringOrdinal initial_ordinal =
216 syncer::StringOrdinal::CreateInitialOrdinal();
217 app_sorting()->SetPageOrdinal(extensions::kWebStoreAppId,
218 initial_ordinal);
219 app_sorting()->SetAppLaunchOrdinal(extensions::kWebStoreAppId,
220 initial_ordinal);
222 void Verify() override {
223 syncer::StringOrdinal page =
224 app_sorting()->GetPageOrdinal(extensions::kWebStoreAppId);
225 EXPECT_TRUE(page.IsValid());
227 ChromeAppSorting::PageOrdinalMap::iterator page_it =
228 app_sorting()->ntp_ordinal_map_.find(page);
229 EXPECT_TRUE(page_it != app_sorting()->ntp_ordinal_map_.end());
231 syncer::StringOrdinal app_launch =
232 app_sorting()->GetPageOrdinal(extensions::kWebStoreAppId);
233 EXPECT_TRUE(app_launch.IsValid());
235 ChromeAppSorting::AppLaunchOrdinalMap::iterator app_launch_it =
236 page_it->second.find(app_launch);
237 EXPECT_TRUE(app_launch_it != page_it->second.end());
240 TEST_F(ChromeAppSortingInitializeWithNoApps,
241 ChromeAppSortingInitializeWithNoApps) {}
243 // Tests the application index to ordinal migration code for values that
244 // shouldn't be converted. This should be removed when the migrate code
245 // is taken out.
246 // http://crbug.com/107376
247 class ChromeAppSortingMigrateAppIndexInvalid
248 : public PrefsPrepopulatedTestBase {
249 public:
250 ChromeAppSortingMigrateAppIndexInvalid() {}
251 ~ChromeAppSortingMigrateAppIndexInvalid() override {}
253 void Initialize() override {
254 // A preference determining the order of which the apps appear on the NTP.
255 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
256 // A preference determining the page on which an app appears in the NTP.
257 const char kPrefPageIndexDeprecated[] = "page_index";
259 // Setup the deprecated preference.
260 ExtensionScopedPrefs* scoped_prefs =
261 static_cast<ExtensionScopedPrefs*>(prefs());
262 scoped_prefs->UpdateExtensionPref(extension1()->id(),
263 kPrefAppLaunchIndexDeprecated,
264 new base::FundamentalValue(0));
265 scoped_prefs->UpdateExtensionPref(extension1()->id(),
266 kPrefPageIndexDeprecated,
267 new base::FundamentalValue(-1));
269 void Verify() override {
270 // Make sure that the invalid page_index wasn't converted over.
271 EXPECT_FALSE(app_sorting()->GetAppLaunchOrdinal(
272 extension1()->id()).IsValid());
275 TEST_F(ChromeAppSortingMigrateAppIndexInvalid,
276 ChromeAppSortingMigrateAppIndexInvalid) {}
278 class ChromeAppSortingFixNTPCollisionsAllCollide
279 : public PrefsPrepopulatedTestBase {
280 public:
281 ChromeAppSortingFixNTPCollisionsAllCollide() {}
282 ~ChromeAppSortingFixNTPCollisionsAllCollide() override {}
284 void Initialize() override {
285 repeated_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
287 app_sorting()->SetAppLaunchOrdinal(extension1()->id(),
288 repeated_ordinal_);
289 app_sorting()->SetPageOrdinal(extension1()->id(), repeated_ordinal_);
291 app_sorting()->SetAppLaunchOrdinal(extension2()->id(), repeated_ordinal_);
292 app_sorting()->SetPageOrdinal(extension2()->id(), repeated_ordinal_);
294 app_sorting()->SetAppLaunchOrdinal(extension3()->id(), repeated_ordinal_);
295 app_sorting()->SetPageOrdinal(extension3()->id(), repeated_ordinal_);
297 app_sorting()->FixNTPOrdinalCollisions();
299 void Verify() override {
300 syncer::StringOrdinal extension1_app_launch =
301 app_sorting()->GetAppLaunchOrdinal(extension1()->id());
302 syncer::StringOrdinal extension2_app_launch =
303 app_sorting()->GetAppLaunchOrdinal(extension2()->id());
304 syncer::StringOrdinal extension3_app_launch =
305 app_sorting()->GetAppLaunchOrdinal(extension3()->id());
307 // The overlapping extensions should have be adjusted so that they are
308 // sorted by their id.
309 EXPECT_EQ(extension1()->id() < extension2()->id(),
310 extension1_app_launch.LessThan(extension2_app_launch));
311 EXPECT_EQ(extension1()->id() < extension3()->id(),
312 extension1_app_launch.LessThan(extension3_app_launch));
313 EXPECT_EQ(extension2()->id() < extension3()->id(),
314 extension2_app_launch.LessThan(extension3_app_launch));
316 // The page ordinal should be unchanged.
317 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension1()->id()).Equals(
318 repeated_ordinal_));
319 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension2()->id()).Equals(
320 repeated_ordinal_));
321 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension3()->id()).Equals(
322 repeated_ordinal_));
325 private:
326 syncer::StringOrdinal repeated_ordinal_;
328 TEST_F(ChromeAppSortingFixNTPCollisionsAllCollide,
329 ChromeAppSortingFixNTPCollisionsAllCollide) {}
331 class ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
332 : public PrefsPrepopulatedTestBase {
333 public:
334 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart() {}
335 ~ChromeAppSortingFixNTPCollisionsSomeCollideAtStart() override {}
337 void Initialize() override {
338 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
339 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
341 // Have the first two extension in the same position, with a third
342 // (non-colliding) extension after.
344 app_sorting()->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
345 app_sorting()->SetPageOrdinal(extension1()->id(), first_ordinal_);
347 app_sorting()->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
348 app_sorting()->SetPageOrdinal(extension2()->id(), first_ordinal_);
350 app_sorting()->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
351 app_sorting()->SetPageOrdinal(extension3()->id(), first_ordinal_);
353 app_sorting()->FixNTPOrdinalCollisions();
355 void Verify() override {
356 syncer::StringOrdinal extension1_app_launch =
357 app_sorting()->GetAppLaunchOrdinal(extension1()->id());
358 syncer::StringOrdinal extension2_app_launch =
359 app_sorting()->GetAppLaunchOrdinal(extension2()->id());
360 syncer::StringOrdinal extension3_app_launch =
361 app_sorting()->GetAppLaunchOrdinal(extension3()->id());
363 // The overlapping extensions should have be adjusted so that they are
364 // sorted by their id, but they both should be before ext3, which wasn't
365 // overlapping.
366 EXPECT_EQ(extension1()->id() < extension2()->id(),
367 extension1_app_launch.LessThan(extension2_app_launch));
368 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
369 EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));
371 // The page ordinal should be unchanged.
372 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension1()->id()).Equals(
373 first_ordinal_));
374 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension2()->id()).Equals(
375 first_ordinal_));
376 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension3()->id()).Equals(
377 first_ordinal_));
380 private:
381 syncer::StringOrdinal first_ordinal_;
383 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtStart,
384 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart) {}
386 class ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
387 : public PrefsPrepopulatedTestBase {
388 public:
389 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd() {}
390 ~ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd() override {}
392 void Initialize() override {
393 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
394 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
396 // Have the first extension in a non-colliding position, followed by two
397 // two extension in the same position.
399 app_sorting()->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
400 app_sorting()->SetPageOrdinal(extension1()->id(), first_ordinal_);
402 app_sorting()->SetAppLaunchOrdinal(extension2()->id(), second_ordinal);
403 app_sorting()->SetPageOrdinal(extension2()->id(), first_ordinal_);
405 app_sorting()->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
406 app_sorting()->SetPageOrdinal(extension3()->id(), first_ordinal_);
408 app_sorting()->FixNTPOrdinalCollisions();
410 void Verify() override {
411 syncer::StringOrdinal extension1_app_launch =
412 app_sorting()->GetAppLaunchOrdinal(extension1()->id());
413 syncer::StringOrdinal extension2_app_launch =
414 app_sorting()->GetAppLaunchOrdinal(extension2()->id());
415 syncer::StringOrdinal extension3_app_launch =
416 app_sorting()->GetAppLaunchOrdinal(extension3()->id());
418 // The overlapping extensions should have be adjusted so that they are
419 // sorted by their id, but they both should be after ext1, which wasn't
420 // overlapping.
421 EXPECT_TRUE(extension1_app_launch.LessThan(extension2_app_launch));
422 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
423 EXPECT_EQ(extension2()->id() < extension3()->id(),
424 extension2_app_launch.LessThan(extension3_app_launch));
426 // The page ordinal should be unchanged.
427 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension1()->id()).Equals(
428 first_ordinal_));
429 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension2()->id()).Equals(
430 first_ordinal_));
431 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension3()->id()).Equals(
432 first_ordinal_));
435 private:
436 syncer::StringOrdinal first_ordinal_;
438 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd,
439 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd) {}
441 class ChromeAppSortingFixNTPCollisionsTwoCollisions
442 : public PrefsPrepopulatedTestBase {
443 public:
444 ChromeAppSortingFixNTPCollisionsTwoCollisions() {}
445 ~ChromeAppSortingFixNTPCollisionsTwoCollisions() override {}
447 void Initialize() override {
448 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
449 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
451 // Have two extensions colliding, followed by two more colliding extensions.
452 app_sorting()->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
453 app_sorting()->SetPageOrdinal(extension1()->id(), first_ordinal_);
455 app_sorting()->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
456 app_sorting()->SetPageOrdinal(extension2()->id(), first_ordinal_);
458 app_sorting()->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
459 app_sorting()->SetPageOrdinal(extension3()->id(), first_ordinal_);
461 app_sorting()->SetAppLaunchOrdinal(extension4()->id(), second_ordinal);
462 app_sorting()->SetPageOrdinal(extension4()->id(), first_ordinal_);
464 app_sorting()->FixNTPOrdinalCollisions();
466 void Verify() override {
467 syncer::StringOrdinal extension1_app_launch =
468 app_sorting()->GetAppLaunchOrdinal(extension1()->id());
469 syncer::StringOrdinal extension2_app_launch =
470 app_sorting()->GetAppLaunchOrdinal(extension2()->id());
471 syncer::StringOrdinal extension3_app_launch =
472 app_sorting()->GetAppLaunchOrdinal(extension3()->id());
473 syncer::StringOrdinal extension4_app_launch =
474 app_sorting()->GetAppLaunchOrdinal(extension4()->id());
476 // The overlapping extensions should have be adjusted so that they are
477 // sorted by their id, with |ext1| and |ext2| appearing before |ext3| and
478 // |ext4|.
479 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
480 EXPECT_TRUE(extension1_app_launch.LessThan(extension4_app_launch));
481 EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));
482 EXPECT_TRUE(extension2_app_launch.LessThan(extension4_app_launch));
484 EXPECT_EQ(extension1()->id() < extension2()->id(),
485 extension1_app_launch.LessThan(extension2_app_launch));
486 EXPECT_EQ(extension3()->id() < extension4()->id(),
487 extension3_app_launch.LessThan(extension4_app_launch));
489 // The page ordinal should be unchanged.
490 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension1()->id()).Equals(
491 first_ordinal_));
492 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension2()->id()).Equals(
493 first_ordinal_));
494 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension3()->id()).Equals(
495 first_ordinal_));
496 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension4()->id()).Equals(
497 first_ordinal_));
500 private:
501 syncer::StringOrdinal first_ordinal_;
503 TEST_F(ChromeAppSortingFixNTPCollisionsTwoCollisions,
504 ChromeAppSortingFixNTPCollisionsTwoCollisions) {}
506 class ChromeAppSortingEnsureValidOrdinals
507 : public PrefsPrepopulatedTestBase {
508 public :
509 ChromeAppSortingEnsureValidOrdinals() {}
510 ~ChromeAppSortingEnsureValidOrdinals() override {}
512 void Initialize() override {}
513 void Verify() override {
514 // Give ext1 invalid ordinals and then check that EnsureValidOrdinals fixes
515 // them.
516 app_sorting()->SetAppLaunchOrdinal(extension1()->id(),
517 syncer::StringOrdinal());
518 app_sorting()->SetPageOrdinal(extension1()->id(), syncer::StringOrdinal());
520 app_sorting()->EnsureValidOrdinals(extension1()->id(),
521 syncer::StringOrdinal());
523 EXPECT_TRUE(
524 app_sorting()->GetAppLaunchOrdinal(extension1()->id()).IsValid());
525 EXPECT_TRUE(app_sorting()->GetPageOrdinal(extension1()->id()).IsValid());
528 TEST_F(ChromeAppSortingEnsureValidOrdinals,
529 ChromeAppSortingEnsureValidOrdinals) {}
531 class ChromeAppSortingPageOrdinalMapping : public PrefsPrepopulatedTestBase {
532 public:
533 ChromeAppSortingPageOrdinalMapping() {}
534 ~ChromeAppSortingPageOrdinalMapping() override {}
536 void Initialize() override {}
537 void Verify() override {
538 std::string ext_1 = "ext_1";
539 std::string ext_2 = "ext_2";
541 syncer::StringOrdinal first_ordinal =
542 syncer::StringOrdinal::CreateInitialOrdinal();
544 // Ensure attempting to removing a mapping with an invalid page doesn't
545 // modify the map.
546 EXPECT_TRUE(app_sorting()->ntp_ordinal_map_.empty());
547 app_sorting()->RemoveOrdinalMapping(
548 ext_1, first_ordinal, first_ordinal);
549 EXPECT_TRUE(app_sorting()->ntp_ordinal_map_.empty());
551 // Add new mappings.
552 app_sorting()->AddOrdinalMapping(ext_1, first_ordinal, first_ordinal);
553 app_sorting()->AddOrdinalMapping(ext_2, first_ordinal, first_ordinal);
555 EXPECT_EQ(1U, app_sorting()->ntp_ordinal_map_.size());
556 EXPECT_EQ(2U, app_sorting()->ntp_ordinal_map_[first_ordinal].size());
558 ChromeAppSorting::AppLaunchOrdinalMap::iterator it =
559 app_sorting()->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
560 EXPECT_EQ(ext_1, it->second);
561 ++it;
562 EXPECT_EQ(ext_2, it->second);
564 app_sorting()->RemoveOrdinalMapping(ext_1, first_ordinal, first_ordinal);
565 EXPECT_EQ(1U, app_sorting()->ntp_ordinal_map_.size());
566 EXPECT_EQ(1U, app_sorting()->ntp_ordinal_map_[first_ordinal].size());
568 it = app_sorting()->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
569 EXPECT_EQ(ext_2, it->second);
571 // Ensure that attempting to remove an extension with a valid page and app
572 // launch ordinals, but a unused id has no effect.
573 app_sorting()->RemoveOrdinalMapping(
574 "invalid_ext", first_ordinal, first_ordinal);
575 EXPECT_EQ(1U, app_sorting()->ntp_ordinal_map_.size());
576 EXPECT_EQ(1U, app_sorting()->ntp_ordinal_map_[first_ordinal].size());
578 it = app_sorting()->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
579 EXPECT_EQ(ext_2, it->second);
582 TEST_F(ChromeAppSortingPageOrdinalMapping,
583 ChromeAppSortingPageOrdinalMapping) {}
585 class ChromeAppSortingPreinstalledAppsBase : public PrefsPrepopulatedTestBase {
586 public:
587 ChromeAppSortingPreinstalledAppsBase() {
588 base::DictionaryValue simple_dict;
589 simple_dict.SetString(keys::kVersion, "1.0.0.0");
590 simple_dict.SetString(keys::kName, "unused");
591 simple_dict.SetString(keys::kApp, "true");
592 simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");
594 std::string error;
595 app1_scoped_ = Extension::Create(
596 prefs_.temp_dir().AppendASCII("app1_"), Manifest::EXTERNAL_PREF,
597 simple_dict, Extension::NO_FLAGS, &error);
598 prefs()->OnExtensionInstalled(app1_scoped_.get(),
599 Extension::ENABLED,
600 syncer::StringOrdinal(),
601 std::string());
603 app2_scoped_ = Extension::Create(
604 prefs_.temp_dir().AppendASCII("app2_"), Manifest::EXTERNAL_PREF,
605 simple_dict, Extension::NO_FLAGS, &error);
606 prefs()->OnExtensionInstalled(app2_scoped_.get(),
607 Extension::ENABLED,
608 syncer::StringOrdinal(),
609 std::string());
611 app1_ = app1_scoped_.get();
612 app2_ = app2_scoped_.get();
614 ~ChromeAppSortingPreinstalledAppsBase() override {}
616 protected:
617 // Weak references, for convenience.
618 Extension* app1_;
619 Extension* app2_;
621 private:
622 scoped_refptr<Extension> app1_scoped_;
623 scoped_refptr<Extension> app2_scoped_;
626 class ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage
627 : public ChromeAppSortingPreinstalledAppsBase {
628 public:
629 ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage() {}
630 ~ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage() override {}
632 void Initialize() override {}
633 void Verify() override {
634 syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
636 syncer::StringOrdinal min =
637 app_sorting()->GetMinOrMaxAppLaunchOrdinalsOnPage(
638 page,
639 ChromeAppSorting::MIN_ORDINAL);
640 syncer::StringOrdinal max =
641 app_sorting()->GetMinOrMaxAppLaunchOrdinalsOnPage(
642 page,
643 ChromeAppSorting::MAX_ORDINAL);
644 EXPECT_TRUE(min.IsValid());
645 EXPECT_TRUE(max.IsValid());
646 EXPECT_TRUE(min.LessThan(max));
648 // Ensure that the min and max values aren't set for empty pages.
649 min = syncer::StringOrdinal();
650 max = syncer::StringOrdinal();
651 syncer::StringOrdinal empty_page = page.CreateAfter();
652 EXPECT_FALSE(min.IsValid());
653 EXPECT_FALSE(max.IsValid());
654 min = app_sorting()->GetMinOrMaxAppLaunchOrdinalsOnPage(
655 empty_page,
656 ChromeAppSorting::MIN_ORDINAL);
657 max = app_sorting()->GetMinOrMaxAppLaunchOrdinalsOnPage(
658 empty_page,
659 ChromeAppSorting::MAX_ORDINAL);
660 EXPECT_FALSE(min.IsValid());
661 EXPECT_FALSE(max.IsValid());
664 TEST_F(ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage,
665 ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage) {}
667 // Make sure that empty pages aren't removed from the integer to ordinal
668 // mapping. See http://crbug.com/109802 for details.
669 class ChromeAppSortingKeepEmptyStringOrdinalPages
670 : public ChromeAppSortingPreinstalledAppsBase {
671 public:
672 ChromeAppSortingKeepEmptyStringOrdinalPages() {}
673 ~ChromeAppSortingKeepEmptyStringOrdinalPages() override {}
675 void Initialize() override {
676 syncer::StringOrdinal first_page =
677 syncer::StringOrdinal::CreateInitialOrdinal();
678 app_sorting()->SetPageOrdinal(app1_->id(), first_page);
679 EXPECT_EQ(0, app_sorting()->PageStringOrdinalAsInteger(first_page));
681 last_page_ = first_page.CreateAfter();
682 app_sorting()->SetPageOrdinal(app2_->id(), last_page_);
683 EXPECT_EQ(1, app_sorting()->PageStringOrdinalAsInteger(last_page_));
685 // Move the second app to create an empty page.
686 app_sorting()->SetPageOrdinal(app2_->id(), first_page);
687 EXPECT_EQ(0, app_sorting()->PageStringOrdinalAsInteger(first_page));
689 void Verify() override {
690 // Move the second app to a new empty page at the end, skipping over
691 // the current empty page.
692 last_page_ = last_page_.CreateAfter();
693 app_sorting()->SetPageOrdinal(app2_->id(), last_page_);
694 EXPECT_EQ(2, app_sorting()->PageStringOrdinalAsInteger(last_page_));
695 EXPECT_TRUE(
696 last_page_.Equals(app_sorting()->PageIntegerAsStringOrdinal(2)));
699 private:
700 syncer::StringOrdinal last_page_;
702 TEST_F(ChromeAppSortingKeepEmptyStringOrdinalPages,
703 ChromeAppSortingKeepEmptyStringOrdinalPages) {}
705 class ChromeAppSortingMakesFillerOrdinals
706 : public ChromeAppSortingPreinstalledAppsBase {
707 public:
708 ChromeAppSortingMakesFillerOrdinals() {}
709 ~ChromeAppSortingMakesFillerOrdinals() override {}
711 void Initialize() override {
712 syncer::StringOrdinal first_page =
713 syncer::StringOrdinal::CreateInitialOrdinal();
714 app_sorting()->SetPageOrdinal(app1_->id(), first_page);
715 EXPECT_EQ(0, app_sorting()->PageStringOrdinalAsInteger(first_page));
717 void Verify() override {
718 // Because the UI can add an unlimited number of empty pages without an app
719 // on them, this test simulates dropping of an app on the 1st and 4th empty
720 // pages (3rd and 6th pages by index) to ensure we don't crash and that
721 // filler ordinals are created as needed. See: http://crbug.com/122214
722 syncer::StringOrdinal page_three =
723 app_sorting()->PageIntegerAsStringOrdinal(2);
724 app_sorting()->SetPageOrdinal(app1_->id(), page_three);
725 EXPECT_EQ(2, app_sorting()->PageStringOrdinalAsInteger(page_three));
727 syncer::StringOrdinal page_six =
728 app_sorting()->PageIntegerAsStringOrdinal(5);
729 app_sorting()->SetPageOrdinal(app1_->id(), page_six);
730 EXPECT_EQ(5, app_sorting()->PageStringOrdinalAsInteger(page_six));
733 TEST_F(ChromeAppSortingMakesFillerOrdinals,
734 ChromeAppSortingMakesFillerOrdinals) {}
736 class ChromeAppSortingDefaultOrdinalsBase : public ExtensionPrefsTest {
737 public:
738 ChromeAppSortingDefaultOrdinalsBase() {}
739 ~ChromeAppSortingDefaultOrdinalsBase() override {}
741 void Initialize() override {
742 app_ = CreateApp("app");
744 InitDefaultOrdinals();
745 ChromeAppSorting::AppOrdinalsMap& sorting_defaults =
746 app_sorting()->default_ordinals_;
747 sorting_defaults[app_->id()].page_ordinal = default_page_ordinal_;
748 sorting_defaults[app_->id()].app_launch_ordinal =
749 default_app_launch_ordinal_;
751 SetupUserOrdinals();
752 InstallApps();
755 protected:
756 scoped_refptr<Extension> CreateApp(const std::string& name) {
757 base::DictionaryValue simple_dict;
758 simple_dict.SetString(keys::kVersion, "1.0.0.0");
759 simple_dict.SetString(keys::kName, name);
760 simple_dict.SetString(keys::kApp, "true");
761 simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");
763 std::string errors;
764 scoped_refptr<Extension> app = Extension::Create(
765 prefs_.temp_dir().AppendASCII(name), Manifest::EXTERNAL_PREF,
766 simple_dict, Extension::NO_FLAGS, &errors);
767 EXPECT_TRUE(app.get()) << errors;
768 EXPECT_TRUE(crx_file::id_util::IdIsValid(app->id()));
769 return app;
772 void InitDefaultOrdinals() {
773 default_page_ordinal_ =
774 syncer::StringOrdinal::CreateInitialOrdinal().CreateAfter();
775 default_app_launch_ordinal_ =
776 syncer::StringOrdinal::CreateInitialOrdinal().CreateBefore();
779 virtual void SetupUserOrdinals() {}
781 virtual void InstallApps() {
782 prefs()->OnExtensionInstalled(app_.get(),
783 Extension::ENABLED,
784 syncer::StringOrdinal(),
785 std::string());
788 scoped_refptr<Extension> app_;
789 syncer::StringOrdinal default_page_ordinal_;
790 syncer::StringOrdinal default_app_launch_ordinal_;
793 // Tests that the app gets its default ordinals.
794 class ChromeAppSortingDefaultOrdinals
795 : public ChromeAppSortingDefaultOrdinalsBase {
796 public:
797 ChromeAppSortingDefaultOrdinals() {}
798 ~ChromeAppSortingDefaultOrdinals() override {}
800 void Verify() override {
801 EXPECT_TRUE(app_sorting()->GetPageOrdinal(app_->id()).Equals(
802 default_page_ordinal_));
803 EXPECT_TRUE(app_sorting()->GetAppLaunchOrdinal(app_->id()).Equals(
804 default_app_launch_ordinal_));
807 TEST_F(ChromeAppSortingDefaultOrdinals,
808 ChromeAppSortingDefaultOrdinals) {}
810 // Tests that the default page ordinal is overridden by install page ordinal.
811 class ChromeAppSortingDefaultOrdinalOverriddenByInstallPage
812 : public ChromeAppSortingDefaultOrdinalsBase {
813 public:
814 ChromeAppSortingDefaultOrdinalOverriddenByInstallPage() {}
815 ~ChromeAppSortingDefaultOrdinalOverriddenByInstallPage() override {}
817 void Verify() override {
818 EXPECT_FALSE(app_sorting()->GetPageOrdinal(app_->id()).Equals(
819 default_page_ordinal_));
820 EXPECT_TRUE(app_sorting()->GetPageOrdinal(app_->id()).Equals(
821 install_page_));
824 protected:
825 void InstallApps() override {
826 install_page_ = default_page_ordinal_.CreateAfter();
827 prefs()->OnExtensionInstalled(app_.get(),
828 Extension::ENABLED,
829 install_page_,
830 std::string());
833 private:
834 syncer::StringOrdinal install_page_;
836 TEST_F(ChromeAppSortingDefaultOrdinalOverriddenByInstallPage,
837 ChromeAppSortingDefaultOrdinalOverriddenByInstallPage) {}
839 // Tests that the default ordinals are overridden by user values.
840 class ChromeAppSortingDefaultOrdinalOverriddenByUserValue
841 : public ChromeAppSortingDefaultOrdinalsBase {
842 public:
843 ChromeAppSortingDefaultOrdinalOverriddenByUserValue() {}
844 ~ChromeAppSortingDefaultOrdinalOverriddenByUserValue() override {}
846 void Verify() override {
847 EXPECT_TRUE(app_sorting()->GetPageOrdinal(app_->id()).Equals(
848 user_page_ordinal_));
849 EXPECT_TRUE(app_sorting()->GetAppLaunchOrdinal(app_->id()).Equals(
850 user_app_launch_ordinal_));
853 protected:
854 void SetupUserOrdinals() override {
855 user_page_ordinal_ = default_page_ordinal_.CreateAfter();
856 user_app_launch_ordinal_ = default_app_launch_ordinal_.CreateBefore();
858 app_sorting()->SetPageOrdinal(app_->id(), user_page_ordinal_);
859 app_sorting()->SetAppLaunchOrdinal(app_->id(), user_app_launch_ordinal_);
862 private:
863 syncer::StringOrdinal user_page_ordinal_;
864 syncer::StringOrdinal user_app_launch_ordinal_;
866 TEST_F(ChromeAppSortingDefaultOrdinalOverriddenByUserValue,
867 ChromeAppSortingDefaultOrdinalOverriddenByUserValue) {}
869 // Tests that the default app launch ordinal is changed to avoid collision.
870 class ChromeAppSortingDefaultOrdinalNoCollision
871 : public ChromeAppSortingDefaultOrdinalsBase {
872 public:
873 ChromeAppSortingDefaultOrdinalNoCollision() {}
874 ~ChromeAppSortingDefaultOrdinalNoCollision() override {}
876 void Verify() override {
877 // Use the default page.
878 EXPECT_TRUE(app_sorting()->GetPageOrdinal(app_->id()).Equals(
879 default_page_ordinal_));
880 // Not using the default app launch ordinal because of the collision.
881 EXPECT_FALSE(app_sorting()->GetAppLaunchOrdinal(app_->id()).Equals(
882 default_app_launch_ordinal_));
885 protected:
886 void SetupUserOrdinals() override {
887 other_app_ = prefs_.AddApp("other_app");
888 // Creates a collision.
889 app_sorting()->SetPageOrdinal(other_app_->id(), default_page_ordinal_);
890 app_sorting()->SetAppLaunchOrdinal(other_app_->id(),
891 default_app_launch_ordinal_);
893 yet_another_app_ = prefs_.AddApp("yet_aother_app");
894 app_sorting()->SetPageOrdinal(yet_another_app_->id(),
895 default_page_ordinal_);
896 app_sorting()->SetAppLaunchOrdinal(yet_another_app_->id(),
897 default_app_launch_ordinal_);
900 private:
901 scoped_refptr<Extension> other_app_;
902 scoped_refptr<Extension> yet_another_app_;
904 TEST_F(ChromeAppSortingDefaultOrdinalNoCollision,
905 ChromeAppSortingDefaultOrdinalNoCollision) {}
907 // Tests that SetExtensionVisible() correctly hides and unhides extensions.
908 class ChromeAppSortingSetExtensionVisible : public ExtensionPrefsTest {
909 public:
910 ChromeAppSortingSetExtensionVisible() {}
911 ~ChromeAppSortingSetExtensionVisible() override {}
913 void Initialize() override {
914 first_app_ = prefs_.AddApp("first_app");
915 second_app_ = prefs_.AddApp("second_app");
918 void Verify() override {
919 ChromeAppSorting* sorting = app_sorting();
920 syncer::StringOrdinal page1 = sorting->GetPageOrdinal(first_app_->id());
921 syncer::StringOrdinal page2 = sorting->GetPageOrdinal(second_app_->id());
922 EXPECT_TRUE(sorting->GetAppLaunchOrdinal(first_app_->id()).IsValid());
923 EXPECT_TRUE(sorting->GetAppLaunchOrdinal(second_app_->id()).IsValid());
924 EXPECT_TRUE(page1.IsValid());
925 EXPECT_TRUE(page2.IsValid());
926 EXPECT_TRUE(page1.Equals(page2));
928 sorting->SetExtensionVisible(first_app_->id(), false);
929 EXPECT_EQ(
930 1U, sorting->CountItemsVisibleOnNtp(sorting->ntp_ordinal_map_[page1]));
932 sorting->SetExtensionVisible(first_app_->id(), true);
933 EXPECT_EQ(
934 2U, sorting->CountItemsVisibleOnNtp(sorting->ntp_ordinal_map_[page1]));
937 private:
938 scoped_refptr<Extension> first_app_;
939 scoped_refptr<Extension> second_app_;
941 TEST_F(ChromeAppSortingSetExtensionVisible,
942 ChromeAppSortingSetExtensionVisible) {
945 } // namespace extensions