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

Side by Side Diff: chrome/browser/webdata/autocomplete_syncable_service.cc

Issue 9959086: Add probability of culling if sync is enabled to https://chromiumcodereview.appspot.com/9585020/ In… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comment Created 8 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/webdata/autocomplete_syncable_service.h" 5 #include "chrome/browser/webdata/autocomplete_syncable_service.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/rand_util.h"
9 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/sync/api/sync_error.h" 12 #include "chrome/browser/sync/api/sync_error.h"
12 #include "chrome/browser/webdata/autofill_table.h" 13 #include "chrome/browser/webdata/autofill_table.h"
13 #include "chrome/browser/webdata/web_data_service.h" 14 #include "chrome/browser/webdata/web_data_service.h"
14 #include "chrome/browser/webdata/web_database.h" 15 #include "chrome/browser/webdata/web_database.h"
15 #include "chrome/common/chrome_notification_types.h" 16 #include "chrome/common/chrome_notification_types.h"
16 #include "chrome/common/guid.h" 17 #include "chrome/common/guid.h"
17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/notification_service.h"
19 #include "net/base/escape.h" 20 #include "net/base/escape.h"
20 #include "sync/protocol/autofill_specifics.pb.h" 21 #include "sync/protocol/autofill_specifics.pb.h"
21 #include "sync/protocol/sync.pb.h" 22 #include "sync/protocol/sync.pb.h"
22 23
23 using content::BrowserThread; 24 using content::BrowserThread;
24 25
25 namespace { 26 namespace {
26 27
27 const char kAutofillEntryNamespaceTag[] = "autofill_entry|"; 28 const char kAutofillEntryNamespaceTag[] = "autofill_entry|";
28 29
29 // Merges timestamps from the |autofill| entry and |timestamps|. Returns 30 // Merges timestamps from the |autofill| entry and |timestamps|. Returns
30 // true if they were different, false if they were the same. 31 // true if they were different, false if they were the same.
31 // All of the timestamp vectors are assummed to be sorted, resulting vector is 32 // All of the timestamp vectors are assummed to be sorted, resulting vector is
32 // sorted as well. 33 // sorted as well. Only two timestamps - the earliest and the latest are stored.
33 bool MergeTimestamps(const sync_pb::AutofillSpecifics& autofill, 34 bool MergeTimestamps(const sync_pb::AutofillSpecifics& autofill,
34 const std::vector<base::Time>& timestamps, 35 const std::vector<base::Time>& timestamps,
35 std::vector<base::Time>* new_timestamps) { 36 std::vector<base::Time>* new_timestamps) {
36 DCHECK(new_timestamps); 37 DCHECK(new_timestamps);
37 std::set<base::Time> timestamp_union(timestamps.begin(),
38 timestamps.end());
39 38
39 new_timestamps->clear();
40 size_t timestamps_count = autofill.usage_timestamp_size(); 40 size_t timestamps_count = autofill.usage_timestamp_size();
41 41 if (timestamps_count == 0 && timestamps.empty()) {
42 bool different = timestamps.size() != timestamps_count; 42 return false;
43 for (size_t i = 0; i < timestamps_count; ++i) { 43 } else if (timestamps_count == 0) {
44 if (timestamp_union.insert(base::Time::FromInternalValue( 44 new_timestamps->insert(new_timestamps->begin(),
45 autofill.usage_timestamp(i))).second) { 45 timestamps.begin(),
46 different = true; 46 timestamps.end());
47 return true;
48 } else if (timestamps.empty()) {
49 new_timestamps->reserve(2);
50 new_timestamps->push_back(base::Time::FromInternalValue(
51 autofill.usage_timestamp(0)));
52 if (timestamps_count > 1) {
53 new_timestamps->push_back(base::Time::FromInternalValue(
54 autofill.usage_timestamp(timestamps_count - 1)));
55 }
56 return true;
57 } else {
58 base::Time sync_time_begin = base::Time::FromInternalValue(
59 autofill.usage_timestamp(0));
60 base::Time sync_time_end = base::Time::FromInternalValue(
61 autofill.usage_timestamp(timestamps_count - 1));
62 if (timestamps.front() != sync_time_begin ||
63 timestamps.back() != sync_time_end) {
64 new_timestamps->push_back(
65 timestamps.front() < sync_time_begin ? timestamps.front() :
66 sync_time_begin);
67 if (new_timestamps->back() != timestamps.back() ||
68 new_timestamps->back() != sync_time_end) {
69 new_timestamps->push_back(
70 timestamps.back() > sync_time_end ? timestamps.back() :
71 sync_time_end);
72 }
73 return true;
74 } else {
75 new_timestamps->insert(new_timestamps->begin(),
76 timestamps.begin(),
77 timestamps.end());
78 return false;
47 } 79 }
48 } 80 }
81 }
49 82
50 if (different) { 83 bool ShouldCullSyncedData() {
51 new_timestamps->insert(new_timestamps->begin(), 84 // To set probability to 10% - set it to 0.1, 5% to 0.05, etc.
52 timestamp_union.begin(), 85 static double kCullingProbability = 0.0;
53 timestamp_union.end()); 86 return (base::RandDouble() < kCullingProbability);
54 }
55 return different;
56 } 87 }
57 88
58 } // namespace 89 } // namespace
59 90
60 AutocompleteSyncableService::AutocompleteSyncableService( 91 AutocompleteSyncableService::AutocompleteSyncableService(
61 WebDataService* web_data_service) 92 WebDataService* web_data_service)
62 : web_data_service_(web_data_service) { 93 : web_data_service_(web_data_service) {
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
64 DCHECK(web_data_service_); 95 DCHECK(web_data_service_);
65 notification_registrar_.Add( 96 notification_registrar_.Add(
(...skipping 28 matching lines...) Expand all
94 125
95 AutocompleteEntryMap new_db_entries; 126 AutocompleteEntryMap new_db_entries;
96 for (std::vector<AutofillEntry>::iterator it = entries.begin(); 127 for (std::vector<AutofillEntry>::iterator it = entries.begin();
97 it != entries.end(); ++it) { 128 it != entries.end(); ++it) {
98 new_db_entries[it->key()] = std::make_pair(SyncChange::ACTION_ADD, it); 129 new_db_entries[it->key()] = std::make_pair(SyncChange::ACTION_ADD, it);
99 } 130 }
100 131
101 sync_processor_ = sync_processor.Pass(); 132 sync_processor_ = sync_processor.Pass();
102 133
103 std::vector<AutofillEntry> new_synced_entries; 134 std::vector<AutofillEntry> new_synced_entries;
135 std::vector<AutofillEntry> synced_expired_entries;
104 // Go through and check for all the entries that sync already knows about. 136 // Go through and check for all the entries that sync already knows about.
105 // CreateOrUpdateEntry() will remove entries that are same with the synced 137 // CreateOrUpdateEntry() will remove entries that are same with the synced
106 // ones from |new_db_entries|. 138 // ones from |new_db_entries|.
107 for (SyncDataList::const_iterator sync_iter = initial_sync_data.begin(); 139 for (SyncDataList::const_iterator sync_iter = initial_sync_data.begin();
108 sync_iter != initial_sync_data.end(); ++sync_iter) { 140 sync_iter != initial_sync_data.end(); ++sync_iter) {
109 CreateOrUpdateEntry(*sync_iter, &new_db_entries, &new_synced_entries); 141 CreateOrUpdateEntry(*sync_iter, &new_db_entries,
142 &new_synced_entries, &synced_expired_entries);
110 } 143 }
111 144
145 // Check if newly received items need culling.
146 bool need_to_cull_data = !synced_expired_entries.empty();
147
112 if (!SaveChangesToWebData(new_synced_entries)) 148 if (!SaveChangesToWebData(new_synced_entries))
113 return SyncError(FROM_HERE, "Failed to update webdata.", model_type()); 149 return SyncError(FROM_HERE, "Failed to update webdata.", model_type());
114 150
115 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_); 151 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_);
152 keys_to_ignore_.clear();
116 153
117 SyncChangeList new_changes; 154 SyncChangeList new_changes;
118 for (AutocompleteEntryMap::iterator i = new_db_entries.begin(); 155 for (AutocompleteEntryMap::iterator i = new_db_entries.begin();
119 i != new_db_entries.end(); ++i) { 156 i != new_db_entries.end(); ++i) {
120 new_changes.push_back( 157 // Sync back only the data that appeared after
121 SyncChange(i->second.first, CreateSyncData(*(i->second.second)))); 158 // |AutofillEntry::ExpirationTime()|.
159 if (!i->second.second->IsExpired()) {
160 new_changes.push_back(
161 SyncChange(i->second.first, CreateSyncData(*(i->second.second))));
162 } else {
163 need_to_cull_data = true;
164 // Key is not on the server and is too old, it will not ever be synced -
165 // delete it locally.
166 if (i->second.first == SyncChange::ACTION_ADD)
167 keys_to_ignore_.insert(i->first);
168 }
169 }
170
171 if (ShouldCullSyncedData()) {
172 // Delete only the changes never synced to the db as they are too old.
173 for (size_t i = 0; i < synced_expired_entries.size(); ++i) {
174 // Key is on the server and not local and is too old, we need to notify
175 // sync that it has expired.
176 if (keys_to_ignore_.find(synced_expired_entries[i].key()) ==
177 keys_to_ignore_.end()) {
178 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE,
179 CreateSyncData(synced_expired_entries[i])));
180 }
181 }
182
183 if (need_to_cull_data) {
184 // This will schedule deletion operation later on DB thread and we will
185 // be notified on the results of the deletion and deletes will be synced
186 // to the sync.
187 web_data_service_->RemoveExpiredFormElements();
188 }
122 } 189 }
123 190
124 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 191 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
125 192
126 return error; 193 return error;
127 } 194 }
128 195
129 void AutocompleteSyncableService::StopSyncing(syncable::ModelType type) { 196 void AutocompleteSyncableService::StopSyncing(syncable::ModelType type) {
130 DCHECK(CalledOnValidThread()); 197 DCHECK(CalledOnValidThread());
131 DCHECK_EQ(syncable::AUTOFILL, type); 198 DCHECK_EQ(syncable::AUTOFILL, type);
(...skipping 30 matching lines...) Expand all
162 if (!sync_processor_.get()) { 229 if (!sync_processor_.get()) {
163 SyncError error(FROM_HERE, "Models not yet associated.", 230 SyncError error(FROM_HERE, "Models not yet associated.",
164 syncable::AUTOFILL); 231 syncable::AUTOFILL);
165 return error; 232 return error;
166 } 233 }
167 234
168 // Data is loaded only if we get new ADD/UPDATE change. 235 // Data is loaded only if we get new ADD/UPDATE change.
169 std::vector<AutofillEntry> entries; 236 std::vector<AutofillEntry> entries;
170 scoped_ptr<AutocompleteEntryMap> db_entries; 237 scoped_ptr<AutocompleteEntryMap> db_entries;
171 std::vector<AutofillEntry> new_entries; 238 std::vector<AutofillEntry> new_entries;
239 std::vector<AutofillEntry> ignored_entries;
172 240
173 SyncError list_processing_error; 241 SyncError list_processing_error;
174 242
175 for (SyncChangeList::const_iterator i = change_list.begin(); 243 for (SyncChangeList::const_iterator i = change_list.begin();
176 i != change_list.end() && !list_processing_error.IsSet(); ++i) { 244 i != change_list.end() && !list_processing_error.IsSet(); ++i) {
177 DCHECK(i->IsValid()); 245 DCHECK(i->IsValid());
178 switch (i->change_type()) { 246 switch (i->change_type()) {
179 case SyncChange::ACTION_ADD: 247 case SyncChange::ACTION_ADD:
180 case SyncChange::ACTION_UPDATE: 248 case SyncChange::ACTION_UPDATE:
181 if (!db_entries.get()) { 249 if (!db_entries.get()) {
182 if (!LoadAutofillData(&entries)) { 250 if (!LoadAutofillData(&entries)) {
183 return SyncError( 251 return SyncError(
184 FROM_HERE, 252 FROM_HERE,
185 "Could not get the autocomplete data from WebDatabase.", 253 "Could not get the autocomplete data from WebDatabase.",
186 model_type()); 254 model_type());
187 } 255 }
188 db_entries.reset(new AutocompleteEntryMap); 256 db_entries.reset(new AutocompleteEntryMap);
189 for (std::vector<AutofillEntry>::iterator it = entries.begin(); 257 for (std::vector<AutofillEntry>::iterator it = entries.begin();
190 it != entries.end(); ++it) { 258 it != entries.end(); ++it) {
191 (*db_entries)[it->key()] = 259 (*db_entries)[it->key()] =
192 std::make_pair(SyncChange::ACTION_ADD, it); 260 std::make_pair(SyncChange::ACTION_ADD, it);
193 } 261 }
194 } 262 }
195 CreateOrUpdateEntry(i->sync_data(), db_entries.get(), &new_entries); 263 CreateOrUpdateEntry(i->sync_data(), db_entries.get(),
264 &new_entries, &ignored_entries);
196 break; 265 break;
197 case SyncChange::ACTION_DELETE: { 266 case SyncChange::ACTION_DELETE: {
198 DCHECK(i->sync_data().GetSpecifics().has_autofill()) 267 DCHECK(i->sync_data().GetSpecifics().has_autofill())
199 << "Autofill specifics data not present on delete!"; 268 << "Autofill specifics data not present on delete!";
200 const sync_pb::AutofillSpecifics& autofill = 269 const sync_pb::AutofillSpecifics& autofill =
201 i->sync_data().GetSpecifics().autofill(); 270 i->sync_data().GetSpecifics().autofill();
202 if (autofill.has_value()) { 271 if (autofill.has_value()) {
203 list_processing_error = AutofillEntryDelete(autofill); 272 list_processing_error = AutofillEntryDelete(autofill);
204 } else { 273 } else {
205 DLOG(WARNING) 274 DLOG(WARNING)
206 << "Delete for old-style autofill profile being dropped!"; 275 << "Delete for old-style autofill profile being dropped!";
207 } 276 }
208 } break; 277 } break;
209 default: 278 default:
210 NOTREACHED() << "Unexpected sync change state."; 279 NOTREACHED() << "Unexpected sync change state.";
211 return SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " + 280 return SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " +
212 SyncChange::ChangeTypeToString(i->change_type()), 281 SyncChange::ChangeTypeToString(i->change_type()),
213 syncable::AUTOFILL); 282 syncable::AUTOFILL);
214 } 283 }
215 } 284 }
216 285
217 if (!SaveChangesToWebData(new_entries)) 286 if (!SaveChangesToWebData(new_entries))
218 return SyncError(FROM_HERE, "Failed to update webdata.", model_type()); 287 return SyncError(FROM_HERE, "Failed to update webdata.", model_type());
219 288
289 // Remove already expired data.
290 for (size_t i = 0; i < ignored_entries.size(); ++i) {
291 if (db_entries.get() &&
292 db_entries->find(ignored_entries[i].key()) != db_entries->end()) {
293 bool success = web_data_service_->GetDatabase()->GetAutofillTable()->
294 RemoveFormElement(ignored_entries[i].key().name(),
295 ignored_entries[i].key().value());
296 DCHECK(success);
297 }
298 }
299
220 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_); 300 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_);
221 301
222 return list_processing_error; 302 return list_processing_error;
223 } 303 }
224 304
225 void AutocompleteSyncableService::Observe(int type, 305 void AutocompleteSyncableService::Observe(int type,
226 const content::NotificationSource& source, 306 const content::NotificationSource& source,
227 const content::NotificationDetails& details) { 307 const content::NotificationDetails& details) {
228 DCHECK_EQ(chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, type); 308 DCHECK_EQ(chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, type);
229 309
(...skipping 27 matching lines...) Expand all
257 GetAutofillTable()->UpdateAutofillEntries(new_entries)) { 337 GetAutofillTable()->UpdateAutofillEntries(new_entries)) {
258 return false; 338 return false;
259 } 339 }
260 return true; 340 return true;
261 } 341 }
262 342
263 // Creates or updates an autocomplete entry based on |data|. 343 // Creates or updates an autocomplete entry based on |data|.
264 void AutocompleteSyncableService::CreateOrUpdateEntry( 344 void AutocompleteSyncableService::CreateOrUpdateEntry(
265 const SyncData& data, 345 const SyncData& data,
266 AutocompleteEntryMap* loaded_data, 346 AutocompleteEntryMap* loaded_data,
267 std::vector<AutofillEntry>* new_entries) { 347 std::vector<AutofillEntry>* new_entries,
348 std::vector<AutofillEntry>* ignored_entries) {
268 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); 349 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
269 const sync_pb::AutofillSpecifics& autofill_specifics( 350 const sync_pb::AutofillSpecifics& autofill_specifics(
270 specifics.autofill()); 351 specifics.autofill());
271 352
272 if (!autofill_specifics.has_value()) { 353 if (!autofill_specifics.has_value()) {
273 DLOG(WARNING) 354 DLOG(WARNING)
274 << "Add/Update for old-style autofill profile being dropped!"; 355 << "Add/Update for old-style autofill profile being dropped!";
275 return; 356 return;
276 } 357 }
277 358
278 AutofillKey key(autofill_specifics.name().c_str(), 359 AutofillKey key(autofill_specifics.name().c_str(),
279 autofill_specifics.value().c_str()); 360 autofill_specifics.value().c_str());
280 AutocompleteEntryMap::iterator it = loaded_data->find(key); 361 AutocompleteEntryMap::iterator it = loaded_data->find(key);
281 if (it == loaded_data->end()) { 362 if (it == loaded_data->end()) {
282 // New entry. 363 // New entry.
283 std::vector<base::Time> timestamps; 364 std::vector<base::Time> timestamps;
284 size_t timestamps_count = autofill_specifics.usage_timestamp_size(); 365 size_t timestamps_count = autofill_specifics.usage_timestamp_size();
285 timestamps.resize(timestamps_count); 366 timestamps.reserve(2);
286 for (size_t ts = 0; ts < timestamps_count; ++ts) { 367 if (timestamps_count) {
287 timestamps[ts] = base::Time::FromInternalValue( 368 timestamps.push_back(base::Time::FromInternalValue(
288 autofill_specifics.usage_timestamp(ts)); 369 autofill_specifics.usage_timestamp(0)));
289 } 370 }
290 new_entries->push_back(AutofillEntry(key, timestamps)); 371 if (timestamps_count > 1) {
372 timestamps.push_back(base::Time::FromInternalValue(
373 autofill_specifics.usage_timestamp(timestamps_count - 1)));
374 }
375 AutofillEntry new_entry(key, timestamps);
376 if (new_entry.IsExpired())
377 ignored_entries->push_back(new_entry);
378 else
379 new_entries->push_back(new_entry);
291 } else { 380 } else {
292 // Entry already present - merge if necessary. 381 // Entry already present - merge if necessary.
293 std::vector<base::Time> timestamps; 382 std::vector<base::Time> timestamps;
294 bool different = MergeTimestamps( 383 bool different = MergeTimestamps(
295 autofill_specifics, it->second.second->timestamps(), &timestamps); 384 autofill_specifics, it->second.second->timestamps(), &timestamps);
296 if (different) { 385 if (different) {
297 AutofillEntry new_entry(it->second.second->key(), timestamps); 386 AutofillEntry new_entry(it->second.second->key(), timestamps);
298 new_entries->push_back(new_entry); 387 if (new_entry.IsExpired()) {
299 388 ignored_entries->push_back(new_entry);
300 // Update the sync db if the list of timestamps have changed. 389 } else {
301 *(it->second.second) = new_entry; 390 new_entries->push_back(new_entry);
302 it->second.first = SyncChange::ACTION_UPDATE; 391 // Update the sync db if the list of timestamps have changed.
392 *(it->second.second) = new_entry;
393 it->second.first = SyncChange::ACTION_UPDATE;
394 }
303 } else { 395 } else {
304 loaded_data->erase(it); 396 loaded_data->erase(it);
305 } 397 }
306 } 398 }
307 } 399 }
308 400
309 // static 401 // static
310 void AutocompleteSyncableService::WriteAutofillEntry( 402 void AutocompleteSyncableService::WriteAutofillEntry(
311 const AutofillEntry& entry, sync_pb::EntitySpecifics* autofill_specifics) { 403 const AutofillEntry& entry, sync_pb::EntitySpecifics* autofill_specifics) {
312 sync_pb::AutofillSpecifics* autofill = 404 sync_pb::AutofillSpecifics* autofill =
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 443 }
352 AutofillEntry entry(change->key(), timestamps); 444 AutofillEntry entry(change->key(), timestamps);
353 SyncChange::SyncChangeType change_type = 445 SyncChange::SyncChangeType change_type =
354 (change->type() == AutofillChange::ADD) ? 446 (change->type() == AutofillChange::ADD) ?
355 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE; 447 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE;
356 new_changes.push_back(SyncChange(change_type, 448 new_changes.push_back(SyncChange(change_type,
357 CreateSyncData(entry))); 449 CreateSyncData(entry)));
358 break; 450 break;
359 } 451 }
360 case AutofillChange::REMOVE: { 452 case AutofillChange::REMOVE: {
361 std::vector<base::Time> timestamps; 453 if (keys_to_ignore_.find(change->key()) == keys_to_ignore_.end()) {
362 AutofillEntry entry(change->key(), timestamps); 454 std::vector<base::Time> timestamps;
363 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE, 455 AutofillEntry entry(change->key(), timestamps);
364 CreateSyncData(entry))); 456 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE,
457 CreateSyncData(entry)));
458 }
365 break; 459 break;
366 } 460 }
367 default: 461 default:
368 NOTREACHED(); 462 NOTREACHED();
369 break; 463 break;
370 } 464 }
371 } 465 }
372 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 466 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
373 if (error.IsSet()) { 467 if (error.IsSet()) {
374 DLOG(WARNING) << "[AUTOCOMPLETE SYNC]" 468 DLOG(WARNING) << "[AUTOCOMPLETE SYNC]"
375 << " Failed processing change:" 469 << " Failed processing change:"
376 << " Error:" << error.message(); 470 << " Error:" << error.message();
377 } 471 }
472 // |keys_to_ignore_| are only needed for the very first notification.
473 keys_to_ignore_.clear();
378 } 474 }
379 475
380 SyncData AutocompleteSyncableService::CreateSyncData( 476 SyncData AutocompleteSyncableService::CreateSyncData(
381 const AutofillEntry& entry) const { 477 const AutofillEntry& entry) const {
382 sync_pb::EntitySpecifics autofill_specifics; 478 sync_pb::EntitySpecifics autofill_specifics;
383 WriteAutofillEntry(entry, &autofill_specifics); 479 WriteAutofillEntry(entry, &autofill_specifics);
384 std::string tag(KeyToTag(UTF16ToUTF8(entry.key().name()), 480 std::string tag(KeyToTag(UTF16ToUTF8(entry.key().name()),
385 UTF16ToUTF8(entry.key().value()))); 481 UTF16ToUTF8(entry.key().value())));
386 return SyncData::CreateLocalData(tag, tag, autofill_specifics); 482 return SyncData::CreateLocalData(tag, tag, autofill_specifics);
387 } 483 }
388 484
389 // static 485 // static
390 std::string AutocompleteSyncableService::KeyToTag(const std::string& name, 486 std::string AutocompleteSyncableService::KeyToTag(const std::string& name,
391 const std::string& value) { 487 const std::string& value) {
392 std::string ns(kAutofillEntryNamespaceTag); 488 std::string ns(kAutofillEntryNamespaceTag);
393 return ns + net::EscapePath(name) + "|" + net::EscapePath(value); 489 return ns + net::EscapePath(name) + "|" + net::EscapePath(value);
394 } 490 }
OLDNEW
« no previous file with comments | « chrome/browser/webdata/autocomplete_syncable_service.h ('k') | chrome/browser/webdata/autofill_entry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698