Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h" | 5 #include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 #include <set> | |
| 7 #include <unordered_set> | 9 #include <unordered_set> |
| 8 #include <utility> | 10 #include <utility> |
| 9 #include <vector> | 11 #include <vector> |
| 10 | 12 |
| 11 #include "base/bind.h" | 13 #include "base/bind.h" |
| 12 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 14 #include "components/autofill/core/browser/proto/autofill_sync.pb.h" | 16 #include "components/autofill/core/browser/proto/autofill_sync.pb.h" |
| 15 #include "components/autofill/core/browser/webdata/autofill_metadata_change_list .h" | 17 #include "components/autofill/core/browser/webdata/autofill_metadata_change_list .h" |
| 16 #include "components/autofill/core/browser/webdata/autofill_table.h" | 18 #include "components/autofill/core/browser/webdata/autofill_table.h" |
| 17 #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" | 19 #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" |
| 18 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" | 20 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" |
| 19 #include "components/sync/model/entity_data.h" | 21 #include "components/sync/model/entity_data.h" |
| 20 #include "components/sync/model/model_type_change_processor.h" | 22 #include "components/sync/model/model_type_change_processor.h" |
| 21 #include "components/sync/model/mutable_data_batch.h" | 23 #include "components/sync/model/mutable_data_batch.h" |
| 22 #include "net/base/escape.h" | 24 #include "net/base/escape.h" |
| 23 | 25 |
| 26 using base::Optional; | |
| 27 using base::Time; | |
| 28 using sync_pb::AutofillSpecifics; | |
| 29 using syncer::EntityChange; | |
| 30 using syncer::EntityChangeList; | |
| 31 using syncer::EntityData; | |
| 32 using syncer::EntityDataMap; | |
| 33 using syncer::MetadataChangeList; | |
| 34 using syncer::ModelError; | |
| 35 using syncer::ModelTypeChangeProcessor; | |
| 36 using syncer::MutableDataBatch; | |
| 37 | |
| 24 namespace autofill { | 38 namespace autofill { |
| 25 | 39 |
| 26 namespace { | 40 namespace { |
| 27 | 41 |
| 28 const char kAutocompleteEntryNamespaceTag[] = "autofill_entry|"; | 42 const char kAutocompleteEntryNamespaceTag[] = "autofill_entry|"; |
| 29 const char kAutocompleteTagDelimiter[] = "|"; | 43 const char kAutocompleteTagDelimiter[] = "|"; |
| 30 | 44 |
| 45 // Simplify checking for optional errors and returning only when present. | |
| 46 #define RETURN_IF_ERROR(x) \ | |
| 47 if (Optional<ModelError> ret_val = x) { \ | |
| 48 return ret_val; \ | |
| 49 } | |
| 50 | |
| 31 void* UserDataKey() { | 51 void* UserDataKey() { |
| 32 // Use the address of a static that COMDAT folding won't ever collide | 52 // Use the address of a static that COMDAT folding won't ever collide |
| 33 // with something else. | 53 // with something else. |
| 34 static int user_data_key = 0; | 54 static int user_data_key = 0; |
| 35 return reinterpret_cast<void*>(&user_data_key); | 55 return reinterpret_cast<void*>(&user_data_key); |
| 36 } | 56 } |
| 37 | 57 |
| 38 std::unique_ptr<syncer::EntityData> CreateEntityData( | 58 std::unique_ptr<EntityData> CreateEntityData(const AutofillEntry& entry) { |
| 39 const AutofillEntry& entry) { | 59 auto entity_data = base::MakeUnique<EntityData>(); |
| 40 auto entity_data = base::MakeUnique<syncer::EntityData>(); | |
| 41 entity_data->non_unique_name = base::UTF16ToUTF8(entry.key().name()); | 60 entity_data->non_unique_name = base::UTF16ToUTF8(entry.key().name()); |
| 42 sync_pb::AutofillSpecifics* autofill = | 61 AutofillSpecifics* autofill = entity_data->specifics.mutable_autofill(); |
| 43 entity_data->specifics.mutable_autofill(); | |
| 44 autofill->set_name(base::UTF16ToUTF8(entry.key().name())); | 62 autofill->set_name(base::UTF16ToUTF8(entry.key().name())); |
| 45 autofill->set_value(base::UTF16ToUTF8(entry.key().value())); | 63 autofill->set_value(base::UTF16ToUTF8(entry.key().value())); |
| 46 autofill->add_usage_timestamp(entry.date_created().ToInternalValue()); | 64 autofill->add_usage_timestamp(entry.date_created().ToInternalValue()); |
| 47 if (entry.date_created() != entry.date_last_used()) | 65 if (entry.date_created() != entry.date_last_used()) |
| 48 autofill->add_usage_timestamp(entry.date_last_used().ToInternalValue()); | 66 autofill->add_usage_timestamp(entry.date_last_used().ToInternalValue()); |
| 49 return entity_data; | 67 return entity_data; |
| 50 } | 68 } |
| 51 | 69 |
| 52 std::string BuildSerializedStorageKey(const std::string& name, | 70 std::string BuildSerializedStorageKey(const std::string& name, |
| 53 const std::string& value) { | 71 const std::string& value) { |
| 54 AutofillSyncStorageKey proto; | 72 AutofillSyncStorageKey proto; |
| 55 proto.set_name(name); | 73 proto.set_name(name); |
| 56 proto.set_value(value); | 74 proto.set_value(value); |
| 57 return proto.SerializeAsString(); | 75 return proto.SerializeAsString(); |
| 58 } | 76 } |
| 59 | 77 |
| 60 std::string GetStorageKeyFromModel(const AutofillKey& key) { | 78 std::string GetStorageKeyFromModel(const AutofillKey& key) { |
| 61 return BuildSerializedStorageKey(base::UTF16ToUTF8(key.name()), | 79 return BuildSerializedStorageKey(base::UTF16ToUTF8(key.name()), |
| 62 base::UTF16ToUTF8(key.value())); | 80 base::UTF16ToUTF8(key.value())); |
| 63 } | 81 } |
| 64 | 82 |
| 83 AutofillEntry MergeEntryDates(const AutofillEntry& entry1, | |
| 84 const AutofillEntry& entry2) { | |
| 85 DCHECK(entry1.key() == entry2.key()); | |
| 86 return AutofillEntry( | |
| 87 entry1.key(), std::min(entry1.date_created(), entry2.date_created()), | |
| 88 std::max(entry1.date_last_used(), entry2.date_last_used())); | |
| 89 } | |
| 90 | |
| 91 bool ParseStorageKey(const std::string& storage_key, AutofillKey* out_key) { | |
| 92 AutofillSyncStorageKey proto; | |
| 93 if (proto.ParseFromString(storage_key)) { | |
| 94 *out_key = AutofillKey(base::UTF8ToUTF16(proto.name()), | |
| 95 base::UTF8ToUTF16((proto.value()))); | |
| 96 return true; | |
| 97 } else { | |
| 98 return false; | |
| 99 } | |
| 100 } | |
| 101 | |
| 102 AutofillEntry CreateAutofillEntry(const AutofillSpecifics& autofill_specifics) { | |
| 103 AutofillKey key(base::UTF8ToUTF16(autofill_specifics.name()), | |
| 104 base::UTF8ToUTF16(autofill_specifics.value())); | |
| 105 Time date_created, date_last_used; | |
| 106 const google::protobuf::RepeatedField<int64_t>& timestamps = | |
| 107 autofill_specifics.usage_timestamp(); | |
| 108 if (!timestamps.empty()) { | |
| 109 auto iter_pair = std::minmax_element(timestamps.begin(), timestamps.end()); | |
| 110 date_created = Time::FromInternalValue(*iter_pair.first); | |
| 111 date_last_used = Time::FromInternalValue(*iter_pair.second); | |
| 112 } | |
| 113 return AutofillEntry(key, date_created, date_last_used); | |
| 114 } | |
| 115 | |
| 116 // This is used to respond to ApplySyncChanges() and MergeSyncData(). Attempts | |
| 117 // to lazily load local data, and then react to sync data by maintain internal | |
|
maxbogue
2017/01/12 22:54:07
maintaining
skym
2017/01/13 16:46:44
Done.
| |
| 118 // state until flush calls are made, at which point the applicable modifications | |
| 119 // should be sent towards local and sync directions. | |
| 120 class SyncDifferenceTracker { | |
| 121 public: | |
| 122 explicit SyncDifferenceTracker(AutofillTable* table) : table_(table) {} | |
| 123 | |
| 124 Optional<ModelError> IncorporateRemoteSpecifics( | |
| 125 const std::string& storage_key, | |
| 126 const AutofillSpecifics& specifics) { | |
| 127 if (!specifics.has_value()) { | |
| 128 // A long time ago autofill had a different format, and it's possible we | |
| 129 // could encounter some of that legacy data. It is not useful to us, | |
| 130 // because an autofill entry with no value will not place any text in a | |
| 131 // form for the user. So drop all of these on the floor. | |
| 132 DVLOG(1) << "Dropping old-style autofill profile change."; | |
| 133 return {}; | |
| 134 } | |
| 135 | |
| 136 const AutofillEntry remote = CreateAutofillEntry(specifics); | |
| 137 DCHECK_EQ(storage_key, GetStorageKeyFromModel(remote.key())); | |
| 138 | |
| 139 Optional<AutofillEntry> local; | |
| 140 if (!ReadEntry(remote.key(), &local)) { | |
| 141 return ModelError(FROM_HERE, "Failed reading from WebDatabase."); | |
| 142 } else if (!local) { | |
| 143 save_to_local_.push_back(remote); | |
| 144 } else if (remote != local.value()) { | |
| 145 if (specifics.usage_timestamp().empty()) { | |
| 146 // Skip merging if there are no timestamps. We don't want to wipe out | |
| 147 // a local value of |date_created| if the remote copy is oddly formed. | |
| 148 save_to_sync_.push_back(local.value()); | |
| 149 } else { | |
| 150 const AutofillEntry merged = MergeEntryDates(local.value(), remote); | |
| 151 save_to_local_.push_back(merged); | |
| 152 save_to_sync_.push_back(merged); | |
| 153 } | |
| 154 unique_to_local_.erase(local.value()); | |
| 155 } | |
| 156 return {}; | |
| 157 } | |
| 158 | |
| 159 Optional<ModelError> IncorporateRemoteDelete(const std::string& storage_key) { | |
| 160 AutofillKey key; | |
| 161 if (!ParseStorageKey(storage_key, &key)) { | |
| 162 return ModelError(FROM_HERE, "Failed parsing storage key."); | |
| 163 } | |
| 164 delete_from_local_.insert(key); | |
| 165 return {}; | |
| 166 } | |
| 167 | |
| 168 Optional<ModelError> FlushToLocal(AutofillWebDataBackend* web_data_backend) { | |
| 169 for (const AutofillKey& key : delete_from_local_) { | |
| 170 if (!table_->RemoveFormElement(key.name(), key.value())) { | |
| 171 return ModelError(FROM_HERE, "Failed deleting from WebDatabase"); | |
| 172 } | |
| 173 } | |
| 174 if (!table_->UpdateAutofillEntries(save_to_local_)) { | |
| 175 return ModelError(FROM_HERE, "Failed updating WebDatabase"); | |
| 176 } | |
| 177 if (!delete_from_local_.empty() || !save_to_local_.empty()) { | |
| 178 web_data_backend->NotifyOfMultipleAutofillChanges(); | |
| 179 } | |
| 180 return {}; | |
| 181 } | |
| 182 | |
| 183 Optional<ModelError> FlushToSync( | |
| 184 bool include_local_only, | |
| 185 std::unique_ptr<MetadataChangeList> metadata_change_list, | |
| 186 ModelTypeChangeProcessor* change_processor) { | |
| 187 for (const AutofillEntry& entry : save_to_sync_) { | |
| 188 change_processor->Put(GetStorageKeyFromModel(entry.key()), | |
| 189 CreateEntityData(entry), | |
| 190 metadata_change_list.get()); | |
| 191 } | |
| 192 if (include_local_only) { | |
| 193 if (!InitializeIfNeeded()) { | |
| 194 return ModelError(FROM_HERE, "Failed reading from WebDatabase."); | |
| 195 } | |
| 196 for (const AutofillEntry& entry : unique_to_local_) { | |
| 197 // This should never be true because only ApplySyncChanges should be | |
| 198 // calling IncorporateRemoteDelete, while only MergeSyncData should be | |
| 199 // passing in true for |include_local_only|. If this requirement | |
| 200 // changes, this DCHECK can change to act as a filter. | |
| 201 DCHECK(delete_from_local_.find(entry.key()) == | |
| 202 delete_from_local_.end()); | |
| 203 change_processor->Put(GetStorageKeyFromModel(entry.key()), | |
| 204 CreateEntityData(entry), | |
| 205 metadata_change_list.get()); | |
| 206 } | |
| 207 } | |
| 208 return static_cast<AutofillMetadataChangeList*>(metadata_change_list.get()) | |
| 209 ->TakeError(); | |
| 210 } | |
| 211 | |
| 212 private: | |
| 213 // There are three major outcomes of this method. | |
| 214 // 1. An error is encountered reading from the db, false is returned. | |
| 215 // 2. The entry is not found, |entry| will not be touched. | |
| 216 // 3. The entry is found, |entry| will be set. | |
| 217 bool ReadEntry(const AutofillKey& key, Optional<AutofillEntry>* entry) { | |
| 218 if (!InitializeIfNeeded()) { | |
| 219 return false; | |
| 220 } | |
| 221 auto iter = unique_to_local_.find(AutofillEntry(key, Time(), Time())); | |
| 222 if (iter != unique_to_local_.end()) { | |
| 223 *entry = *iter; | |
| 224 } | |
| 225 return true; | |
| 226 } | |
| 227 | |
| 228 bool InitializeIfNeeded() { | |
| 229 if (initialized_) { | |
| 230 return true; | |
| 231 } | |
| 232 | |
| 233 std::vector<AutofillEntry> vector; | |
| 234 if (!table_->GetAllAutofillEntries(&vector)) { | |
| 235 return false; | |
| 236 } | |
| 237 | |
| 238 unique_to_local_ = std::set<AutofillEntry>(vector.begin(), vector.end()); | |
| 239 initialized_ = true; | |
| 240 return true; | |
| 241 } | |
| 242 | |
| 243 AutofillTable* table_; | |
| 244 | |
| 245 // This class attempts to lazily load data from |table_|. This field tracks | |
| 246 // if that has happened or not yet. To facilitate this, the first usage of | |
| 247 // |unique_to_local_| should typically be done through ReadEntry(). | |
|
maxbogue
2017/01/12 22:54:07
My previous comment here was wrong. What I meant t
skym
2017/01/13 16:46:44
Done.
| |
| 248 bool initialized_ = false; | |
| 249 | |
| 250 // Important to note that because AutofillEntry's operator > simply compares | |
|
maxbogue
2017/01/12 22:54:08
the most nit of nits: s/>/<
skym
2017/01/13 16:46:43
Done.
| |
| 251 // contained AutofillKeys, this acts as a map<AutofillKey, AutofillEntry>. | |
| 252 // This initially contains all local data, but as sync data is encountered, | |
| 253 // entries are removed from here. | |
| 254 std::set<AutofillEntry> unique_to_local_; | |
| 255 | |
| 256 std::set<AutofillKey> delete_from_local_; | |
| 257 std::vector<AutofillEntry> save_to_local_; | |
| 258 | |
| 259 // Contains merged data for entries that existed on both sync and local sides | |
| 260 // and need to be saved back to sync. | |
| 261 std::vector<AutofillEntry> save_to_sync_; | |
| 262 | |
| 263 DISALLOW_COPY_AND_ASSIGN(SyncDifferenceTracker); | |
| 264 }; | |
| 265 | |
| 65 } // namespace | 266 } // namespace |
| 66 | 267 |
| 67 // static | 268 // static |
| 68 void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend( | 269 void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend( |
| 69 AutofillWebDataService* web_data_service, | 270 AutofillWebDataService* web_data_service, |
| 70 AutofillWebDataBackend* web_data_backend) { | 271 AutofillWebDataBackend* web_data_backend) { |
| 71 web_data_service->GetDBUserData()->SetUserData( | 272 web_data_service->GetDBUserData()->SetUserData( |
| 72 UserDataKey(), | 273 UserDataKey(), |
| 73 new AutocompleteSyncBridge( | 274 new AutocompleteSyncBridge( |
| 74 web_data_backend, | 275 web_data_backend, base::Bind(&ModelTypeChangeProcessor::Create))); |
| 75 base::Bind(&syncer::ModelTypeChangeProcessor::Create))); | |
| 76 } | 276 } |
| 77 | 277 |
| 78 // static | 278 // static |
| 79 AutocompleteSyncBridge* AutocompleteSyncBridge::FromWebDataService( | 279 AutocompleteSyncBridge* AutocompleteSyncBridge::FromWebDataService( |
| 80 AutofillWebDataService* web_data_service) { | 280 AutofillWebDataService* web_data_service) { |
| 81 return static_cast<AutocompleteSyncBridge*>( | 281 return static_cast<AutocompleteSyncBridge*>( |
| 82 web_data_service->GetDBUserData()->GetUserData(UserDataKey())); | 282 web_data_service->GetDBUserData()->GetUserData(UserDataKey())); |
| 83 } | 283 } |
| 84 | 284 |
| 85 AutocompleteSyncBridge::AutocompleteSyncBridge( | 285 AutocompleteSyncBridge::AutocompleteSyncBridge( |
| 86 AutofillWebDataBackend* backend, | 286 AutofillWebDataBackend* backend, |
| 87 const ChangeProcessorFactory& change_processor_factory) | 287 const ChangeProcessorFactory& change_processor_factory) |
| 88 : ModelTypeSyncBridge(change_processor_factory, syncer::AUTOFILL), | 288 : ModelTypeSyncBridge(change_processor_factory, syncer::AUTOFILL), |
| 89 web_data_backend_(backend), | 289 web_data_backend_(backend), |
| 90 scoped_observer_(this) { | 290 scoped_observer_(this) { |
| 91 DCHECK(web_data_backend_); | 291 DCHECK(web_data_backend_); |
| 92 | 292 |
| 93 scoped_observer_.Add(web_data_backend_); | 293 scoped_observer_.Add(web_data_backend_); |
| 94 } | 294 } |
| 95 | 295 |
| 96 AutocompleteSyncBridge::~AutocompleteSyncBridge() { | 296 AutocompleteSyncBridge::~AutocompleteSyncBridge() { |
| 97 DCHECK(thread_checker_.CalledOnValidThread()); | 297 DCHECK(thread_checker_.CalledOnValidThread()); |
| 98 } | 298 } |
| 99 | 299 |
| 100 std::unique_ptr<syncer::MetadataChangeList> | 300 std::unique_ptr<MetadataChangeList> |
| 101 AutocompleteSyncBridge::CreateMetadataChangeList() { | 301 AutocompleteSyncBridge::CreateMetadataChangeList() { |
| 102 DCHECK(thread_checker_.CalledOnValidThread()); | 302 DCHECK(thread_checker_.CalledOnValidThread()); |
| 103 return base::MakeUnique<AutofillMetadataChangeList>(GetAutofillTable(), | 303 return base::MakeUnique<AutofillMetadataChangeList>(GetAutofillTable(), |
| 104 syncer::AUTOFILL); | 304 syncer::AUTOFILL); |
| 105 } | 305 } |
| 106 | 306 |
| 107 base::Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData( | 307 Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData( |
| 108 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, | 308 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 109 syncer::EntityDataMap entity_data_map) { | 309 EntityDataMap entity_data_map) { |
| 110 DCHECK(thread_checker_.CalledOnValidThread()); | 310 DCHECK(thread_checker_.CalledOnValidThread()); |
| 111 NOTIMPLEMENTED(); | 311 |
| 312 // TODO(skym, crbug.com/680218): Uncomment and add unit tests. | |
| 313 /*SyncDifferenceTracker tracker(GetAutofillTable()); | |
| 314 for (auto kv : entity_data_map) { | |
| 315 // TODO(skym, crbug.com/680550): Does this need to handle deletes? | |
|
maxbogue
2017/01/12 22:54:07
Re offline discussion: no! :)
skym
2017/01/13 16:46:44
Done.
| |
| 316 DCHECK(kv.second->specifics.has_autofill()); | |
| 317 RETURN_IF_ERROR(tracker.IncorporateRemoteSpecifics( | |
| 318 kv.first, kv.second->specifics.autofill())); | |
| 319 } | |
| 320 | |
| 321 RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_)); | |
| 322 RETURN_IF_ERROR(tracker.FlushToSync(true, std::move(metadata_change_list), | |
| 323 change_processor())); | |
| 324 web_data_backend_->RemoveExpiredFormElements(); | |
| 325 web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL);*/ | |
| 112 return {}; | 326 return {}; |
| 113 } | 327 } |
| 114 | 328 |
| 115 base::Optional<syncer::ModelError> AutocompleteSyncBridge::ApplySyncChanges( | 329 Optional<ModelError> AutocompleteSyncBridge::ApplySyncChanges( |
| 116 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, | 330 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 117 syncer::EntityChangeList entity_changes) { | 331 EntityChangeList entity_changes) { |
| 118 DCHECK(thread_checker_.CalledOnValidThread()); | 332 DCHECK(thread_checker_.CalledOnValidThread()); |
| 119 NOTIMPLEMENTED(); | 333 |
| 334 SyncDifferenceTracker tracker(GetAutofillTable()); | |
| 335 for (const EntityChange& change : entity_changes) { | |
| 336 if (change.type() == EntityChange::ACTION_DELETE) { | |
| 337 RETURN_IF_ERROR(tracker.IncorporateRemoteDelete(change.storage_key())); | |
| 338 } else { | |
| 339 DCHECK(change.data().specifics.has_autofill()); | |
| 340 RETURN_IF_ERROR(tracker.IncorporateRemoteSpecifics( | |
| 341 change.storage_key(), change.data().specifics.autofill())); | |
| 342 } | |
| 343 } | |
| 344 | |
| 345 RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_)); | |
| 346 RETURN_IF_ERROR(tracker.FlushToSync(false, std::move(metadata_change_list), | |
| 347 change_processor())); | |
| 348 web_data_backend_->RemoveExpiredFormElements(); | |
| 120 return {}; | 349 return {}; |
| 121 } | 350 } |
| 122 | 351 |
| 123 void AutocompleteSyncBridge::AutocompleteSyncBridge::GetData( | 352 void AutocompleteSyncBridge::AutocompleteSyncBridge::GetData( |
| 124 StorageKeyList storage_keys, | 353 StorageKeyList storage_keys, |
| 125 DataCallback callback) { | 354 DataCallback callback) { |
| 126 DCHECK(thread_checker_.CalledOnValidThread()); | 355 DCHECK(thread_checker_.CalledOnValidThread()); |
| 127 std::vector<AutofillEntry> entries; | 356 std::vector<AutofillEntry> entries; |
| 128 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { | 357 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { |
| 129 change_processor()->ReportError(FROM_HERE, | 358 change_processor()->ReportError(FROM_HERE, |
| 130 "Failed to load entries from table."); | 359 "Failed to load entries from table."); |
| 131 return; | 360 return; |
| 132 } | 361 } |
| 133 | 362 |
| 134 std::unordered_set<std::string> keys_set; | 363 std::unordered_set<std::string> keys_set(storage_keys.begin(), |
| 135 for (const auto& key : storage_keys) { | 364 storage_keys.end()); |
| 136 keys_set.insert(key); | 365 auto batch = base::MakeUnique<MutableDataBatch>(); |
| 137 } | |
| 138 | |
| 139 auto batch = base::MakeUnique<syncer::MutableDataBatch>(); | |
| 140 for (const AutofillEntry& entry : entries) { | 366 for (const AutofillEntry& entry : entries) { |
| 141 std::string key = GetStorageKeyFromModel(entry.key()); | 367 std::string key = GetStorageKeyFromModel(entry.key()); |
| 142 if (keys_set.find(key) != keys_set.end()) { | 368 if (keys_set.find(key) != keys_set.end()) { |
| 143 batch->Put(key, CreateEntityData(entry)); | 369 batch->Put(key, CreateEntityData(entry)); |
| 144 } | 370 } |
| 145 } | 371 } |
| 146 callback.Run(std::move(batch)); | 372 callback.Run(std::move(batch)); |
| 147 } | 373 } |
| 148 | 374 |
| 149 void AutocompleteSyncBridge::GetAllData(DataCallback callback) { | 375 void AutocompleteSyncBridge::GetAllData(DataCallback callback) { |
| 150 DCHECK(thread_checker_.CalledOnValidThread()); | 376 DCHECK(thread_checker_.CalledOnValidThread()); |
| 151 | 377 |
| 152 std::vector<AutofillEntry> entries; | 378 std::vector<AutofillEntry> entries; |
| 153 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { | 379 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { |
| 154 change_processor()->ReportError(FROM_HERE, | 380 change_processor()->ReportError(FROM_HERE, |
| 155 "Failed to load entries from table."); | 381 "Failed to load entries from table."); |
| 156 return; | 382 return; |
| 157 } | 383 } |
| 158 | 384 |
| 159 auto batch = base::MakeUnique<syncer::MutableDataBatch>(); | 385 auto batch = base::MakeUnique<MutableDataBatch>(); |
| 160 for (const AutofillEntry& entry : entries) { | 386 for (const AutofillEntry& entry : entries) { |
| 161 batch->Put(GetStorageKeyFromModel(entry.key()), CreateEntityData(entry)); | 387 batch->Put(GetStorageKeyFromModel(entry.key()), CreateEntityData(entry)); |
| 162 } | 388 } |
| 163 callback.Run(std::move(batch)); | 389 callback.Run(std::move(batch)); |
| 164 } | 390 } |
| 165 | 391 |
| 166 std::string AutocompleteSyncBridge::GetClientTag( | 392 std::string AutocompleteSyncBridge::GetClientTag( |
| 167 const syncer::EntityData& entity_data) { | 393 const EntityData& entity_data) { |
| 168 DCHECK(entity_data.specifics.has_autofill()); | 394 DCHECK(entity_data.specifics.has_autofill()); |
| 169 const sync_pb::AutofillSpecifics specifics = entity_data.specifics.autofill(); | 395 const AutofillSpecifics specifics = entity_data.specifics.autofill(); |
| 170 return std::string(kAutocompleteEntryNamespaceTag) + | 396 return std::string(kAutocompleteEntryNamespaceTag) + |
| 171 net::EscapePath(specifics.name()) + | 397 net::EscapePath(specifics.name()) + |
| 172 std::string(kAutocompleteTagDelimiter) + | 398 std::string(kAutocompleteTagDelimiter) + |
| 173 net::EscapePath(specifics.value()); | 399 net::EscapePath(specifics.value()); |
| 174 } | 400 } |
| 175 | 401 |
| 176 std::string AutocompleteSyncBridge::GetStorageKey( | 402 std::string AutocompleteSyncBridge::GetStorageKey( |
| 177 const syncer::EntityData& entity_data) { | 403 const EntityData& entity_data) { |
| 178 DCHECK(entity_data.specifics.has_autofill()); | 404 DCHECK(entity_data.specifics.has_autofill()); |
| 179 const sync_pb::AutofillSpecifics specifics = entity_data.specifics.autofill(); | 405 const AutofillSpecifics specifics = entity_data.specifics.autofill(); |
| 180 return BuildSerializedStorageKey(specifics.name(), specifics.value()); | 406 return BuildSerializedStorageKey(specifics.name(), specifics.value()); |
| 181 } | 407 } |
| 182 | 408 |
| 183 // AutofillWebDataServiceObserverOnDBThread implementation. | 409 // AutofillWebDataServiceObserverOnDBThread implementation. |
| 184 void AutocompleteSyncBridge::AutofillEntriesChanged( | 410 void AutocompleteSyncBridge::AutofillEntriesChanged( |
| 185 const AutofillChangeList& changes) { | 411 const AutofillChangeList& changes) { |
| 186 DCHECK(thread_checker_.CalledOnValidThread()); | 412 DCHECK(thread_checker_.CalledOnValidThread()); |
| 187 } | 413 } |
| 188 | 414 |
| 189 // static | |
| 190 AutofillEntry AutocompleteSyncBridge::CreateAutofillEntry( | |
| 191 const sync_pb::AutofillSpecifics& autofill_specifics) { | |
| 192 AutofillKey key(base::UTF8ToUTF16(autofill_specifics.name()), | |
| 193 base::UTF8ToUTF16(autofill_specifics.value())); | |
| 194 base::Time date_created, date_last_used; | |
| 195 const google::protobuf::RepeatedField<int64_t>& timestamps = | |
| 196 autofill_specifics.usage_timestamp(); | |
| 197 if (!timestamps.empty()) { | |
| 198 date_created = base::Time::FromInternalValue(*timestamps.begin()); | |
| 199 date_last_used = base::Time::FromInternalValue(*timestamps.rbegin()); | |
| 200 } | |
| 201 return AutofillEntry(key, date_created, date_last_used); | |
| 202 } | |
| 203 | |
| 204 AutofillTable* AutocompleteSyncBridge::GetAutofillTable() const { | 415 AutofillTable* AutocompleteSyncBridge::GetAutofillTable() const { |
| 205 return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); | 416 return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); |
| 206 } | 417 } |
| 207 | 418 |
| 208 } // namespace autofill | 419 } // namespace autofill |
| OLD | NEW |