Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc

Issue 2624883002: [Sync] ApplySyncChanges autofill implementation. (Closed)
Patch Set: Rebasing and removed a few useless autos. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698