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