1 // Copyright 2015 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_SYNC_MODEL_MODEL_TYPE_SYNC_BRIDGE_H_
6 #define COMPONENTS_SYNC_MODEL_MODEL_TYPE_SYNC_BRIDGE_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/callback.h"
13 #include "base/optional.h"
14 #include "components/sync/engine/commit_and_get_updates_types.h"
15 #include "components/sync/model/entity_change.h"
16 #include "components/sync/model/model_type_change_processor.h"
17 
18 namespace syncer {
19 
20 enum class ConflictResolution;
21 class DataBatch;
22 struct DataTypeActivationRequest;
23 struct EntityData;
24 class MetadataChangeList;
25 class ModelError;
26 
27 // Interface implemented by model types to receive updates from sync via a
28 // ModelTypeChangeProcessor. Provides a way for sync to update the data and
29 // metadata for entities, as well as the model type state. Sync bridge
30 // implementations must provide their change_processor() with metadata through
31 // ModelReadyToSync() as soon as possible. Once this is called, sync will
32 // immediately begin locally tracking changes and can start syncing with the
33 // server soon afterward. If an error occurs during startup, the processor's
34 // ReportError() method should be called instead of ModelReadyToSync().
35 class ModelTypeSyncBridge {
36  public:
37   using DataCallback = base::OnceCallback<void(std::unique_ptr<DataBatch>)>;
38   using StorageKeyList = std::vector<std::string>;
39 
40   ModelTypeSyncBridge(
41       std::unique_ptr<ModelTypeChangeProcessor> change_processor);
42 
43   virtual ~ModelTypeSyncBridge();
44 
45   // Called by the processor as a notification that sync has been started by the
46   // ModelTypeController.
47   virtual void OnSyncStarting(const DataTypeActivationRequest& request);
48 
49   // Creates an object used to communicate changes in the sync metadata to the
50   // model type store.
51   virtual std::unique_ptr<MetadataChangeList> CreateMetadataChangeList() = 0;
52 
53   // Perform the initial merge between local and sync data.
54   //
55   // If the bridge supports incremental updates, this is only called when a data
56   // type is first enabled to start syncing, and there is no sync metadata.
57   // In this case, best effort should be made to match local and sync data.
58   //
59   // For datatypes that do not support incremental updates, the processor will
60   // call this method every time it gets new sync data from the server. It is
61   // then the responsibility of the bridge to clear all existing sync data, and
62   // replace it with the passed in |entity_data|.
63   //
64   // Storage key in entity_data elements will be set to result of
65   // GetStorageKey() call if the bridge supports it. Otherwise it will be left
66   // empty, bridge is responsible for updating storage keys of new entities with
67   // change_processor()->UpdateStorageKey() in this case.
68   //
69   // If a local and sync data should match/merge but disagree on storage key,
70   // the bridge should delete one of the records (preferably local). Any local
71   // pieces of data that are not present in sync should immediately be Put(...)
72   // to the processor before returning. The same MetadataChangeList that was
73   // passed into this function can be passed to Put(...) calls. Delete(...) can
74   // also be called but should not be needed for most model types. Durable
75   // storage writes, if not able to combine all change atomically, should save
76   // the metadata after the data changes, so that this merge will be re-driven
77   // by sync if is not completely saved during the current run.
78   virtual base::Optional<ModelError> MergeSyncData(
79       std::unique_ptr<MetadataChangeList> metadata_change_list,
80       EntityChangeList entity_data) = 0;
81 
82   // Apply changes from the sync server locally.
83   // Please note that |entity_changes| might have fewer entries than
84   // |metadata_change_list| in case when some of the data changes are filtered
85   // out, or even be empty in case when a commit confirmation is processed and
86   // only the metadata needs to persisted.
87   virtual base::Optional<ModelError> ApplySyncChanges(
88       std::unique_ptr<MetadataChangeList> metadata_change_list,
89       EntityChangeList entity_changes) = 0;
90 
91   // Asynchronously retrieve the corresponding sync data for |storage_keys|.
92   // |callback| should be invoked if the operation is successful, otherwise
93   // the processor's ReportError method should be called.
94   virtual void GetData(StorageKeyList storage_keys, DataCallback callback) = 0;
95 
96   // Asynchronously retrieve all of the local sync data. |callback| should be
97   // invoked if the operation is successful, otherwise the processor's
98   // ReportError method should be called.
99   // Used for getting all data in Sync Node Browser of chrome://sync-internals.
100   virtual void GetAllDataForDebugging(DataCallback callback) = 0;
101 
102   // Must not be called unless SupportsGetClientTag() returns true.
103   //
104   // Get or generate a client tag for |entity_data|. This must be the same tag
105   // that was/would have been generated in the SyncableService/Directory world
106   // for backward compatibility with pre-USS clients. The only time this
107   // theoretically needs to be called is on the creation of local data.
108   //
109   // If a model type was never launched pre-USS, then method does not need to be
110   // different from GetStorageKey(). Only the hash of this value is kept.
111   virtual std::string GetClientTag(const EntityData& entity_data) = 0;
112 
113   // Must not be called unless SupportsGetStorageKey() returns true.
114   //
115   // Get or generate a storage key for |entity_data|. This will only ever be
116   // called once when first encountering a remote entity. Local changes will
117   // provide their storage keys directly to Put instead of using this method.
118   // Theoretically this function doesn't need to be stable across multiple calls
119   // on the same or different clients, but to keep things simple, it probably
120   // should be. Storage keys are kept in memory at steady state, so each model
121   // type should strive to keep these keys as small as possible.
122   // Returning an empty string means the remote creation should be ignored (i.e.
123   // it contains invalid data).
124   // TODO(crbug.com/1057947): introduce a dedicated method to validate data from
125   // the server to solve the inconsistency with bridges that don't support
126   // GetStorageKey() and with remote updates which are not creations.
127   virtual std::string GetStorageKey(const EntityData& entity_data) = 0;
128 
129   // Whether or not the bridge is capable of producing a client tag from
130   // |EntityData| (usually remote changes), via GetClientTag(). Most bridges do,
131   // but in rare cases including commit-only types and read-only types, it may
132   // not.
133   virtual bool SupportsGetClientTag() const;
134 
135   // By returning true in this function datatype indicates that it can generate
136   // storage key from EntityData. In this case for all new entities received
137   // from server, change processor will call GetStorageKey and update
138   // EntityChange structures before passing them to MergeSyncData and
139   // ApplySyncChanges.
140   //
141   // This function should return false when datatype's native storage is not
142   // indexed by some combination of values from EntityData, when key into the
143   // storage is obtained at the time the record is inserted into it (e.g. ROWID
144   // in SQLite). In this case entity changes for new entities passed to
145   // MergeSyncData and ApplySyncChanges will have empty storage_key. It is
146   // datatype's responsibility to call UpdateStorageKey for such entities.
147   virtual bool SupportsGetStorageKey() const;
148 
149   // By returning true in this function, the datatype indicates that it supports
150   // receiving partial (incremental) updates. If it returns false, the type
151   // indicates that it requires the full data set to be sent to it through
152   // MergeSyncData for any change to the data set.
153   virtual bool SupportsIncrementalUpdates() const;
154 
155   // Resolve a conflict between the client and server versions of data. They are
156   // guaranteed not to match (both be deleted or have identical specifics). A
157   // default implementation chooses the server data unless it is a deletion.
158   virtual ConflictResolution ResolveConflict(
159       const std::string& storage_key,
160       const EntityData& remote_data) const;
161 
162   // Similar to ApplySyncChanges() but called by the processor when sync
163   // is in the process of being stopped. If |delete_metadata_change_list| is not
164   // null, it indicates that sync metadata must be deleted (i.e. the datatype
165   // was disabled), and |*delete_metadata_change_list| contains a change list to
166   // remove all metadata that the processor knows about (the bridge may decide
167   // to implement deletion by other means).
168   virtual void ApplyStopSyncChanges(
169       std::unique_ptr<MetadataChangeList> delete_metadata_change_list);
170 
171   // Called only when some items in a commit haven't been committed due to an
172   // error.
173   virtual void OnCommitAttemptErrors(
174       const syncer::FailedCommitResponseDataList& error_response_list);
175 
176   // Called only when a commit failed due to server error. The commit will
177   // automatically be retried, so most implementations don't need to handle
178   // this.
179   virtual void OnCommitAttemptFailed(SyncCommitError commit_error);
180 
181   // Returns an estimate of memory usage attributed to sync (that is, excludes
182   // the actual model). Because the resulting UMA metrics are often used to
183   // compare with the non-USS equivalent implementations (SyncableService), it's
184   // a good idea to account for overhead that would also get accounted for the
185   // SyncableService by other means.
186   virtual size_t EstimateSyncOverheadMemoryUsage() const;
187 
188   // Needs to be informed about any model change occurring via Delete() and
189   // Put(). The changing metadata should be stored to persistent storage
190   // before or atomically with the model changes.
191   ModelTypeChangeProcessor* change_processor();
192   const ModelTypeChangeProcessor* change_processor() const;
193 
194  private:
195   std::unique_ptr<ModelTypeChangeProcessor> change_processor_;
196 };
197 
198 }  // namespace syncer
199 
200 #endif  // COMPONENTS_SYNC_MODEL_MODEL_TYPE_SYNC_BRIDGE_H_
201