Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / extensions / chrome_app_sorting_unittest.cc
blobf5d242ce2bd73fbb00904dc25b64a91fc9ae71db
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 <map>
9 #include "chrome/browser/extensions/extension_prefs_unittest.h"
10 #include "components/crx_file/id_util.h"
11 #include "extensions/common/constants.h"
12 #include "extensions/common/manifest_constants.h"
13 #include "sync/api/string_ordinal.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace extensions {
18 namespace keys = manifest_keys;
20 class ChromeAppSortingTest : public ExtensionPrefsTest {
21 protected:
22 ChromeAppSorting* app_sorting() {
23 return static_cast<ChromeAppSorting*>(prefs()->app_sorting());
27 class ChromeAppSortingAppLocation : public ChromeAppSortingTest {
28 public:
29 void Initialize() override {
30 extension_ = prefs_.AddExtension("not_an_app");
31 // Non-apps should not have any app launch ordinal or page ordinal.
32 prefs()->OnExtensionInstalled(extension_.get(),
33 Extension::ENABLED,
34 syncer::StringOrdinal(),
35 std::string());
38 void Verify() override {
39 EXPECT_FALSE(
40 app_sorting()->GetAppLaunchOrdinal(extension_->id()).IsValid());
41 EXPECT_FALSE(
42 app_sorting()->GetPageOrdinal(extension_->id()).IsValid());
45 private:
46 scoped_refptr<Extension> extension_;
48 TEST_F(ChromeAppSortingAppLocation, ChromeAppSortingAppLocation) {}
50 class ChromeAppSortingAppLaunchOrdinal : public ChromeAppSortingTest {
51 public:
52 void Initialize() override {
53 // No extensions yet.
54 syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
55 EXPECT_TRUE(syncer::StringOrdinal::CreateInitialOrdinal().Equals(
56 app_sorting()->CreateNextAppLaunchOrdinal(page)));
58 extension_ = prefs_.AddApp("on_extension_installed");
59 EXPECT_FALSE(prefs()->IsExtensionDisabled(extension_->id()));
60 prefs()->OnExtensionInstalled(extension_.get(),
61 Extension::ENABLED,
62 syncer::StringOrdinal(),
63 std::string());
66 void Verify() override {
67 syncer::StringOrdinal launch_ordinal =
68 app_sorting()->GetAppLaunchOrdinal(extension_->id());
69 syncer::StringOrdinal page_ordinal =
70 syncer::StringOrdinal::CreateInitialOrdinal();
72 // Extension should have been assigned a valid StringOrdinal.
73 EXPECT_TRUE(launch_ordinal.IsValid());
74 EXPECT_TRUE(launch_ordinal.LessThan(
75 app_sorting()->CreateNextAppLaunchOrdinal(page_ordinal)));
76 // Set a new launch ordinal of and verify it comes after.
77 app_sorting()->SetAppLaunchOrdinal(
78 extension_->id(),
79 app_sorting()->CreateNextAppLaunchOrdinal(page_ordinal));
80 syncer::StringOrdinal new_launch_ordinal =
81 app_sorting()->GetAppLaunchOrdinal(extension_->id());
82 EXPECT_TRUE(launch_ordinal.LessThan(new_launch_ordinal));
84 // This extension doesn't exist, so it should return an invalid
85 // StringOrdinal.
86 syncer::StringOrdinal invalid_app_launch_ordinal =
87 app_sorting()->GetAppLaunchOrdinal("foo");
88 EXPECT_FALSE(invalid_app_launch_ordinal.IsValid());
89 EXPECT_EQ(-1, app_sorting()->PageStringOrdinalAsInteger(
90 invalid_app_launch_ordinal));
92 // The second page doesn't have any apps so its next launch ordinal should
93 // be the first launch ordinal.
94 syncer::StringOrdinal next_page = page_ordinal.CreateAfter();
95 syncer::StringOrdinal next_page_app_launch_ordinal =
96 app_sorting()->CreateNextAppLaunchOrdinal(next_page);
97 EXPECT_TRUE(next_page_app_launch_ordinal.Equals(
98 app_sorting()->CreateFirstAppLaunchOrdinal(next_page)));
101 private:
102 scoped_refptr<Extension> extension_;
104 TEST_F(ChromeAppSortingAppLaunchOrdinal, ChromeAppSortingAppLaunchOrdinal) {}
106 class ChromeAppSortingPageOrdinal : public ChromeAppSortingTest {
107 public:
108 void Initialize() override {
109 extension_ = prefs_.AddApp("page_ordinal");
110 // Install with a page preference.
111 first_page_ = syncer::StringOrdinal::CreateInitialOrdinal();
112 prefs()->OnExtensionInstalled(extension_.get(),
113 Extension::ENABLED,
114 first_page_,
115 std::string());
116 EXPECT_TRUE(first_page_.Equals(
117 app_sorting()->GetPageOrdinal(extension_->id())));
118 EXPECT_EQ(0, app_sorting()->PageStringOrdinalAsInteger(first_page_));
120 scoped_refptr<Extension> extension2 = prefs_.AddApp("page_ordinal_2");
121 // Install without any page preference.
122 prefs()->OnExtensionInstalled(extension2.get(),
123 Extension::ENABLED,
124 syncer::StringOrdinal(),
125 std::string());
126 EXPECT_TRUE(first_page_.Equals(
127 app_sorting()->GetPageOrdinal(extension2->id())));
129 void Verify() override {
130 // Set the page ordinal.
131 syncer::StringOrdinal new_page = first_page_.CreateAfter();
132 app_sorting()->SetPageOrdinal(extension_->id(), new_page);
133 // Verify the page ordinal.
134 EXPECT_TRUE(
135 new_page.Equals(app_sorting()->GetPageOrdinal(extension_->id())));
136 EXPECT_EQ(1, app_sorting()->PageStringOrdinalAsInteger(new_page));
138 // This extension doesn't exist, so it should return an invalid
139 // StringOrdinal.
140 EXPECT_FALSE(app_sorting()->GetPageOrdinal("foo").IsValid());
143 private:
144 syncer::StringOrdinal first_page_;
145 scoped_refptr<Extension> extension_;
147 TEST_F(ChromeAppSortingPageOrdinal, ChromeAppSortingPageOrdinal) {}
149 // Ensure that ChromeAppSorting is able to properly initialize off a set
150 // of old page and app launch indices and properly convert them.
151 class ChromeAppSortingInitialize : public PrefsPrepopulatedTestBase {
152 public:
153 ChromeAppSortingInitialize() {}
154 ~ChromeAppSortingInitialize() override {}
156 void Initialize() override {
157 // A preference determining the order of which the apps appear on the NTP.
158 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
159 // A preference determining the page on which an app appears in the NTP.
160 const char kPrefPageIndexDeprecated[] = "page_index";
162 // Setup the deprecated preferences.
163 ExtensionScopedPrefs* scoped_prefs =
164 static_cast<ExtensionScopedPrefs*>(prefs());
165 scoped_prefs->UpdateExtensionPref(extension1()->id(),
166 kPrefAppLaunchIndexDeprecated,
167 new base::FundamentalValue(0));
168 scoped_prefs->UpdateExtensionPref(extension1()->id(),
169 kPrefPageIndexDeprecated,
170 new base::FundamentalValue(0));
172 scoped_prefs->UpdateExtensionPref(extension2()->id(),
173 kPrefAppLaunchIndexDeprecated,
174 new base::FundamentalValue(1));
175 scoped_prefs->UpdateExtensionPref(extension2()->id(),
176 kPrefPageIndexDeprecated,
177 new base::FundamentalValue(0));
179 scoped_prefs->UpdateExtensionPref(extension3()->id(),
180 kPrefAppLaunchIndexDeprecated,
181 new base::FundamentalValue(0));
182 scoped_prefs->UpdateExtensionPref(extension3()->id(),
183 kPrefPageIndexDeprecated,
184 new base::FundamentalValue(1));
186 // We insert the ids in reserve order so that we have to deal with the
187 // element on the 2nd page before the 1st page is seen.
188 ExtensionIdList ids;
189 ids.push_back(extension3()->id());
190 ids.push_back(extension2()->id());
191 ids.push_back(extension1()->id());
193 prefs()->app_sorting()->Initialize(ids);
195 void Verify() override {
196 syncer::StringOrdinal first_ordinal =
197 syncer::StringOrdinal::CreateInitialOrdinal();
198 AppSorting* app_sorting = prefs()->app_sorting();
200 EXPECT_TRUE(first_ordinal.Equals(
201 app_sorting->GetAppLaunchOrdinal(extension1()->id())));
202 EXPECT_TRUE(first_ordinal.LessThan(
203 app_sorting->GetAppLaunchOrdinal(extension2()->id())));
204 EXPECT_TRUE(first_ordinal.Equals(
205 app_sorting->GetAppLaunchOrdinal(extension3()->id())));
207 EXPECT_TRUE(first_ordinal.Equals(
208 app_sorting->GetPageOrdinal(extension1()->id())));
209 EXPECT_TRUE(first_ordinal.Equals(
210 app_sorting->GetPageOrdinal(extension2()->id())));
211 EXPECT_TRUE(first_ordinal.LessThan(
212 app_sorting->GetPageOrdinal(extension3()->id())));
215 TEST_F(ChromeAppSortingInitialize, ChromeAppSortingInitialize) {}
217 // Make sure that initialization still works when no extensions are present
218 // (i.e. make sure that the web store icon is still loaded into the map).
219 class ChromeAppSortingInitializeWithNoApps : public PrefsPrepopulatedTestBase {
220 public:
221 ChromeAppSortingInitializeWithNoApps() {}
222 ~ChromeAppSortingInitializeWithNoApps() override {}
224 void Initialize() override {
225 AppSorting* app_sorting = prefs()->app_sorting();
227 // Make sure that the web store has valid ordinals.
228 syncer::StringOrdinal initial_ordinal =
229 syncer::StringOrdinal::CreateInitialOrdinal();
230 app_sorting->SetPageOrdinal(extensions::kWebStoreAppId,
231 initial_ordinal);
232 app_sorting->SetAppLaunchOrdinal(extensions::kWebStoreAppId,
233 initial_ordinal);
235 ExtensionIdList ids;
236 app_sorting->Initialize(ids);
238 void Verify() override {
239 ChromeAppSorting* app_sorting =
240 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
242 syncer::StringOrdinal page =
243 app_sorting->GetPageOrdinal(extensions::kWebStoreAppId);
244 EXPECT_TRUE(page.IsValid());
246 ChromeAppSorting::PageOrdinalMap::iterator page_it =
247 app_sorting->ntp_ordinal_map_.find(page);
248 EXPECT_TRUE(page_it != app_sorting->ntp_ordinal_map_.end());
250 syncer::StringOrdinal app_launch =
251 app_sorting->GetPageOrdinal(extensions::kWebStoreAppId);
252 EXPECT_TRUE(app_launch.IsValid());
254 ChromeAppSorting::AppLaunchOrdinalMap::iterator app_launch_it =
255 page_it->second.find(app_launch);
256 EXPECT_TRUE(app_launch_it != page_it->second.end());
259 TEST_F(ChromeAppSortingInitializeWithNoApps,
260 ChromeAppSortingInitializeWithNoApps) {}
262 // Tests the application index to ordinal migration code for values that
263 // shouldn't be converted. This should be removed when the migrate code
264 // is taken out.
265 // http://crbug.com/107376
266 class ChromeAppSortingMigrateAppIndexInvalid
267 : public PrefsPrepopulatedTestBase {
268 public:
269 ChromeAppSortingMigrateAppIndexInvalid() {}
270 ~ChromeAppSortingMigrateAppIndexInvalid() override {}
272 void Initialize() override {
273 // A preference determining the order of which the apps appear on the NTP.
274 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
275 // A preference determining the page on which an app appears in the NTP.
276 const char kPrefPageIndexDeprecated[] = "page_index";
278 // Setup the deprecated preference.
279 ExtensionScopedPrefs* scoped_prefs =
280 static_cast<ExtensionScopedPrefs*>(prefs());
281 scoped_prefs->UpdateExtensionPref(extension1()->id(),
282 kPrefAppLaunchIndexDeprecated,
283 new base::FundamentalValue(0));
284 scoped_prefs->UpdateExtensionPref(extension1()->id(),
285 kPrefPageIndexDeprecated,
286 new base::FundamentalValue(-1));
288 ExtensionIdList ids;
289 ids.push_back(extension1()->id());
291 prefs()->app_sorting()->Initialize(ids);
293 void Verify() override {
294 // Make sure that the invalid page_index wasn't converted over.
295 EXPECT_FALSE(prefs()->app_sorting()->GetAppLaunchOrdinal(
296 extension1()->id()).IsValid());
299 TEST_F(ChromeAppSortingMigrateAppIndexInvalid,
300 ChromeAppSortingMigrateAppIndexInvalid) {}
302 class ChromeAppSortingFixNTPCollisionsAllCollide
303 : public PrefsPrepopulatedTestBase {
304 public:
305 ChromeAppSortingFixNTPCollisionsAllCollide() {}
306 ~ChromeAppSortingFixNTPCollisionsAllCollide() override {}
308 void Initialize() override {
309 repeated_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
311 AppSorting* app_sorting = prefs()->app_sorting();
313 app_sorting->SetAppLaunchOrdinal(extension1()->id(),
314 repeated_ordinal_);
315 app_sorting->SetPageOrdinal(extension1()->id(), repeated_ordinal_);
317 app_sorting->SetAppLaunchOrdinal(extension2()->id(), repeated_ordinal_);
318 app_sorting->SetPageOrdinal(extension2()->id(), repeated_ordinal_);
320 app_sorting->SetAppLaunchOrdinal(extension3()->id(), repeated_ordinal_);
321 app_sorting->SetPageOrdinal(extension3()->id(), repeated_ordinal_);
323 app_sorting->FixNTPOrdinalCollisions();
325 void Verify() override {
326 AppSorting* app_sorting = prefs()->app_sorting();
327 syncer::StringOrdinal extension1_app_launch =
328 app_sorting->GetAppLaunchOrdinal(extension1()->id());
329 syncer::StringOrdinal extension2_app_launch =
330 app_sorting->GetAppLaunchOrdinal(extension2()->id());
331 syncer::StringOrdinal extension3_app_launch =
332 app_sorting->GetAppLaunchOrdinal(extension3()->id());
334 // The overlapping extensions should have be adjusted so that they are
335 // sorted by their id.
336 EXPECT_EQ(extension1()->id() < extension2()->id(),
337 extension1_app_launch.LessThan(extension2_app_launch));
338 EXPECT_EQ(extension1()->id() < extension3()->id(),
339 extension1_app_launch.LessThan(extension3_app_launch));
340 EXPECT_EQ(extension2()->id() < extension3()->id(),
341 extension2_app_launch.LessThan(extension3_app_launch));
343 // The page ordinal should be unchanged.
344 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
345 repeated_ordinal_));
346 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
347 repeated_ordinal_));
348 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
349 repeated_ordinal_));
352 private:
353 syncer::StringOrdinal repeated_ordinal_;
355 TEST_F(ChromeAppSortingFixNTPCollisionsAllCollide,
356 ChromeAppSortingFixNTPCollisionsAllCollide) {}
358 class ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
359 : public PrefsPrepopulatedTestBase {
360 public:
361 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart() {}
362 ~ChromeAppSortingFixNTPCollisionsSomeCollideAtStart() override {}
364 void Initialize() override {
365 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
366 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
368 AppSorting* app_sorting = prefs()->app_sorting();
370 // Have the first two extension in the same position, with a third
371 // (non-colliding) extension after.
373 app_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
374 app_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);
376 app_sorting->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
377 app_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);
379 app_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
380 app_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);
382 app_sorting->FixNTPOrdinalCollisions();
384 void Verify() override {
385 AppSorting* app_sorting = prefs()->app_sorting();
386 syncer::StringOrdinal extension1_app_launch =
387 app_sorting->GetAppLaunchOrdinal(extension1()->id());
388 syncer::StringOrdinal extension2_app_launch =
389 app_sorting->GetAppLaunchOrdinal(extension2()->id());
390 syncer::StringOrdinal extension3_app_launch =
391 app_sorting->GetAppLaunchOrdinal(extension3()->id());
393 // The overlapping extensions should have be adjusted so that they are
394 // sorted by their id, but they both should be before ext3, which wasn't
395 // overlapping.
396 EXPECT_EQ(extension1()->id() < extension2()->id(),
397 extension1_app_launch.LessThan(extension2_app_launch));
398 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
399 EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));
401 // The page ordinal should be unchanged.
402 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
403 first_ordinal_));
404 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
405 first_ordinal_));
406 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
407 first_ordinal_));
410 private:
411 syncer::StringOrdinal first_ordinal_;
413 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtStart,
414 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart) {}
416 class ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
417 : public PrefsPrepopulatedTestBase {
418 public:
419 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd() {}
420 ~ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd() override {}
422 void Initialize() override {
423 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
424 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
426 AppSorting* app_sorting = prefs()->app_sorting();
428 // Have the first extension in a non-colliding position, followed by two
429 // two extension in the same position.
431 app_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
432 app_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);
434 app_sorting->SetAppLaunchOrdinal(extension2()->id(), second_ordinal);
435 app_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);
437 app_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
438 app_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);
440 app_sorting->FixNTPOrdinalCollisions();
442 void Verify() override {
443 AppSorting* app_sorting = prefs()->app_sorting();
444 syncer::StringOrdinal extension1_app_launch =
445 app_sorting->GetAppLaunchOrdinal(extension1()->id());
446 syncer::StringOrdinal extension2_app_launch =
447 app_sorting->GetAppLaunchOrdinal(extension2()->id());
448 syncer::StringOrdinal extension3_app_launch =
449 app_sorting->GetAppLaunchOrdinal(extension3()->id());
451 // The overlapping extensions should have be adjusted so that they are
452 // sorted by their id, but they both should be after ext1, which wasn't
453 // overlapping.
454 EXPECT_TRUE(extension1_app_launch.LessThan(extension2_app_launch));
455 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
456 EXPECT_EQ(extension2()->id() < extension3()->id(),
457 extension2_app_launch.LessThan(extension3_app_launch));
459 // The page ordinal should be unchanged.
460 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
461 first_ordinal_));
462 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
463 first_ordinal_));
464 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
465 first_ordinal_));
468 private:
469 syncer::StringOrdinal first_ordinal_;
471 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd,
472 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd) {}
474 class ChromeAppSortingFixNTPCollisionsTwoCollisions
475 : public PrefsPrepopulatedTestBase {
476 public:
477 ChromeAppSortingFixNTPCollisionsTwoCollisions() {}
478 ~ChromeAppSortingFixNTPCollisionsTwoCollisions() override {}
480 void Initialize() override {
481 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
482 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
484 AppSorting* app_sorting = prefs()->app_sorting();
486 // Have two extensions colliding, followed by two more colliding extensions.
487 app_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
488 app_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);
490 app_sorting->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
491 app_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);
493 app_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
494 app_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);
496 app_sorting->SetAppLaunchOrdinal(extension4()->id(), second_ordinal);
497 app_sorting->SetPageOrdinal(extension4()->id(), first_ordinal_);
499 app_sorting->FixNTPOrdinalCollisions();
501 void Verify() override {
502 AppSorting* app_sorting = prefs()->app_sorting();
503 syncer::StringOrdinal extension1_app_launch =
504 app_sorting->GetAppLaunchOrdinal(extension1()->id());
505 syncer::StringOrdinal extension2_app_launch =
506 app_sorting->GetAppLaunchOrdinal(extension2()->id());
507 syncer::StringOrdinal extension3_app_launch =
508 app_sorting->GetAppLaunchOrdinal(extension3()->id());
509 syncer::StringOrdinal extension4_app_launch =
510 app_sorting->GetAppLaunchOrdinal(extension4()->id());
512 // The overlapping extensions should have be adjusted so that they are
513 // sorted by their id, with |ext1| and |ext2| appearing before |ext3| and
514 // |ext4|.
515 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
516 EXPECT_TRUE(extension1_app_launch.LessThan(extension4_app_launch));
517 EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));
518 EXPECT_TRUE(extension2_app_launch.LessThan(extension4_app_launch));
520 EXPECT_EQ(extension1()->id() < extension2()->id(),
521 extension1_app_launch.LessThan(extension2_app_launch));
522 EXPECT_EQ(extension3()->id() < extension4()->id(),
523 extension3_app_launch.LessThan(extension4_app_launch));
525 // The page ordinal should be unchanged.
526 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
527 first_ordinal_));
528 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
529 first_ordinal_));
530 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
531 first_ordinal_));
532 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension4()->id()).Equals(
533 first_ordinal_));
536 private:
537 syncer::StringOrdinal first_ordinal_;
539 TEST_F(ChromeAppSortingFixNTPCollisionsTwoCollisions,
540 ChromeAppSortingFixNTPCollisionsTwoCollisions) {}
542 class ChromeAppSortingEnsureValidOrdinals
543 : public PrefsPrepopulatedTestBase {
544 public :
545 ChromeAppSortingEnsureValidOrdinals() {}
546 ~ChromeAppSortingEnsureValidOrdinals() override {}
548 void Initialize() override {}
549 void Verify() override {
550 AppSorting* app_sorting = prefs()->app_sorting();
552 // Give ext1 invalid ordinals and then check that EnsureValidOrdinals fixes
553 // them.
554 app_sorting->SetAppLaunchOrdinal(extension1()->id(),
555 syncer::StringOrdinal());
556 app_sorting->SetPageOrdinal(extension1()->id(), syncer::StringOrdinal());
558 app_sorting->EnsureValidOrdinals(extension1()->id(),
559 syncer::StringOrdinal());
561 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(extension1()->id()).IsValid());
562 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).IsValid());
565 TEST_F(ChromeAppSortingEnsureValidOrdinals,
566 ChromeAppSortingEnsureValidOrdinals) {}
568 class ChromeAppSortingPageOrdinalMapping : public PrefsPrepopulatedTestBase {
569 public:
570 ChromeAppSortingPageOrdinalMapping() {}
571 ~ChromeAppSortingPageOrdinalMapping() override {}
573 void Initialize() override {}
574 void Verify() override {
575 std::string ext_1 = "ext_1";
576 std::string ext_2 = "ext_2";
578 ChromeAppSorting* app_sorting =
579 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
580 syncer::StringOrdinal first_ordinal =
581 syncer::StringOrdinal::CreateInitialOrdinal();
583 // Ensure attempting to removing a mapping with an invalid page doesn't
584 // modify the map.
585 EXPECT_TRUE(app_sorting->ntp_ordinal_map_.empty());
586 app_sorting->RemoveOrdinalMapping(
587 ext_1, first_ordinal, first_ordinal);
588 EXPECT_TRUE(app_sorting->ntp_ordinal_map_.empty());
590 // Add new mappings.
591 app_sorting->AddOrdinalMapping(ext_1, first_ordinal, first_ordinal);
592 app_sorting->AddOrdinalMapping(ext_2, first_ordinal, first_ordinal);
594 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_.size());
595 EXPECT_EQ(2U, app_sorting->ntp_ordinal_map_[first_ordinal].size());
597 ChromeAppSorting::AppLaunchOrdinalMap::iterator it =
598 app_sorting->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
599 EXPECT_EQ(ext_1, it->second);
600 ++it;
601 EXPECT_EQ(ext_2, it->second);
603 app_sorting->RemoveOrdinalMapping(ext_1, first_ordinal, first_ordinal);
604 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_.size());
605 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_[first_ordinal].size());
607 it = app_sorting->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
608 EXPECT_EQ(ext_2, it->second);
610 // Ensure that attempting to remove an extension with a valid page and app
611 // launch ordinals, but a unused id has no effect.
612 app_sorting->RemoveOrdinalMapping(
613 "invalid_ext", first_ordinal, first_ordinal);
614 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_.size());
615 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_[first_ordinal].size());
617 it = app_sorting->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
618 EXPECT_EQ(ext_2, it->second);
621 TEST_F(ChromeAppSortingPageOrdinalMapping,
622 ChromeAppSortingPageOrdinalMapping) {}
624 class ChromeAppSortingPreinstalledAppsBase : public PrefsPrepopulatedTestBase {
625 public:
626 ChromeAppSortingPreinstalledAppsBase() {
627 base::DictionaryValue simple_dict;
628 simple_dict.SetString(keys::kVersion, "1.0.0.0");
629 simple_dict.SetString(keys::kName, "unused");
630 simple_dict.SetString(keys::kApp, "true");
631 simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");
633 std::string error;
634 app1_scoped_ = Extension::Create(
635 prefs_.temp_dir().AppendASCII("app1_"), Manifest::EXTERNAL_PREF,
636 simple_dict, Extension::NO_FLAGS, &error);
637 prefs()->OnExtensionInstalled(app1_scoped_.get(),
638 Extension::ENABLED,
639 syncer::StringOrdinal(),
640 std::string());
642 app2_scoped_ = Extension::Create(
643 prefs_.temp_dir().AppendASCII("app2_"), Manifest::EXTERNAL_PREF,
644 simple_dict, Extension::NO_FLAGS, &error);
645 prefs()->OnExtensionInstalled(app2_scoped_.get(),
646 Extension::ENABLED,
647 syncer::StringOrdinal(),
648 std::string());
650 app1_ = app1_scoped_.get();
651 app2_ = app2_scoped_.get();
653 ~ChromeAppSortingPreinstalledAppsBase() override {}
655 protected:
656 // Weak references, for convenience.
657 Extension* app1_;
658 Extension* app2_;
660 private:
661 scoped_refptr<Extension> app1_scoped_;
662 scoped_refptr<Extension> app2_scoped_;
665 class ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage
666 : public ChromeAppSortingPreinstalledAppsBase {
667 public:
668 ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage() {}
669 ~ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage() override {}
671 void Initialize() override {}
672 void Verify() override {
673 syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
674 ChromeAppSorting* app_sorting =
675 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
677 syncer::StringOrdinal min =
678 app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
679 page,
680 ChromeAppSorting::MIN_ORDINAL);
681 syncer::StringOrdinal max =
682 app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
683 page,
684 ChromeAppSorting::MAX_ORDINAL);
685 EXPECT_TRUE(min.IsValid());
686 EXPECT_TRUE(max.IsValid());
687 EXPECT_TRUE(min.LessThan(max));
689 // Ensure that the min and max values aren't set for empty pages.
690 min = syncer::StringOrdinal();
691 max = syncer::StringOrdinal();
692 syncer::StringOrdinal empty_page = page.CreateAfter();
693 EXPECT_FALSE(min.IsValid());
694 EXPECT_FALSE(max.IsValid());
695 min = app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
696 empty_page,
697 ChromeAppSorting::MIN_ORDINAL);
698 max = app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
699 empty_page,
700 ChromeAppSorting::MAX_ORDINAL);
701 EXPECT_FALSE(min.IsValid());
702 EXPECT_FALSE(max.IsValid());
705 TEST_F(ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage,
706 ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage) {}
708 // Make sure that empty pages aren't removed from the integer to ordinal
709 // mapping. See http://crbug.com/109802 for details.
710 class ChromeAppSortingKeepEmptyStringOrdinalPages
711 : public ChromeAppSortingPreinstalledAppsBase {
712 public:
713 ChromeAppSortingKeepEmptyStringOrdinalPages() {}
714 ~ChromeAppSortingKeepEmptyStringOrdinalPages() override {}
716 void Initialize() override {
717 AppSorting* app_sorting = prefs()->app_sorting();
719 syncer::StringOrdinal first_page =
720 syncer::StringOrdinal::CreateInitialOrdinal();
721 app_sorting->SetPageOrdinal(app1_->id(), first_page);
722 EXPECT_EQ(0, app_sorting->PageStringOrdinalAsInteger(first_page));
724 last_page_ = first_page.CreateAfter();
725 app_sorting->SetPageOrdinal(app2_->id(), last_page_);
726 EXPECT_EQ(1, app_sorting->PageStringOrdinalAsInteger(last_page_));
728 // Move the second app to create an empty page.
729 app_sorting->SetPageOrdinal(app2_->id(), first_page);
730 EXPECT_EQ(0, app_sorting->PageStringOrdinalAsInteger(first_page));
732 void Verify() override {
733 AppSorting* app_sorting = prefs()->app_sorting();
735 // Move the second app to a new empty page at the end, skipping over
736 // the current empty page.
737 last_page_ = last_page_.CreateAfter();
738 app_sorting->SetPageOrdinal(app2_->id(), last_page_);
739 EXPECT_EQ(2, app_sorting->PageStringOrdinalAsInteger(last_page_));
740 EXPECT_TRUE(last_page_.Equals(app_sorting->PageIntegerAsStringOrdinal(2)));
743 private:
744 syncer::StringOrdinal last_page_;
746 TEST_F(ChromeAppSortingKeepEmptyStringOrdinalPages,
747 ChromeAppSortingKeepEmptyStringOrdinalPages) {}
749 class ChromeAppSortingMakesFillerOrdinals
750 : public ChromeAppSortingPreinstalledAppsBase {
751 public:
752 ChromeAppSortingMakesFillerOrdinals() {}
753 ~ChromeAppSortingMakesFillerOrdinals() override {}
755 void Initialize() override {
756 AppSorting* app_sorting = prefs()->app_sorting();
758 syncer::StringOrdinal first_page =
759 syncer::StringOrdinal::CreateInitialOrdinal();
760 app_sorting->SetPageOrdinal(app1_->id(), first_page);
761 EXPECT_EQ(0, app_sorting->PageStringOrdinalAsInteger(first_page));
763 void Verify() override {
764 AppSorting* app_sorting = prefs()->app_sorting();
766 // Because the UI can add an unlimited number of empty pages without an app
767 // on them, this test simulates dropping of an app on the 1st and 4th empty
768 // pages (3rd and 6th pages by index) to ensure we don't crash and that
769 // filler ordinals are created as needed. See: http://crbug.com/122214
770 syncer::StringOrdinal page_three =
771 app_sorting->PageIntegerAsStringOrdinal(2);
772 app_sorting->SetPageOrdinal(app1_->id(), page_three);
773 EXPECT_EQ(2, app_sorting->PageStringOrdinalAsInteger(page_three));
775 syncer::StringOrdinal page_six = app_sorting->PageIntegerAsStringOrdinal(5);
776 app_sorting->SetPageOrdinal(app1_->id(), page_six);
777 EXPECT_EQ(5, app_sorting->PageStringOrdinalAsInteger(page_six));
780 TEST_F(ChromeAppSortingMakesFillerOrdinals,
781 ChromeAppSortingMakesFillerOrdinals) {}
783 class ChromeAppSortingDefaultOrdinalsBase : public ChromeAppSortingTest {
784 public:
785 ChromeAppSortingDefaultOrdinalsBase() {}
786 ~ChromeAppSortingDefaultOrdinalsBase() override {}
788 void Initialize() override {
789 app_ = CreateApp("app");
791 InitDefaultOrdinals();
792 ChromeAppSorting* app_sorting =
793 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
794 ChromeAppSorting::AppOrdinalsMap& sorting_defaults =
795 app_sorting->default_ordinals_;
796 sorting_defaults[app_->id()].page_ordinal = default_page_ordinal_;
797 sorting_defaults[app_->id()].app_launch_ordinal =
798 default_app_launch_ordinal_;
800 SetupUserOrdinals();
801 InstallApps();
804 protected:
805 scoped_refptr<Extension> CreateApp(const std::string& name) {
806 base::DictionaryValue simple_dict;
807 simple_dict.SetString(keys::kVersion, "1.0.0.0");
808 simple_dict.SetString(keys::kName, name);
809 simple_dict.SetString(keys::kApp, "true");
810 simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");
812 std::string errors;
813 scoped_refptr<Extension> app = Extension::Create(
814 prefs_.temp_dir().AppendASCII(name), Manifest::EXTERNAL_PREF,
815 simple_dict, Extension::NO_FLAGS, &errors);
816 EXPECT_TRUE(app.get()) << errors;
817 EXPECT_TRUE(crx_file::id_util::IdIsValid(app->id()));
818 return app;
821 void InitDefaultOrdinals() {
822 default_page_ordinal_ =
823 syncer::StringOrdinal::CreateInitialOrdinal().CreateAfter();
824 default_app_launch_ordinal_ =
825 syncer::StringOrdinal::CreateInitialOrdinal().CreateBefore();
828 virtual void SetupUserOrdinals() {}
830 virtual void InstallApps() {
831 prefs()->OnExtensionInstalled(app_.get(),
832 Extension::ENABLED,
833 syncer::StringOrdinal(),
834 std::string());
837 scoped_refptr<Extension> app_;
838 syncer::StringOrdinal default_page_ordinal_;
839 syncer::StringOrdinal default_app_launch_ordinal_;
842 // Tests that the app gets its default ordinals.
843 class ChromeAppSortingDefaultOrdinals
844 : public ChromeAppSortingDefaultOrdinalsBase {
845 public:
846 ChromeAppSortingDefaultOrdinals() {}
847 ~ChromeAppSortingDefaultOrdinals() override {}
849 void Verify() override {
850 AppSorting* app_sorting = prefs()->app_sorting();
851 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(
852 default_page_ordinal_));
853 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
854 default_app_launch_ordinal_));
857 TEST_F(ChromeAppSortingDefaultOrdinals,
858 ChromeAppSortingDefaultOrdinals) {}
860 // Tests that the default page ordinal is overridden by install page ordinal.
861 class ChromeAppSortingDefaultOrdinalOverriddenByInstallPage
862 : public ChromeAppSortingDefaultOrdinalsBase {
863 public:
864 ChromeAppSortingDefaultOrdinalOverriddenByInstallPage() {}
865 ~ChromeAppSortingDefaultOrdinalOverriddenByInstallPage() override {}
867 void Verify() override {
868 AppSorting* app_sorting = prefs()->app_sorting();
870 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_->id()).Equals(
871 default_page_ordinal_));
872 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(install_page_));
875 protected:
876 void InstallApps() override {
877 install_page_ = default_page_ordinal_.CreateAfter();
878 prefs()->OnExtensionInstalled(app_.get(),
879 Extension::ENABLED,
880 install_page_,
881 std::string());
884 private:
885 syncer::StringOrdinal install_page_;
887 TEST_F(ChromeAppSortingDefaultOrdinalOverriddenByInstallPage,
888 ChromeAppSortingDefaultOrdinalOverriddenByInstallPage) {}
890 // Tests that the default ordinals are overridden by user values.
891 class ChromeAppSortingDefaultOrdinalOverriddenByUserValue
892 : public ChromeAppSortingDefaultOrdinalsBase {
893 public:
894 ChromeAppSortingDefaultOrdinalOverriddenByUserValue() {}
895 ~ChromeAppSortingDefaultOrdinalOverriddenByUserValue() override {}
897 void Verify() override {
898 AppSorting* app_sorting = prefs()->app_sorting();
900 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(
901 user_page_ordinal_));
902 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
903 user_app_launch_ordinal_));
906 protected:
907 void SetupUserOrdinals() override {
908 user_page_ordinal_ = default_page_ordinal_.CreateAfter();
909 user_app_launch_ordinal_ = default_app_launch_ordinal_.CreateBefore();
911 AppSorting* app_sorting = prefs()->app_sorting();
912 app_sorting->SetPageOrdinal(app_->id(), user_page_ordinal_);
913 app_sorting->SetAppLaunchOrdinal(app_->id(), user_app_launch_ordinal_);
916 private:
917 syncer::StringOrdinal user_page_ordinal_;
918 syncer::StringOrdinal user_app_launch_ordinal_;
920 TEST_F(ChromeAppSortingDefaultOrdinalOverriddenByUserValue,
921 ChromeAppSortingDefaultOrdinalOverriddenByUserValue) {}
923 // Tests that the default app launch ordinal is changed to avoid collision.
924 class ChromeAppSortingDefaultOrdinalNoCollision
925 : public ChromeAppSortingDefaultOrdinalsBase {
926 public:
927 ChromeAppSortingDefaultOrdinalNoCollision() {}
928 ~ChromeAppSortingDefaultOrdinalNoCollision() override {}
930 void Verify() override {
931 AppSorting* app_sorting = prefs()->app_sorting();
933 // Use the default page.
934 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(
935 default_page_ordinal_));
936 // Not using the default app launch ordinal because of the collision.
937 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
938 default_app_launch_ordinal_));
941 protected:
942 void SetupUserOrdinals() override {
943 other_app_ = prefs_.AddApp("other_app");
944 // Creates a collision.
945 AppSorting* app_sorting = prefs()->app_sorting();
946 app_sorting->SetPageOrdinal(other_app_->id(), default_page_ordinal_);
947 app_sorting->SetAppLaunchOrdinal(other_app_->id(),
948 default_app_launch_ordinal_);
950 yet_another_app_ = prefs_.AddApp("yet_aother_app");
951 app_sorting->SetPageOrdinal(yet_another_app_->id(), default_page_ordinal_);
952 app_sorting->SetAppLaunchOrdinal(yet_another_app_->id(),
953 default_app_launch_ordinal_);
956 private:
957 scoped_refptr<Extension> other_app_;
958 scoped_refptr<Extension> yet_another_app_;
960 TEST_F(ChromeAppSortingDefaultOrdinalNoCollision,
961 ChromeAppSortingDefaultOrdinalNoCollision) {}
963 // Tests that SetExtensionVisible() correctly hides and unhides extensions.
964 class ChromeAppSortingSetExtensionVisible : public ChromeAppSortingTest {
965 public:
966 ChromeAppSortingSetExtensionVisible() {}
967 ~ChromeAppSortingSetExtensionVisible() override {}
969 void Initialize() override {
970 first_app_ = prefs_.AddApp("first_app");
971 second_app_ = prefs_.AddApp("second_app");
974 void Verify() override {
975 ChromeAppSorting* sorting = app_sorting();
976 syncer::StringOrdinal page1 = sorting->GetPageOrdinal(first_app_->id());
977 syncer::StringOrdinal page2 = sorting->GetPageOrdinal(second_app_->id());
978 EXPECT_TRUE(sorting->GetAppLaunchOrdinal(first_app_->id()).IsValid());
979 EXPECT_TRUE(sorting->GetAppLaunchOrdinal(second_app_->id()).IsValid());
980 EXPECT_TRUE(page1.IsValid());
981 EXPECT_TRUE(page2.IsValid());
982 EXPECT_TRUE(page1.Equals(page2));
984 sorting->SetExtensionVisible(first_app_->id(), false);
985 EXPECT_EQ(
986 1U, sorting->CountItemsVisibleOnNtp(sorting->ntp_ordinal_map_[page1]));
988 sorting->SetExtensionVisible(first_app_->id(), true);
989 EXPECT_EQ(
990 2U, sorting->CountItemsVisibleOnNtp(sorting->ntp_ordinal_map_[page1]));
993 private:
994 scoped_refptr<Extension> first_app_;
995 scoped_refptr<Extension> second_app_;
997 TEST_F(ChromeAppSortingSetExtensionVisible,
998 ChromeAppSortingSetExtensionVisible) {
1001 } // namespace extensions