| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_sorting.h" | 5 #include "chrome/browser/extensions/extension_sorting.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 8 #include <vector> |
| 9 |
| 7 #include "chrome/browser/extensions/extension_scoped_prefs.h" | 10 #include "chrome/browser/extensions/extension_scoped_prefs.h" |
| 8 #include "chrome/browser/extensions/extension_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
| 9 #include "chrome/browser/prefs/pref_service.h" | 12 #include "chrome/browser/prefs/pref_service.h" |
| 10 #include "chrome/common/chrome_notification_types.h" | 13 #include "chrome/common/chrome_notification_types.h" |
| 11 #include "content/public/browser/notification_service.h" | 14 #include "content/public/browser/notification_service.h" |
| 12 | 15 |
| 13 using extensions::ExtensionPrefs; | 16 using extensions::ExtensionPrefs; |
| 14 | 17 |
| 15 namespace { | 18 namespace { |
| 16 | 19 |
| 17 // The number of apps per page. This isn't a hard limit, but new apps installed | 20 // The number of apps per page. This isn't a hard limit, but new apps installed |
| 18 // from the webstore will overflow onto a new page if this limit is reached. | 21 // from the webstore will overflow onto a new page if this limit is reached. |
| 19 const size_t kNaturalAppPageSize = 18; | 22 const size_t kNaturalAppPageSize = 18; |
| 20 | 23 |
| 21 // A preference determining the order of which the apps appear on the NTP. | 24 // A preference determining the order of which the apps appear on the NTP. |
| 22 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index"; | 25 const char kPrefAppLaunchIndexDeprecated[] = "app_launcher_index"; |
| 23 const char kPrefAppLaunchOrdinal[] = "app_launcher_ordinal"; | 26 const char kPrefAppLaunchOrdinal[] = "app_launcher_ordinal"; |
| 24 | 27 |
| 25 // A preference determining the page on which an app appears in the NTP. | 28 // A preference determining the page on which an app appears in the NTP. |
| 26 const char kPrefPageIndexDeprecated[] = "page_index"; | 29 const char kPrefPageIndexDeprecated[] = "page_index"; |
| 27 const char kPrefPageOrdinal[] = "page_ordinal"; | 30 const char kPrefPageOrdinal[] = "page_ordinal"; |
| 28 | 31 |
| 29 } // namespace | 32 } // namespace |
| 30 | 33 |
| 34 //////////////////////////////////////////////////////////////////////////////// |
| 35 // ExtensionSorting::AppOrdinals |
| 36 |
| 37 ExtensionSorting::AppOrdinals::AppOrdinals() {} |
| 38 |
| 39 ExtensionSorting::AppOrdinals::~AppOrdinals() {} |
| 40 |
| 41 //////////////////////////////////////////////////////////////////////////////// |
| 42 // ExtensionSorting |
| 43 |
| 31 ExtensionSorting::ExtensionSorting(ExtensionScopedPrefs* extension_scoped_prefs, | 44 ExtensionSorting::ExtensionSorting(ExtensionScopedPrefs* extension_scoped_prefs, |
| 32 PrefService* pref_service) | 45 PrefService* pref_service) |
| 33 : extension_scoped_prefs_(extension_scoped_prefs), | 46 : extension_scoped_prefs_(extension_scoped_prefs), |
| 34 pref_service_(pref_service), | 47 pref_service_(pref_service), |
| 35 extension_service_(NULL) { | 48 extension_service_(NULL) { |
| 49 CreateDefaultOrdinals(); |
| 36 } | 50 } |
| 37 | 51 |
| 38 ExtensionSorting::~ExtensionSorting() { | 52 ExtensionSorting::~ExtensionSorting() { |
| 39 } | 53 } |
| 40 | 54 |
| 41 void ExtensionSorting::SetExtensionService( | 55 void ExtensionSorting::SetExtensionService( |
| 42 ExtensionServiceInterface* extension_service) { | 56 ExtensionServiceInterface* extension_service) { |
| 43 extension_service_ = extension_service; | 57 extension_service_ = extension_service; |
| 44 } | 58 } |
| 45 | 59 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 } | 209 } |
| 196 } | 210 } |
| 197 } | 211 } |
| 198 | 212 |
| 199 content::NotificationService::current()->Notify( | 213 content::NotificationService::current()->Notify( |
| 200 chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, | 214 chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, |
| 201 content::Source<ExtensionSorting>(this), | 215 content::Source<ExtensionSorting>(this), |
| 202 content::NotificationService::NoDetails()); | 216 content::NotificationService::NoDetails()); |
| 203 } | 217 } |
| 204 | 218 |
| 205 void ExtensionSorting::EnsureValidOrdinals(const std::string& extension_id) { | 219 void ExtensionSorting::EnsureValidOrdinals( |
| 220 const std::string& extension_id, |
| 221 const syncer::StringOrdinal& suggested_page) { |
| 206 syncer::StringOrdinal page_ordinal = GetPageOrdinal(extension_id); | 222 syncer::StringOrdinal page_ordinal = GetPageOrdinal(extension_id); |
| 207 if (!page_ordinal.IsValid()) { | 223 if (!page_ordinal.IsValid()) { |
| 208 // The webstore app should always start be on the first page. | 224 if (suggested_page.IsValid()) { |
| 209 page_ordinal = extension_id == extension_misc::kWebStoreAppId ? | 225 page_ordinal = suggested_page; |
| 210 CreateFirstAppPageOrdinal() : | 226 } else if (!GetDefaultOrdinals(extension_id, &page_ordinal, NULL) || |
| 211 GetNaturalAppPageOrdinal(); | 227 !page_ordinal.IsValid()) { |
| 228 page_ordinal = GetNaturalAppPageOrdinal(); |
| 229 } |
| 230 |
| 212 SetPageOrdinal(extension_id, page_ordinal); | 231 SetPageOrdinal(extension_id, page_ordinal); |
| 213 } | 232 } |
| 214 | 233 |
| 215 syncer::StringOrdinal app_launch_ordinal = GetAppLaunchOrdinal(extension_id); | 234 syncer::StringOrdinal app_launch_ordinal = GetAppLaunchOrdinal(extension_id); |
| 216 if (!app_launch_ordinal.IsValid()) { | 235 if (!app_launch_ordinal.IsValid()) { |
| 217 // The webstore app should always start in the position. | 236 // If using default app launcher ordinal, make sure there is no collision. |
| 218 app_launch_ordinal = extension_id == extension_misc::kWebStoreAppId ? | 237 if (GetDefaultOrdinals(extension_id, NULL, &app_launch_ordinal) && |
| 219 CreateFirstAppLaunchOrdinal(page_ordinal) : | 238 app_launch_ordinal.IsValid()) |
| 220 CreateNextAppLaunchOrdinal(page_ordinal); | 239 app_launch_ordinal = ResolveCollision(page_ordinal, app_launch_ordinal); |
| 221 SetAppLaunchOrdinal(extension_id, | 240 else |
| 222 app_launch_ordinal); | 241 app_launch_ordinal = CreateNextAppLaunchOrdinal(page_ordinal); |
| 242 |
| 243 SetAppLaunchOrdinal(extension_id, app_launch_ordinal); |
| 223 } | 244 } |
| 224 } | 245 } |
| 225 | 246 |
| 226 void ExtensionSorting::OnExtensionMoved( | 247 void ExtensionSorting::OnExtensionMoved( |
| 227 const std::string& moved_extension_id, | 248 const std::string& moved_extension_id, |
| 228 const std::string& predecessor_extension_id, | 249 const std::string& predecessor_extension_id, |
| 229 const std::string& successor_extension_id) { | 250 const std::string& successor_extension_id) { |
| 230 // We only need to change the StringOrdinal if there are neighbours. | 251 // We only need to change the StringOrdinal if there are neighbours. |
| 231 if (!predecessor_extension_id.empty() || !successor_extension_id.empty()) { | 252 if (!predecessor_extension_id.empty() || !successor_extension_id.empty()) { |
| 232 if (predecessor_extension_id.empty()) { | 253 if (predecessor_extension_id.empty()) { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 if (ext) { | 529 if (ext) { |
| 509 // It is possible for old extension to have ordinal values, but they | 530 // It is possible for old extension to have ordinal values, but they |
| 510 // shouldn't so we clear them. | 531 // shouldn't so we clear them. |
| 511 if (!ext->is_app()) | 532 if (!ext->is_app()) |
| 512 ClearOrdinals(extension_id); | 533 ClearOrdinals(extension_id); |
| 513 | 534 |
| 514 extension_service_->SyncExtensionChangeIfNeeded(*ext); | 535 extension_service_->SyncExtensionChangeIfNeeded(*ext); |
| 515 } | 536 } |
| 516 } | 537 } |
| 517 } | 538 } |
| 539 |
| 540 void ExtensionSorting::CreateDefaultOrdinals() { |
| 541 // The following defines the default order of apps. |
| 542 #if defined(OS_CHROMEOS) |
| 543 const char* kDefaultAppOrder[] = { |
| 544 extension_misc::kChromeAppId, |
| 545 extension_misc::kWebStoreAppId, |
| 546 "coobgpohoikkiipiblmjeljniedjpjpf", // Search |
| 547 "blpcfgokakmgnkcojhhkbfbldkacnbeo", // Youtube |
| 548 "pjkljhegncpnkpknbcohdijeoejaedia", // Gmail |
| 549 "ejjicmeblgpmajnghnpcppodonldlgfn", // Calendar |
| 550 "kjebfhglflhjjjiceimfkgicifkhjlnm", // Scratchpad |
| 551 "lneaknkopdijkpnocmklfnjbeapigfbh", // Google Maps |
| 552 "apdfllckaahabafndbhieahigkjlhalf", // Drive |
| 553 "aohghmighlieiainnegkcijnfilokake", // Docs |
| 554 "felcaaldnbdncclmgdcncolpebgiejap", // Sheets |
| 555 "aapocclcgogkmnckokdopfmhonfmgoek", // Slides |
| 556 "dlppkpafhbajpcmmoheippocdidnckmm", // Google+ |
| 557 "kbpgddbgniojgndnhlkjbkpknjhppkbk", // Google+ Hangouts |
| 558 "hhaomjibdihmijegdhdafkllkbggdgoj", // Files |
| 559 "hkhhlkdconhgemhegnplaldnmnmkaemd", // Tips & Tricks |
| 560 "icppfcnhkcmnfdhfhphakoifcfokfdhg", // Play Music |
| 561 "mmimngoggfoobjdlefbcabngfnmieonb", // Play Books |
| 562 "fppdphmgcddhjeddoeghpjefkdlccljb", // Play Movies |
| 563 "fobcpibfeplaikcclojfdhfdmbbeofai", // Games |
| 564 "joodangkbfjnajiiifokapkpmhfnpleo", // Calculator |
| 565 "cmbmjjimlbmpkonhnfabflhampihgnea", // Camera |
| 566 "gbchcmhmhahfdphkhkmpfmihenigjmpp", // Chrome Remote Desktop |
| 567 }; |
| 568 #else |
| 569 const char* kDefaultAppOrder[] = { |
| 570 extension_misc::kWebStoreAppId, |
| 571 }; |
| 572 #endif |
| 573 |
| 574 syncer::StringOrdinal page_ordinal = CreateFirstAppPageOrdinal(); |
| 575 syncer::StringOrdinal app_launch_ordinal = |
| 576 CreateFirstAppLaunchOrdinal(page_ordinal); |
| 577 for (size_t i = 0; i < arraysize(kDefaultAppOrder); ++i) { |
| 578 const std::string extension_id = kDefaultAppOrder[i]; |
| 579 default_ordinals_[extension_id].page_ordinal = page_ordinal; |
| 580 default_ordinals_[extension_id].app_launch_ordinal = app_launch_ordinal; |
| 581 app_launch_ordinal = app_launch_ordinal.CreateAfter(); |
| 582 } |
| 583 } |
| 584 |
| 585 bool ExtensionSorting::GetDefaultOrdinals( |
| 586 const std::string& extension_id, |
| 587 syncer::StringOrdinal* page_ordinal, |
| 588 syncer::StringOrdinal* app_launch_ordinal) const { |
| 589 AppOrdinalsMap::const_iterator it = default_ordinals_.find(extension_id); |
| 590 if (it == default_ordinals_.end()) |
| 591 return false; |
| 592 |
| 593 if (page_ordinal) |
| 594 *page_ordinal = it->second.page_ordinal; |
| 595 if (app_launch_ordinal) |
| 596 *app_launch_ordinal = it->second.app_launch_ordinal; |
| 597 return true; |
| 598 } |
| 599 |
| 600 syncer::StringOrdinal ExtensionSorting::ResolveCollision( |
| 601 const syncer::StringOrdinal& page_ordinal, |
| 602 const syncer::StringOrdinal& app_launch_ordinal) const { |
| 603 DCHECK(page_ordinal.IsValid() && app_launch_ordinal.IsValid()); |
| 604 |
| 605 PageOrdinalMap::const_iterator page_it = ntp_ordinal_map_.find(page_ordinal); |
| 606 if (page_it == ntp_ordinal_map_.end()) |
| 607 return app_launch_ordinal; |
| 608 |
| 609 const AppLaunchOrdinalMap& page = page_it->second; |
| 610 AppLaunchOrdinalMap::const_iterator app_it = page.find(app_launch_ordinal); |
| 611 if (app_it == page.end()) |
| 612 return app_launch_ordinal; |
| 613 |
| 614 // If there is no next after the collision, returns the next ordinal. |
| 615 if (++app_it == page.end()) |
| 616 return app_launch_ordinal.CreateAfter(); |
| 617 |
| 618 // Otherwise, returns the ordinal between the collision and the next ordinal. |
| 619 return app_launch_ordinal.CreateBetween(app_it->first); |
| 620 } |
| 621 |
| OLD | NEW |