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