consent_sync_bridge_impl.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // Copyright 2018 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. #include "components/consent_auditor/consent_sync_bridge_impl.h"
  5. #include <set>
  6. #include <utility>
  7. #include <vector>
  8. #include "base/big_endian.h"
  9. #include "base/bind.h"
  10. #include "base/callback_helpers.h"
  11. #include "base/location.h"
  12. #include "base/logging.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "build/build_config.h"
  15. #include "components/sync/model/data_type_activation_request.h"
  16. #include "components/sync/model/entity_change.h"
  17. #include "components/sync/model/metadata_batch.h"
  18. #include "components/sync/model/mutable_data_batch.h"
  19. #include "components/sync/protocol/user_consent_specifics.pb.h"
  20. namespace consent_auditor {
  21. using sync_pb::UserConsentSpecifics;
  22. using syncer::EntityChange;
  23. using syncer::EntityChangeList;
  24. using syncer::EntityData;
  25. using syncer::MetadataBatch;
  26. using syncer::MetadataChangeList;
  27. using syncer::ModelError;
  28. using syncer::ModelTypeChangeProcessor;
  29. using syncer::ModelTypeStore;
  30. using syncer::ModelTypeSyncBridge;
  31. using syncer::MutableDataBatch;
  32. using syncer::OnceModelTypeStoreFactory;
  33. using IdList = ModelTypeStore::IdList;
  34. using Record = ModelTypeStore::Record;
  35. using RecordList = ModelTypeStore::RecordList;
  36. using WriteBatch = ModelTypeStore::WriteBatch;
  37. namespace {
  38. std::string GetStorageKeyFromSpecifics(const UserConsentSpecifics& specifics) {
  39. // Force Big Endian, this means newly created keys are last in sort order,
  40. // which allows leveldb to append new writes, which it is best at.
  41. // TODO(skym): Until we force |event_time_usec| to never conflict, this has
  42. // the potential for errors.
  43. std::string key(8, 0);
  44. base::WriteBigEndian(&key[0], specifics.client_consent_time_usec());
  45. return key;
  46. }
  47. std::unique_ptr<EntityData> MoveToEntityData(
  48. std::unique_ptr<UserConsentSpecifics> specifics) {
  49. auto entity_data = std::make_unique<EntityData>();
  50. entity_data->name =
  51. base::NumberToString(specifics->client_consent_time_usec());
  52. entity_data->specifics.set_allocated_user_consent(specifics.release());
  53. return entity_data;
  54. }
  55. } // namespace
  56. ConsentSyncBridgeImpl::ConsentSyncBridgeImpl(
  57. OnceModelTypeStoreFactory store_factory,
  58. std::unique_ptr<ModelTypeChangeProcessor> change_processor)
  59. : ModelTypeSyncBridge(std::move(change_processor)) {
  60. std::move(store_factory)
  61. .Run(syncer::USER_CONSENTS,
  62. base::BindOnce(&ConsentSyncBridgeImpl::OnStoreCreated,
  63. weak_ptr_factory_.GetWeakPtr()));
  64. }
  65. ConsentSyncBridgeImpl::~ConsentSyncBridgeImpl() {
  66. if (!deferred_consents_while_initializing_.empty())
  67. LOG(ERROR) << "Non-empty event queue at shutdown!";
  68. }
  69. std::unique_ptr<MetadataChangeList>
  70. ConsentSyncBridgeImpl::CreateMetadataChangeList() {
  71. return WriteBatch::CreateMetadataChangeList();
  72. }
  73. absl::optional<ModelError> ConsentSyncBridgeImpl::MergeSyncData(
  74. std::unique_ptr<MetadataChangeList> metadata_change_list,
  75. EntityChangeList entity_data) {
  76. DCHECK(entity_data.empty());
  77. DCHECK(change_processor()->IsTrackingMetadata());
  78. DCHECK(!change_processor()->TrackedAccountId().empty());
  79. ReadAllDataAndResubmit();
  80. return ApplySyncChanges(std::move(metadata_change_list),
  81. std::move(entity_data));
  82. }
  83. absl::optional<ModelError> ConsentSyncBridgeImpl::ApplySyncChanges(
  84. std::unique_ptr<MetadataChangeList> metadata_change_list,
  85. EntityChangeList entity_changes) {
  86. std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
  87. for (const std::unique_ptr<EntityChange>& change : entity_changes) {
  88. DCHECK_EQ(EntityChange::ACTION_DELETE, change->type());
  89. batch->DeleteData(change->storage_key());
  90. }
  91. batch->TakeMetadataChangesFrom(std::move(metadata_change_list));
  92. store_->CommitWriteBatch(std::move(batch),
  93. base::BindOnce(&ConsentSyncBridgeImpl::OnCommit,
  94. weak_ptr_factory_.GetWeakPtr()));
  95. return {};
  96. }
  97. void ConsentSyncBridgeImpl::GetData(StorageKeyList storage_keys,
  98. DataCallback callback) {
  99. store_->ReadData(
  100. storage_keys,
  101. base::BindOnce(&ConsentSyncBridgeImpl::OnReadData,
  102. weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  103. }
  104. void ConsentSyncBridgeImpl::GetAllDataForDebugging(DataCallback callback) {
  105. store_->ReadAllData(base::BindOnce(&ConsentSyncBridgeImpl::OnReadAllData,
  106. weak_ptr_factory_.GetWeakPtr(),
  107. std::move(callback)));
  108. }
  109. std::string ConsentSyncBridgeImpl::GetClientTag(const EntityData& entity_data) {
  110. return GetStorageKey(entity_data);
  111. }
  112. std::string ConsentSyncBridgeImpl::GetStorageKey(
  113. const EntityData& entity_data) {
  114. return GetStorageKeyFromSpecifics(entity_data.specifics.user_consent());
  115. }
  116. void ConsentSyncBridgeImpl::ApplyStopSyncChanges(
  117. std::unique_ptr<MetadataChangeList> delete_metadata_change_list) {
  118. // Sync can only be stopped after initialization.
  119. DCHECK(deferred_consents_while_initializing_.empty());
  120. if (delete_metadata_change_list) {
  121. // Preserve all consents in the store, but delete their metadata, because it
  122. // may become invalid when the sync is reenabled. It is important to report
  123. // all user consents, thus, they are persisted for some time even after
  124. // signout. We will try to resubmit these consents once the sync is enabled
  125. // again. This may lead to same consent being submitted multiple times, but
  126. // this is allowed.
  127. std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
  128. batch->TakeMetadataChangesFrom(std::move(delete_metadata_change_list));
  129. store_->CommitWriteBatch(std::move(batch),
  130. base::BindOnce(&ConsentSyncBridgeImpl::OnCommit,
  131. weak_ptr_factory_.GetWeakPtr()));
  132. }
  133. }
  134. void ConsentSyncBridgeImpl::ReadAllDataAndResubmit() {
  135. DCHECK(!change_processor()->TrackedAccountId().empty());
  136. DCHECK(change_processor()->IsTrackingMetadata());
  137. DCHECK(store_);
  138. store_->ReadAllData(
  139. base::BindOnce(&ConsentSyncBridgeImpl::OnReadAllDataToResubmit,
  140. weak_ptr_factory_.GetWeakPtr()));
  141. }
  142. void ConsentSyncBridgeImpl::OnReadAllDataToResubmit(
  143. const absl::optional<ModelError>& error,
  144. std::unique_ptr<RecordList> data_records) {
  145. if (change_processor()->TrackedAccountId().empty()) {
  146. // Meanwhile the sync has been disabled. We will try next time.
  147. return;
  148. }
  149. DCHECK(change_processor()->IsTrackingMetadata());
  150. if (error) {
  151. change_processor()->ReportError(*error);
  152. return;
  153. }
  154. std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
  155. for (const Record& r : *data_records) {
  156. auto specifics = std::make_unique<UserConsentSpecifics>();
  157. if (specifics->ParseFromString(r.value)) {
  158. if (specifics->account_id() == change_processor()->TrackedAccountId()) {
  159. change_processor()->Put(r.id, MoveToEntityData(std::move(specifics)),
  160. batch->GetMetadataChangeList());
  161. }
  162. }
  163. }
  164. store_->CommitWriteBatch(std::move(batch),
  165. base::BindOnce(&ConsentSyncBridgeImpl::OnCommit,
  166. weak_ptr_factory_.GetWeakPtr()));
  167. }
  168. void ConsentSyncBridgeImpl::RecordConsent(
  169. std::unique_ptr<UserConsentSpecifics> specifics) {
  170. // TODO(vitaliii): Sanity-check specifics->account_id() against
  171. // change_processor()->TrackedAccountId(), maybe DCHECK.
  172. DCHECK(!specifics->account_id().empty());
  173. if (store_) {
  174. RecordConsentImpl(std::move(specifics));
  175. return;
  176. }
  177. deferred_consents_while_initializing_.push_back(std::move(specifics));
  178. }
  179. // static
  180. std::string ConsentSyncBridgeImpl::GetStorageKeyFromSpecificsForTest(
  181. const UserConsentSpecifics& specifics) {
  182. return GetStorageKeyFromSpecifics(specifics);
  183. }
  184. std::unique_ptr<ModelTypeStore> ConsentSyncBridgeImpl::StealStoreForTest() {
  185. return std::move(store_);
  186. }
  187. void ConsentSyncBridgeImpl::RecordConsentImpl(
  188. std::unique_ptr<UserConsentSpecifics> specifics) {
  189. DCHECK(store_);
  190. std::string storage_key = GetStorageKeyFromSpecifics(*specifics);
  191. std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
  192. batch->WriteData(storage_key, specifics->SerializeAsString());
  193. if (specifics->account_id() == change_processor()->TrackedAccountId()) {
  194. change_processor()->Put(storage_key, MoveToEntityData(std::move(specifics)),
  195. batch->GetMetadataChangeList());
  196. }
  197. store_->CommitWriteBatch(std::move(batch),
  198. base::BindOnce(&ConsentSyncBridgeImpl::OnCommit,
  199. weak_ptr_factory_.GetWeakPtr()));
  200. }
  201. base::WeakPtr<syncer::ModelTypeControllerDelegate>
  202. ConsentSyncBridgeImpl::GetControllerDelegate() {
  203. return change_processor()->GetControllerDelegate();
  204. }
  205. void ConsentSyncBridgeImpl::ProcessQueuedEvents() {
  206. for (std::unique_ptr<sync_pb::UserConsentSpecifics>& event :
  207. deferred_consents_while_initializing_) {
  208. RecordConsentImpl(std::move(event));
  209. }
  210. deferred_consents_while_initializing_.clear();
  211. }
  212. void ConsentSyncBridgeImpl::OnStoreCreated(
  213. const absl::optional<ModelError>& error,
  214. std::unique_ptr<ModelTypeStore> store) {
  215. if (error) {
  216. change_processor()->ReportError(*error);
  217. return;
  218. }
  219. store_ = std::move(store);
  220. store_->ReadAllMetadata(
  221. base::BindOnce(&ConsentSyncBridgeImpl::OnReadAllMetadata,
  222. weak_ptr_factory_.GetWeakPtr()));
  223. }
  224. void ConsentSyncBridgeImpl::OnReadAllMetadata(
  225. const absl::optional<ModelError>& error,
  226. std::unique_ptr<MetadataBatch> metadata_batch) {
  227. if (error) {
  228. change_processor()->ReportError(*error);
  229. } else {
  230. change_processor()->ModelReadyToSync(std::move(metadata_batch));
  231. if (!change_processor()->TrackedAccountId().empty()) {
  232. // We resubmit all data in case the client crashed immediately after
  233. // MergeSyncData(), where submissions are supposed to happen and
  234. // metadata populated. This would be simpler if MergeSyncData() were
  235. // asynchronous.
  236. ReadAllDataAndResubmit();
  237. }
  238. ProcessQueuedEvents();
  239. }
  240. }
  241. void ConsentSyncBridgeImpl::OnCommit(const absl::optional<ModelError>& error) {
  242. if (error) {
  243. change_processor()->ReportError(*error);
  244. }
  245. }
  246. void ConsentSyncBridgeImpl::OnReadData(
  247. DataCallback callback,
  248. const absl::optional<ModelError>& error,
  249. std::unique_ptr<RecordList> data_records,
  250. std::unique_ptr<IdList> missing_id_list) {
  251. OnReadAllData(std::move(callback), error, std::move(data_records));
  252. }
  253. void ConsentSyncBridgeImpl::OnReadAllData(
  254. DataCallback callback,
  255. const absl::optional<ModelError>& error,
  256. std::unique_ptr<RecordList> data_records) {
  257. if (error) {
  258. change_processor()->ReportError(*error);
  259. return;
  260. }
  261. auto batch = std::make_unique<MutableDataBatch>();
  262. for (const Record& r : *data_records) {
  263. auto specifics = std::make_unique<UserConsentSpecifics>();
  264. if (specifics->ParseFromString(r.value)) {
  265. DCHECK_EQ(r.id, GetStorageKeyFromSpecifics(*specifics));
  266. batch->Put(r.id, MoveToEntityData(std::move(specifics)));
  267. } else {
  268. change_processor()->ReportError(
  269. {FROM_HERE, "Failed deserializing user events."});
  270. return;
  271. }
  272. }
  273. std::move(callback).Run(std::move(batch));
  274. }
  275. } // namespace consent_auditor