1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_syncable_service.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h" 86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/apps/drive/drive_app_provider.h" 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/chrome_notification_types.h" 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/app_list/app_list_service.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/app_list/extension_app_item.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/app_list/extension_app_model_builder.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/common/extensions/extension_constants.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/browser/notification_source.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/constants.h" 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_change_processor.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_data.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/api/sync_merge_result.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "sync/protocol/sync.pb.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_folder_item.h" 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_item.h" 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/app_list/app_list_model.h" 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_model_observer.h" 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/app_list/app_list_switches.h" 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_CHROMEOS) 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/file_manager/app_id.h" 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chromeos/genius_app/app_id.h" 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using syncer::SyncChange; 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace app_list { 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const char kOemFolderId[] = "ddb1da55-d478-4243-8642-56d3041f0263"; 4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics, 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListSyncableService::SyncItem* item) { 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(item->item_id, specifics.item_id()); 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) item->item_type = specifics.item_type(); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) item->item_name = specifics.item_name(); 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) item->parent_id = specifics.parent_id(); 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!specifics.page_ordinal().empty()) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) item->page_ordinal = syncer::StringOrdinal(specifics.page_ordinal()); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!specifics.item_ordinal().empty()) 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) item->item_ordinal = syncer::StringOrdinal(specifics.item_ordinal()); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool UpdateSyncItemFromAppItem(const AppListItem* app_item, 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListSyncableService::SyncItem* sync_item) { 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(sync_item->item_id, app_item->id()); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool changed = false; 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_list::switches::IsFolderUIEnabled() && 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_item->parent_id != app_item->folder_id()) { 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_item->parent_id = app_item->folder_id(); 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) changed = true; 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (sync_item->item_name != app_item->name()) { 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sync_item->item_name = app_item->name(); 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) changed = true; 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!sync_item->item_ordinal.IsValid() || 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !app_item->position().Equals(sync_item->item_ordinal)) { 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_item->item_ordinal = app_item->position(); 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) changed = true; 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(stevenjb): Set page_ordinal. 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return changed; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void GetSyncSpecificsFromSyncItem(const AppListSyncableService::SyncItem* item, 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics* specifics) { 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(specifics); 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics->set_item_id(item->item_id); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics->set_item_type(item->item_type); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics->set_item_name(item->item_name); 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics->set_parent_id(item->parent_id); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item->page_ordinal.IsValid()) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics->set_page_ordinal(item->page_ordinal.ToInternalValue()); 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item->item_ordinal.IsValid()) 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics->set_item_ordinal(item->item_ordinal.ToInternalValue()); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncData GetSyncDataFromSyncItem( 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppListSyncableService::SyncItem* item) { 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::EntitySpecifics specifics; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetSyncSpecificsFromSyncItem(item, specifics.mutable_app_list()); 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return syncer::SyncData::CreateLocalData(item->item_id, 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) item->item_id, 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics); 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppIsDefault(ExtensionService* service, const std::string& id) { 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return service && extensions::ExtensionPrefs::Get(service->profile()) 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ->WasInstalledByDefault(id); 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool IsUnRemovableDefaultApp(const std::string& id) { 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (id == extension_misc::kChromeAppId || 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci id == extensions::kWebStoreAppId) 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_CHROMEOS) 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (id == file_manager::kFileManagerAppId || id == genius_app::kGeniusAppId) 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void UninstallExtension(ExtensionService* service, const std::string& id) { 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (service && service->GetInstalledExtension(id)) { 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) service->UninstallExtension(id, 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UNINSTALL_REASON_SYNC, 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&base::DoNothing), 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL); 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool GetAppListItemType(AppListItem* item, 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::AppListItemType* type) { 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* item_type = item->GetItemType(); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item_type == ExtensionAppItem::kItemType) { 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *type = sync_pb::AppListSpecifics::TYPE_APP; 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (item_type == AppListFolderItem::kItemType) { 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *type = sync_pb::AppListSpecifics::TYPE_FOLDER; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Unrecognized model type: " << item_type; 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// AppListSyncableService::SyncItem 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::SyncItem::SyncItem( 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& id, 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::AppListItemType type) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : item_id(id), 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) item_type(type) { 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::SyncItem::~SyncItem() { 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// AppListSyncableService::ModelObserver 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class AppListSyncableService::ModelObserver : public AppListModelObserver { 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit ModelObserver(AppListSyncableService* owner) 162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : owner_(owner), 163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch adding_item_(NULL) { 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << owner_ << ": ModelObserver Added"; 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->model()->AddObserver(this); 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~ModelObserver() { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->model()->RemoveObserver(this); 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << owner_ << ": ModelObserver Removed"; 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // AppListModelObserver 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnAppListItemAdded(AppListItem* item) OVERRIDE { 176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!adding_item_); 177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch adding_item_ = item; // Ignore updates while adding an item. 178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << owner_ << " OnAppListItemAdded: " << item->ToDebugString(); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->AddOrUpdateFromSyncItem(item); 180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch adding_item_ = NULL; 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnAppListItemWillBeDeleted(AppListItem* item) OVERRIDE { 184c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!adding_item_); 185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << owner_ << " OnAppListItemDeleted: " << item->ToDebugString(); 186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Don't sync folder removal in case the folder still exists on another 187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // device (e.g. with device specific items in it). Empty folders will be 188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // deleted when the last item is removed (in PruneEmptySyncFolders()). 189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (item->GetItemType() == AppListFolderItem::kItemType) 190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->RemoveSyncItem(item->id()); 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnAppListItemUpdated(AppListItem* item) OVERRIDE { 195c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (adding_item_) { 196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Adding an item may trigger update notifications which should be 197c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // ignored. 198c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK_EQ(adding_item_, item); 199c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return; 200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << owner_ << " OnAppListItemUpdated: " << item->ToDebugString(); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) owner_->UpdateSyncItem(item); 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListSyncableService* owner_; 206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch AppListItem* adding_item_; // Unowned pointer to item being added. 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ModelObserver); 2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// AppListSyncableService 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)AppListSyncableService::AppListSyncableService( 214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Profile* profile, 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::ExtensionSystem* extension_system) 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : profile_(profile), 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_system_(extension_system), 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch model_(new AppListModel), 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci initial_sync_data_processed_(false), 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch first_app_list_sync_(true) { 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!extension_system) { 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "AppListSyncableService created with no ExtensionSystem"; 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) oem_folder_name_ = 22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) l10n_util::GetStringUTF8(IDS_APP_LIST_OEM_DEFAULT_FOLDER_NAME); 22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Note: model_observer_ is constructed after the initial sync changes are 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // received in MergeDataAndStartSyncing(). Changes to the model before that 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // will be synced after the initial sync occurs. 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extension_system->extension_service() && 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_system->extension_service()->is_ready()) { 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BuildModel(); 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // The extensions for this profile have not yet all been loaded. 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) registrar_.Add(this, 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::Source<Profile>(profile)); 242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)AppListSyncableService::~AppListSyncableService() { 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Remove observers. 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_observer_.reset(); 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) STLDeleteContainerPairSecondPointers(sync_items_.begin(), sync_items_.end()); 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AppListSyncableService::BuildModel() { 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // For now, use the AppListControllerDelegate associated with the native 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // desktop. TODO(stevenjb): Remove ExtensionAppModelBuilder controller 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // dependency and move the dependent methods from AppListControllerDelegate 255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // to an extension service delegate associated with this class. 256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AppListControllerDelegate* controller = NULL; 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AppListService* service = 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE); 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (service) 260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) controller = service->GetControllerDelegate(); 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps_builder_.reset(new ExtensionAppModelBuilder(controller)); 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(profile_); 263a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (app_list::switches::IsAppListSyncEnabled()) { 264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << this << ": AppListSyncableService: InitializeWithService."; 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncStarted(); 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps_builder_->InitializeWithService(this); 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << this << ": AppListSyncableService: InitializeWithProfile."; 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) apps_builder_->InitializeWithProfile(profile_, model_.get()); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (app_list::switches::IsDriveAppsInAppListEnabled()) 2736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) drive_app_provider_.reset(new DriveAppProvider(profile_)); 2746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 2756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppListSyncableService::ResetDriveAppProviderForTest() { 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci drive_app_provider_.reset(); 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void AppListSyncableService::Shutdown() { 2816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // DriveAppProvider touches other KeyedServices in its dtor and needs be 2826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // released in shutdown stage. 2836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) drive_app_provider_.reset(); 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void AppListSyncableService::Observe( 287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int type, 288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const content::NotificationSource& source, 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const content::NotificationDetails& details) { 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, type); 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_EQ(profile_, content::Source<Profile>(source).ptr()); 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) registrar_.RemoveAll(); 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) BuildModel(); 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const AppListSyncableService::SyncItem* 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::GetSyncItem(const std::string& id) const { 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItemMap::const_iterator iter = sync_items_.find(id); 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter != sync_items_.end()) 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return iter->second; 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void AppListSyncableService::SetOemFolderName(const std::string& name) { 30523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) oem_folder_name_ = name; 30623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) AppListFolderItem* oem_folder = model_->FindFolderItem(kOemFolderId); 30723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (oem_folder) 30823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) model_->SetItemName(oem_folder, oem_folder_name_); 30923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 31023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::AddItem(scoped_ptr<AppListItem> app_item) { 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = FindOrAddSyncItem(app_item.get()); 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!sync_item) 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; // Item is not valid. 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string folder_id; 317e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (app_list::switches::IsFolderUIEnabled()) { 318e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (AppIsOem(app_item->id())) { 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) folder_id = FindOrCreateOemFolder(); 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG_IF(2, !folder_id.empty()) 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << this << ": AddItem to OEM folder: " << sync_item->ToString(); 322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else { 323e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch folder_id = sync_item->parent_id; 324e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 32523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 326c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << ": AddItem: " << sync_item->ToString() 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << " Folder: '" << folder_id << "'"; 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->AddItemToFolder(app_item.Pass(), folder_id); 3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::SyncItem* AppListSyncableService::FindOrAddSyncItem( 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListItem* app_item) { 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& item_id = app_item->id(); 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item_id.empty()) { 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "AppListItem item with empty ID"; 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = FindSyncItem(item_id); 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item) { 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If there is an existing, non-REMOVE_DEFAULT entry, return it. 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item->item_type != 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << this << ": AddItem already exists: " << sync_item->ToString(); 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return sync_item; 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (RemoveDefaultApp(app_item, sync_item)) 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Fall through. The REMOVE_DEFAULT_APP entry has been deleted, now a new 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // App entry can be added. 3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CreateSyncItemFromAppItem(app_item); 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::SyncItem* 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::CreateSyncItemFromAppItem(AppListItem* app_item) { 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::AppListItemType type; 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!GetAppListItemType(app_item, &type)) 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 362c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " CreateSyncItemFromAppItem:" << app_item->ToDebugString(); 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = CreateSyncItem(app_item->id(), type); 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateSyncItemFromAppItem(app_item, sync_item); 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SendSyncChange(sync_item, SyncChange::ACTION_ADD); 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return sync_item; 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::AddOrUpdateFromSyncItem(AppListItem* app_item) { 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Do not create a sync item for the OEM folder here, do that in 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ResolveFolderPositions once the position has been resolved. 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (app_item->id() == kOemFolderId) 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = FindSyncItem(app_item->id()); 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item) { 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateAppItemFromSyncItem(sync_item, app_item); 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateSyncItemFromAppItem(app_item); 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppListSyncableService::RemoveDefaultApp(AppListItem* item, 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item) { 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_EQ(sync_item->item_type, 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP); 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If there is an existing REMOVE_DEFAULT_APP entry, and the app is 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // installed as a Default app, uninstall the app instead of adding it. 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_APP && 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIsDefault(extension_system_->extension_service(), item->id())) { 392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << ": HandleDefaultApp: Uninstall: " 393c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << sync_item->ToString(); 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UninstallExtension(extension_system_->extension_service(), item->id()); 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Otherwise, we are adding the app as a non-default app (i.e. an app that 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // was installed by Default and removed is getting installed explicitly by 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the user), so delete the REMOVE_DEFAULT_APP. 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteSyncItem(sync_item); 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::DeleteSyncItem(SyncItem* sync_item) { 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (SyncStarted()) { 407c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString(); 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE, 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetSyncDataFromSyncItem(sync_item)); 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_->ProcessSyncChanges( 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, syncer::SyncChangeList(1, sync_change)); 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string item_id = sync_item->item_id; 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete sync_item; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_items_.erase(item_id); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::UpdateSyncItem(AppListItem* app_item) { 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = FindSyncItem(app_item->id()); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!sync_item) { 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "UpdateItem: no sync item: " << app_item->id(); 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool changed = UpdateSyncItemFromAppItem(app_item, sync_item); 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!changed) { 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString(); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::RemoveItem(const std::string& id) { 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RemoveSyncItem(id); 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->DeleteItem(id); 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PruneEmptySyncFolders(); 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 43823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void AppListSyncableService::UpdateItem(AppListItem* app_item) { 43923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Check to see if the item needs to be moved to/from the OEM folder. 440e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!app_list::switches::IsFolderUIEnabled()) 441e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return; 442effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool is_oem = AppIsOem(app_item->id()); 44323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!is_oem && app_item->folder_id() == kOemFolderId) 44423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) model_->MoveItemToFolder(app_item, ""); 44523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) else if (is_oem && app_item->folder_id() != kOemFolderId) 44623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) model_->MoveItemToFolder(app_item, kOemFolderId); 44723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 44823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::RemoveSyncItem(const std::string& id) { 450c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << ": RemoveSyncItem: " << id.substr(0, 8); 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItemMap::iterator iter = sync_items_.find(id); 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter == sync_items_.end()) { 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << this << " : RemoveSyncItem: No Item."; 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check for existing RemoveDefault sync item. 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = iter->second; 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::AppListItemType type = sync_item->item_type; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // RemoveDefault item exists, just return. 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << this << " : RemoveDefault Item exists."; 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type == sync_pb::AppListSpecifics::TYPE_APP && 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppIsDefault(extension_system_->extension_service(), id)) { 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This is a Default app; update the entry to a REMOVE_DEFAULT entry. This 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // will overwrite any existing entry for the item. 470c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " -> SYNC UPDATE: REMOVE_DEFAULT: " 471c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << sync_item->item_id; 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_item->item_type = sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP; 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SendSyncChange(sync_item, SyncChange::ACTION_UPDATE); 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteSyncItem(sync_item); 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 480116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid AppListSyncableService::ResolveFolderPositions() { 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_list::switches::IsFolderUIEnabled()) 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "ResolveFolderPositions."; 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SyncItemMap::iterator iter = sync_items_.begin(); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != sync_items_.end(); ++iter) { 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = iter->second; 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item->item_type != sync_pb::AppListSpecifics::TYPE_FOLDER) 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListItem* app_item = model_->FindItem(sync_item->item_id); 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_item) 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateAppItemFromSyncItem(sync_item, app_item); 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Move the OEM folder if one exists and we have not synced its position. 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AppListFolderItem* oem_folder = model_->FindFolderItem(kOemFolderId); 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (oem_folder && !FindSyncItem(kOemFolderId)) { 4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) model_->SetItemPosition(oem_folder, GetOemFolderPos()); 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "Creating new OEM folder sync item: " 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << oem_folder->position().ToDebugString(); 5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateSyncItemFromAppItem(oem_folder); 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::PruneEmptySyncFolders() { 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_list::switches::IsFolderUIEnabled()) 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::set<std::string> parent_ids; 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SyncItemMap::iterator iter = sync_items_.begin(); 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != sync_items_.end(); ++iter) { 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) parent_ids.insert(iter->second->parent_id); 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SyncItemMap::iterator iter = sync_items_.begin(); 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != sync_items_.end(); ) { 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = (iter++)->second; 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item->item_type != sync_pb::AppListSpecifics::TYPE_FOLDER) 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ContainsKey(parent_ids, sync_item->item_id)) 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteSyncItem(sync_item); 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// AppListSyncableService syncer::SyncableService 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing( 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type, 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncDataList& initial_sync_data, 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<syncer::SyncErrorFactory> error_handler) { 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!sync_processor_.get()); 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(sync_processor.get()); 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(error_handler.get()); 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_ = sync_processor.Pass(); 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_error_handler_ = error_handler.Pass(); 53846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (switches::IsFolderUIEnabled()) 53946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) model_->SetFoldersEnabled(true); 5405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::SyncMergeResult result = syncer::SyncMergeResult(type); 5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.set_num_items_before_association(sync_items_.size()); 543c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << this << ": MergeDataAndStartSyncing: " 544c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << initial_sync_data.size(); 5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Copy all sync items to |unsynced_items|. 5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::set<std::string> unsynced_items; 5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SyncItemMap::const_iterator iter = sync_items_.begin(); 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != sync_items_.end(); ++iter) { 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsynced_items.insert(iter->first); 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create SyncItem entries for initial_sync_data. 5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t new_items = 0, updated_items = 0; 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (syncer::SyncDataList::const_iterator iter = initial_sync_data.begin(); 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != initial_sync_data.end(); ++iter) { 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncData& data = *iter; 558e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const std::string& item_id = data.GetSpecifics().app_list().item_id(); 559116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const sync_pb::AppListSpecifics& specifics = data.GetSpecifics().app_list(); 560e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DVLOG(2) << this << " Initial Sync Item: " << item_id 561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << " Type: " << specifics.item_type(); 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(syncer::APP_LIST, data.GetDataType()); 563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ProcessSyncItemSpecifics(specifics)) 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++new_items; 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++updated_items; 567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (specifics.item_type() != sync_pb::AppListSpecifics::TYPE_FOLDER && 568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !IsUnRemovableDefaultApp(item_id) && 569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !AppIsOem(item_id) && 570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !AppIsDefault(extension_system_->extension_service(), item_id)) { 571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(2) << "Syncing non-default item: " << item_id; 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch first_app_list_sync_ = false; 573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 574e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch unsynced_items.erase(item_id); 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.set_num_items_after_association(sync_items_.size()); 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.set_num_items_added(new_items); 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.set_num_items_deleted(0); 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) result.set_num_items_modified(updated_items); 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Initial sync data has been processed, it is safe now to add new sync items. 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci initial_sync_data_processed_ = true; 5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Send unsynced items. Does not affect |result|. 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::SyncChangeList change_list; 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (std::set<std::string>::iterator iter = unsynced_items.begin(); 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != unsynced_items.end(); ++iter) { 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = FindSyncItem(*iter); 589116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Sync can cause an item to change folders, causing an unsynced folder 590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // item to be removed. 591116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!sync_item) 592116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch continue; 593c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString(); 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) change_list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_ADD, 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetSyncDataFromSyncItem(sync_item))); 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Adding items may have created folders without setting their positions 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // since we haven't started observing the item list yet. Resolve those. 601116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ResolveFolderPositions(); 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Start observing app list model changes. 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_observer_.reset(new ModelObserver(this)); 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::StopSyncing(syncer::ModelType type) { 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(type, syncer::APP_LIST); 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_.reset(); 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_error_handler_.reset(); 61446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) model_->SetFoldersEnabled(false); 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncDataList AppListSyncableService::GetAllSyncData( 6185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::ModelType type) const { 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(syncer::APP_LIST, type); 6205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 621c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << this << ": GetAllSyncData: " << sync_items_.size(); 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::SyncDataList list; 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (SyncItemMap::const_iterator iter = sync_items_.begin(); 6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != sync_items_.end(); ++iter) { 625c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " -> SYNC: " << iter->second->ToString(); 6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) list.push_back(GetSyncDataFromSyncItem(iter->second)); 6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return list; 6295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)syncer::SyncError AppListSyncableService::ProcessSyncChanges( 6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const tracked_objects::Location& from_here, 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const syncer::SyncChangeList& change_list) { 6345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!sync_processor_.get()) { 6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return syncer::SyncError(FROM_HERE, 6365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::SyncError::DATATYPE_ERROR, 6375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "App List syncable service is not started.", 6385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) syncer::APP_LIST); 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Don't observe the model while processing incoming sync changes. 6425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_observer_.reset(); 6435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 644c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << this << ": ProcessSyncChanges: " << change_list.size(); 6455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (syncer::SyncChangeList::const_iterator iter = change_list.begin(); 6465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter != change_list.end(); ++iter) { 6475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SyncChange& change = *iter; 648c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " Change: " 649c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << change.sync_data().GetSpecifics().app_list().item_id() 650c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << " (" << change.change_type() << ")"; 6515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (change.change_type() == SyncChange::ACTION_ADD || 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) change.change_type() == SyncChange::ACTION_UPDATE) { 6535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProcessSyncItemSpecifics(change.sync_data().GetSpecifics().app_list()); 6545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (change.change_type() == SyncChange::ACTION_DELETE) { 6555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeleteSyncItemSpecifics(change.sync_data().GetSpecifics().app_list()); 6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Invalid sync change"; 6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Continue observing app list model changes. 6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_observer_.reset(new ModelObserver(this)); 6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return syncer::SyncError(); 6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// AppListSyncableService private 6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppListSyncableService::ProcessSyncItemSpecifics( 6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const sync_pb::AppListSpecifics& specifics) { 6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& item_id = specifics.item_id(); 6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item_id.empty()) { 6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "AppList item with empty ID"; 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = FindSyncItem(item_id); 6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item) { 6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If an item of the same type exists, update it. 6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item->item_type == specifics.item_type()) { 6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateSyncItemFromSync(specifics, sync_item); 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProcessExistingSyncItem(sync_item); 682c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString(); 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Otherwise, one of the entries should be TYPE_REMOVE_DEFAULT_APP. 6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item->item_type != 6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP && 6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) specifics.item_type() != 6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { 6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Synced item type: " << specifics.item_type() 6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " != existing sync item type: " << sync_item->item_type 6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " Deleting item from model!"; 6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->DeleteItem(item_id); 6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 695c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " - ProcessSyncItem: Delete existing entry: " 696c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch << sync_item->ToString(); 6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete sync_item; 6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_items_.erase(item_id); 6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_item = CreateSyncItem(item_id, specifics.item_type()); 7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateSyncItemFromSync(specifics, sync_item); 7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProcessNewSyncItem(sync_item); 704c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString(); 7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) { 709c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << "ProcessNewSyncItem: " << sync_item->ToString(); 7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (sync_item->item_type) { 7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case sync_pb::AppListSpecifics::TYPE_APP: { 7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // New apps are added through ExtensionAppModelBuilder. 7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(stevenjb): Determine how to handle app items in sync that 7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // are not installed (e.g. default / OEM apps). 7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP: { 718c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << this << ": Uninstall: " << sync_item->ToString(); 7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UninstallExtension(extension_system_->extension_service(), 7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_item->item_id); 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case sync_pb::AppListSpecifics::TYPE_FOLDER: { 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListItem* app_item = model_->FindItem(sync_item->item_id); 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_item) 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; // Don't create new folders here, the model will do that. 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateAppItemFromSyncItem(sync_item, app_item); 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case sync_pb::AppListSpecifics::TYPE_URL: { 7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(stevenjb): Implement 7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(WARNING) << "TYPE_URL not supported"; 7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED() << "Unrecognized sync item type: " << sync_item->ToString(); 7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::ProcessExistingSyncItem(SyncItem* sync_item) { 7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_item->item_type == 7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { 7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 744c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << "ProcessExistingSyncItem: " << sync_item->ToString(); 7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListItem* app_item = model_->FindItem(sync_item->item_id); 7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << " AppItem: " << app_item->ToDebugString(); 7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_item) { 7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Item not found in model: " << sync_item->ToString(); 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This is the only place where sync can cause an item to change folders. 7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (app_list::switches::IsFolderUIEnabled() && 753effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch app_item->folder_id() != sync_item->parent_id && 754effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !AppIsOem(app_item->id())) { 7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(2) << " Moving Item To Folder: " << sync_item->parent_id; 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->MoveItemToFolder(app_item, sync_item->parent_id); 7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateAppItemFromSyncItem(sync_item, app_item); 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::UpdateAppItemFromSyncItem( 7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppListSyncableService::SyncItem* sync_item, 7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppListItem* app_item) { 764116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(2) << this << " UpdateAppItemFromSyncItem: " << sync_item->ToString(); 7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!app_item->position().Equals(sync_item->item_ordinal)) 7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->SetItemPosition(app_item, sync_item->item_ordinal); 767a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Only update the item name if it is a Folder or the name is empty. 768a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (sync_item->item_name != app_item->name() && 76923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) sync_item->item_id != kOemFolderId && 770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (app_item->GetItemType() == AppListFolderItem::kItemType || 771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) app_item->name().empty())) { 772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) model_->SetItemName(app_item, sync_item->item_name); 773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool AppListSyncableService::SyncStarted() { 7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_processor_.get()) 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flare_.is_null()) { 780c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(1) << this << ": SyncStarted: Flare."; 7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flare_ = sync_start_util::GetFlareForSyncableService(profile_->GetPath()); 7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flare_.Run(syncer::APP_LIST); 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::SendSyncChange( 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item, 7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncChange::SyncChangeType sync_change_type) { 7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!SyncStarted()) { 7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(2) << this << " - SendSyncChange: SYNC NOT STARTED: " 7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << sync_item->ToString(); 7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 7951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!initial_sync_data_processed_ && 7961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sync_change_type == SyncChange::ACTION_ADD) { 7971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This can occur if an initial item is created before its folder item. 7981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // A sync item should already exist for the folder, so we do not want to 7991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // send an ADD event, since that would trigger a CHECK in the sync code. 8001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(sync_item->item_type == sync_pb::AppListSpecifics::TYPE_FOLDER); 8011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DVLOG(2) << this << " - SendSyncChange: ADD before initial data processed: " 8021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << sync_item->ToString(); 8031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 8041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (sync_change_type == SyncChange::ACTION_ADD) 806c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString(); 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else 808c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " -> SYNC UPDATE: " << sync_item->ToString(); 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncChange sync_change(FROM_HERE, sync_change_type, 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetSyncDataFromSyncItem(sync_item)); 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_processor_->ProcessSyncChanges( 8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, syncer::SyncChangeList(1, sync_change)); 8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::SyncItem* 8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::FindSyncItem(const std::string& item_id) { 8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItemMap::iterator iter = sync_items_.find(item_id); 8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter == sync_items_.end()) 8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return NULL; 8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return iter->second; 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::SyncItem* 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppListSyncableService::CreateSyncItem( 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& item_id, 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::AppListItemType item_type) { 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!ContainsKey(sync_items_, item_id)); 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItem* sync_item = new SyncItem(item_id, item_type); 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_items_[item_id] = sync_item; 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return sync_item; 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AppListSyncableService::DeleteSyncItemSpecifics( 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const sync_pb::AppListSpecifics& specifics) { 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& item_id = specifics.item_id(); 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item_id.empty()) { 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Delete AppList item with empty ID"; 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 840c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << ": DeleteSyncItemSpecifics: " << item_id.substr(0, 8); 8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncItemMap::iterator iter = sync_items_.find(item_id); 8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (iter == sync_items_.end()) 8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_pb::AppListSpecifics::AppListItemType item_type = 8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter->second->item_type; 846c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch VLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString(); 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete iter->second; 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sync_items_.erase(iter); 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only delete apps from the model. Folders will be deleted when all 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // children have been deleted. 8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item_type == sync_pb::AppListSpecifics::TYPE_APP) 8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->DeleteItem(item_id); 8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)std::string AppListSyncableService::FindOrCreateOemFolder() { 85623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) AppListFolderItem* oem_folder = model_->FindFolderItem(kOemFolderId); 85723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!oem_folder) { 85823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) scoped_ptr<AppListFolderItem> new_folder(new AppListFolderItem( 85923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) kOemFolderId, AppListFolderItem::FOLDER_TYPE_OEM)); 86023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) oem_folder = static_cast<AppListFolderItem*>( 86123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) model_->AddItem(new_folder.PassAs<app_list::AppListItem>())); 862116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SyncItem* oem_sync_item = FindSyncItem(kOemFolderId); 863116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (oem_sync_item) { 8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "Creating OEM folder from existing sync item: " 865116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << oem_sync_item->item_ordinal.ToDebugString(); 866116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch model_->SetItemPosition(oem_folder, oem_sync_item->item_ordinal); 867116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 868116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch model_->SetItemPosition(oem_folder, GetOemFolderPos()); 8695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Do not create a sync item for the OEM folder here, do it in 8705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ResolveFolderPositions() when the item position is finalized. 871116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 87223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 87323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) model_->SetItemName(oem_folder, oem_folder_name_); 87423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return oem_folder->id(); 87523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 87623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 877116680a4aac90f2aa7413d9095a592090648e557Ben Murdochsyncer::StringOrdinal AppListSyncableService::GetOemFolderPos() { 878116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(1) << "GetOemFolderPos: " << first_app_list_sync_; 879116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!first_app_list_sync_) { 8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) VLOG(1) << "Sync items exist, placing OEM folder at end."; 881116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncer::StringOrdinal last; 882116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (SyncItemMap::iterator iter = sync_items_.begin(); 883116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != sync_items_.end(); ++iter) { 884116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SyncItem* sync_item = iter->second; 885116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!last.IsValid() || sync_item->item_ordinal.GreaterThan(last)) 886116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch last = sync_item->item_ordinal; 887116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 888116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return last.CreateAfter(); 889116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 891116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Place the OEM folder just after the web store, which should always be 892116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // followed by a pre-installed app (e.g. Search), so the poosition should be 893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // stable. TODO(stevenjb): consider explicitly setting the OEM folder location 894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // along with the name in ServicesCustomizationDocument::SetOemFolderName(). 895116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AppListItemList* item_list = model_->top_level_item_list(); 896116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (item_list->item_count() == 0) 897116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return syncer::StringOrdinal(); 898116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 899116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t oem_index = 0; 900116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (; oem_index < item_list->item_count() - 1; ++oem_index) { 901116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AppListItem* cur_item = item_list->item_at(oem_index); 9021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (cur_item->id() == extensions::kWebStoreAppId) 903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 904116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncer::StringOrdinal oem_ordinal; 906116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AppListItem* prev = item_list->item_at(oem_index); 907116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (oem_index + 1 < item_list->item_count()) { 908116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AppListItem* next = item_list->item_at(oem_index + 1); 909116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch oem_ordinal = prev->position().CreateBetween(next->position()); 910116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 911116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch oem_ordinal = prev->position().CreateAfter(); 912116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 913116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(1) << "Placing OEM Folder at: " << oem_index 914116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << " position: " << oem_ordinal.ToDebugString(); 915116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return oem_ordinal; 916116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 918effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool AppListSyncableService::AppIsOem(const std::string& id) { 919effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!extension_system_->extension_service()) 920effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 921effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const extensions::Extension* extension = 922effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extension_system_->extension_service()->GetExtensionById(id, true); 923effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return extension && extension->was_installed_by_oem(); 924effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 925effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string AppListSyncableService::SyncItem::ToString() const { 9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string res = item_id.substr(0, 8); 9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) { 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res += " { RemoveDefault }"; 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res += " { " + item_name + " }"; 9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res += " [" + item_ordinal.ToDebugString() + "]"; 9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!parent_id.empty()) 9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) res += " <" + parent_id.substr(0, 8) + ">"; 9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return res; 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 939f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace app_list 940