Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: chrome/browser/ui/ash/chrome_launcher_prefs.cc

Issue 2416133002: Implement local storage for App List in case app sync is off. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/ui/ash/chrome_launcher_prefs.h" 5 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <set> 9 #include <set>
10 10
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/browser/app_mode/app_mode_utils.h" 14 #include "chrome/browser/app_mode/app_mode_utils.h"
15 #include "chrome/browser/chromeos/arc/arc_auth_service.h" 15 #include "chrome/browser/chromeos/arc/arc_auth_service.h"
16 #include "chrome/browser/chromeos/arc/arc_support_host.h" 16 #include "chrome/browser/chromeos/arc/arc_support_host.h"
17 #include "chrome/browser/prefs/pref_service_syncable_util.h" 17 #include "chrome/browser/prefs/pref_service_syncable_util.h"
18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/app_list/app_list_syncable_service.h" 19 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
19 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" 20 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
20 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" 21 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
21 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h" 22 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h"
22 #include "chrome/common/extensions/extension_constants.h" 23 #include "chrome/common/extensions/extension_constants.h"
23 #include "chrome/common/pref_names.h" 24 #include "chrome/common/pref_names.h"
24 #include "components/pref_registry/pref_registry_syncable.h" 25 #include "components/pref_registry/pref_registry_syncable.h"
25 #include "components/prefs/pref_service.h" 26 #include "components/prefs/pref_service.h"
26 #include "components/prefs/scoped_user_pref_update.h" 27 #include "components/prefs/scoped_user_pref_update.h"
27 #include "components/sync/model/string_ordinal.h" 28 #include "components/sync/model/string_ordinal.h"
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 MaybeAddApp(app_id, helper); 264 MaybeAddApp(app_id, helper);
264 } 265 }
265 266
266 const std::vector<std::string>& app_list() const { return app_list_; } 267 const std::vector<std::string>& app_list() const { return app_list_; }
267 268
268 private: 269 private:
269 std::vector<std::string> app_list_; 270 std::vector<std::string> app_list_;
270 std::set<std::string> app_set_; 271 std::set<std::string> app_set_;
271 }; 272 };
272 273
274 // If sync is running then return position from sync service, otherwise use
275 // local copy.
276 syncer::StringOrdinal GetPinPosition(
277 app_list::AppListSyncableService* app_service,
278 const std::string& app_id) {
279 DCHECK(app_service);
280 if (app_service->is_active())
281 return app_service->GetPinPosition(app_id);
282
283 const base::DictionaryValue* apps =
284 app_service->profile()->GetPrefs()->GetDictionary(prefs::kShelfPins);
285 DCHECK(apps);
286 std::string position_string;
287 if (!apps->GetString(app_id, &position_string))
288 return syncer::StringOrdinal();
289
290 const syncer::StringOrdinal position(position_string);
291 if (!position.IsValid()) {
292 LOG(ERROR) << "Found wrong pin position " << position_string
293 << " in local copy for " << app_id;
294 return syncer::StringOrdinal();
295 }
296
297 return position;
298 }
299
273 } // namespace 300 } // namespace
274 301
275 const char kPinnedAppsPrefAppIDPath[] = "id"; 302 const char kPinnedAppsPrefAppIDPath[] = "id";
276 const char kPinnedAppsPrefPinnedByPolicy[] = "pinned_by_policy"; 303 const char kPinnedAppsPrefPinnedByPolicy[] = "pinned_by_policy";
277 const char kPinnedAppsPlaceholder[] = "AppShelfIDPlaceholder--------"; 304 const char kPinnedAppsPlaceholder[] = "AppShelfIDPlaceholder--------";
278 305
279 const char kShelfAutoHideBehaviorAlways[] = "Always"; 306 const char kShelfAutoHideBehaviorAlways[] = "Always";
280 const char kShelfAutoHideBehaviorNever[] = "Never"; 307 const char kShelfAutoHideBehaviorNever[] = "Never";
281 308
282 const char kShelfAlignmentBottom[] = "Bottom"; 309 const char kShelfAlignmentBottom[] = "Bottom";
(...skipping 17 matching lines...) Expand all
300 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 327 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
301 registry->RegisterStringPref(prefs::kShelfAutoHideBehaviorLocal, 328 registry->RegisterStringPref(prefs::kShelfAutoHideBehaviorLocal,
302 std::string()); 329 std::string());
303 registry->RegisterStringPref(prefs::kShelfAlignment, 330 registry->RegisterStringPref(prefs::kShelfAlignment,
304 kShelfAlignmentBottom, 331 kShelfAlignmentBottom,
305 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 332 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
306 registry->RegisterStringPref(prefs::kShelfAlignmentLocal, std::string()); 333 registry->RegisterStringPref(prefs::kShelfAlignmentLocal, std::string());
307 registry->RegisterDictionaryPref(prefs::kShelfPreferences); 334 registry->RegisterDictionaryPref(prefs::kShelfPreferences);
308 registry->RegisterIntegerPref(prefs::kLogoutDialogDurationMs, 20000); 335 registry->RegisterIntegerPref(prefs::kLogoutDialogDurationMs, 20000);
309 registry->RegisterBooleanPref(prefs::kShowLogoutButtonInTray, false); 336 registry->RegisterBooleanPref(prefs::kShowLogoutButtonInTray, false);
337 registry->RegisterDictionaryPref(prefs::kShelfPins);
310 } 338 }
311 339
312 base::DictionaryValue* CreateAppDict(const std::string& app_id) { 340 base::DictionaryValue* CreateAppDict(const std::string& app_id) {
313 std::unique_ptr<base::DictionaryValue> app_value(new base::DictionaryValue); 341 std::unique_ptr<base::DictionaryValue> app_value(new base::DictionaryValue);
314 app_value->SetString(kPinnedAppsPrefAppIDPath, app_id); 342 app_value->SetString(kPinnedAppsPrefAppIDPath, app_id);
315 return app_value.release(); 343 return app_value.release();
316 } 344 }
317 345
318 ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs, 346 ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs,
319 int64_t display_id) { 347 int64_t display_id) {
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 const PrefService* prefs, 564 const PrefService* prefs,
537 LauncherControllerHelper* helper, 565 LauncherControllerHelper* helper,
538 const AppTracker& policy_apps) { 566 const AppTracker& policy_apps) {
539 std::vector<std::string> legacy_pins = 567 std::vector<std::string> legacy_pins =
540 GetPinnedAppsFromPrefsLegacy(prefs, helper); 568 GetPinnedAppsFromPrefsLegacy(prefs, helper);
541 DCHECK(!legacy_pins.empty()); 569 DCHECK(!legacy_pins.empty());
542 570
543 app_list::AppListSyncableService* app_service = 571 app_list::AppListSyncableService* app_service =
544 app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile()); 572 app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile());
545 573
574 // Update pin info in local copy in order to keep it up to date.
575 DictionaryPrefUpdate pref_update(helper->profile()->GetPrefs(),
576 prefs::kShelfPins);
577
546 syncer::StringOrdinal last_position = 578 syncer::StringOrdinal last_position =
547 syncer::StringOrdinal::CreateInitialOrdinal(); 579 syncer::StringOrdinal::CreateInitialOrdinal();
548 // Convert to sync item record. 580 // Convert to sync item record.
549 for (const auto& app_id : legacy_pins) { 581 for (const auto& app_id : legacy_pins) {
550 DCHECK_NE(kPinnedAppsPlaceholder, app_id); 582 DCHECK_NE(kPinnedAppsPlaceholder, app_id);
551 app_service->SetPinPosition(app_id, last_position); 583 app_service->SetPinPosition(app_id, last_position);
584 pref_update->SetString(app_id, last_position.ToInternalValue());
552 last_position = last_position.CreateAfter(); 585 last_position = last_position.CreateAfter();
553 } 586 }
554 587
555 // Now process default apps. 588 // Now process default apps.
556 for (size_t i = 0; i < arraysize(kDefaultPinnedApps); ++i) { 589 for (size_t i = 0; i < arraysize(kDefaultPinnedApps); ++i) {
557 const std::string& app_id = kDefaultPinnedApps[i]; 590 const std::string& app_id = kDefaultPinnedApps[i];
558 // Check if it is already imported. 591 // Check if it is already imported.
559 if (app_service->GetPinPosition(app_id).IsValid()) 592 if (GetPinPosition(app_service, app_id).IsValid())
560 continue; 593 continue;
561 // Check if it is present but not in legacy pin. 594 // Check if it is present but not in legacy pin.
562 if (helper->IsValidIDForCurrentUser(app_id)) 595 if (helper->IsValidIDForCurrentUser(app_id))
563 continue; 596 continue;
564 app_service->SetPinPosition(app_id, last_position); 597 app_service->SetPinPosition(app_id, last_position);
598 pref_update->SetString(app_id, last_position.ToInternalValue());
565 last_position = last_position.CreateAfter(); 599 last_position = last_position.CreateAfter();
566 } 600 }
567 601
568 return legacy_pins; 602 return legacy_pins;
569 } 603 }
570 604
605 void SavePinnedAppsInLocalCopy(Profile* profile,
606 const std::vector<PinInfo>& pins) {
607 DictionaryPrefUpdate pref_update(profile->GetPrefs(), prefs::kShelfPins);
608 pref_update->Clear();
609 for (const auto pin : pins) {
610 pref_update->SetString(pin.app_id, pin.item_ordinal.ToInternalValue());
611 }
612 }
613
571 std::vector<std::string> GetPinnedAppsFromPrefs( 614 std::vector<std::string> GetPinnedAppsFromPrefs(
572 const PrefService* prefs, 615 const PrefService* prefs,
573 LauncherControllerHelper* helper) { 616 LauncherControllerHelper* helper) {
574 app_list::AppListSyncableService* app_service = 617 app_list::AppListSyncableService* app_service =
575 app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile()); 618 app_list::AppListSyncableServiceFactory::GetForProfile(helper->profile());
576 // Some unit tests may not have it. 619 // Some unit tests may not have it.
577 if (!app_service) 620 if (!app_service)
578 return std::vector<std::string>(); 621 return std::vector<std::string>();
579 622
580 std::vector<PinInfo> pin_infos; 623 std::vector<PinInfo> pin_infos;
581 624
582 AppTracker policy_apps; 625 AppTracker policy_apps;
583 GetAppsPinnedByPolicy(prefs, helper, &policy_apps); 626 GetAppsPinnedByPolicy(prefs, helper, &policy_apps);
584 627
628 const base::DictionaryValue* apps_in_local_copy =
629 helper->profile()->GetPrefs()->GetDictionary(prefs::kShelfPins);
630 DCHECK(apps_in_local_copy);
631
585 // Empty pins indicates that sync based pin model is used for the first 632 // Empty pins indicates that sync based pin model is used for the first
586 // time. In normal workflow we have at least Chrome browser pin info. 633 // time. In normal workflow we have at least Chrome browser pin info.
587 bool first_run = true; 634 // In case sync is not started, first run is detected by absence of local
635 // pins copy.
636 bool first_run = apps_in_local_copy->empty();
588 637
589 for (const auto& sync_peer : app_service->sync_items()) { 638 if (app_service->is_active()) {
590 if (!sync_peer.second->item_pin_ordinal.IsValid()) 639 for (const auto& sync_peer : app_service->sync_items()) {
591 continue; 640 if (!sync_peer.second->item_pin_ordinal.IsValid())
641 continue;
592 642
593 first_run = false; 643 first_run = false;
594 // Don't include apps that currently do not exist on device. 644 // Don't include apps that currently do not exist on device.
595 if (sync_peer.first != extension_misc::kChromeAppId && 645 if (sync_peer.first != extension_misc::kChromeAppId &&
596 !helper->IsValidIDForCurrentUser(sync_peer.first)) { 646 !helper->IsValidIDForCurrentUser(sync_peer.first)) {
597 continue; 647 continue;
648 }
649
650 pin_infos.push_back(
651 PinInfo(sync_peer.first, sync_peer.second->item_pin_ordinal));
598 } 652 }
653 } else {
654 // If sync is not active, use information from local copy.
655 for (base::DictionaryValue::Iterator app(*apps_in_local_copy);
656 !app.IsAtEnd(); app.Advance()) {
657 // Don't include apps that currently do not exist on device.
658 if (app.key() != extension_misc::kChromeAppId &&
659 !helper->IsValidIDForCurrentUser(app.key())) {
660 continue;
661 }
599 662
600 pin_infos.push_back( 663 std::string position_string;
601 PinInfo(sync_peer.first, sync_peer.second->item_pin_ordinal)); 664 app.value().GetAsString(&position_string);
665 const syncer::StringOrdinal position(position_string);
666 if (!position.IsValid()) {
667 NOTREACHED();
668 continue;
669 }
stevenjb 2016/10/14 20:27:25 This should just be: DCHECK(position.IsValid());
khmel 2016/10/17 21:10:57 Yes, I agree with your point of view, thanks for e
670
671 pin_infos.push_back(PinInfo(app.key(), position));
672 }
602 } 673 }
603 674
604 if (first_run) { 675 if (first_run) {
605 // We need to import legacy pins model and convert it to sync based 676 // We need to import legacy pins model and convert it to sync based
606 // model. 677 // model.
607 return ImportLegacyPinnedApps(prefs, helper, policy_apps); 678 return ImportLegacyPinnedApps(prefs, helper, policy_apps);
608 } 679 }
609 680
610 // Sort pins according their ordinals. 681 // Sort pins according their ordinals.
611 std::sort(pin_infos.begin(), pin_infos.end(), ComparePinInfo()); 682 std::sort(pin_infos.begin(), pin_infos.end(), ComparePinInfo());
612 683
613 // Pinned by policy apps appear first, if they were not shown before. 684 // Pinned by policy apps appear first, if they were not shown before.
614 syncer::StringOrdinal front_position = GetFirstPinPosition(helper->profile()); 685 syncer::StringOrdinal front_position = GetFirstPinPosition(helper->profile());
615 std::vector<std::string>::const_reverse_iterator it; 686 std::vector<std::string>::const_reverse_iterator it;
616 for (it = policy_apps.app_list().rbegin(); 687 for (it = policy_apps.app_list().rbegin();
617 it != policy_apps.app_list().rend(); ++it) { 688 it != policy_apps.app_list().rend(); ++it) {
618 const std::string& app_id = *it; 689 const std::string& app_id = *it;
619 if (app_id == kPinnedAppsPlaceholder) 690 if (app_id == kPinnedAppsPlaceholder)
620 continue; 691 continue;
621 692
622 // Check if we already processed current app. 693 // Check if we already processed current app.
623 if (app_service->GetPinPosition(app_id).IsValid()) 694 if (GetPinPosition(app_service, app_id).IsValid())
624 continue; 695 continue;
625 696
626 // Now move it to the front. 697 // Now move it to the front.
627 pin_infos.insert(pin_infos.begin(), PinInfo(app_id, front_position)); 698 pin_infos.insert(pin_infos.begin(), PinInfo(app_id, front_position));
628 app_service->SetPinPosition(app_id, front_position); 699 app_service->SetPinPosition(app_id, front_position);
629 front_position = front_position.CreateBefore(); 700 front_position = front_position.CreateBefore();
630 } 701 }
631 702
632 // Now insert Chrome browser app if needed. 703 // Now insert Chrome browser app if needed.
633 if (!app_service->GetPinPosition(extension_misc::kChromeAppId).IsValid()) { 704 if (!GetPinPosition(app_service, extension_misc::kChromeAppId).IsValid()) {
634 pin_infos.insert(pin_infos.begin(), 705 pin_infos.insert(pin_infos.begin(),
635 PinInfo(extension_misc::kChromeAppId, front_position)); 706 PinInfo(extension_misc::kChromeAppId, front_position));
636 app_service->SetPinPosition(extension_misc::kChromeAppId, front_position); 707 app_service->SetPinPosition(extension_misc::kChromeAppId, front_position);
637 } 708 }
638 709
639 if (helper->IsValidIDForCurrentUser(ArcSupportHost::kHostAppId)) { 710 if (helper->IsValidIDForCurrentUser(ArcSupportHost::kHostAppId)) {
640 if (!app_service->GetSyncItem(ArcSupportHost::kHostAppId)) { 711 // TODO(khmel) Find the better way to initial pin PlayStore item when sync
712 // is off.
stevenjb 2016/10/14 20:27:24 'find a way' ? It looks like we currently don't ha
khmel 2016/10/17 21:10:57 With new approach this is not required.
713 if (app_service->is_active() &&
714 !app_service->GetSyncItem(ArcSupportHost::kHostAppId)) {
641 const syncer::StringOrdinal arc_host_position = 715 const syncer::StringOrdinal arc_host_position =
642 GetLastPinPosition(helper->profile()); 716 GetLastPinPosition(helper->profile());
643 pin_infos.insert(pin_infos.begin(), 717 pin_infos.insert(pin_infos.begin(),
644 PinInfo(ArcSupportHost::kHostAppId, arc_host_position)); 718 PinInfo(ArcSupportHost::kHostAppId, arc_host_position));
645 app_service->SetPinPosition(ArcSupportHost::kHostAppId, 719 app_service->SetPinPosition(ArcSupportHost::kHostAppId,
646 arc_host_position); 720 arc_host_position);
647 } 721 }
648 } 722 }
649 723
650 // Convert to string array. 724 // Convert to string array.
651 std::vector<std::string> pins(pin_infos.size()); 725 std::vector<std::string> pins(pin_infos.size());
652 for (size_t i = 0; i < pin_infos.size(); ++i) 726 for (size_t i = 0; i < pin_infos.size(); ++i)
653 pins[i] = pin_infos[i].app_id; 727 pins[i] = pin_infos[i].app_id;
654 728
729 // Sync current pins with local copy if required.
730 if (app_service->is_active())
731 SavePinnedAppsInLocalCopy(helper->profile(), pin_infos);
732
655 return pins; 733 return pins;
656 } 734 }
657 735
658 void RemovePinPosition(Profile* profile, const std::string& app_id) { 736 void RemovePinPosition(Profile* profile, const std::string& app_id) {
659 DCHECK(profile); 737 DCHECK(profile);
660 DCHECK(!app_id.empty()); 738 DCHECK(!app_id.empty());
739
740 // Remove pin info from local copy in order to keep it up to date.
741 DictionaryPrefUpdate pref_update(profile->GetPrefs(), prefs::kShelfPins);
742 pref_update->Remove(app_id, nullptr);
743
661 app_list::AppListSyncableService* app_service = 744 app_list::AppListSyncableService* app_service =
662 app_list::AppListSyncableServiceFactory::GetForProfile(profile); 745 app_list::AppListSyncableServiceFactory::GetForProfile(profile);
663 app_service->SetPinPosition(app_id, syncer::StringOrdinal()); 746 app_service->SetPinPosition(app_id, syncer::StringOrdinal());
664 } 747 }
665 748
666 void SetPinPosition(Profile* profile, 749 void SetPinPosition(Profile* profile,
667 const std::string& app_id, 750 const std::string& app_id,
668 const std::string& app_id_before, 751 const std::string& app_id_before,
669 const std::vector<std::string>& app_ids_after) { 752 const std::vector<std::string>& app_ids_after) {
670 DCHECK(profile); 753 DCHECK(profile);
671 DCHECK(!app_id.empty()); 754 DCHECK(!app_id.empty());
672 DCHECK_NE(app_id, app_id_before); 755 DCHECK_NE(app_id, app_id_before);
673 756
674 app_list::AppListSyncableService* app_service = 757 app_list::AppListSyncableService* app_service =
675 app_list::AppListSyncableServiceFactory::GetForProfile(profile); 758 app_list::AppListSyncableServiceFactory::GetForProfile(profile);
676 // Some unit tests may not have this service. 759 // Some unit tests may not have this service.
677 if (!app_service) 760 if (!app_service)
678 return; 761 return;
679 762
680 syncer::StringOrdinal position_before = 763 syncer::StringOrdinal position_before =
681 app_id_before.empty() ? syncer::StringOrdinal() 764 app_id_before.empty() ? syncer::StringOrdinal()
682 : app_service->GetPinPosition(app_id_before); 765 : GetPinPosition(app_service, app_id_before);
683 syncer::StringOrdinal position_after; 766 syncer::StringOrdinal position_after;
684 for (const auto& app_id_after : app_ids_after) { 767 for (const auto& app_id_after : app_ids_after) {
685 DCHECK_NE(app_id_after, app_id); 768 DCHECK_NE(app_id_after, app_id);
686 DCHECK_NE(app_id_after, app_id_before); 769 DCHECK_NE(app_id_after, app_id_before);
687 syncer::StringOrdinal position = app_service->GetPinPosition(app_id_after); 770 syncer::StringOrdinal position = GetPinPosition(app_service, app_id_after);
688 DCHECK(position.IsValid()); 771 DCHECK(position.IsValid());
689 if (!position.IsValid()) { 772 if (!position.IsValid()) {
690 LOG(ERROR) << "Sync pin position was not found for " << app_id_after; 773 LOG(ERROR) << "Sync pin position was not found for " << app_id_after;
691 continue; 774 continue;
692 } 775 }
693 if (!position_before.IsValid() || !position.Equals(position_before)) { 776 if (!position_before.IsValid() || !position.Equals(position_before)) {
694 position_after = position; 777 position_after = position;
695 break; 778 break;
696 } 779 }
697 } 780 }
698 781
699 syncer::StringOrdinal pin_position; 782 syncer::StringOrdinal pin_position;
700 if (position_before.IsValid() && position_after.IsValid()) 783 if (position_before.IsValid() && position_after.IsValid())
701 pin_position = position_before.CreateBetween(position_after); 784 pin_position = position_before.CreateBetween(position_after);
702 else if (position_before.IsValid()) 785 else if (position_before.IsValid())
703 pin_position = position_before.CreateAfter(); 786 pin_position = position_before.CreateAfter();
704 else if (position_after.IsValid()) 787 else if (position_after.IsValid())
705 pin_position = position_after.CreateBefore(); 788 pin_position = position_after.CreateBefore();
706 else 789 else
707 pin_position = syncer::StringOrdinal::CreateInitialOrdinal(); 790 pin_position = syncer::StringOrdinal::CreateInitialOrdinal();
791
792 // Update pin info in local copy in order to keep it up to date.
793 DictionaryPrefUpdate pref_update(profile->GetPrefs(), prefs::kShelfPins);
794 pref_update->SetString(app_id, pin_position.ToInternalValue());
795
708 app_service->SetPinPosition(app_id, pin_position); 796 app_service->SetPinPosition(app_id, pin_position);
709 } 797 }
710 798
711 } // namespace launcher 799 } // namespace launcher
712 } // namespace ash 800 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698