| 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 maintaining |
| 118 // internal state until flush calls are made, at which point the applicable |
| 119 // modification 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(). |
| 248 bool initialized_ = false; |
| 249 |
| 250 // Important to note that because AutofillEntry's operator < simply compares |
| 251 // contained AutofillKeys, this acts as a map<AutofillKey, AutofillEntry>. |
| 252 // Shouldn't be accessed until either ReadEntry() or InitializeIfNeeded() is |
| 253 // called, afterward it will start with all the local data. As sync data is |
| 254 // encountered entries are removed from here, leaving only entries that exist |
| 255 // solely on the local client. |
| 256 std::set<AutofillEntry> unique_to_local_; |
| 257 |
| 258 std::set<AutofillKey> delete_from_local_; |
| 259 std::vector<AutofillEntry> save_to_local_; |
| 260 |
| 261 // Contains merged data for entries that existed on both sync and local sides |
| 262 // and need to be saved back to sync. |
| 263 std::vector<AutofillEntry> save_to_sync_; |
| 264 |
| 265 DISALLOW_COPY_AND_ASSIGN(SyncDifferenceTracker); |
| 266 }; |
| 267 |
| 65 } // namespace | 268 } // namespace |
| 66 | 269 |
| 67 // static | 270 // static |
| 68 void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend( | 271 void AutocompleteSyncBridge::CreateForWebDataServiceAndBackend( |
| 69 AutofillWebDataService* web_data_service, | 272 AutofillWebDataService* web_data_service, |
| 70 AutofillWebDataBackend* web_data_backend) { | 273 AutofillWebDataBackend* web_data_backend) { |
| 71 web_data_service->GetDBUserData()->SetUserData( | 274 web_data_service->GetDBUserData()->SetUserData( |
| 72 UserDataKey(), | 275 UserDataKey(), |
| 73 new AutocompleteSyncBridge( | 276 new AutocompleteSyncBridge( |
| 74 web_data_backend, | 277 web_data_backend, base::Bind(&ModelTypeChangeProcessor::Create))); |
| 75 base::Bind(&syncer::ModelTypeChangeProcessor::Create))); | |
| 76 } | 278 } |
| 77 | 279 |
| 78 // static | 280 // static |
| 79 AutocompleteSyncBridge* AutocompleteSyncBridge::FromWebDataService( | 281 AutocompleteSyncBridge* AutocompleteSyncBridge::FromWebDataService( |
| 80 AutofillWebDataService* web_data_service) { | 282 AutofillWebDataService* web_data_service) { |
| 81 return static_cast<AutocompleteSyncBridge*>( | 283 return static_cast<AutocompleteSyncBridge*>( |
| 82 web_data_service->GetDBUserData()->GetUserData(UserDataKey())); | 284 web_data_service->GetDBUserData()->GetUserData(UserDataKey())); |
| 83 } | 285 } |
| 84 | 286 |
| 85 AutocompleteSyncBridge::AutocompleteSyncBridge( | 287 AutocompleteSyncBridge::AutocompleteSyncBridge( |
| 86 AutofillWebDataBackend* backend, | 288 AutofillWebDataBackend* backend, |
| 87 const ChangeProcessorFactory& change_processor_factory) | 289 const ChangeProcessorFactory& change_processor_factory) |
| 88 : ModelTypeSyncBridge(change_processor_factory, syncer::AUTOFILL), | 290 : ModelTypeSyncBridge(change_processor_factory, syncer::AUTOFILL), |
| 89 web_data_backend_(backend), | 291 web_data_backend_(backend), |
| 90 scoped_observer_(this) { | 292 scoped_observer_(this) { |
| 91 DCHECK(web_data_backend_); | 293 DCHECK(web_data_backend_); |
| 92 | 294 |
| 93 scoped_observer_.Add(web_data_backend_); | 295 scoped_observer_.Add(web_data_backend_); |
| 94 } | 296 } |
| 95 | 297 |
| 96 AutocompleteSyncBridge::~AutocompleteSyncBridge() { | 298 AutocompleteSyncBridge::~AutocompleteSyncBridge() { |
| 97 DCHECK(thread_checker_.CalledOnValidThread()); | 299 DCHECK(thread_checker_.CalledOnValidThread()); |
| 98 } | 300 } |
| 99 | 301 |
| 100 std::unique_ptr<syncer::MetadataChangeList> | 302 std::unique_ptr<MetadataChangeList> |
| 101 AutocompleteSyncBridge::CreateMetadataChangeList() { | 303 AutocompleteSyncBridge::CreateMetadataChangeList() { |
| 102 DCHECK(thread_checker_.CalledOnValidThread()); | 304 DCHECK(thread_checker_.CalledOnValidThread()); |
| 103 return base::MakeUnique<AutofillMetadataChangeList>(GetAutofillTable(), | 305 return base::MakeUnique<AutofillMetadataChangeList>(GetAutofillTable(), |
| 104 syncer::AUTOFILL); | 306 syncer::AUTOFILL); |
| 105 } | 307 } |
| 106 | 308 |
| 107 base::Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData( | 309 Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData( |
| 108 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, | 310 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 109 syncer::EntityDataMap entity_data_map) { | 311 EntityDataMap entity_data_map) { |
| 110 DCHECK(thread_checker_.CalledOnValidThread()); | 312 DCHECK(thread_checker_.CalledOnValidThread()); |
| 111 NOTIMPLEMENTED(); | 313 |
| 314 // TODO(skym, crbug.com/680218): Uncomment and add unit tests. |
| 315 /*SyncDifferenceTracker tracker(GetAutofillTable()); |
| 316 for (auto kv : entity_data_map) { |
| 317 DCHECK(kv.second->specifics.has_autofill()); |
| 318 RETURN_IF_ERROR(tracker.IncorporateRemoteSpecifics( |
| 319 kv.first, kv.second->specifics.autofill())); |
| 320 } |
| 321 |
| 322 RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_)); |
| 323 RETURN_IF_ERROR(tracker.FlushToSync(true, std::move(metadata_change_list), |
| 324 change_processor())); |
| 325 web_data_backend_->RemoveExpiredFormElements(); |
| 326 web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL);*/ |
| 112 return {}; | 327 return {}; |
| 113 } | 328 } |
| 114 | 329 |
| 115 base::Optional<syncer::ModelError> AutocompleteSyncBridge::ApplySyncChanges( | 330 Optional<ModelError> AutocompleteSyncBridge::ApplySyncChanges( |
| 116 std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, | 331 std::unique_ptr<MetadataChangeList> metadata_change_list, |
| 117 syncer::EntityChangeList entity_changes) { | 332 EntityChangeList entity_changes) { |
| 118 DCHECK(thread_checker_.CalledOnValidThread()); | 333 DCHECK(thread_checker_.CalledOnValidThread()); |
| 119 NOTIMPLEMENTED(); | 334 |
| 335 SyncDifferenceTracker tracker(GetAutofillTable()); |
| 336 for (const EntityChange& change : entity_changes) { |
| 337 if (change.type() == EntityChange::ACTION_DELETE) { |
| 338 RETURN_IF_ERROR(tracker.IncorporateRemoteDelete(change.storage_key())); |
| 339 } else { |
| 340 DCHECK(change.data().specifics.has_autofill()); |
| 341 RETURN_IF_ERROR(tracker.IncorporateRemoteSpecifics( |
| 342 change.storage_key(), change.data().specifics.autofill())); |
| 343 } |
| 344 } |
| 345 |
| 346 RETURN_IF_ERROR(tracker.FlushToLocal(web_data_backend_)); |
| 347 RETURN_IF_ERROR(tracker.FlushToSync(false, std::move(metadata_change_list), |
| 348 change_processor())); |
| 349 web_data_backend_->RemoveExpiredFormElements(); |
| 120 return {}; | 350 return {}; |
| 121 } | 351 } |
| 122 | 352 |
| 123 void AutocompleteSyncBridge::AutocompleteSyncBridge::GetData( | 353 void AutocompleteSyncBridge::AutocompleteSyncBridge::GetData( |
| 124 StorageKeyList storage_keys, | 354 StorageKeyList storage_keys, |
| 125 DataCallback callback) { | 355 DataCallback callback) { |
| 126 DCHECK(thread_checker_.CalledOnValidThread()); | 356 DCHECK(thread_checker_.CalledOnValidThread()); |
| 127 std::vector<AutofillEntry> entries; | 357 std::vector<AutofillEntry> entries; |
| 128 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { | 358 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { |
| 129 change_processor()->ReportError(FROM_HERE, | 359 change_processor()->ReportError(FROM_HERE, |
| 130 "Failed to load entries from table."); | 360 "Failed to load entries from table."); |
| 131 return; | 361 return; |
| 132 } | 362 } |
| 133 | 363 |
| 134 std::unordered_set<std::string> keys_set; | 364 std::unordered_set<std::string> keys_set(storage_keys.begin(), |
| 135 for (const auto& key : storage_keys) { | 365 storage_keys.end()); |
| 136 keys_set.insert(key); | 366 auto batch = base::MakeUnique<MutableDataBatch>(); |
| 137 } | |
| 138 | |
| 139 auto batch = base::MakeUnique<syncer::MutableDataBatch>(); | |
| 140 for (const AutofillEntry& entry : entries) { | 367 for (const AutofillEntry& entry : entries) { |
| 141 std::string key = GetStorageKeyFromModel(entry.key()); | 368 std::string key = GetStorageKeyFromModel(entry.key()); |
| 142 if (keys_set.find(key) != keys_set.end()) { | 369 if (keys_set.find(key) != keys_set.end()) { |
| 143 batch->Put(key, CreateEntityData(entry)); | 370 batch->Put(key, CreateEntityData(entry)); |
| 144 } | 371 } |
| 145 } | 372 } |
| 146 callback.Run(std::move(batch)); | 373 callback.Run(std::move(batch)); |
| 147 } | 374 } |
| 148 | 375 |
| 149 void AutocompleteSyncBridge::GetAllData(DataCallback callback) { | 376 void AutocompleteSyncBridge::GetAllData(DataCallback callback) { |
| 150 DCHECK(thread_checker_.CalledOnValidThread()); | 377 DCHECK(thread_checker_.CalledOnValidThread()); |
| 151 | 378 |
| 152 std::vector<AutofillEntry> entries; | 379 std::vector<AutofillEntry> entries; |
| 153 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { | 380 if (!GetAutofillTable()->GetAllAutofillEntries(&entries)) { |
| 154 change_processor()->ReportError(FROM_HERE, | 381 change_processor()->ReportError(FROM_HERE, |
| 155 "Failed to load entries from table."); | 382 "Failed to load entries from table."); |
| 156 return; | 383 return; |
| 157 } | 384 } |
| 158 | 385 |
| 159 auto batch = base::MakeUnique<syncer::MutableDataBatch>(); | 386 auto batch = base::MakeUnique<MutableDataBatch>(); |
| 160 for (const AutofillEntry& entry : entries) { | 387 for (const AutofillEntry& entry : entries) { |
| 161 batch->Put(GetStorageKeyFromModel(entry.key()), CreateEntityData(entry)); | 388 batch->Put(GetStorageKeyFromModel(entry.key()), CreateEntityData(entry)); |
| 162 } | 389 } |
| 163 callback.Run(std::move(batch)); | 390 callback.Run(std::move(batch)); |
| 164 } | 391 } |
| 165 | 392 |
| 166 std::string AutocompleteSyncBridge::GetClientTag( | 393 std::string AutocompleteSyncBridge::GetClientTag( |
| 167 const syncer::EntityData& entity_data) { | 394 const EntityData& entity_data) { |
| 168 DCHECK(entity_data.specifics.has_autofill()); | 395 DCHECK(entity_data.specifics.has_autofill()); |
| 169 const sync_pb::AutofillSpecifics specifics = entity_data.specifics.autofill(); | 396 const AutofillSpecifics specifics = entity_data.specifics.autofill(); |
| 170 return std::string(kAutocompleteEntryNamespaceTag) + | 397 return std::string(kAutocompleteEntryNamespaceTag) + |
| 171 net::EscapePath(specifics.name()) + | 398 net::EscapePath(specifics.name()) + |
| 172 std::string(kAutocompleteTagDelimiter) + | 399 std::string(kAutocompleteTagDelimiter) + |
| 173 net::EscapePath(specifics.value()); | 400 net::EscapePath(specifics.value()); |
| 174 } | 401 } |
| 175 | 402 |
| 176 std::string AutocompleteSyncBridge::GetStorageKey( | 403 std::string AutocompleteSyncBridge::GetStorageKey( |
| 177 const syncer::EntityData& entity_data) { | 404 const EntityData& entity_data) { |
| 178 DCHECK(entity_data.specifics.has_autofill()); | 405 DCHECK(entity_data.specifics.has_autofill()); |
| 179 const sync_pb::AutofillSpecifics specifics = entity_data.specifics.autofill(); | 406 const AutofillSpecifics specifics = entity_data.specifics.autofill(); |
| 180 return BuildSerializedStorageKey(specifics.name(), specifics.value()); | 407 return BuildSerializedStorageKey(specifics.name(), specifics.value()); |
| 181 } | 408 } |
| 182 | 409 |
| 183 // AutofillWebDataServiceObserverOnDBThread implementation. | 410 // AutofillWebDataServiceObserverOnDBThread implementation. |
| 184 void AutocompleteSyncBridge::AutofillEntriesChanged( | 411 void AutocompleteSyncBridge::AutofillEntriesChanged( |
| 185 const AutofillChangeList& changes) { | 412 const AutofillChangeList& changes) { |
| 186 DCHECK(thread_checker_.CalledOnValidThread()); | 413 DCHECK(thread_checker_.CalledOnValidThread()); |
| 187 } | 414 } |
| 188 | 415 |
| 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 { | 416 AutofillTable* AutocompleteSyncBridge::GetAutofillTable() const { |
| 205 return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); | 417 return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase()); |
| 206 } | 418 } |
| 207 | 419 |
| 208 } // namespace autofill | 420 } // namespace autofill |
| OLD | NEW |