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 "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
{
22 ChromeAppSorting
* app_sorting() {
23 return static_cast<ChromeAppSorting
*>(prefs()->app_sorting());
27 class ChromeAppSortingAppLocation
: public ChromeAppSortingTest
{
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(),
34 syncer::StringOrdinal(),
38 void Verify() override
{
40 app_sorting()->GetAppLaunchOrdinal(extension_
->id()).IsValid());
42 app_sorting()->GetPageOrdinal(extension_
->id()).IsValid());
46 scoped_refptr
<Extension
> extension_
;
48 TEST_F(ChromeAppSortingAppLocation
, ChromeAppSortingAppLocation
) {}
50 class ChromeAppSortingAppLaunchOrdinal
: public ChromeAppSortingTest
{
52 void Initialize() override
{
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(),
62 syncer::StringOrdinal(),
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(
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
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
)));
102 scoped_refptr
<Extension
> extension_
;
104 TEST_F(ChromeAppSortingAppLaunchOrdinal
, ChromeAppSortingAppLaunchOrdinal
) {}
106 class ChromeAppSortingPageOrdinal
: public ChromeAppSortingTest
{
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(),
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(),
124 syncer::StringOrdinal(),
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.
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
140 EXPECT_FALSE(app_sorting()->GetPageOrdinal("foo").IsValid());
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
{
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.
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
{
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
,
232 app_sorting
->SetAppLaunchOrdinal(extensions::kWebStoreAppId
,
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
265 // http://crbug.com/107376
266 class ChromeAppSortingMigrateAppIndexInvalid
267 : public PrefsPrepopulatedTestBase
{
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));
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
{
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(),
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(
346 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
348 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
353 syncer::StringOrdinal repeated_ordinal_
;
355 TEST_F(ChromeAppSortingFixNTPCollisionsAllCollide
,
356 ChromeAppSortingFixNTPCollisionsAllCollide
) {}
358 class ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
359 : public PrefsPrepopulatedTestBase
{
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
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(
404 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
406 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
411 syncer::StringOrdinal first_ordinal_
;
413 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
,
414 ChromeAppSortingFixNTPCollisionsSomeCollideAtStart
) {}
416 class ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
417 : public PrefsPrepopulatedTestBase
{
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
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(
462 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
464 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
469 syncer::StringOrdinal first_ordinal_
;
471 TEST_F(ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
,
472 ChromeAppSortingFixNTPCollisionsSomeCollideAtEnd
) {}
474 class ChromeAppSortingFixNTPCollisionsTwoCollisions
475 : public PrefsPrepopulatedTestBase
{
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
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(
528 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension2()->id()).Equals(
530 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension3()->id()).Equals(
532 EXPECT_TRUE(app_sorting
->GetPageOrdinal(extension4()->id()).Equals(
537 syncer::StringOrdinal first_ordinal_
;
539 TEST_F(ChromeAppSortingFixNTPCollisionsTwoCollisions
,
540 ChromeAppSortingFixNTPCollisionsTwoCollisions
) {}
542 class ChromeAppSortingEnsureValidOrdinals
543 : public PrefsPrepopulatedTestBase
{
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
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
{
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
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());
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
);
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
{
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");
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(),
639 syncer::StringOrdinal(),
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(),
647 syncer::StringOrdinal(),
650 app1_
= app1_scoped_
.get();
651 app2_
= app2_scoped_
.get();
653 ~ChromeAppSortingPreinstalledAppsBase() override
{}
656 // Weak references, for convenience.
661 scoped_refptr
<Extension
> app1_scoped_
;
662 scoped_refptr
<Extension
> app2_scoped_
;
665 class ChromeAppSortingGetMinOrMaxAppLaunchOrdinalsOnPage
666 : public ChromeAppSortingPreinstalledAppsBase
{
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(
680 ChromeAppSorting::MIN_ORDINAL
);
681 syncer::StringOrdinal max
=
682 app_sorting
->GetMinOrMaxAppLaunchOrdinalsOnPage(
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(
697 ChromeAppSorting::MIN_ORDINAL
);
698 max
= app_sorting
->GetMinOrMaxAppLaunchOrdinalsOnPage(
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
{
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)));
744 syncer::StringOrdinal last_page_
;
746 TEST_F(ChromeAppSortingKeepEmptyStringOrdinalPages
,
747 ChromeAppSortingKeepEmptyStringOrdinalPages
) {}
749 class ChromeAppSortingMakesFillerOrdinals
750 : public ChromeAppSortingPreinstalledAppsBase
{
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
{
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_
;
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");
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()));
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(),
833 syncer::StringOrdinal(),
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
{
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
{
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_
));
876 void InstallApps() override
{
877 install_page_
= default_page_ordinal_
.CreateAfter();
878 prefs()->OnExtensionInstalled(app_
.get(),
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
{
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_
));
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_
);
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
{
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_
));
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_
);
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
{
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);
986 1U, sorting
->CountItemsVisibleOnNtp(sorting
->ntp_ordinal_map_
[page1
]));
988 sorting
->SetExtensionVisible(first_app_
->id(), true);
990 2U, sorting
->CountItemsVisibleOnNtp(sorting
->ntp_ordinal_map_
[page1
]));
994 scoped_refptr
<Extension
> first_app_
;
995 scoped_refptr
<Extension
> second_app_
;
997 TEST_F(ChromeAppSortingSetExtensionVisible
,
998 ChromeAppSortingSetExtensionVisible
) {
1001 } // namespace extensions