Chromium Code Reviews| 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 |
| 31 ExtensionSorting::ExtensionSorting(ExtensionScopedPrefs* extension_scoped_prefs, | 34 ExtensionSorting::ExtensionSorting(ExtensionScopedPrefs* extension_scoped_prefs, |
| 32 PrefService* pref_service) | 35 PrefService* pref_service) |
| 33 : extension_scoped_prefs_(extension_scoped_prefs), | 36 : extension_scoped_prefs_(extension_scoped_prefs), |
| 34 pref_service_(pref_service), | 37 pref_service_(pref_service), |
| 35 extension_service_(NULL) { | 38 extension_service_(NULL) { |
| 39 CreateDefaultOrdinals(); | |
| 36 } | 40 } |
| 37 | 41 |
| 38 ExtensionSorting::~ExtensionSorting() { | 42 ExtensionSorting::~ExtensionSorting() { |
| 39 } | 43 } |
| 40 | 44 |
| 41 void ExtensionSorting::SetExtensionService( | 45 void ExtensionSorting::SetExtensionService( |
| 42 ExtensionServiceInterface* extension_service) { | 46 ExtensionServiceInterface* extension_service) { |
| 43 extension_service_ = extension_service; | 47 extension_service_ = extension_service; |
| 44 } | 48 } |
| 45 | 49 |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 } | 199 } |
| 196 } | 200 } |
| 197 } | 201 } |
| 198 | 202 |
| 199 content::NotificationService::current()->Notify( | 203 content::NotificationService::current()->Notify( |
| 200 chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, | 204 chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED, |
| 201 content::Source<ExtensionSorting>(this), | 205 content::Source<ExtensionSorting>(this), |
| 202 content::NotificationService::NoDetails()); | 206 content::NotificationService::NoDetails()); |
| 203 } | 207 } |
| 204 | 208 |
| 205 void ExtensionSorting::EnsureValidOrdinals(const std::string& extension_id) { | 209 void ExtensionSorting::EnsureValidOrdinals( |
| 210 const std::string& extension_id, | |
| 211 const syncer::StringOrdinal& suggested_page) { | |
| 206 syncer::StringOrdinal page_ordinal = GetPageOrdinal(extension_id); | 212 syncer::StringOrdinal page_ordinal = GetPageOrdinal(extension_id); |
| 207 if (!page_ordinal.IsValid()) { | 213 if (!page_ordinal.IsValid()) { |
| 208 // The webstore app should always start be on the first page. | 214 if (suggested_page.IsValid()) { |
| 209 page_ordinal = extension_id == extension_misc::kWebStoreAppId ? | 215 page_ordinal = suggested_page; |
| 210 CreateFirstAppPageOrdinal() : | 216 } else if (!GetDefaultOrdinals(extension_id, &page_ordinal, NULL) || |
| 211 GetNaturalAppPageOrdinal(); | 217 !page_ordinal.IsValid()) { |
| 218 page_ordinal = GetNaturalAppPageOrdinal(); | |
| 219 } | |
| 220 | |
| 212 SetPageOrdinal(extension_id, page_ordinal); | 221 SetPageOrdinal(extension_id, page_ordinal); |
| 213 } | 222 } |
| 214 | 223 |
| 215 syncer::StringOrdinal app_launch_ordinal = GetAppLaunchOrdinal(extension_id); | 224 syncer::StringOrdinal app_launch_ordinal = GetAppLaunchOrdinal(extension_id); |
| 216 if (!app_launch_ordinal.IsValid()) { | 225 if (!app_launch_ordinal.IsValid()) { |
| 217 // The webstore app should always start in the position. | 226 // If using default app launcher ordinal, make sure there is no collision. |
| 218 app_launch_ordinal = extension_id == extension_misc::kWebStoreAppId ? | 227 if (GetDefaultOrdinals(extension_id, NULL, &app_launch_ordinal) && |
| 219 CreateFirstAppLaunchOrdinal(page_ordinal) : | 228 app_launch_ordinal.IsValid()) |
| 220 CreateNextAppLaunchOrdinal(page_ordinal); | 229 app_launch_ordinal = ResolveCollision(page_ordinal, app_launch_ordinal); |
| 221 SetAppLaunchOrdinal(extension_id, | 230 else |
| 222 app_launch_ordinal); | 231 app_launch_ordinal = CreateNextAppLaunchOrdinal(page_ordinal); |
| 232 | |
| 233 SetAppLaunchOrdinal(extension_id, app_launch_ordinal); | |
| 223 } | 234 } |
| 224 } | 235 } |
| 225 | 236 |
| 226 void ExtensionSorting::OnExtensionMoved( | 237 void ExtensionSorting::OnExtensionMoved( |
| 227 const std::string& moved_extension_id, | 238 const std::string& moved_extension_id, |
| 228 const std::string& predecessor_extension_id, | 239 const std::string& predecessor_extension_id, |
| 229 const std::string& successor_extension_id) { | 240 const std::string& successor_extension_id) { |
| 230 // We only need to change the StringOrdinal if there are neighbours. | 241 // We only need to change the StringOrdinal if there are neighbours. |
| 231 if (!predecessor_extension_id.empty() || !successor_extension_id.empty()) { | 242 if (!predecessor_extension_id.empty() || !successor_extension_id.empty()) { |
| 232 if (predecessor_extension_id.empty()) { | 243 if (predecessor_extension_id.empty()) { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 if (ext) { | 519 if (ext) { |
| 509 // It is possible for old extension to have ordinal values, but they | 520 // It is possible for old extension to have ordinal values, but they |
| 510 // shouldn't so we clear them. | 521 // shouldn't so we clear them. |
| 511 if (!ext->is_app()) | 522 if (!ext->is_app()) |
| 512 ClearOrdinals(extension_id); | 523 ClearOrdinals(extension_id); |
| 513 | 524 |
| 514 extension_service_->SyncExtensionChangeIfNeeded(*ext); | 525 extension_service_->SyncExtensionChangeIfNeeded(*ext); |
| 515 } | 526 } |
| 516 } | 527 } |
| 517 } | 528 } |
| 529 | |
| 530 void ExtensionSorting::CreateDefaultOrdinals() { | |
| 531 // The following defines the default order of apps. | |
| 532 #if defined(OS_CHROMEOS) | |
| 533 const char* kDefaultAppOrder[] = { | |
| 534 extension_misc::kChromeAppId, | |
| 535 extension_misc::kWebStoreAppId, | |
| 536 "coobgpohoikkiipiblmjeljniedjpjpf", // Search | |
| 537 "blpcfgokakmgnkcojhhkbfbldkacnbeo", // Youtube | |
| 538 "pjkljhegncpnkpknbcohdijeoejaedia", // Gmail | |
| 539 "ejjicmeblgpmajnghnpcppodonldlgfn", // Calendar | |
| 540 "kjebfhglflhjjjiceimfkgicifkhjlnm", // Scratchpad | |
| 541 "lneaknkopdijkpnocmklfnjbeapigfbh", // Google Maps | |
| 542 "apdfllckaahabafndbhieahigkjlhalf", // Drive | |
| 543 "aohghmighlieiainnegkcijnfilokake", // Docs | |
| 544 "felcaaldnbdncclmgdcncolpebgiejap", // Sheets | |
| 545 "aapocclcgogkmnckokdopfmhonfmgoek", // Slides | |
| 546 "dlppkpafhbajpcmmoheippocdidnckmm", // Google+ | |
| 547 "kbpgddbgniojgndnhlkjbkpknjhppkbk", // Google+ Hangouts | |
| 548 "hhaomjibdihmijegdhdafkllkbggdgoj", // Files | |
| 549 "hkhhlkdconhgemhegnplaldnmnmkaemd", // Tips & Tricks | |
| 550 "icppfcnhkcmnfdhfhphakoifcfokfdhg", // Play Music | |
| 551 "mmimngoggfoobjdlefbcabngfnmieonb", // Play Books | |
| 552 "fppdphmgcddhjeddoeghpjefkdlccljb", // Play Movies | |
| 553 "fobcpibfeplaikcclojfdhfdmbbeofai", // Games | |
| 554 "joodangkbfjnajiiifokapkpmhfnpleo", // Calculator | |
| 555 "cmbmjjimlbmpkonhnfabflhampihgnea", // Camera | |
| 556 "gbchcmhmhahfdphkhkmpfmihenigjmpp", // Chrome Remote Desktop | |
| 557 }; | |
| 558 #else | |
| 559 const char* kDefaultAppOrder[] = { | |
| 560 extension_misc::kWebStoreAppId, | |
| 561 }; | |
| 562 #endif | |
| 563 | |
| 564 syncer::StringOrdinal page_ordinal = CreateFirstAppPageOrdinal(); | |
| 565 syncer::StringOrdinal app_launch_ordinal = | |
| 566 CreateFirstAppLaunchOrdinal(page_ordinal); | |
| 567 for (size_t i = 0; i < arraysize(kDefaultAppOrder); ++i) { | |
| 568 const std::string extension_id = kDefaultAppOrder[i]; | |
| 569 default_ordinals_[extension_id].page_ordinal = page_ordinal; | |
| 570 default_ordinals_[extension_id].app_launch_ordinal = app_launch_ordinal; | |
| 571 app_launch_ordinal = app_launch_ordinal.CreateAfter(); | |
| 572 } | |
| 573 } | |
| 574 | |
| 575 bool ExtensionSorting::GetDefaultOrdinals( | |
| 576 const std::string& extension_id, | |
| 577 syncer::StringOrdinal* page_ordinal, | |
| 578 syncer::StringOrdinal* app_launch_ordinal) const { | |
| 579 AppOrdinalsMap::const_iterator it = default_ordinals_.find(extension_id); | |
| 580 if (it == default_ordinals_.end()) | |
| 581 return false; | |
| 582 | |
| 583 if (page_ordinal) | |
| 584 *page_ordinal = it->second.page_ordinal; | |
| 585 if (app_launch_ordinal) | |
| 586 *app_launch_ordinal = it->second.app_launch_ordinal; | |
| 587 return true; | |
| 588 } | |
| 589 | |
| 590 syncer::StringOrdinal ExtensionSorting::ResolveCollision( | |
| 591 const syncer::StringOrdinal& page_ordinal, | |
| 592 const syncer::StringOrdinal& app_launch_ordinal) const { | |
| 593 DCHECK(page_ordinal.IsValid() && app_launch_ordinal.IsValid()); | |
| 594 | |
| 595 PageOrdinalMap::const_iterator page_it = ntp_ordinal_map_.find(page_ordinal); | |
| 596 if (page_it == ntp_ordinal_map_.end()) | |
| 597 return app_launch_ordinal; | |
| 598 | |
| 599 const AppLaunchOrdinalMap& page = page_it->second; | |
| 600 if (page.find(app_launch_ordinal) == page.end()) | |
| 601 return app_launch_ordinal; | |
| 602 | |
| 603 syncer::StringOrdinal next_ordinal = app_launch_ordinal.CreateAfter(); | |
|
csharp
2012/09/24 14:09:45
I think this section should be replaced by:
return
xiyuan
2012/09/24 16:37:12
Done. Good call. This is much better than using a
| |
| 604 while (page.find(next_ordinal) != page.end()) | |
| 605 next_ordinal = app_launch_ordinal.CreateBetween(next_ordinal); | |
| 606 | |
| 607 return next_ordinal; | |
| 608 } | |
| 609 | |
| OLD | NEW |