Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / extensions / chrome_app_sorting_unittest.cc
blobb405214e2cf1869820f3e783991db27d7a315f2d
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 "chrome/common/extensions/extension_constants.h"
11 #include "extensions/common/manifest_constants.h"
12 #include "sync/api/string_ordinal.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace extensions {
17 namespace keys = manifest_keys;
19 class ChromeAppSortingTest : public ExtensionPrefsTest {
20 protected:
21 ChromeAppSorting* app_sorting() {
22 return static_cast<ChromeAppSorting*>(prefs()->app_sorting());
26 class ChromeAppSortingAppLocation : public ChromeAppSortingTest {
27 public:
28 virtual void Initialize() OVERRIDE {
29 extension_ = prefs_.AddExtension("not_an_app");
30 // Non-apps should not have any app launch ordinal or page ordinal.
31 prefs()->OnExtensionInstalled(extension_.get(),
32 Extension::ENABLED,
33 false,
34 syncer::StringOrdinal());
37 virtual void Verify() OVERRIDE {
38 EXPECT_FALSE(
39 app_sorting()->GetAppLaunchOrdinal(extension_->id()).IsValid());
40 EXPECT_FALSE(
41 app_sorting()->GetPageOrdinal(extension_->id()).IsValid());
44 private:
45 scoped_refptr<Extension> extension_;
47 TEST_F(ChromeAppSortingAppLocation, ChromeAppSortingAppLocation) {}
49 class ChromeAppSortingAppLaunchOrdinal : public ChromeAppSortingTest {
50 public:
51 virtual void Initialize() OVERRIDE {
52 // No extensions yet.
53 syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
54 EXPECT_TRUE(syncer::StringOrdinal::CreateInitialOrdinal().Equals(
55 app_sorting()->CreateNextAppLaunchOrdinal(page)));
57 extension_ = prefs_.AddApp("on_extension_installed");
58 EXPECT_FALSE(prefs()->IsExtensionDisabled(extension_->id()));
59 prefs()->OnExtensionInstalled(extension_.get(),
60 Extension::ENABLED,
61 false,
62 syncer::StringOrdinal());
65 virtual void Verify() OVERRIDE {
66 syncer::StringOrdinal launch_ordinal =
67 app_sorting()->GetAppLaunchOrdinal(extension_->id());
68 syncer::StringOrdinal page_ordinal =
69 syncer::StringOrdinal::CreateInitialOrdinal();
71 // Extension should have been assigned a valid StringOrdinal.
72 EXPECT_TRUE(launch_ordinal.IsValid());
73 EXPECT_TRUE(launch_ordinal.LessThan(
74 app_sorting()->CreateNextAppLaunchOrdinal(page_ordinal)));
75 // Set a new launch ordinal of and verify it comes after.
76 app_sorting()->SetAppLaunchOrdinal(
77 extension_->id(),
78 app_sorting()->CreateNextAppLaunchOrdinal(page_ordinal));
79 syncer::StringOrdinal new_launch_ordinal =
80 app_sorting()->GetAppLaunchOrdinal(extension_->id());
81 EXPECT_TRUE(launch_ordinal.LessThan(new_launch_ordinal));
83 // This extension doesn't exist, so it should return an invalid
84 // StringOrdinal.
85 syncer::StringOrdinal invalid_app_launch_ordinal =
86 app_sorting()->GetAppLaunchOrdinal("foo");
87 EXPECT_FALSE(invalid_app_launch_ordinal.IsValid());
88 EXPECT_EQ(-1, app_sorting()->PageStringOrdinalAsInteger(
89 invalid_app_launch_ordinal));
91 // The second page doesn't have any apps so its next launch ordinal should
92 // be the first launch ordinal.
93 syncer::StringOrdinal next_page = page_ordinal.CreateAfter();
94 syncer::StringOrdinal next_page_app_launch_ordinal =
95 app_sorting()->CreateNextAppLaunchOrdinal(next_page);
96 EXPECT_TRUE(next_page_app_launch_ordinal.Equals(
97 app_sorting()->CreateFirstAppLaunchOrdinal(next_page)));
100 private:
101 scoped_refptr<Extension> extension_;
103 TEST_F(ChromeAppSortingAppLaunchOrdinal, ChromeAppSortingAppLaunchOrdinal) {}
105 class ChromeAppSortingPageOrdinal : public ChromeAppSortingTest {
106 public:
107 virtual void Initialize() OVERRIDE {
108 extension_ = prefs_.AddApp("page_ordinal");
109 // Install with a page preference.
110 first_page_ = syncer::StringOrdinal::CreateInitialOrdinal();
111 prefs()->OnExtensionInstalled(extension_.get(),
112 Extension::ENABLED,
113 false,
114 first_page_);
115 EXPECT_TRUE(first_page_.Equals(
116 app_sorting()->GetPageOrdinal(extension_->id())));
117 EXPECT_EQ(0, app_sorting()->PageStringOrdinalAsInteger(first_page_));
119 scoped_refptr<Extension> extension2 = prefs_.AddApp("page_ordinal_2");
120 // Install without any page preference.
121 prefs()->OnExtensionInstalled(extension2.get(),
122 Extension::ENABLED,
123 false,
124 syncer::StringOrdinal());
125 EXPECT_TRUE(first_page_.Equals(
126 app_sorting()->GetPageOrdinal(extension2->id())));
128 virtual void Verify() OVERRIDE {
129 // Set the page ordinal.
130 syncer::StringOrdinal new_page = first_page_.CreateAfter();
131 app_sorting()->SetPageOrdinal(extension_->id(), new_page);
132 // Verify the page ordinal.
133 EXPECT_TRUE(
134 new_page.Equals(app_sorting()->GetPageOrdinal(extension_->id())));
135 EXPECT_EQ(1, app_sorting()->PageStringOrdinalAsInteger(new_page));
137 // This extension doesn't exist, so it should return an invalid
138 // StringOrdinal.
139 EXPECT_FALSE(app_sorting()->GetPageOrdinal("foo").IsValid());
142 private:
143 syncer::StringOrdinal first_page_;
144 scoped_refptr<Extension> extension_;
146 TEST_F(ChromeAppSortingPageOrdinal, ChromeAppSortingPageOrdinal) {}
148 // Ensure that ChromeAppSorting is able to properly initialize off a set
149 // of old page and app launch indices and properly convert them.
150 class ChromeAppSortingInitialize : public PrefsPrepopulatedTestBase {
151 public:
152 ChromeAppSortingInitialize() {}
153 virtual ~ChromeAppSortingInitialize() {}
155 virtual void Initialize() OVERRIDE {
156 // A preference determining the order of which the apps appear on the NTP.
157 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
158 // A preference determining the page on which an app appears in the NTP.
159 const char kPrefPageIndexDeprecated[] = "page_index";
161 // Setup the deprecated preferences.
162 ExtensionScopedPrefs* scoped_prefs =
163 static_cast<ExtensionScopedPrefs*>(prefs());
164 scoped_prefs->UpdateExtensionPref(extension1()->id(),
165 kPrefAppLaunchIndexDeprecated,
166 new base::FundamentalValue(0));
167 scoped_prefs->UpdateExtensionPref(extension1()->id(),
168 kPrefPageIndexDeprecated,
169 new base::FundamentalValue(0));
171 scoped_prefs->UpdateExtensionPref(extension2()->id(),
172 kPrefAppLaunchIndexDeprecated,
173 new base::FundamentalValue(1));
174 scoped_prefs->UpdateExtensionPref(extension2()->id(),
175 kPrefPageIndexDeprecated,
176 new base::FundamentalValue(0));
178 scoped_prefs->UpdateExtensionPref(extension3()->id(),
179 kPrefAppLaunchIndexDeprecated,
180 new base::FundamentalValue(0));
181 scoped_prefs->UpdateExtensionPref(extension3()->id(),
182 kPrefPageIndexDeprecated,
183 new base::FundamentalValue(1));
185 // We insert the ids in reserve order so that we have to deal with the
186 // element on the 2nd page before the 1st page is seen.
187 ExtensionIdList ids;
188 ids.push_back(extension3()->id());
189 ids.push_back(extension2()->id());
190 ids.push_back(extension1()->id());
192 prefs()->app_sorting()->Initialize(ids);
194 virtual void Verify() OVERRIDE {
195 syncer::StringOrdinal first_ordinal =
196 syncer::StringOrdinal::CreateInitialOrdinal();
197 AppSorting* app_sorting = prefs()->app_sorting();
199 EXPECT_TRUE(first_ordinal.Equals(
200 app_sorting->GetAppLaunchOrdinal(extension1()->id())));
201 EXPECT_TRUE(first_ordinal.LessThan(
202 app_sorting->GetAppLaunchOrdinal(extension2()->id())));
203 EXPECT_TRUE(first_ordinal.Equals(
204 app_sorting->GetAppLaunchOrdinal(extension3()->id())));
206 EXPECT_TRUE(first_ordinal.Equals(
207 app_sorting->GetPageOrdinal(extension1()->id())));
208 EXPECT_TRUE(first_ordinal.Equals(
209 app_sorting->GetPageOrdinal(extension2()->id())));
210 EXPECT_TRUE(first_ordinal.LessThan(
211 app_sorting->GetPageOrdinal(extension3()->id())));
214 TEST_F(ChromeAppSortingInitialize, ChromeAppSortingInitialize) {}
216 // Make sure that initialization still works when no extensions are present
217 // (i.e. make sure that the web store icon is still loaded into the map).
218 class ChromeAppSortingInitializeWithNoApps : public PrefsPrepopulatedTestBase {
219 public:
220 ChromeAppSortingInitializeWithNoApps() {}
221 virtual ~ChromeAppSortingInitializeWithNoApps() {}
223 virtual void Initialize() OVERRIDE {
224 AppSorting* app_sorting = prefs()->app_sorting();
226 // Make sure that the web store has valid ordinals.
227 syncer::StringOrdinal initial_ordinal =
228 syncer::StringOrdinal::CreateInitialOrdinal();
229 app_sorting->SetPageOrdinal(extension_misc::kWebStoreAppId,
230 initial_ordinal);
231 app_sorting->SetAppLaunchOrdinal(extension_misc::kWebStoreAppId,
232 initial_ordinal);
234 ExtensionIdList ids;
235 app_sorting->Initialize(ids);
237 virtual void Verify() OVERRIDE {
238 ChromeAppSorting* app_sorting =
239 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
241 syncer::StringOrdinal page =
242 app_sorting->GetPageOrdinal(extension_misc::kWebStoreAppId);
243 EXPECT_TRUE(page.IsValid());
245 ChromeAppSorting::PageOrdinalMap::iterator page_it =
246 app_sorting->ntp_ordinal_map_.find(page);
247 EXPECT_TRUE(page_it != app_sorting->ntp_ordinal_map_.end());
249 syncer::StringOrdinal app_launch =
250 app_sorting->GetPageOrdinal(extension_misc::kWebStoreAppId);
251 EXPECT_TRUE(app_launch.IsValid());
253 ChromeAppSorting::AppLaunchOrdinalMap::iterator app_launch_it =
254 page_it->second.find(app_launch);
255 EXPECT_TRUE(app_launch_it != page_it->second.end());
258 TEST_F(ChromeAppSortingInitializeWithNoApps,
259 ChromeAppSortingInitializeWithNoApps) {}
261 // Tests the application index to ordinal migration code for values that
262 // shouldn't be converted. This should be removed when the migrate code
263 // is taken out.
264 // http://crbug.com/107376
265 class ChromeAppSortingMigrateAppIndexInvalid
266 : public PrefsPrepopulatedTestBase {
267 public:
268 ChromeAppSortingMigrateAppIndexInvalid() {}
269 virtual ~ChromeAppSortingMigrateAppIndexInvalid() {}
271 virtual void Initialize() OVERRIDE {
272 // A preference determining the order of which the apps appear on the NTP.
273 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index";
274 // A preference determining the page on which an app appears in the NTP.
275 const char kPrefPageIndexDeprecated[] = "page_index";
277 // Setup the deprecated preference.
278 ExtensionScopedPrefs* scoped_prefs =
279 static_cast<ExtensionScopedPrefs*>(prefs());
280 scoped_prefs->UpdateExtensionPref(extension1()->id(),
281 kPrefAppLaunchIndexDeprecated,
282 new base::FundamentalValue(0));
283 scoped_prefs->UpdateExtensionPref(extension1()->id(),
284 kPrefPageIndexDeprecated,
285 new base::FundamentalValue(-1));
287 ExtensionIdList ids;
288 ids.push_back(extension1()->id());
290 prefs()->app_sorting()->Initialize(ids);
292 virtual void Verify() OVERRIDE {
293 // Make sure that the invalid page_index wasn't converted over.
294 EXPECT_FALSE(prefs()->app_sorting()->GetAppLaunchOrdinal(
295 extension1()->id()).IsValid());
298 TEST_F(ChromeAppSortingMigrateAppIndexInvalid,
299 ChromeAppSortingMigrateAppIndexInvalid) {}
301 class ChromeAppSortingFixNTPCollisionsAllCollide
302 : public PrefsPrepopulatedTestBase {
303 public:
304 ChromeAppSortingFixNTPCollisionsAllCollide() {}
305 virtual ~ChromeAppSortingFixNTPCollisionsAllCollide() {}
307 virtual void Initialize() OVERRIDE {
308 repeated_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
310 AppSorting* app_sorting = prefs()->app_sorting();
312 app_sorting->SetAppLaunchOrdinal(extension1()->id(),
313 repeated_ordinal_);
314 app_sorting->SetPageOrdinal(extension1()->id(), repeated_ordinal_);
316 app_sorting->SetAppLaunchOrdinal(extension2()->id(), repeated_ordinal_);
317 app_sorting->SetPageOrdinal(extension2()->id(), repeated_ordinal_);
319 app_sorting->SetAppLaunchOrdinal(extension3()->id(), repeated_ordinal_);
320 app_sorting->SetPageOrdinal(extension3()->id(), repeated_ordinal_);
322 app_sorting->FixNTPOrdinalCollisions();
324 virtual void Verify() OVERRIDE {
325 AppSorting* app_sorting = prefs()->app_sorting();
326 syncer::StringOrdinal extension1_app_launch =
327 app_sorting->GetAppLaunchOrdinal(extension1()->id());
328 syncer::StringOrdinal extension2_app_launch =
329 app_sorting->GetAppLaunchOrdinal(extension2()->id());
330 syncer::StringOrdinal extension3_app_launch =
331 app_sorting->GetAppLaunchOrdinal(extension3()->id());
333 // The overlapping extensions should have be adjusted so that they are
334 // sorted by their id.
335 EXPECT_EQ(extension1()->id() < extension2()->id(),
336 extension1_app_launch.LessThan(extension2_app_launch));
337 EXPECT_EQ(extension1()->id() < extension3()->id(),
338 extension1_app_launch.LessThan(extension3_app_launch));
339 EXPECT_EQ(extension2()->id() < extension3()->id(),
340 extension2_app_launch.LessThan(extension3_app_launch));
342 // The page ordinal should be unchanged.
343 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
344 repeated_ordinal_));
345 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
346 repeated_ordinal_));
347 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
348 repeated_ordinal_));
351 private:
352 syncer::StringOrdinal repeated_ordinal_;
354 TEST_F(ChromeAppSortingFixNTPCollisionsAllCollide,
355 ChromeAppSortingFixNTPCollisionsAllCollide) {}
357 class ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
358 : public PrefsPrepopulatedTestBase {
359 public:
360 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart() {}
361 virtual ~ChromeAppSortingFixNTPCollisionsSomeCollideAtStart() {}
363 virtual void Initialize() OVERRIDE {
364 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
365 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
367 AppSorting* app_sorting = prefs()->app_sorting();
369 // Have the first two extension in the same position, with a third
370 // (non-colliding) extension after.
372 app_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
373 app_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);
375 app_sorting->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
376 app_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);
378 app_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
379 app_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);
381 app_sorting->FixNTPOrdinalCollisions();
383 virtual void Verify() OVERRIDE {
384 AppSorting* app_sorting = prefs()->app_sorting();
385 syncer::StringOrdinal extension1_app_launch =
386 app_sorting->GetAppLaunchOrdinal(extension1()->id());
387 syncer::StringOrdinal extension2_app_launch =
388 app_sorting->GetAppLaunchOrdinal(extension2()->id());
389 syncer::StringOrdinal extension3_app_launch =
390 app_sorting->GetAppLaunchOrdinal(extension3()->id());
392 // The overlapping extensions should have be adjusted so that they are
393 // sorted by their id, but they both should be before ext3, which wasn't
394 // overlapping.
395 EXPECT_EQ(extension1()->id() < extension2()->id(),
396 extension1_app_launch.LessThan(extension2_app_launch));
397 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
398 EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));
400 // The page ordinal should be unchanged.
401 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
402 first_ordinal_));
403 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
404 first_ordinal_));
405 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
406 first_ordinal_));
409 private:
410 syncer::StringOrdinal first_ordinal_;
412 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtStart,
413 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart) {}
415 class ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
416 : public PrefsPrepopulatedTestBase {
417 public:
418 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd() {}
419 virtual ~ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd() {}
421 virtual void Initialize() OVERRIDE {
422 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
423 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
425 AppSorting* app_sorting = prefs()->app_sorting();
427 // Have the first extension in a non-colliding position, followed by two
428 // two extension in the same position.
430 app_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
431 app_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);
433 app_sorting->SetAppLaunchOrdinal(extension2()->id(), second_ordinal);
434 app_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);
436 app_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
437 app_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);
439 app_sorting->FixNTPOrdinalCollisions();
441 virtual void Verify() OVERRIDE {
442 AppSorting* app_sorting = prefs()->app_sorting();
443 syncer::StringOrdinal extension1_app_launch =
444 app_sorting->GetAppLaunchOrdinal(extension1()->id());
445 syncer::StringOrdinal extension2_app_launch =
446 app_sorting->GetAppLaunchOrdinal(extension2()->id());
447 syncer::StringOrdinal extension3_app_launch =
448 app_sorting->GetAppLaunchOrdinal(extension3()->id());
450 // The overlapping extensions should have be adjusted so that they are
451 // sorted by their id, but they both should be after ext1, which wasn't
452 // overlapping.
453 EXPECT_TRUE(extension1_app_launch.LessThan(extension2_app_launch));
454 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
455 EXPECT_EQ(extension2()->id() < extension3()->id(),
456 extension2_app_launch.LessThan(extension3_app_launch));
458 // The page ordinal should be unchanged.
459 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
460 first_ordinal_));
461 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
462 first_ordinal_));
463 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
464 first_ordinal_));
467 private:
468 syncer::StringOrdinal first_ordinal_;
470 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd,
471 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd) {}
473 class ChromeAppSortingFixNTPCollisionsTwoCollisions
474 : public PrefsPrepopulatedTestBase {
475 public:
476 ChromeAppSortingFixNTPCollisionsTwoCollisions() {}
477 virtual ~ChromeAppSortingFixNTPCollisionsTwoCollisions() {}
479 virtual void Initialize() OVERRIDE {
480 first_ordinal_ = syncer::StringOrdinal::CreateInitialOrdinal();
481 syncer::StringOrdinal second_ordinal = first_ordinal_.CreateAfter();
483 AppSorting* app_sorting = prefs()->app_sorting();
485 // Have two extensions colliding, followed by two more colliding extensions.
486 app_sorting->SetAppLaunchOrdinal(extension1()->id(), first_ordinal_);
487 app_sorting->SetPageOrdinal(extension1()->id(), first_ordinal_);
489 app_sorting->SetAppLaunchOrdinal(extension2()->id(), first_ordinal_);
490 app_sorting->SetPageOrdinal(extension2()->id(), first_ordinal_);
492 app_sorting->SetAppLaunchOrdinal(extension3()->id(), second_ordinal);
493 app_sorting->SetPageOrdinal(extension3()->id(), first_ordinal_);
495 app_sorting->SetAppLaunchOrdinal(extension4()->id(), second_ordinal);
496 app_sorting->SetPageOrdinal(extension4()->id(), first_ordinal_);
498 app_sorting->FixNTPOrdinalCollisions();
500 virtual void Verify() OVERRIDE {
501 AppSorting* app_sorting = prefs()->app_sorting();
502 syncer::StringOrdinal extension1_app_launch =
503 app_sorting->GetAppLaunchOrdinal(extension1()->id());
504 syncer::StringOrdinal extension2_app_launch =
505 app_sorting->GetAppLaunchOrdinal(extension2()->id());
506 syncer::StringOrdinal extension3_app_launch =
507 app_sorting->GetAppLaunchOrdinal(extension3()->id());
508 syncer::StringOrdinal extension4_app_launch =
509 app_sorting->GetAppLaunchOrdinal(extension4()->id());
511 // The overlapping extensions should have be adjusted so that they are
512 // sorted by their id, with |ext1| and |ext2| appearing before |ext3| and
513 // |ext4|.
514 EXPECT_TRUE(extension1_app_launch.LessThan(extension3_app_launch));
515 EXPECT_TRUE(extension1_app_launch.LessThan(extension4_app_launch));
516 EXPECT_TRUE(extension2_app_launch.LessThan(extension3_app_launch));
517 EXPECT_TRUE(extension2_app_launch.LessThan(extension4_app_launch));
519 EXPECT_EQ(extension1()->id() < extension2()->id(),
520 extension1_app_launch.LessThan(extension2_app_launch));
521 EXPECT_EQ(extension3()->id() < extension4()->id(),
522 extension3_app_launch.LessThan(extension4_app_launch));
524 // The page ordinal should be unchanged.
525 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).Equals(
526 first_ordinal_));
527 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension2()->id()).Equals(
528 first_ordinal_));
529 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension3()->id()).Equals(
530 first_ordinal_));
531 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension4()->id()).Equals(
532 first_ordinal_));
535 private:
536 syncer::StringOrdinal first_ordinal_;
538 TEST_F(ChromeAppSortingFixNTPCollisionsTwoCollisions,
539 ChromeAppSortingFixNTPCollisionsTwoCollisions) {}
541 class ChromeAppSortingEnsureValidOrdinals
542 : public PrefsPrepopulatedTestBase {
543 public :
544 ChromeAppSortingEnsureValidOrdinals() {}
545 virtual ~ChromeAppSortingEnsureValidOrdinals() {}
547 virtual void Initialize() OVERRIDE {}
548 virtual void Verify() OVERRIDE {
549 AppSorting* app_sorting = prefs()->app_sorting();
551 // Give ext1 invalid ordinals and then check that EnsureValidOrdinals fixes
552 // them.
553 app_sorting->SetAppLaunchOrdinal(extension1()->id(),
554 syncer::StringOrdinal());
555 app_sorting->SetPageOrdinal(extension1()->id(), syncer::StringOrdinal());
557 app_sorting->EnsureValidOrdinals(extension1()->id(),
558 syncer::StringOrdinal());
560 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(extension1()->id()).IsValid());
561 EXPECT_TRUE(app_sorting->GetPageOrdinal(extension1()->id()).IsValid());
564 TEST_F(ChromeAppSortingEnsureValidOrdinals,
565 ChromeAppSortingEnsureValidOrdinals) {}
567 class ChromeAppSortingPageOrdinalMapping : public PrefsPrepopulatedTestBase {
568 public:
569 ChromeAppSortingPageOrdinalMapping() {}
570 virtual ~ChromeAppSortingPageOrdinalMapping() {}
572 virtual void Initialize() OVERRIDE {}
573 virtual void Verify() OVERRIDE {
574 std::string ext_1 = "ext_1";
575 std::string ext_2 = "ext_2";
577 ChromeAppSorting* app_sorting =
578 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
579 syncer::StringOrdinal first_ordinal =
580 syncer::StringOrdinal::CreateInitialOrdinal();
582 // Ensure attempting to removing a mapping with an invalid page doesn't
583 // modify the map.
584 EXPECT_TRUE(app_sorting->ntp_ordinal_map_.empty());
585 app_sorting->RemoveOrdinalMapping(
586 ext_1, first_ordinal, first_ordinal);
587 EXPECT_TRUE(app_sorting->ntp_ordinal_map_.empty());
589 // Add new mappings.
590 app_sorting->AddOrdinalMapping(ext_1, first_ordinal, first_ordinal);
591 app_sorting->AddOrdinalMapping(ext_2, first_ordinal, first_ordinal);
593 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_.size());
594 EXPECT_EQ(2U, app_sorting->ntp_ordinal_map_[first_ordinal].size());
596 ChromeAppSorting::AppLaunchOrdinalMap::iterator it =
597 app_sorting->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
598 EXPECT_EQ(ext_1, it->second);
599 ++it;
600 EXPECT_EQ(ext_2, it->second);
602 app_sorting->RemoveOrdinalMapping(ext_1, first_ordinal, first_ordinal);
603 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_.size());
604 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_[first_ordinal].size());
606 it = app_sorting->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
607 EXPECT_EQ(ext_2, it->second);
609 // Ensure that attempting to remove an extension with a valid page and app
610 // launch ordinals, but a unused id has no effect.
611 app_sorting->RemoveOrdinalMapping(
612 "invalid_ext", first_ordinal, first_ordinal);
613 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_.size());
614 EXPECT_EQ(1U, app_sorting->ntp_ordinal_map_[first_ordinal].size());
616 it = app_sorting->ntp_ordinal_map_[first_ordinal].find(first_ordinal);
617 EXPECT_EQ(ext_2, it->second);
620 TEST_F(ChromeAppSortingPageOrdinalMapping,
621 ChromeAppSortingPageOrdinalMapping) {}
623 class ChromeAppSortingPreinstalledAppsBase : public PrefsPrepopulatedTestBase {
624 public:
625 ChromeAppSortingPreinstalledAppsBase() {
626 base::DictionaryValue simple_dict;
627 simple_dict.SetString(keys::kVersion, "1.0.0.0");
628 simple_dict.SetString(keys::kName, "unused");
629 simple_dict.SetString(keys::kApp, "true");
630 simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");
632 std::string error;
633 app1_scoped_ = Extension::Create(
634 prefs_.temp_dir().AppendASCII("app1_"), Manifest::EXTERNAL_PREF,
635 simple_dict, Extension::NO_FLAGS, &error);
636 prefs()->OnExtensionInstalled(app1_scoped_.get(),
637 Extension::ENABLED,
638 false,
639 syncer::StringOrdinal());
641 app2_scoped_ = Extension::Create(
642 prefs_.temp_dir().AppendASCII("app2_"), Manifest::EXTERNAL_PREF,
643 simple_dict, Extension::NO_FLAGS, &error);
644 prefs()->OnExtensionInstalled(app2_scoped_.get(),
645 Extension::ENABLED,
646 false,
647 syncer::StringOrdinal());
649 app1_ = app1_scoped_.get();
650 app2_ = app2_scoped_.get();
652 virtual ~ChromeAppSortingPreinstalledAppsBase() {}
654 protected:
655 // Weak references, for convenience.
656 Extension* app1_;
657 Extension* app2_;
659 private:
660 scoped_refptr<Extension> app1_scoped_;
661 scoped_refptr<Extension> app2_scoped_;
664 class ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage
665 : public ChromeAppSortingPreinstalledAppsBase {
666 public:
667 ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage() {}
668 virtual ~ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage() {}
670 virtual void Initialize() OVERRIDE {}
671 virtual void Verify() OVERRIDE {
672 syncer::StringOrdinal page = syncer::StringOrdinal::CreateInitialOrdinal();
673 ChromeAppSorting* app_sorting =
674 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
676 syncer::StringOrdinal min =
677 app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
678 page,
679 ChromeAppSorting::MIN_ORDINAL);
680 syncer::StringOrdinal max =
681 app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
682 page,
683 ChromeAppSorting::MAX_ORDINAL);
684 EXPECT_TRUE(min.IsValid());
685 EXPECT_TRUE(max.IsValid());
686 EXPECT_TRUE(min.LessThan(max));
688 // Ensure that the min and max values aren't set for empty pages.
689 min = syncer::StringOrdinal();
690 max = syncer::StringOrdinal();
691 syncer::StringOrdinal empty_page = page.CreateAfter();
692 EXPECT_FALSE(min.IsValid());
693 EXPECT_FALSE(max.IsValid());
694 min = app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
695 empty_page,
696 ChromeAppSorting::MIN_ORDINAL);
697 max = app_sorting->GetMinOrMaxAppLaunchOrdinalsOnPage(
698 empty_page,
699 ChromeAppSorting::MAX_ORDINAL);
700 EXPECT_FALSE(min.IsValid());
701 EXPECT_FALSE(max.IsValid());
704 TEST_F(ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage,
705 ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage) {}
707 // Make sure that empty pages aren't removed from the integer to ordinal
708 // mapping. See http://crbug.com/109802 for details.
709 class ChromeAppSortingKeepEmptyStringOrdinalPages
710 : public ChromeAppSortingPreinstalledAppsBase {
711 public:
712 ChromeAppSortingKeepEmptyStringOrdinalPages() {}
713 virtual ~ChromeAppSortingKeepEmptyStringOrdinalPages() {}
715 virtual void Initialize() OVERRIDE {
716 AppSorting* app_sorting = prefs()->app_sorting();
718 syncer::StringOrdinal first_page =
719 syncer::StringOrdinal::CreateInitialOrdinal();
720 app_sorting->SetPageOrdinal(app1_->id(), first_page);
721 EXPECT_EQ(0, app_sorting->PageStringOrdinalAsInteger(first_page));
723 last_page_ = first_page.CreateAfter();
724 app_sorting->SetPageOrdinal(app2_->id(), last_page_);
725 EXPECT_EQ(1, app_sorting->PageStringOrdinalAsInteger(last_page_));
727 // Move the second app to create an empty page.
728 app_sorting->SetPageOrdinal(app2_->id(), first_page);
729 EXPECT_EQ(0, app_sorting->PageStringOrdinalAsInteger(first_page));
731 virtual void Verify() OVERRIDE {
732 AppSorting* app_sorting = prefs()->app_sorting();
734 // Move the second app to a new empty page at the end, skipping over
735 // the current empty page.
736 last_page_ = last_page_.CreateAfter();
737 app_sorting->SetPageOrdinal(app2_->id(), last_page_);
738 EXPECT_EQ(2, app_sorting->PageStringOrdinalAsInteger(last_page_));
739 EXPECT_TRUE(last_page_.Equals(app_sorting->PageIntegerAsStringOrdinal(2)));
742 private:
743 syncer::StringOrdinal last_page_;
745 TEST_F(ChromeAppSortingKeepEmptyStringOrdinalPages,
746 ChromeAppSortingKeepEmptyStringOrdinalPages) {}
748 class ChromeAppSortingMakesFillerOrdinals
749 : public ChromeAppSortingPreinstalledAppsBase {
750 public:
751 ChromeAppSortingMakesFillerOrdinals() {}
752 virtual ~ChromeAppSortingMakesFillerOrdinals() {}
754 virtual void Initialize() OVERRIDE {
755 AppSorting* app_sorting = prefs()->app_sorting();
757 syncer::StringOrdinal first_page =
758 syncer::StringOrdinal::CreateInitialOrdinal();
759 app_sorting->SetPageOrdinal(app1_->id(), first_page);
760 EXPECT_EQ(0, app_sorting->PageStringOrdinalAsInteger(first_page));
762 virtual void Verify() OVERRIDE {
763 AppSorting* app_sorting = prefs()->app_sorting();
765 // Because the UI can add an unlimited number of empty pages without an app
766 // on them, this test simulates dropping of an app on the 1st and 4th empty
767 // pages (3rd and 6th pages by index) to ensure we don't crash and that
768 // filler ordinals are created as needed. See: http://crbug.com/122214
769 syncer::StringOrdinal page_three =
770 app_sorting->PageIntegerAsStringOrdinal(2);
771 app_sorting->SetPageOrdinal(app1_->id(), page_three);
772 EXPECT_EQ(2, app_sorting->PageStringOrdinalAsInteger(page_three));
774 syncer::StringOrdinal page_six = app_sorting->PageIntegerAsStringOrdinal(5);
775 app_sorting->SetPageOrdinal(app1_->id(), page_six);
776 EXPECT_EQ(5, app_sorting->PageStringOrdinalAsInteger(page_six));
779 TEST_F(ChromeAppSortingMakesFillerOrdinals,
780 ChromeAppSortingMakesFillerOrdinals) {}
782 class ChromeAppSortingDefaultOrdinalsBase : public ChromeAppSortingTest {
783 public:
784 ChromeAppSortingDefaultOrdinalsBase() {}
785 virtual ~ChromeAppSortingDefaultOrdinalsBase() {}
787 virtual void Initialize() OVERRIDE {
788 app_ = CreateApp("app");
790 InitDefaultOrdinals();
791 ChromeAppSorting* app_sorting =
792 static_cast<ChromeAppSorting*>(prefs()->app_sorting());
793 ChromeAppSorting::AppOrdinalsMap& sorting_defaults =
794 app_sorting->default_ordinals_;
795 sorting_defaults[app_->id()].page_ordinal = default_page_ordinal_;
796 sorting_defaults[app_->id()].app_launch_ordinal =
797 default_app_launch_ordinal_;
799 SetupUserOrdinals();
800 InstallApps();
803 protected:
804 scoped_refptr<Extension> CreateApp(const std::string& name) {
805 base::DictionaryValue simple_dict;
806 simple_dict.SetString(keys::kVersion, "1.0.0.0");
807 simple_dict.SetString(keys::kName, name);
808 simple_dict.SetString(keys::kApp, "true");
809 simple_dict.SetString(keys::kLaunchLocalPath, "fake.html");
811 std::string errors;
812 scoped_refptr<Extension> app = Extension::Create(
813 prefs_.temp_dir().AppendASCII(name), Manifest::EXTERNAL_PREF,
814 simple_dict, Extension::NO_FLAGS, &errors);
815 EXPECT_TRUE(app.get()) << errors;
816 EXPECT_TRUE(Extension::IdIsValid(app->id()));
817 return app;
820 void InitDefaultOrdinals() {
821 default_page_ordinal_ =
822 syncer::StringOrdinal::CreateInitialOrdinal().CreateAfter();
823 default_app_launch_ordinal_ =
824 syncer::StringOrdinal::CreateInitialOrdinal().CreateBefore();
827 virtual void SetupUserOrdinals() {}
829 virtual void InstallApps() {
830 prefs()->OnExtensionInstalled(app_.get(),
831 Extension::ENABLED,
832 false,
833 syncer::StringOrdinal());
836 scoped_refptr<Extension> app_;
837 syncer::StringOrdinal default_page_ordinal_;
838 syncer::StringOrdinal default_app_launch_ordinal_;
841 // Tests that the app gets its default ordinals.
842 class ChromeAppSortingDefaultOrdinals
843 : public ChromeAppSortingDefaultOrdinalsBase {
844 public:
845 ChromeAppSortingDefaultOrdinals() {}
846 virtual ~ChromeAppSortingDefaultOrdinals() {}
848 virtual void Verify() OVERRIDE {
849 AppSorting* app_sorting = prefs()->app_sorting();
850 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(
851 default_page_ordinal_));
852 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
853 default_app_launch_ordinal_));
856 TEST_F(ChromeAppSortingDefaultOrdinals,
857 ChromeAppSortingDefaultOrdinals) {}
859 // Tests that the default page ordinal is overridden by install page ordinal.
860 class ChromeAppSortingDefaultOrdinalOverriddenByInstallPage
861 : public ChromeAppSortingDefaultOrdinalsBase {
862 public:
863 ChromeAppSortingDefaultOrdinalOverriddenByInstallPage() {}
864 virtual ~ChromeAppSortingDefaultOrdinalOverriddenByInstallPage() {}
866 virtual void Verify() OVERRIDE {
867 AppSorting* app_sorting = prefs()->app_sorting();
869 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_->id()).Equals(
870 default_page_ordinal_));
871 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(install_page_));
874 protected:
875 virtual void InstallApps() OVERRIDE {
876 install_page_ = default_page_ordinal_.CreateAfter();
877 prefs()->OnExtensionInstalled(app_.get(),
878 Extension::ENABLED,
879 false,
880 install_page_);
883 private:
884 syncer::StringOrdinal install_page_;
886 TEST_F(ChromeAppSortingDefaultOrdinalOverriddenByInstallPage,
887 ChromeAppSortingDefaultOrdinalOverriddenByInstallPage) {}
889 // Tests that the default ordinals are overridden by user values.
890 class ChromeAppSortingDefaultOrdinalOverriddenByUserValue
891 : public ChromeAppSortingDefaultOrdinalsBase {
892 public:
893 ChromeAppSortingDefaultOrdinalOverriddenByUserValue() {}
894 virtual ~ChromeAppSortingDefaultOrdinalOverriddenByUserValue() {}
896 virtual void Verify() OVERRIDE {
897 AppSorting* app_sorting = prefs()->app_sorting();
899 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(
900 user_page_ordinal_));
901 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
902 user_app_launch_ordinal_));
905 protected:
906 virtual void SetupUserOrdinals() OVERRIDE {
907 user_page_ordinal_ = default_page_ordinal_.CreateAfter();
908 user_app_launch_ordinal_ = default_app_launch_ordinal_.CreateBefore();
910 AppSorting* app_sorting = prefs()->app_sorting();
911 app_sorting->SetPageOrdinal(app_->id(), user_page_ordinal_);
912 app_sorting->SetAppLaunchOrdinal(app_->id(), user_app_launch_ordinal_);
915 private:
916 syncer::StringOrdinal user_page_ordinal_;
917 syncer::StringOrdinal user_app_launch_ordinal_;
919 TEST_F(ChromeAppSortingDefaultOrdinalOverriddenByUserValue,
920 ChromeAppSortingDefaultOrdinalOverriddenByUserValue) {}
922 // Tests that the default app launch ordinal is changed to avoid collision.
923 class ChromeAppSortingDefaultOrdinalNoCollision
924 : public ChromeAppSortingDefaultOrdinalsBase {
925 public:
926 ChromeAppSortingDefaultOrdinalNoCollision() {}
927 virtual ~ChromeAppSortingDefaultOrdinalNoCollision() {}
929 virtual void Verify() OVERRIDE {
930 AppSorting* app_sorting = prefs()->app_sorting();
932 // Use the default page.
933 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_->id()).Equals(
934 default_page_ordinal_));
935 // Not using the default app launch ordinal because of the collision.
936 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_->id()).Equals(
937 default_app_launch_ordinal_));
940 protected:
941 virtual void SetupUserOrdinals() OVERRIDE {
942 other_app_ = prefs_.AddApp("other_app");
943 // Creates a collision.
944 AppSorting* app_sorting = prefs()->app_sorting();
945 app_sorting->SetPageOrdinal(other_app_->id(), default_page_ordinal_);
946 app_sorting->SetAppLaunchOrdinal(other_app_->id(),
947 default_app_launch_ordinal_);
949 yet_another_app_ = prefs_.AddApp("yet_aother_app");
950 app_sorting->SetPageOrdinal(yet_another_app_->id(), default_page_ordinal_);
951 app_sorting->SetAppLaunchOrdinal(yet_another_app_->id(),
952 default_app_launch_ordinal_);
955 private:
956 scoped_refptr<Extension> other_app_;
957 scoped_refptr<Extension> yet_another_app_;
959 TEST_F(ChromeAppSortingDefaultOrdinalNoCollision,
960 ChromeAppSortingDefaultOrdinalNoCollision) {}
962 } // namespace extensions