1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sync/internal_api/sync_backup_manager.h" 6 7 #include "sync/internal_api/public/read_node.h" 8 #include "sync/internal_api/public/write_transaction.h" 9 #include "sync/syncable/directory.h" 10 #include "sync/syncable/mutable_entry.h" 11 #include "url/gurl.h" 12 13 namespace syncer { 14 15 SyncBackupManager::SyncBackupManager() 16 : in_normalization_(false) { 17 } 18 19 SyncBackupManager::~SyncBackupManager() { 20 } 21 22 void SyncBackupManager::Init(InitArgs* args) { 23 if (SyncRollbackManagerBase::InitInternal( 24 args->database_location, 25 args->internal_components_factory.get(), 26 InternalComponentsFactory::STORAGE_ON_DISK_DEFERRED, 27 args->unrecoverable_error_handler.Pass(), 28 args->report_unrecoverable_error_function)) { 29 GetUserShare()->directory->CollectMetaHandleCounts( 30 &status_.num_entries_by_type, &status_.num_to_delete_entries_by_type); 31 32 HideSyncPreference(PRIORITY_PREFERENCES); 33 HideSyncPreference(PREFERENCES); 34 } 35 } 36 37 void SyncBackupManager::SaveChanges() { 38 if (initialized()) 39 NormalizeEntries(); 40 } 41 42 SyncStatus SyncBackupManager::GetDetailedStatus() const { 43 return status_; 44 } 45 46 ModelTypeSet SyncBackupManager::HandleTransactionEndingChangeEvent( 47 const syncable::ImmutableWriteTransactionInfo& write_transaction_info, 48 syncable::BaseTransaction* trans) { 49 ModelTypeSet types; 50 if (in_normalization_) { 51 // Skip if in our own WriteTransaction from NormalizeEntries(). 52 in_normalization_ = false; 53 return types; 54 } 55 56 for (syncable::EntryKernelMutationMap::const_iterator it = 57 write_transaction_info.Get().mutations.Get().begin(); 58 it != write_transaction_info.Get().mutations.Get().end(); ++it) { 59 int64 id = it->first; 60 if (unsynced_.find(id) == unsynced_.end()) { 61 unsynced_.insert(id); 62 63 const syncable::EntryKernel& e = it->second.mutated; 64 ModelType type = e.GetModelType(); 65 types.Put(type); 66 if (!e.ref(syncable::ID).ServerKnows()) 67 status_.num_entries_by_type[type]++; 68 if (e.ref(syncable::IS_DEL)) 69 status_.num_to_delete_entries_by_type[type]++; 70 } 71 } 72 return types; 73 } 74 75 void SyncBackupManager::NormalizeEntries() { 76 WriteTransaction trans(FROM_HERE, GetUserShare()); 77 in_normalization_ = true; 78 for (std::set<int64>::const_iterator it = unsynced_.begin(); 79 it != unsynced_.end(); ++it) { 80 syncable::MutableEntry entry(trans.GetWrappedWriteTrans(), 81 syncable::GET_BY_HANDLE, *it); 82 CHECK(entry.good()); 83 84 if (!entry.GetId().ServerKnows()) 85 entry.PutId(syncable::Id::CreateFromServerId(entry.GetId().value())); 86 if (!entry.GetParentId().ServerKnows()) { 87 entry.PutParentIdPropertyOnly(syncable::Id::CreateFromServerId( 88 entry.GetParentId().value())); 89 } 90 entry.PutBaseVersion(1); 91 entry.PutIsUnsynced(false); 92 } 93 unsynced_.clear(); 94 } 95 96 void SyncBackupManager::HideSyncPreference(ModelType type) { 97 WriteTransaction trans(FROM_HERE, GetUserShare()); 98 ReadNode pref_root(&trans); 99 if (BaseNode::INIT_OK != pref_root.InitTypeRoot(type)) 100 return; 101 102 std::vector<int64> pref_ids; 103 pref_root.GetChildIds(&pref_ids); 104 for (uint32 i = 0; i < pref_ids.size(); ++i) { 105 syncable::MutableEntry entry(trans.GetWrappedWriteTrans(), 106 syncable::GET_BY_HANDLE, pref_ids[i]); 107 if (entry.good()) { 108 // HACKY: Set IS_DEL to true to remove entry from parent-children 109 // index so that it's not returned when syncable service asks 110 // for sync data. Syncable service then creates entry for local 111 // model. Then the existing entry is undeleted and set to local value 112 // because it has the same unique client tag. 113 entry.PutIsDel(true); 114 entry.PutIsUnsynced(false); 115 116 // Don't persist on disk so that if backup is aborted before receiving 117 // local preference values, values in sync DB are saved. 118 GetUserShare()->directory->UnmarkDirtyEntry( 119 trans.GetWrappedWriteTrans(), &entry); 120 } 121 } 122 } 123 124 void SyncBackupManager::ShutdownOnSyncThread(ShutdownReason reason) { 125 if (reason == SWITCH_MODE_SYNC) { 126 NormalizeEntries(); 127 GetUserShare()->directory->SaveChanges(); 128 } 129 130 SyncRollbackManagerBase::ShutdownOnSyncThread(reason); 131 } 132 133 void SyncBackupManager::RegisterDirectoryTypeDebugInfoObserver( 134 syncer::TypeDebugInfoObserver* observer) {} 135 136 void SyncBackupManager::UnregisterDirectoryTypeDebugInfoObserver( 137 syncer::TypeDebugInfoObserver* observer) {} 138 139 bool SyncBackupManager::HasDirectoryTypeDebugInfoObserver( 140 syncer::TypeDebugInfoObserver* observer) { return false; } 141 142 void SyncBackupManager::RequestEmitDebugInfo() {} 143 144 } // namespace syncer 145