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(x) \ | |
|
maxbogue
2017/01/12 00:15:16
Reading through where this is used, I think I'd pr
skym
2017/01/12 17:44:00
Done.
| |
| 47 if (auto 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& first, | |
|
maxbogue
2017/01/12 00:15:16
Honestly variable names like a and b would probabl
skym
2017/01/12 17:44:00
Done.
| |
| 84 const AutofillEntry& second) { | |
| 85 DCHECK(first.key() == second.key()); | |
| 86 return AutofillEntry( | |
| 87 first.key(), std::min(first.date_created(), second.date_created()), | |
| 88 std::max(first.date_last_used(), second.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 std::vector<int64_t> sorted(timestamps.begin(), timestamps.end()); | |
|
maxbogue
2017/01/12 00:15:16
Consider using std::minmax_element (http://en.cppr
skym
2017/01/12 17:44:00
Love it! Done.
| |
| 110 std::sort(sorted.begin(), sorted.end()); | |
| 111 date_created = Time::FromInternalValue(*sorted.begin()); | |
| 112 date_last_used = Time::FromInternalValue(*sorted.rbegin()); | |
| 113 } | |
| 114 return AutofillEntry(key, date_created, date_last_used); | |
| 115 } | |
| 116 | |
| 117 // This is used to respond to ApplySyncChanges() and MergeSyncData(). Attempts | |
| 118 // to lazily load local data, and then react to sync data by maintain internal | |
| 119 // state until flush calls are made, at which point the applicable modifications | |
| 120 // should be sent towards local and sync directions. | |
| 121 class SyncDifferenceTracker { | |
| 122 public: | |
| 123 explicit SyncDifferenceTracker(AutofillTable* table) : table_(table) {} | |
| 124 | |
| 125 Optional<ModelError> IncorporateRemoteSpecifics( | |
| 126 const std::string& storage_key, | |
| 127 const AutofillSpecifics& specifics) { | |
| 128 if (!specifics.has_value()) { | |
| 129 // A long time ago autofill had a different format, and it's possible we | |
| 130 // could encounter some of that legacy data. It is not useful to us, | |
| 131 // because an autofill entry with no value will not place any text in a | |
| 132 // form for the user. So drop all of these on the floor. | |
| 133 DVLOG(1) << "Dropping old-style autofill profile change."; | |
| 134 return {}; | |
| 135 } | |
| 136 | |
| 137 const AutofillEntry remote = CreateAutofillEntry(specifics); | |
| 138 DCHECK_EQ(storage_key, GetStorageKeyFromModel(remote.key())); | |
| 139 | |
| 140 Optional<AutofillEntry> local; | |
| 141 if (!ReadEntry(remote.key(), &local)) { | |
| 142 return ModelError(FROM_HERE, "Failed reading from WebDatabase."); | |
| 143 } else if (!local) { | |
| 144 save_to_local_.push_back(remote); | |
| 145 } else if (remote != local.value()) { | |
| 146 if (specifics.usage_timestamp().empty()) { | |
| 147 // Skip merging if there are no timestamps. We don't want to wipe out | |
| 148 // a local value of |date_created| if the remote copy is oddly formed. | |
| 149 save_to_sync_.push_back(local.value()); | |
| 150 } else { | |
| 151 const AutofillEntry merged = MergeEntryDates(local.value(), remote); | |
| 152 save_to_local_.push_back(merged); | |
| 153 save_to_sync_.push_back(merged); | |
| 154 } | |
| 155 unique_to_local_.erase(local.value()); | |
| 156 } | |
| 157 return {}; | |
| 158 } | |
| 159 | |
| 160 Optional<ModelError> IncorporateRemoteDelete(const std::string& storage_key) { | |
| 161 AutofillKey key; | |
| 162 if (!ParseStorageKey(storage_key, &key)) { | |
| 163 return ModelError(FROM_HERE, "Failed parsing storage key."); | |
| 164 } | |
| 165 delete_from_local_.insert(key); | |
| 166 return {}; | |
| 167 } | |
| 168 | |
| 169 Optional<ModelError> FlushToLocal(AutofillWebDataBackend* web_data_backend) { | |
| 170 for (const AutofillKey& key : delete_from_local_) { | |
| 171 if (!table_->RemoveFormElement(key.name(), key.value())) { | |
| 172 return ModelError(FROM_HERE, "Failed deleting from WebDatabase"); | |
| 173 } | |
| 174 } | |
| 175 if (!table_->UpdateAutofillEntries(save_to_local_)) { | |
| 176 return ModelError(FROM_HERE, "Failed updating WebDatabase"); | |
| 177 } | |
| 178 if (!delete_from_local_.empty() || !save_to_local_.empty()) { | |
| 179 web_data_backend->NotifyOfMultipleAutofillChanges(); | |
| 180 } | |
| 181 return {}; | |
| 182 } | |
| 183 | |
| 184 Optional<ModelError> FlushToSync( | |
| 185 bool include_local_only, | |
| 186 std::unique_ptr<MetadataChangeList> metadata_change_list, | |
| 187 ModelTypeChangeProcessor* change_processor) { | |
| 188 for (const AutofillEntry& entry : save_to_sync_) { | |
| 189 change_processor->Put(GetStorageKeyFromModel(entry.key()), | |
| 190 CreateEntityData(entry), | |
| 191 metadata_change_list.get()); | |
| 192 } | |
| 193 if (include_local_only) { | |
| 194 if (!InitializeIfNeeded()) { | |
| 195 return ModelError(FROM_HERE, "Failed reading from WebDatabase."); | |
| 196 } | |
| 197 for (const AutofillEntry& entry : unique_to_local_) { | |
| 198 // This should never be true because only ApplySyncChanges should be | |
|
maxbogue
2017/01/12 00:15:16
I don't believe this is true; deletes can come thr
skym
2017/01/12 17:44:00
Sigh... Yeah, I messed this up (great catch btw Ma
| |
| 199 // calling IncorporateRemoteDelete. While only MergeSyncData should be | |
|
maxbogue
2017/01/12 00:15:16
s/. While/, while
skym
2017/01/12 17:44:00
Done.
| |
| 200 // passing in true for |include_local_only|. If this requirement | |
| 201 // changes, this DCHECK can change to act as a filter. | |
| 202 DCHECK(delete_from_local_.find(entry.key()) == | |
| 203 delete_from_local_.end()); | |
| 204 change_processor->Put(GetStorageKeyFromModel(entry.key()), | |
| 205 CreateEntityData(entry), | |
| 206 metadata_change_list.get()); | |
| 207 } | |
| 208 } | |
| 209 return static_cast<AutofillMetadataChangeList*>(metadata_change_list.get()) | |
| 210 ->TakeError(); | |
| 211 } | |
| 212 | |
| 213 private: | |
| 214 // There are three major outcomes of this method. | |
| 215 // 1. An error is encountered reading from the db, false is returned. | |
| 216 // 2. The entry is not found, |entry| will not be touched. | |
| 217 // 3. The entry is found, |entry| will be set. | |
| 218 bool ReadEntry(const AutofillKey& key, Optional<AutofillEntry>* entry) { | |
| 219 if (!InitializeIfNeeded()) { | |
| 220 return false; | |
| 221 } | |
| 222 std::set<AutofillEntry>::iterator iter = | |
|
maxbogue
2017/01/12 00:15:16
auto
skym
2017/01/12 17:44:00
Done.
| |
| 223 unique_to_local_.find(AutofillEntry(key, Time(), Time())); | |
| 224 if (iter != unique_to_local_.end()) { | |
| 225 *entry = *iter; | |
| 226 } | |
| 227 return true; | |
| 228 } | |
| 229 | |
| 230 bool InitializeIfNeeded() { | |
| 231 if (initialized_) { | |
| 232 return true; | |
| 233 } | |
| 234 | |
| 235 std::vector<AutofillEntry> vector; | |
| 236 if (!table_->GetAllAutofillEntries(&vector)) { | |
| 237 return false; | |
| 238 } | |
| 239 | |
| 240 unique_to_local_ = std::set<AutofillEntry>(vector.begin(), vector.end()); | |
| 241 initialized_ = true; | |
| 242 return true; | |
| 243 } | |
| 244 | |
| 245 AutofillTable* table_; | |
| 246 | |
| 247 // This class attempts to lazily load data from |table_|. This field tracks | |
| 248 // if that has happened or not yet. To facilitate this, the first usage of | |
| 249 // |unique_to_local_| should typically be done through ReadEntry(). | |
|
maxbogue
2017/01/12 00:15:16
s/should typically/must
skym
2017/01/12 17:44:00
I'm going to keep "should typically". The thing is
| |
| 250 bool initialized_ = false; | |
| 251 | |
| 252 // Important to note that because AutofillEntry's operator > simply compares | |
| 253 // contained AutofillKeys, this acts as a map<AutofillKey, AutofillEntry>. | |
| 254 // This initially contains all local data, but as sync data is encountered, | |
| 255 // entries are removed from here. | |
| 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 current data for entries that are know to exist on both sync and | |
|
maxbogue
2017/01/12 00:15:16
Maybe "Contains merged data for entries that exist
skym
2017/01/12 17:44:00
Done.
| |
| 262 // local sides, as a result of merging timestamps, sync needs to be updated. | |
| 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(tracker.IncorporateRemoteSpecifics( | |
| 319 kv.first, kv.second->specifics.autofill())); | |
| 320 } | |
| 321 | |
| 322 RETURN_IF(tracker.FlushToLocal(web_data_backend_)); | |
| 323 RETURN_IF(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(tracker.IncorporateRemoteDelete(change.storage_key())); | |
| 339 } else { | |
| 340 DCHECK(change.data().specifics.has_autofill()); | |
| 341 RETURN_IF(tracker.IncorporateRemoteSpecifics( | |
| 342 change.storage_key(), change.data().specifics.autofill())); | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 RETURN_IF(tracker.FlushToLocal(web_data_backend_)); | |
| 347 RETURN_IF(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 |