model_type_worker.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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. #ifndef COMPONENTS_SYNC_ENGINE_MODEL_TYPE_WORKER_H_
  5. #define COMPONENTS_SYNC_ENGINE_MODEL_TYPE_WORKER_H_
  6. #include <stddef.h>
  7. #include <map>
  8. #include <memory>
  9. #include <string>
  10. #include <vector>
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/memory/weak_ptr.h"
  14. #include "base/sequence_checker.h"
  15. #include "base/synchronization/waitable_event.h"
  16. #include "components/sync/base/model_type.h"
  17. #include "components/sync/base/passphrase_enums.h"
  18. #include "components/sync/engine/cancelation_signal.h"
  19. #include "components/sync/engine/commit_and_get_updates_types.h"
  20. #include "components/sync/engine/commit_contributor.h"
  21. #include "components/sync/engine/commit_queue.h"
  22. #include "components/sync/engine/nigori/cryptographer.h"
  23. #include "components/sync/engine/nudge_handler.h"
  24. #include "components/sync/engine/sync_encryption_handler.h"
  25. #include "components/sync/engine/update_handler.h"
  26. #include "components/sync/protocol/model_type_state.pb.h"
  27. namespace sync_pb {
  28. class SyncEntity;
  29. }
  30. namespace syncer {
  31. class CancelationSignal;
  32. class ModelTypeProcessor;
  33. // These values are persisted to logs. Entries should not be renumbered and
  34. // numeric values should never be reused.
  35. enum class PasswordNotesStateForUMA {
  36. // No password note is set in the proto or the backup.
  37. kUnset = 0,
  38. // Password note is set in the password specifics data. Indicates an entity
  39. // created on a client supporting password notes. This doesn't guarantee the
  40. // backup is set too, but in practice it will be set in both (in the
  41. // foreseeable future).
  42. kSetInSpecificsData = 1,
  43. // Password notes is set in the backup, indicates that after the note was
  44. // created on the client, and update from a legacy client was committed and
  45. // the server carried the backup blob over.
  46. kSetOnlyInBackup = 2,
  47. // Similar to kSetOnlyInBackup, but the backup is corrupted. This should be
  48. // rare
  49. // to happen.
  50. kSetOnlyInBackupButCorrupted = 3,
  51. kMaxValue = kSetOnlyInBackupButCorrupted,
  52. };
  53. // A smart cache for sync types to communicate with the sync thread.
  54. //
  55. // When the sync data type wants to talk to the sync server, it will
  56. // send a message from its thread to this object on the sync thread. This
  57. // object ensures the appropriate sync server communication gets scheduled and
  58. // executed. The response, if any, will be returned to the data types's thread
  59. // eventually.
  60. //
  61. // This object also has a role to play in communications in the opposite
  62. // direction. Sometimes the sync thread will receive changes from the sync
  63. // server and deliver them here. This object will post this information back to
  64. // the appropriate component on the model type's thread.
  65. //
  66. // This object does more than just pass along messages. It understands the sync
  67. // protocol, and it can make decisions when it sees conflicting messages. For
  68. // example, if the sync server sends down an update for a sync entity that is
  69. // currently pending for commit, this object will detect this condition and
  70. // cancel the pending commit.
  71. class ModelTypeWorker : public UpdateHandler,
  72. public CommitContributor,
  73. public CommitQueue {
  74. public:
  75. // Public for testing.
  76. enum DecryptionStatus { SUCCESS, DECRYPTION_PENDING, FAILED_TO_DECRYPT };
  77. // This enum reflects the processor's state of having local changes.
  78. enum HasLocalChangesState {
  79. // There are no new nudged pending changes in the processor.
  80. kNoNudgedLocalChanges,
  81. // There are new pending changes in the processor which are not committed
  82. // yet.
  83. kNewlyNudgedLocalChanges,
  84. // All known local changes are contributed in the last commit request (and
  85. // there is no commit response yet).
  86. kAllNudgedLocalChangesInFlight,
  87. };
  88. // |cryptographer|, |nudge_handler| and |cancelation_signal| must be non-null
  89. // and outlive the worker. Calling this will construct the object but not
  90. // more, ConnectSync() must be called immediately afterwards.
  91. ModelTypeWorker(ModelType type,
  92. const sync_pb::ModelTypeState& initial_state,
  93. Cryptographer* cryptographer,
  94. bool encryption_enabled,
  95. PassphraseType passphrase_type,
  96. NudgeHandler* nudge_handler,
  97. CancelationSignal* cancelation_signal);
  98. ModelTypeWorker(const ModelTypeWorker&) = delete;
  99. ModelTypeWorker& operator=(const ModelTypeWorker&) = delete;
  100. ~ModelTypeWorker() override;
  101. // Public for testing.
  102. // |response_data| must be not null.
  103. static DecryptionStatus PopulateUpdateResponseData(
  104. const Cryptographer& cryptographer,
  105. ModelType model_type,
  106. const sync_pb::SyncEntity& update_entity,
  107. UpdateResponseData* response_data);
  108. // Initializes the two relevant communication channels: ModelTypeWorker ->
  109. // ModelTypeProcessor (GetUpdates) and ModelTypeProcessor -> ModelTypeWorker
  110. // (Commit). Both channels are closed when the worker is destroyed. This is
  111. // done outside of the constructor to avoid the object being used while it's
  112. // still being built.
  113. // Must be called immediately after the constructor, prior to using other
  114. // methods.
  115. void ConnectSync(std::unique_ptr<ModelTypeProcessor> model_type_processor);
  116. ModelType GetModelType() const;
  117. // Makes this an encrypted type, which means:
  118. // a) Commits will be encrypted using the cryptographer passed on
  119. // construction. Note that updates are always decrypted if possible,
  120. // regardless of this method.
  121. // b) The worker can only commit or push updates once the cryptographer has
  122. // selected a default key to encrypt data (Cryptographer::CanEncrypt()). That
  123. // used key will be listed in ModelTypeState.
  124. // This is a no-op if encryption was already enabled on construction or by
  125. // a previous call to this method.
  126. void EnableEncryption();
  127. // Must be called on every change to the state of the cryptographer passed on
  128. // construction.
  129. void OnCryptographerChange();
  130. void UpdatePassphraseType(PassphraseType type);
  131. // UpdateHandler implementation.
  132. bool IsInitialSyncEnded() const override;
  133. const sync_pb::DataTypeProgressMarker& GetDownloadProgress() const override;
  134. const sync_pb::DataTypeContext& GetDataTypeContext() const override;
  135. void ProcessGetUpdatesResponse(
  136. const sync_pb::DataTypeProgressMarker& progress_marker,
  137. const sync_pb::DataTypeContext& mutated_context,
  138. const SyncEntityList& applicable_updates,
  139. StatusController* status) override;
  140. void ApplyUpdates(StatusController* status) override;
  141. // CommitQueue implementation.
  142. void NudgeForCommit() override;
  143. // CommitContributor implementation.
  144. std::unique_ptr<CommitContribution> GetContribution(
  145. size_t max_entries) override;
  146. // Public for testing.
  147. // Returns true if this type should stop communicating because of outstanding
  148. // encryption issues and must wait for keys to be updated.
  149. bool BlockForEncryption() const;
  150. // Returns the estimate of dynamically allocated memory in bytes.
  151. size_t EstimateMemoryUsage() const;
  152. bool HasLocalChangesForTest() const;
  153. void SetMinGetUpdatesToIgnoreKeyForTest(int min_get_updates_to_ignore_key) {
  154. min_get_updates_to_ignore_key_ = min_get_updates_to_ignore_key;
  155. }
  156. bool IsEncryptionEnabledForTest() const { return encryption_enabled_; }
  157. private:
  158. struct UnknownEncryptionKeyInfo {
  159. // Not increased if the cryptographer knows it's in a pending state
  160. // (cf. Cryptographer::CanEncrypt()).
  161. int get_updates_while_should_have_been_known = 0;
  162. };
  163. // Sends |pending_updates_| and |model_type_state_| to the processor if there
  164. // are no encryption pendencies and initial sync is done. This is called in
  165. // ApplyUpdates() during a GetUpdates cycle, but also if the processor must be
  166. // informed of a new encryption key, or the worker just managed to decrypt
  167. // some pending updates.
  168. // If initial sync isn't done yet, the first ApplyUpdates() will take care of
  169. // pushing the data in such cases instead (the processor relies on this).
  170. void SendPendingUpdatesToProcessorIfReady();
  171. // Returns true if this type has successfully fetched all available updates
  172. // from the server at least once. Our state may or may not be stale, but at
  173. // least we know that it was valid at some point in the past.
  174. bool IsTypeInitialized() const;
  175. // Returns true if this type is prepared to commit items. Currently, this
  176. // depends on having downloaded the initial data and having the encryption
  177. // settings in a good state.
  178. bool CanCommitItems() const;
  179. // If |encryption_enabled_| is false, sets the encryption key name in
  180. // |model_type_state_| to the empty string. This should usually be a no-op.
  181. // If |encryption_enabled_| is true *and* the cryptographer has selected a
  182. // (non-empty) default key, sets the value to that default key.
  183. // Returns whether the |model_type_state_| key name changed.
  184. bool UpdateTypeEncryptionKeyName();
  185. // Iterates through all elements in |entries_pending_decryption_| and tries to
  186. // decrypt anything that has encrypted data.
  187. // Should only be called during a GetUpdates cycle.
  188. void DecryptStoredEntities();
  189. // Nudges nudge_handler_ when initial sync is done, processor has local
  190. // changes and either encryption is disabled for the type or cryptographer is
  191. // ready (doesn't have pending keys).
  192. void NudgeIfReadyToCommit();
  193. // Filters our duplicate updates from |pending_updates_| based on the server
  194. // id. It discards all of them except the last one.
  195. void DeduplicatePendingUpdatesBasedOnServerId();
  196. // Filters our duplicate updates from |pending_updates_| based on the client
  197. // tag hash. It discards all of them except the last one.
  198. void DeduplicatePendingUpdatesBasedOnClientTagHash();
  199. // Filters our duplicate updates from |pending_updates_| based on the
  200. // originator item ID (in practice used for bookmarks only). It discards all
  201. // of them except the last one.
  202. void DeduplicatePendingUpdatesBasedOnOriginatorClientItemId();
  203. // Callback for when our contribution gets a response.
  204. void OnCommitResponse(
  205. const CommitResponseDataList& committed_response_list,
  206. const FailedCommitResponseDataList& error_response_list);
  207. // Callback when there is no response or server returns an error without
  208. // response body.
  209. void OnFullCommitFailure(SyncCommitError commit_error);
  210. // Returns true for keys that have remained unknown for so long that they are
  211. // not expected to arrive anytime soon. The worker ignores incoming updates
  212. // encrypted with them, and drops pending ones on the next GetUpdates.
  213. // Those keys remain in |unknown_encryption_keys_by_name_|.
  214. bool ShouldIgnoreUpdatesEncryptedWith(const std::string& key_name);
  215. // If |key_name| should be ignored (cf. ShouldIgnoreUpdatesEncryptedWith()),
  216. // drops elements of |entries_pending_decryption_| encrypted with it.
  217. void MaybeDropPendingUpdatesEncryptedWith(const std::string& key_name);
  218. // Removes elements of |unknown_encryption_keys_by_name_| that no longer fit
  219. // the definition of an unknown key, and returns their info.
  220. std::vector<UnknownEncryptionKeyInfo> RemoveKeysNoLongerUnknown();
  221. // Returns whether |pending_updates_| contain any non-deletion update.
  222. bool HasNonDeletionUpdates() const;
  223. const ModelType type_;
  224. const raw_ptr<Cryptographer> cryptographer_;
  225. // Interface used to access and send nudges to the sync scheduler. Not owned.
  226. const raw_ptr<NudgeHandler> nudge_handler_;
  227. // Cancellation signal is used to cancel blocking operation on engine
  228. // shutdown.
  229. const raw_ptr<CancelationSignal> cancelation_signal_;
  230. // Pointer to the ModelTypeProcessor associated with this worker. Initialized
  231. // with ConnectSync().
  232. std::unique_ptr<ModelTypeProcessor> model_type_processor_;
  233. // State that applies to the entire model type.
  234. sync_pb::ModelTypeState model_type_state_;
  235. bool encryption_enabled_;
  236. // A private copy of the most recent passphrase type. Initialized at
  237. // construction time and updated with UpdatePassphraseType().
  238. PassphraseType passphrase_type_;
  239. // A map of sync entities, keyed by server_id. Holds updates encrypted with
  240. // pending keys. Entries are stored in a map for de-duplication (applying only
  241. // the latest).
  242. // TODO(crbug.com/1109221): Use a name mentioning "updates" and "server id".
  243. std::map<std::string, sync_pb::SyncEntity> entries_pending_decryption_;
  244. // A key is said to be unknown if one of these is true:
  245. // a) It encrypts some updates(s) in |entries_pending_decryption_|.
  246. // b) (a) happened for so long that the worker dropped those updates in an
  247. // attempt to unblock itself (cf. ShouldIgnoreUpdatesEncryptedWith()).
  248. // The key is added here when the worker receives the first update entity
  249. // encrypted with it.
  250. std::map<std::string, UnknownEncryptionKeyInfo>
  251. unknown_encryption_keys_by_name_;
  252. // Accumulates all the updates from a single GetUpdates cycle in memory so
  253. // they can all be sent to the processor at once. Some updates may be
  254. // deduplicated, e.g. in DeduplicatePendingUpdatesBasedOnServerId(). The
  255. // ordering here is NOT guaranteed to stick to the download ordering or any
  256. // other.
  257. UpdateResponseDataList pending_updates_;
  258. // Indicates if processor has local changes. Processor only nudges worker once
  259. // and worker might not be ready to commit entities at the time.
  260. HasLocalChangesState has_local_changes_state_ = kNoNudgedLocalChanges;
  261. // Remains constant in production code. Can be overridden in tests.
  262. // |UnknownEncryptionKeyInfo::get_updates_while_should_have_been_known| must
  263. // be above this value before updates encrypted with the key are ignored.
  264. int min_get_updates_to_ignore_key_;
  265. SEQUENCE_CHECKER(sequence_checker_);
  266. base::WeakPtrFactory<ModelTypeWorker> weak_ptr_factory_{this};
  267. };
  268. // GetLocalChangesRequest is a container for GetLocalChanges call response. It
  269. // allows sync thread to block waiting for model thread to call SetResponse.
  270. // This class supports canceling blocking call through CancelationSignal during
  271. // sync engine shutdown.
  272. //
  273. // It should be used in the following manner:
  274. // scoped_refptr<GetLocalChangesRequest> request =
  275. // base::MakeRefCounted<GetLocalChangesRequest>(cancelation_signal_);
  276. // model_type_processor_->GetLocalChanges(
  277. // max_entries,
  278. // base::BindOnce(&GetLocalChangesRequest::SetResponse, request));
  279. // request->WaitForResponseOrCancelation();
  280. // CommitRequestDataList response;
  281. // if (!request->WasCancelled())
  282. // response = request->ExtractResponse();
  283. class GetLocalChangesRequest
  284. : public base::RefCountedThreadSafe<GetLocalChangesRequest>,
  285. public CancelationSignal::Observer {
  286. public:
  287. explicit GetLocalChangesRequest(CancelationSignal* cancelation_signal);
  288. GetLocalChangesRequest(const GetLocalChangesRequest&) = delete;
  289. GetLocalChangesRequest& operator=(const GetLocalChangesRequest&) = delete;
  290. // CancelationSignal::Observer implementation.
  291. void OnCancelationSignalReceived() override;
  292. // Blocks current thread until either SetResponse is called or
  293. // cancelation_signal_ is signaled.
  294. void WaitForResponseOrCancelation();
  295. // SetResponse takes ownership of |local_changes| and unblocks
  296. // WaitForResponseOrCancelation call. It is called by model type through
  297. // callback passed to GetLocalChanges.
  298. void SetResponse(CommitRequestDataList&& local_changes);
  299. // Checks if WaitForResponseOrCancelation was canceled through
  300. // CancelationSignal. When returns true calling ExtractResponse is unsafe.
  301. bool WasCancelled();
  302. // Returns response set by SetResponse().
  303. CommitRequestDataList&& ExtractResponse();
  304. private:
  305. friend class base::RefCountedThreadSafe<GetLocalChangesRequest>;
  306. ~GetLocalChangesRequest() override;
  307. raw_ptr<CancelationSignal> cancelation_signal_;
  308. base::WaitableEvent response_accepted_;
  309. CommitRequestDataList response_;
  310. };
  311. } // namespace syncer
  312. #endif // COMPONENTS_SYNC_ENGINE_MODEL_TYPE_WORKER_H_