1 // Copyright 2019 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 "chrome/browser/security_events/security_event_sync_bridge_impl.h"
6
7 #include <set>
8 #include <utility>
9 #include <vector>
10
11 #include "base/big_endian.h"
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/check_op.h"
15 #include "base/location.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "build/build_config.h"
18 #include "components/sync/model/entity_change.h"
19 #include "components/sync/model/metadata_batch.h"
20 #include "components/sync/model/mutable_data_batch.h"
21
22 namespace {
23
GetStorageKeyFromSpecifics(const sync_pb::SecurityEventSpecifics & specifics)24 std::string GetStorageKeyFromSpecifics(
25 const sync_pb::SecurityEventSpecifics& specifics) {
26 // Force Big Endian, this means newly created keys are last in sort order,
27 // which allows leveldb to append new writes, which it is best at.
28 // TODO(markusheintz): Until we force |event_time_usec| to never conflict,
29 // this has the potential for errors.
30 std::string key(8, 0);
31 base::WriteBigEndian(&key[0], specifics.event_time_usec());
32 return key;
33 }
34
ToEntityData(sync_pb::SecurityEventSpecifics specifics)35 std::unique_ptr<syncer::EntityData> ToEntityData(
36 sync_pb::SecurityEventSpecifics specifics) {
37 auto entity_data = std::make_unique<syncer::EntityData>();
38 entity_data->name = base::NumberToString(specifics.event_time_usec());
39 entity_data->specifics.mutable_security_event()->Swap(&specifics);
40 return entity_data;
41 }
42
43 } // namespace
44
SecurityEventSyncBridgeImpl(syncer::OnceModelTypeStoreFactory store_factory,std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor)45 SecurityEventSyncBridgeImpl::SecurityEventSyncBridgeImpl(
46 syncer::OnceModelTypeStoreFactory store_factory,
47 std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor)
48 : syncer::ModelTypeSyncBridge(std::move(change_processor)) {
49 std::move(store_factory)
50 .Run(syncer::SECURITY_EVENTS,
51 base::BindOnce(&SecurityEventSyncBridgeImpl::OnStoreCreated,
52 weak_ptr_factory_.GetWeakPtr()));
53 }
54
~SecurityEventSyncBridgeImpl()55 SecurityEventSyncBridgeImpl::~SecurityEventSyncBridgeImpl() {}
56
RecordSecurityEvent(sync_pb::SecurityEventSpecifics specifics)57 void SecurityEventSyncBridgeImpl::RecordSecurityEvent(
58 sync_pb::SecurityEventSpecifics specifics) {
59 if (!store_) {
60 return;
61 }
62 if (!change_processor()->IsTrackingMetadata()) {
63 return;
64 }
65
66 std::string storage_key = GetStorageKeyFromSpecifics(specifics);
67
68 std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch =
69 store_->CreateWriteBatch();
70 write_batch->WriteData(storage_key, specifics.SerializeAsString());
71
72 change_processor()->Put(storage_key, ToEntityData(std::move(specifics)),
73 write_batch->GetMetadataChangeList());
74
75 store_->CommitWriteBatch(
76 std::move(write_batch),
77 base::BindOnce(&SecurityEventSyncBridgeImpl::OnCommit,
78 weak_ptr_factory_.GetWeakPtr()));
79 }
80
81 base::WeakPtr<syncer::ModelTypeControllerDelegate>
GetControllerDelegate()82 SecurityEventSyncBridgeImpl::GetControllerDelegate() {
83 return change_processor()->GetControllerDelegate();
84 }
85
86 std::unique_ptr<syncer::MetadataChangeList>
CreateMetadataChangeList()87 SecurityEventSyncBridgeImpl::CreateMetadataChangeList() {
88 return syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList();
89 }
90
MergeSyncData(std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,syncer::EntityChangeList entity_data)91 base::Optional<syncer::ModelError> SecurityEventSyncBridgeImpl::MergeSyncData(
92 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
93 syncer::EntityChangeList entity_data) {
94 DCHECK(entity_data.empty());
95 DCHECK(change_processor()->IsTrackingMetadata());
96 DCHECK(!change_processor()->TrackedAccountId().empty());
97 return ApplySyncChanges(std::move(metadata_change_list),
98 std::move(entity_data));
99 }
100
101 base::Optional<syncer::ModelError>
ApplySyncChanges(std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,syncer::EntityChangeList entity_changes)102 SecurityEventSyncBridgeImpl::ApplySyncChanges(
103 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
104 syncer::EntityChangeList entity_changes) {
105 std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch =
106 store_->CreateWriteBatch();
107 for (const std::unique_ptr<syncer::EntityChange>& change : entity_changes) {
108 DCHECK_EQ(syncer::EntityChange::ACTION_DELETE, change->type());
109 write_batch->DeleteData(change->storage_key());
110 }
111
112 write_batch->TakeMetadataChangesFrom(std::move(metadata_change_list));
113 store_->CommitWriteBatch(
114 std::move(write_batch),
115 base::BindOnce(&SecurityEventSyncBridgeImpl::OnCommit,
116 weak_ptr_factory_.GetWeakPtr()));
117 return {};
118 }
119
GetData(StorageKeyList storage_keys,DataCallback callback)120 void SecurityEventSyncBridgeImpl::GetData(StorageKeyList storage_keys,
121 DataCallback callback) {
122 store_->ReadData(
123 storage_keys,
124 base::BindOnce(&SecurityEventSyncBridgeImpl::OnReadData,
125 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
126 }
127
GetAllDataForDebugging(DataCallback callback)128 void SecurityEventSyncBridgeImpl::GetAllDataForDebugging(
129 DataCallback callback) {
130 store_->ReadAllData(
131 base::BindOnce(&SecurityEventSyncBridgeImpl::OnReadAllData,
132 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
133 }
134
GetClientTag(const syncer::EntityData & entity_data)135 std::string SecurityEventSyncBridgeImpl::GetClientTag(
136 const syncer::EntityData& entity_data) {
137 return GetStorageKey(entity_data);
138 }
139
GetStorageKey(const syncer::EntityData & entity_data)140 std::string SecurityEventSyncBridgeImpl::GetStorageKey(
141 const syncer::EntityData& entity_data) {
142 return GetStorageKeyFromSpecifics(entity_data.specifics.security_event());
143 }
144
ApplyStopSyncChanges(std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list)145 void SecurityEventSyncBridgeImpl::ApplyStopSyncChanges(
146 std::unique_ptr<syncer::MetadataChangeList> delete_metadata_change_list) {
147 if (delete_metadata_change_list) {
148 store_->DeleteAllDataAndMetadata(
149 base::BindOnce(&SecurityEventSyncBridgeImpl::OnCommit,
150 weak_ptr_factory_.GetWeakPtr()));
151 }
152 }
153
OnStoreCreated(const base::Optional<syncer::ModelError> & error,std::unique_ptr<syncer::ModelTypeStore> store)154 void SecurityEventSyncBridgeImpl::OnStoreCreated(
155 const base::Optional<syncer::ModelError>& error,
156 std::unique_ptr<syncer::ModelTypeStore> store) {
157 if (error) {
158 change_processor()->ReportError(*error);
159 return;
160 }
161
162 store_ = std::move(store);
163 store_->ReadAllMetadata(
164 base::BindOnce(&SecurityEventSyncBridgeImpl::OnReadAllMetadata,
165 weak_ptr_factory_.GetWeakPtr()));
166 }
167
OnReadData(DataCallback callback,const base::Optional<syncer::ModelError> & error,std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records,std::unique_ptr<syncer::ModelTypeStore::IdList> missing_id_list)168 void SecurityEventSyncBridgeImpl::OnReadData(
169 DataCallback callback,
170 const base::Optional<syncer::ModelError>& error,
171 std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records,
172 std::unique_ptr<syncer::ModelTypeStore::IdList> missing_id_list) {
173 OnReadAllData(std::move(callback), error, std::move(data_records));
174 }
175
OnReadAllData(DataCallback callback,const base::Optional<syncer::ModelError> & error,std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records)176 void SecurityEventSyncBridgeImpl::OnReadAllData(
177 DataCallback callback,
178 const base::Optional<syncer::ModelError>& error,
179 std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records) {
180 if (error) {
181 change_processor()->ReportError(*error);
182 return;
183 }
184
185 auto batch = std::make_unique<syncer::MutableDataBatch>();
186 for (const syncer::ModelTypeStore::Record& r : *data_records) {
187 sync_pb::SecurityEventSpecifics specifics;
188
189 if (specifics.ParseFromString(r.value)) {
190 DCHECK_EQ(r.id, GetStorageKeyFromSpecifics(specifics));
191 batch->Put(r.id, ToEntityData(std::move(specifics)));
192 } else {
193 change_processor()->ReportError(
194 {FROM_HERE, "Failed deserializing security events."});
195 return;
196 }
197 }
198 std::move(callback).Run(std::move(batch));
199 }
200
OnReadAllMetadata(const base::Optional<syncer::ModelError> & error,std::unique_ptr<syncer::MetadataBatch> metadata_batch)201 void SecurityEventSyncBridgeImpl::OnReadAllMetadata(
202 const base::Optional<syncer::ModelError>& error,
203 std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
204 if (error) {
205 change_processor()->ReportError(*error);
206 } else {
207 change_processor()->ModelReadyToSync(std::move(metadata_batch));
208 }
209 }
210
OnCommit(const base::Optional<syncer::ModelError> & error)211 void SecurityEventSyncBridgeImpl::OnCommit(
212 const base::Optional<syncer::ModelError>& error) {
213 if (error) {
214 change_processor()->ReportError(*error);
215 }
216 }
217