Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/app_list/app_list_syncable_service.h" | 5 #include "chrome/browser/ui/app_list/app_list_syncable_service.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "build/build_config.h" | 12 #include "build/build_config.h" |
| 13 #include "chrome/browser/apps/drive/drive_app_provider.h" | 13 #include "chrome/browser/apps/drive/drive_app_provider.h" |
| 14 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/browser/ui/app_list/app_list_prefs.h" | 16 #include "chrome/browser/ui/app_list/app_list_prefs.h" |
| 17 #include "chrome/browser/ui/app_list/app_list_service.h" | 17 #include "chrome/browser/ui/app_list/app_list_service.h" |
| 18 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" | |
| 18 #include "chrome/browser/ui/app_list/extension_app_item.h" | 19 #include "chrome/browser/ui/app_list/extension_app_item.h" |
| 19 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" | 20 #include "chrome/browser/ui/app_list/extension_app_model_builder.h" |
| 20 #include "chrome/browser/ui/app_list/model_pref_updater.h" | 21 #include "chrome/browser/ui/app_list/model_pref_updater.h" |
| 21 #include "chrome/common/chrome_switches.h" | 22 #include "chrome/common/chrome_switches.h" |
| 22 #include "chrome/common/extensions/extension_constants.h" | 23 #include "chrome/common/extensions/extension_constants.h" |
| 23 #include "chrome/grit/generated_resources.h" | 24 #include "chrome/grit/generated_resources.h" |
| 24 #include "extensions/browser/extension_prefs.h" | 25 #include "extensions/browser/extension_prefs.h" |
| 25 #include "extensions/browser/extension_system.h" | 26 #include "extensions/browser/extension_system.h" |
| 26 #include "extensions/browser/uninstall_reason.h" | 27 #include "extensions/browser/uninstall_reason.h" |
| 27 #include "extensions/common/constants.h" | 28 #include "extensions/common/constants.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 59 const char kDriveAppSyncIdPrefix[] = "drive-app-"; | 60 const char kDriveAppSyncIdPrefix[] = "drive-app-"; |
| 60 | 61 |
| 61 void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics, | 62 void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics, |
| 62 AppListSyncableService::SyncItem* item) { | 63 AppListSyncableService::SyncItem* item) { |
| 63 DCHECK_EQ(item->item_id, specifics.item_id()); | 64 DCHECK_EQ(item->item_id, specifics.item_id()); |
| 64 item->item_type = specifics.item_type(); | 65 item->item_type = specifics.item_type(); |
| 65 item->item_name = specifics.item_name(); | 66 item->item_name = specifics.item_name(); |
| 66 item->parent_id = specifics.parent_id(); | 67 item->parent_id = specifics.parent_id(); |
| 67 if (!specifics.item_ordinal().empty()) | 68 if (!specifics.item_ordinal().empty()) |
| 68 item->item_ordinal = syncer::StringOrdinal(specifics.item_ordinal()); | 69 item->item_ordinal = syncer::StringOrdinal(specifics.item_ordinal()); |
| 70 item->item_pin_ordinal = syncer::StringOrdinal(specifics.item_pin_ordinal()); | |
| 71 item->item_pin_by_policy = specifics.item_pin_by_policy(); | |
| 69 } | 72 } |
| 70 | 73 |
| 71 bool UpdateSyncItemFromAppItem(const AppListItem* app_item, | 74 bool UpdateSyncItemFromAppItem(const AppListItem* app_item, |
| 72 AppListSyncableService::SyncItem* sync_item) { | 75 AppListSyncableService::SyncItem* sync_item) { |
| 73 DCHECK_EQ(sync_item->item_id, app_item->id()); | 76 DCHECK_EQ(sync_item->item_id, app_item->id()); |
| 74 bool changed = false; | 77 bool changed = false; |
| 75 if (app_list::switches::IsFolderUIEnabled() && | 78 if (app_list::switches::IsFolderUIEnabled() && |
| 76 sync_item->parent_id != app_item->folder_id()) { | 79 sync_item->parent_id != app_item->folder_id()) { |
| 77 sync_item->parent_id = app_item->folder_id(); | 80 sync_item->parent_id = app_item->folder_id(); |
| 78 changed = true; | 81 changed = true; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 91 | 94 |
| 92 void GetSyncSpecificsFromSyncItem(const AppListSyncableService::SyncItem* item, | 95 void GetSyncSpecificsFromSyncItem(const AppListSyncableService::SyncItem* item, |
| 93 sync_pb::AppListSpecifics* specifics) { | 96 sync_pb::AppListSpecifics* specifics) { |
| 94 DCHECK(specifics); | 97 DCHECK(specifics); |
| 95 specifics->set_item_id(item->item_id); | 98 specifics->set_item_id(item->item_id); |
| 96 specifics->set_item_type(item->item_type); | 99 specifics->set_item_type(item->item_type); |
| 97 specifics->set_item_name(item->item_name); | 100 specifics->set_item_name(item->item_name); |
| 98 specifics->set_parent_id(item->parent_id); | 101 specifics->set_parent_id(item->parent_id); |
| 99 if (item->item_ordinal.IsValid()) | 102 if (item->item_ordinal.IsValid()) |
| 100 specifics->set_item_ordinal(item->item_ordinal.ToInternalValue()); | 103 specifics->set_item_ordinal(item->item_ordinal.ToInternalValue()); |
| 104 specifics->set_item_pin_ordinal(item->item_pin_ordinal.IsValid() ? | |
| 105 item->item_pin_ordinal.ToInternalValue() : std::string()); | |
|
stevenjb
2016/06/10 18:00:40
We should modify the logic lines 102/103 to match
khmel
2016/06/10 22:08:10
Done.
| |
| 106 specifics->set_item_pin_by_policy(item->item_pin_by_policy); | |
| 101 } | 107 } |
| 102 | 108 |
| 103 syncer::SyncData GetSyncDataFromSyncItem( | 109 syncer::SyncData GetSyncDataFromSyncItem( |
| 104 const AppListSyncableService::SyncItem* item) { | 110 const AppListSyncableService::SyncItem* item) { |
| 105 sync_pb::EntitySpecifics specifics; | 111 sync_pb::EntitySpecifics specifics; |
| 106 GetSyncSpecificsFromSyncItem(item, specifics.mutable_app_list()); | 112 GetSyncSpecificsFromSyncItem(item, specifics.mutable_app_list()); |
| 107 return syncer::SyncData::CreateLocalData(item->item_id, | 113 return syncer::SyncData::CreateLocalData(item->item_id, |
| 108 item->item_id, | 114 item->item_id, |
| 109 specifics); | 115 specifics); |
| 110 } | 116 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 } | 172 } |
| 167 | 173 |
| 168 } // namespace | 174 } // namespace |
| 169 | 175 |
| 170 // AppListSyncableService::SyncItem | 176 // AppListSyncableService::SyncItem |
| 171 | 177 |
| 172 AppListSyncableService::SyncItem::SyncItem( | 178 AppListSyncableService::SyncItem::SyncItem( |
| 173 const std::string& id, | 179 const std::string& id, |
| 174 sync_pb::AppListSpecifics::AppListItemType type) | 180 sync_pb::AppListSpecifics::AppListItemType type) |
| 175 : item_id(id), | 181 : item_id(id), |
| 176 item_type(type) { | 182 item_type(type), |
| 183 item_pin_by_policy(false) { | |
| 177 } | 184 } |
| 178 | 185 |
| 179 AppListSyncableService::SyncItem::~SyncItem() { | 186 AppListSyncableService::SyncItem::~SyncItem() { |
| 180 } | 187 } |
| 181 | 188 |
| 182 // AppListSyncableService::ModelObserver | 189 // AppListSyncableService::ModelObserver |
| 183 | 190 |
| 184 class AppListSyncableService::ModelObserver : public AppListModelObserver { | 191 class AppListSyncableService::ModelObserver : public AppListModelObserver { |
| 185 public: | 192 public: |
| 186 explicit ModelObserver(AppListSyncableService* owner) | 193 explicit ModelObserver(AppListSyncableService* owner) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 } | 235 } |
| 229 | 236 |
| 230 AppListSyncableService* owner_; | 237 AppListSyncableService* owner_; |
| 231 AppListItem* adding_item_; // Unowned pointer to item being added. | 238 AppListItem* adding_item_; // Unowned pointer to item being added. |
| 232 | 239 |
| 233 DISALLOW_COPY_AND_ASSIGN(ModelObserver); | 240 DISALLOW_COPY_AND_ASSIGN(ModelObserver); |
| 234 }; | 241 }; |
| 235 | 242 |
| 236 // AppListSyncableService | 243 // AppListSyncableService |
| 237 | 244 |
| 245 // static | |
| 246 AppListSyncableService* AppListSyncableService::Get(Profile* profile) { | |
| 247 return AppListSyncableServiceFactory::GetForProfile(profile); | |
| 248 } | |
|
stevenjb
2016/06/10 18:00:40
This is unnecessary, we should just use AppListSyn
khmel
2016/06/10 22:08:10
Sorry, I just added this helper similar to some ot
stevenjb
2016/06/14 22:44:08
It's not inherently wrong, but we do try to go by
| |
| 249 | |
| 238 AppListSyncableService::AppListSyncableService( | 250 AppListSyncableService::AppListSyncableService( |
| 239 Profile* profile, | 251 Profile* profile, |
| 240 extensions::ExtensionSystem* extension_system) | 252 extensions::ExtensionSystem* extension_system) |
| 241 : profile_(profile), | 253 : profile_(profile), |
| 242 extension_system_(extension_system), | 254 extension_system_(extension_system), |
| 243 model_(new AppListModel), | 255 model_(new AppListModel), |
| 244 initial_sync_data_processed_(false), | 256 initial_sync_data_processed_(false), |
| 245 first_app_list_sync_(true) { | 257 first_app_list_sync_(true) { |
| 246 if (!extension_system) { | 258 if (!extension_system) { |
| 247 LOG(ERROR) << "AppListSyncableService created with no ExtensionSystem"; | 259 LOG(ERROR) << "AppListSyncableService created with no ExtensionSystem"; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 #endif | 303 #endif |
| 292 } | 304 } |
| 293 | 305 |
| 294 model_pref_updater_.reset( | 306 model_pref_updater_.reset( |
| 295 new ModelPrefUpdater(AppListPrefs::Get(profile_), model_.get())); | 307 new ModelPrefUpdater(AppListPrefs::Get(profile_), model_.get())); |
| 296 | 308 |
| 297 if (app_list::switches::IsDriveAppsInAppListEnabled()) | 309 if (app_list::switches::IsDriveAppsInAppListEnabled()) |
| 298 drive_app_provider_.reset(new DriveAppProvider(profile_, this)); | 310 drive_app_provider_.reset(new DriveAppProvider(profile_, this)); |
| 299 } | 311 } |
| 300 | 312 |
| 313 void AppListSyncableService::AddObserverAndStart(Observer* observer) { | |
| 314 observer_list_.AddObserver(observer); | |
| 315 SyncStarted(); | |
| 316 } | |
| 317 | |
| 318 void AppListSyncableService::RemoveObserver(Observer* observer) { | |
| 319 observer_list_.RemoveObserver(observer); | |
| 320 } | |
| 321 | |
| 322 void AppListSyncableService::NotifyObserversSyncUpdated() { | |
| 323 FOR_EACH_OBSERVER(Observer, observer_list_, OnSyncModelUpdated()); | |
| 324 } | |
| 325 | |
| 301 size_t AppListSyncableService::GetNumSyncItemsForTest() { | 326 size_t AppListSyncableService::GetNumSyncItemsForTest() { |
| 302 // If the model isn't built yet, there will be no sync items. | 327 // If the model isn't built yet, there will be no sync items. |
| 303 GetModel(); | 328 GetModel(); |
| 304 | 329 |
| 305 return sync_items_.size(); | 330 return sync_items_.size(); |
| 306 } | 331 } |
| 307 | 332 |
| 308 void AppListSyncableService::ResetDriveAppProviderForTest() { | 333 void AppListSyncableService::ResetDriveAppProviderForTest() { |
| 309 drive_app_provider_.reset(); | 334 drive_app_provider_.reset(); |
| 310 } | 335 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 415 sync_pb::AppListSpecifics::AppListItemType type; | 440 sync_pb::AppListSpecifics::AppListItemType type; |
| 416 if (!GetAppListItemType(app_item, &type)) | 441 if (!GetAppListItemType(app_item, &type)) |
| 417 return NULL; | 442 return NULL; |
| 418 VLOG(2) << this << " CreateSyncItemFromAppItem:" << app_item->ToDebugString(); | 443 VLOG(2) << this << " CreateSyncItemFromAppItem:" << app_item->ToDebugString(); |
| 419 SyncItem* sync_item = CreateSyncItem(app_item->id(), type); | 444 SyncItem* sync_item = CreateSyncItem(app_item->id(), type); |
| 420 UpdateSyncItemFromAppItem(app_item, sync_item); | 445 UpdateSyncItemFromAppItem(app_item, sync_item); |
| 421 SendSyncChange(sync_item, SyncChange::ACTION_ADD); | 446 SendSyncChange(sync_item, SyncChange::ACTION_ADD); |
| 422 return sync_item; | 447 return sync_item; |
| 423 } | 448 } |
| 424 | 449 |
| 450 bool AppListSyncableService::GetPinByPolicy(const std::string& app_id) { | |
| 451 SyncItem* sync_item = FindSyncItem(app_id); | |
| 452 if (!sync_item) | |
| 453 return false; | |
| 454 return sync_item->item_pin_by_policy; | |
| 455 } | |
| 456 | |
| 457 syncer::StringOrdinal AppListSyncableService::GetPinPosition( | |
| 458 const std::string& app_id) { | |
| 459 SyncItem* sync_item = FindSyncItem(app_id); | |
| 460 if (!sync_item) | |
| 461 return syncer::StringOrdinal(); | |
| 462 return sync_item->item_pin_ordinal; | |
| 463 } | |
| 464 | |
| 465 void AppListSyncableService::SetPinPosition( | |
| 466 const std::string& app_id, | |
| 467 const syncer::StringOrdinal& item_pin_ordinal, | |
| 468 bool pinned_by_policy) { | |
| 469 SyncItem* sync_item = FindSyncItem(app_id); | |
| 470 SyncChange::SyncChangeType sync_change_type; | |
| 471 if (sync_item) { | |
| 472 sync_change_type = SyncChange::ACTION_UPDATE; | |
| 473 } else { | |
| 474 sync_item = CreateSyncItem(app_id, sync_pb::AppListSpecifics::TYPE_APP); | |
| 475 sync_change_type = SyncChange::ACTION_ADD; | |
| 476 } | |
| 477 | |
| 478 sync_item->item_pin_ordinal = item_pin_ordinal; | |
| 479 sync_item->item_pin_by_policy = pinned_by_policy; | |
| 480 SendSyncChange(sync_item, sync_change_type); | |
| 481 } | |
| 482 | |
| 425 void AppListSyncableService::AddOrUpdateFromSyncItem(AppListItem* app_item) { | 483 void AppListSyncableService::AddOrUpdateFromSyncItem(AppListItem* app_item) { |
| 426 // Do not create a sync item for the OEM folder here, do that in | 484 // Do not create a sync item for the OEM folder here, do that in |
| 427 // ResolveFolderPositions once the position has been resolved. | 485 // ResolveFolderPositions once the position has been resolved. |
| 428 if (app_item->id() == kOemFolderId) | 486 if (app_item->id() == kOemFolderId) |
| 429 return; | 487 return; |
| 430 | 488 |
| 431 SyncItem* sync_item = FindSyncItem(app_item->id()); | 489 SyncItem* sync_item = FindSyncItem(app_item->id()); |
| 432 if (sync_item) { | 490 if (sync_item) { |
| 433 UpdateAppItemFromSyncItem(sync_item, app_item); | 491 UpdateAppItemFromSyncItem(sync_item, app_item); |
| 434 return; | 492 return; |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 661 } | 719 } |
| 662 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); | 720 sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); |
| 663 | 721 |
| 664 // Adding items may have created folders without setting their positions | 722 // Adding items may have created folders without setting their positions |
| 665 // since we haven't started observing the item list yet. Resolve those. | 723 // since we haven't started observing the item list yet. Resolve those. |
| 666 ResolveFolderPositions(); | 724 ResolveFolderPositions(); |
| 667 | 725 |
| 668 // Start observing app list model changes. | 726 // Start observing app list model changes. |
| 669 model_observer_.reset(new ModelObserver(this)); | 727 model_observer_.reset(new ModelObserver(this)); |
| 670 | 728 |
| 729 NotifyObserversSyncUpdated(); | |
| 730 | |
| 671 return result; | 731 return result; |
| 672 } | 732 } |
| 673 | 733 |
| 674 void AppListSyncableService::StopSyncing(syncer::ModelType type) { | 734 void AppListSyncableService::StopSyncing(syncer::ModelType type) { |
| 675 DCHECK_EQ(type, syncer::APP_LIST); | 735 DCHECK_EQ(type, syncer::APP_LIST); |
| 676 | 736 |
| 677 sync_processor_.reset(); | 737 sync_processor_.reset(); |
| 678 sync_error_handler_.reset(); | 738 sync_error_handler_.reset(); |
| 679 model_->SetFoldersEnabled(false); | 739 model_->SetFoldersEnabled(false); |
| 680 } | 740 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 719 } else if (change.change_type() == SyncChange::ACTION_DELETE) { | 779 } else if (change.change_type() == SyncChange::ACTION_DELETE) { |
| 720 DeleteSyncItemSpecifics(change.sync_data().GetSpecifics().app_list()); | 780 DeleteSyncItemSpecifics(change.sync_data().GetSpecifics().app_list()); |
| 721 } else { | 781 } else { |
| 722 LOG(ERROR) << "Invalid sync change"; | 782 LOG(ERROR) << "Invalid sync change"; |
| 723 } | 783 } |
| 724 } | 784 } |
| 725 | 785 |
| 726 // Continue observing app list model changes. | 786 // Continue observing app list model changes. |
| 727 model_observer_.reset(new ModelObserver(this)); | 787 model_observer_.reset(new ModelObserver(this)); |
| 728 | 788 |
| 789 NotifyObserversSyncUpdated(); | |
| 790 | |
| 729 return syncer::SyncError(); | 791 return syncer::SyncError(); |
| 730 } | 792 } |
| 731 | 793 |
| 732 // AppListSyncableService private | 794 // AppListSyncableService private |
| 733 | 795 |
| 734 bool AppListSyncableService::ProcessSyncItemSpecifics( | 796 bool AppListSyncableService::ProcessSyncItemSpecifics( |
| 735 const sync_pb::AppListSpecifics& specifics) { | 797 const sync_pb::AppListSpecifics& specifics) { |
| 736 const std::string& item_id = specifics.item_id(); | 798 const std::string& item_id = specifics.item_id(); |
| 737 if (item_id.empty()) { | 799 if (item_id.empty()) { |
| 738 LOG(ERROR) << "AppList item with empty ID"; | 800 LOG(ERROR) << "AppList item with empty ID"; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 827 VLOG(2) << " Moving Item To Folder: " << sync_item->parent_id; | 889 VLOG(2) << " Moving Item To Folder: " << sync_item->parent_id; |
| 828 model_->MoveItemToFolder(app_item, sync_item->parent_id); | 890 model_->MoveItemToFolder(app_item, sync_item->parent_id); |
| 829 } | 891 } |
| 830 UpdateAppItemFromSyncItem(sync_item, app_item); | 892 UpdateAppItemFromSyncItem(sync_item, app_item); |
| 831 } | 893 } |
| 832 | 894 |
| 833 void AppListSyncableService::UpdateAppItemFromSyncItem( | 895 void AppListSyncableService::UpdateAppItemFromSyncItem( |
| 834 const AppListSyncableService::SyncItem* sync_item, | 896 const AppListSyncableService::SyncItem* sync_item, |
| 835 AppListItem* app_item) { | 897 AppListItem* app_item) { |
| 836 VLOG(2) << this << " UpdateAppItemFromSyncItem: " << sync_item->ToString(); | 898 VLOG(2) << this << " UpdateAppItemFromSyncItem: " << sync_item->ToString(); |
| 837 if (!app_item->position().Equals(sync_item->item_ordinal)) | 899 if (sync_item->item_ordinal.IsValid() && |
| 900 !app_item->position().Equals(sync_item->item_ordinal)) | |
| 838 model_->SetItemPosition(app_item, sync_item->item_ordinal); | 901 model_->SetItemPosition(app_item, sync_item->item_ordinal); |
|
stevenjb
2016/06/10 18:00:40
{}
khmel
2016/06/10 22:08:10
Done.
| |
| 839 // Only update the item name if it is a Folder or the name is empty. | 902 // Only update the item name if it is a Folder or the name is empty. |
| 840 if (sync_item->item_name != app_item->name() && | 903 if (sync_item->item_name != app_item->name() && |
| 841 sync_item->item_id != kOemFolderId && | 904 sync_item->item_id != kOemFolderId && |
| 842 (app_item->GetItemType() == AppListFolderItem::kItemType || | 905 (app_item->GetItemType() == AppListFolderItem::kItemType || |
| 843 app_item->name().empty())) { | 906 app_item->name().empty())) { |
| 844 model_->SetItemName(app_item, sync_item->item_name); | 907 model_->SetItemName(app_item, sync_item->item_name); |
| 845 } | 908 } |
| 846 } | 909 } |
| 847 | 910 |
| 848 bool AppListSyncableService::SyncStarted() { | 911 bool AppListSyncableService::SyncStarted() { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1006 | 1069 |
| 1007 std::string AppListSyncableService::SyncItem::ToString() const { | 1070 std::string AppListSyncableService::SyncItem::ToString() const { |
| 1008 std::string res = item_id.substr(0, 8); | 1071 std::string res = item_id.substr(0, 8); |
| 1009 if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { | 1072 if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { |
| 1010 res += " { RemoveDefault }"; | 1073 res += " { RemoveDefault }"; |
| 1011 } else { | 1074 } else { |
| 1012 res += " { " + item_name + " }"; | 1075 res += " { " + item_name + " }"; |
| 1013 res += " [" + item_ordinal.ToDebugString() + "]"; | 1076 res += " [" + item_ordinal.ToDebugString() + "]"; |
| 1014 if (!parent_id.empty()) | 1077 if (!parent_id.empty()) |
| 1015 res += " <" + parent_id.substr(0, 8) + ">"; | 1078 res += " <" + parent_id.substr(0, 8) + ">"; |
| 1079 res += " [" + item_pin_ordinal.ToDebugString() + "]"; | |
| 1016 } | 1080 } |
| 1017 return res; | 1081 return res; |
| 1018 } | 1082 } |
| 1019 | 1083 |
| 1020 } // namespace app_list | 1084 } // namespace app_list |
| OLD | NEW |