1 // Copyright 2016 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 #ifndef COMPONENTS_READING_LIST_CORE_READING_LIST_STORE_H_ 6 #define COMPONENTS_READING_LIST_CORE_READING_LIST_STORE_H_ 7 8 #include <memory> 9 #include <string> 10 11 #include "base/memory/weak_ptr.h" 12 #include "base/sequence_checker.h" 13 #include "components/reading_list/core/reading_list_model_storage.h" 14 #include "components/reading_list/core/reading_list_store_delegate.h" 15 #include "components/sync/model/model_error.h" 16 #include "components/sync/model/model_type_store.h" 17 18 namespace syncer { 19 class MutableDataBatch; 20 } 21 22 class ReadingListModel; 23 24 // A ReadingListModelStorage storing and syncing data in protobufs. 25 class ReadingListStore : public ReadingListModelStorage { 26 public: 27 ReadingListStore( 28 syncer::OnceModelTypeStoreFactory create_store_callback, 29 std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor); 30 ~ReadingListStore() override; 31 32 std::unique_ptr<ScopedBatchUpdate> EnsureBatchCreated() override; 33 34 // ReadingListModelStorage implementation 35 void SetReadingListModel(ReadingListModel* model, 36 ReadingListStoreDelegate* delegate, 37 base::Clock* clock) override; 38 39 void SaveEntry(const ReadingListEntry& entry) override; 40 void RemoveEntry(const ReadingListEntry& entry) override; 41 42 // Creates an object used to communicate changes in the sync metadata to the 43 // model type store. 44 std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() 45 override; 46 47 // Perform the initial merge between local and sync data. This should only be 48 // called when a data type is first enabled to start syncing, and there is no 49 // sync metadata. Best effort should be made to match local and sync data. The 50 // storage keys in the |entity_data| are populated with GetStorageKey(...), 51 // local and sync copies of the same entity should resolve to the same storage 52 // key. Any local pieces of data that are not present in sync should 53 // immediately be Put(...) to the processor before returning. The same 54 // MetadataChangeList that was passed into this function can be passed to 55 // Put(...) calls. Delete(...) can also be called but should not be needed for 56 // most model types. Durable storage writes, if not able to combine all change 57 // atomically, should save the metadata after the data changes, so that this 58 // merge will be re-driven by sync if is not completely saved during the 59 // current run. 60 base::Optional<syncer::ModelError> MergeSyncData( 61 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, 62 syncer::EntityChangeList entity_data) override; 63 64 // Apply changes from the sync server locally. 65 // Please note that |entity_changes| might have fewer entries than 66 // |metadata_change_list| in case when some of the data changes are filtered 67 // out, or even be empty in case when a commit confirmation is processed and 68 // only the metadata needs to persisted. 69 base::Optional<syncer::ModelError> ApplySyncChanges( 70 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, 71 syncer::EntityChangeList entity_changes) override; 72 73 // Returns whether entries respect a strict order for sync and if |rhs| can be 74 // submitted to sync after |lhs| has been received. 75 // The order should ensure that there is no sync loop in sync and should be 76 // submitted to sync in strictly increasing order. 77 // Entries are in increasing order if all the fields respect increasing order. 78 // - URL must be the same. 79 // - update_title_time_us: 80 // rhs.update_title_time_us >= lhs.update_title_time_us 81 // - title: 82 // if rhs.update_title_time_us > lhs.update_title_time_us 83 // title can be anything 84 // if rhs.update_title_time_us == lhs.update_title_time_us 85 // title must verify rhs.title.compare(lhs.title) >= 0 86 // - creation_time_us: 87 // rhs.creation_time_us >= lhs.creation_time_us 88 // - rhs.first_read_time_us: 89 // if rhs.creation_time_us > lhs.creation_time_us, 90 // rhs.first_read_time_us can be anything. 91 // if rhs.creation_time_us == lhs.creation_time_us 92 // and rhs.first_read_time_us == 0 93 // rhs.first_read_time_us can be anything. 94 // if rhs.creation_time_us == lhs.creation_time_us, 95 // rhs.first_read_time_us <= lhs.first_read_time_us 96 // - update_time_us: 97 // rhs.update_time_us >= lhs.update_time_us 98 // - state: 99 // if rhs.update_time_us > lhs.update_time_us 100 // rhs.state can be anything. 101 // if rhs.update_time_us == lhs.update_time_us 102 // rhs.state >= lhs.state in the order UNSEEN, UNREAD, READ. 103 static bool CompareEntriesForSync(const sync_pb::ReadingListSpecifics& lhs, 104 const sync_pb::ReadingListSpecifics& rhs); 105 106 // Asynchronously retrieve the corresponding sync data for |storage_keys|. 107 void GetData(StorageKeyList storage_keys, DataCallback callback) override; 108 109 // Asynchronously retrieve all of the local sync data. 110 void GetAllDataForDebugging(DataCallback callback) override; 111 112 // Get or generate a client tag for |entity_data|. This must be the same tag 113 // that was/would have been generated in the SyncableService/Directory world 114 // for backward compatibility with pre-USS clients. The only time this 115 // theoretically needs to be called is on the creation of local data, however 116 // it is also used to verify the hash of remote data. If a data type was never 117 // launched pre-USS, then method does not need to be different from 118 // GetStorageKey(). 119 std::string GetClientTag(const syncer::EntityData& entity_data) override; 120 121 // Get or generate a storage key for |entity_data|. This will only ever be 122 // called once when first encountering a remote entity. Local changes will 123 // provide their storage keys directly to Put instead of using this method. 124 // Theoretically this function doesn't need to be stable across multiple calls 125 // on the same or different clients, but to keep things simple, it probably 126 // should be. 127 std::string GetStorageKey(const syncer::EntityData& entity_data) override; 128 129 // Methods used as callbacks given to DataTypeStore. 130 void OnStoreCreated(const base::Optional<syncer::ModelError>& error, 131 std::unique_ptr<syncer::ModelTypeStore> store); 132 133 class ScopedBatchUpdate : public ReadingListModelStorage::ScopedBatchUpdate { 134 public: 135 explicit ScopedBatchUpdate(ReadingListStore* store); 136 137 ~ScopedBatchUpdate() override; 138 139 private: 140 ReadingListStore* store_; 141 142 DISALLOW_COPY_AND_ASSIGN(ScopedBatchUpdate); 143 }; 144 145 private: 146 void BeginTransaction(); 147 void CommitTransaction(); 148 // Callbacks needed for the database handling. 149 void OnDatabaseLoad( 150 const base::Optional<syncer::ModelError>& error, 151 std::unique_ptr<syncer::ModelTypeStore::RecordList> entries); 152 void OnDatabaseSave(const base::Optional<syncer::ModelError>& error); 153 void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error, 154 std::unique_ptr<syncer::MetadataBatch> metadata_batch); 155 156 void AddEntryToBatch(syncer::MutableDataBatch* batch, 157 const ReadingListEntry& entry); 158 159 std::unique_ptr<syncer::ModelTypeStore> store_; 160 ReadingListModel* model_; 161 ReadingListStoreDelegate* delegate_; 162 syncer::OnceModelTypeStoreFactory create_store_callback_; 163 164 int pending_transaction_count_; 165 std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch_; 166 167 base::Clock* clock_; 168 169 SEQUENCE_CHECKER(sequence_checker_); 170 171 base::WeakPtrFactory<ReadingListStore> weak_ptr_factory_{this}; 172 173 DISALLOW_COPY_AND_ASSIGN(ReadingListStore); 174 }; 175 176 #endif // COMPONENTS_READING_LIST_CORE_READING_LIST_STORE_H_ 177