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"
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
{
21 ChromeAppSorting
* app_sorting() {
22 return static_cast<ChromeAppSorting
*>(prefs()->app_sorting());
26 class ChromeAppSortingAppLocation
: public ChromeAppSortingTest
{
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(),
34 syncer::StringOrdinal());
37 virtual void Verify() OVERRIDE
{
39 app_sorting()->GetAppLaunchOrdinal(extension_
->id()).IsValid());
41 app_sorting()->GetPageOrdinal(extension_
->id()).IsValid());
45 scoped_refptr
<Extension
> extension_
;
47 TEST_F(ChromeAppSortingAppLocation
, ChromeAppSortingAppLocation
) {}
49 class ChromeAppSortingAppLaunchOrdinal
: public ChromeAppSortingTest
{
51 virtual void Initialize() OVERRIDE
{
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(),
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(
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
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
)));
101 scoped_refptr
<Extension
> extension_
;
103 TEST_F(ChromeAppSortingAppLaunchOrdinal
, ChromeAppSortingAppLaunchOrdinal
) {}
105 class ChromeAppSortingPageOrdinal
: public ChromeAppSortingTest
{
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(),
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(),
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.
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
139 EXPECT_FALSE(app_sorting()->GetPageOrdinal("foo").IsValid());
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
{
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.
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
{
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
,
231 app_sorting
->SetAppLaunchOrdinal(extension_misc::kWebStoreAppId
,
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
264 // http://crbug.com/107376
265 class ChromeAppSortingMigrateAppIndexInvalid
266 : public PrefsPrepopulatedTestBase
{
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));
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
{
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(),
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(
345 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
347 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
352 syncer::StringOrdinal repeated_ordinal_
;
354 TEST_F(ChromeAppSortingFixNTPCollisionsAllCollide
,
355 ChromeAppSortingFixNTPCollisionsAllCollide
) {}
357 class ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
358 : public PrefsPrepopulatedTestBase
{
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
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(
403 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
405 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
410 syncer::StringOrdinal first_ordinal_
;
412 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
,
413 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
) {}
415 class ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
416 : public PrefsPrepopulatedTestBase
{
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
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(
461 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
463 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
468 syncer::StringOrdinal first_ordinal_
;
470 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
,
471 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
) {}
473 class ChromeAppSortingFixNTPCollisionsTwoCollisions
474 : public PrefsPrepopulatedTestBase
{
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
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(
527 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
529 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
531 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension4()->id()).Equals(
536 syncer::StringOrdinal first_ordinal_
;
538 TEST_F(ChromeAppSortingFixNTPCollisionsTwoCollisions
,
539 ChromeAppSortingFixNTPCollisionsTwoCollisions
) {}
541 class ChromeAppSortingEnsureValidOrdinals
542 : public PrefsPrepopulatedTestBase
{
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
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
{
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
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());
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
);
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
{
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");
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(),
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(),
647 syncer::StringOrdinal());
649 app1_
= app1_scoped_
.get();
650 app2_
= app2_scoped_
.get();
652 virtual ~ChromeAppSortingPreinstalledAppsBase() {}
655 // Weak references, for convenience.
660 scoped_refptr
<Extension
> app1_scoped_
;
661 scoped_refptr
<Extension
> app2_scoped_
;
664 class ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage
665 : public ChromeAppSortingPreinstalledAppsBase
{
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(
679 ChromeAppSorting::MIN_ORDINAL
);
680 syncer::StringOrdinal max
=
681 app_sorting
->GetMinOrMaxAppLaunchOrdinalsOnPage(
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(
696 ChromeAppSorting::MIN_ORDINAL
);
697 max
= app_sorting
->GetMinOrMaxAppLaunchOrdinalsOnPage(
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
{
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)));
743 syncer::StringOrdinal last_page_
;
745 TEST_F(ChromeAppSortingKeepEmptyStringOrdinalPages
,
746 ChromeAppSortingKeepEmptyStringOrdinalPages
) {}
748 class ChromeAppSortingMakesFillerOrdinals
749 : public ChromeAppSortingPreinstalledAppsBase
{
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
{
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_
;
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");
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()));
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(),
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
{
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
{
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_
));
875 virtual void InstallApps() OVERRIDE
{
876 install_page_
= default_page_ordinal_
.CreateAfter();
877 prefs()->OnExtensionInstalled(app_
.get(),
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
{
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_
));
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_
);
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
{
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_
));
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_
);
956 scoped_refptr
<Extension
> other_app_
;
957 scoped_refptr
<Extension
> yet_another_app_
;
959 TEST_F(ChromeAppSortingDefaultOrdinalNoCollision
,
960 ChromeAppSortingDefaultOrdinalNoCollision
) {}
962 } // namespace extensions