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

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: 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 CullSyncedData() {
Ilya Sherman 2012/04/03 00:13:36 nit: Actually, perhaps "ShouldCullSyncedData()"?
GeorgeY 2012/04/03 00:28:44 sure
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 // Delete only the changes never synced to the db as they are too old.
172 for (size_t i = 0; i < synced_expired_entries.size(); ++i) {
173 // Key is on the server and not local and is too old, we need to notify
174 // sync that it has expired.
175 if (keys_to_ignore_.find(synced_expired_entries[i].key()) ==
176 keys_to_ignore_.end()) {
177 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE,
Nicolas Zea 2012/04/03 00:39:09 This logic should also be protected by CullSyncedD
GeorgeY 2012/04/03 16:55:02 Done.
178 CreateSyncData(synced_expired_entries[i])));
179 }
180 }
181
182 if (need_to_cull_data && CullSyncedData()) {
183 // This will schedule deletion operation later on DB thread and we will
184 // be notified on the results of the deletion and deletes will be synced to
185 // the sync.
186 web_data_service_->RemoveExpiredFormElements();
122 } 187 }
123 188
124 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 189 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
125 190
126 return error; 191 return error;
127 } 192 }
128 193
129 void AutocompleteSyncableService::StopSyncing(syncable::ModelType type) { 194 void AutocompleteSyncableService::StopSyncing(syncable::ModelType type) {
130 DCHECK(CalledOnValidThread()); 195 DCHECK(CalledOnValidThread());
131 DCHECK_EQ(syncable::AUTOFILL, type); 196 DCHECK_EQ(syncable::AUTOFILL, type);
(...skipping 30 matching lines...) Expand all
162 if (!sync_processor_.get()) { 227 if (!sync_processor_.get()) {
163 SyncError error(FROM_HERE, "Models not yet associated.", 228 SyncError error(FROM_HERE, "Models not yet associated.",
164 syncable::AUTOFILL); 229 syncable::AUTOFILL);
165 return error; 230 return error;
166 } 231 }
167 232
168 // Data is loaded only if we get new ADD/UPDATE change. 233 // Data is loaded only if we get new ADD/UPDATE change.
169 std::vector<AutofillEntry> entries; 234 std::vector<AutofillEntry> entries;
170 scoped_ptr<AutocompleteEntryMap> db_entries; 235 scoped_ptr<AutocompleteEntryMap> db_entries;
171 std::vector<AutofillEntry> new_entries; 236 std::vector<AutofillEntry> new_entries;
237 std::vector<AutofillEntry> ignored_entries;
172 238
173 SyncError list_processing_error; 239 SyncError list_processing_error;
174 240
175 for (SyncChangeList::const_iterator i = change_list.begin(); 241 for (SyncChangeList::const_iterator i = change_list.begin();
176 i != change_list.end() && !list_processing_error.IsSet(); ++i) { 242 i != change_list.end() && !list_processing_error.IsSet(); ++i) {
177 DCHECK(i->IsValid()); 243 DCHECK(i->IsValid());
178 switch (i->change_type()) { 244 switch (i->change_type()) {
179 case SyncChange::ACTION_ADD: 245 case SyncChange::ACTION_ADD:
180 case SyncChange::ACTION_UPDATE: 246 case SyncChange::ACTION_UPDATE:
181 if (!db_entries.get()) { 247 if (!db_entries.get()) {
182 if (!LoadAutofillData(&entries)) { 248 if (!LoadAutofillData(&entries)) {
183 return SyncError( 249 return SyncError(
184 FROM_HERE, 250 FROM_HERE,
185 "Could not get the autocomplete data from WebDatabase.", 251 "Could not get the autocomplete data from WebDatabase.",
186 model_type()); 252 model_type());
187 } 253 }
188 db_entries.reset(new AutocompleteEntryMap); 254 db_entries.reset(new AutocompleteEntryMap);
189 for (std::vector<AutofillEntry>::iterator it = entries.begin(); 255 for (std::vector<AutofillEntry>::iterator it = entries.begin();
190 it != entries.end(); ++it) { 256 it != entries.end(); ++it) {
191 (*db_entries)[it->key()] = 257 (*db_entries)[it->key()] =
192 std::make_pair(SyncChange::ACTION_ADD, it); 258 std::make_pair(SyncChange::ACTION_ADD, it);
193 } 259 }
194 } 260 }
195 CreateOrUpdateEntry(i->sync_data(), db_entries.get(), &new_entries); 261 CreateOrUpdateEntry(i->sync_data(), db_entries.get(),
262 &new_entries, &ignored_entries);
196 break; 263 break;
197 case SyncChange::ACTION_DELETE: { 264 case SyncChange::ACTION_DELETE: {
198 DCHECK(i->sync_data().GetSpecifics().has_autofill()) 265 DCHECK(i->sync_data().GetSpecifics().has_autofill())
199 << "Autofill specifics data not present on delete!"; 266 << "Autofill specifics data not present on delete!";
200 const sync_pb::AutofillSpecifics& autofill = 267 const sync_pb::AutofillSpecifics& autofill =
201 i->sync_data().GetSpecifics().autofill(); 268 i->sync_data().GetSpecifics().autofill();
202 if (autofill.has_value()) { 269 if (autofill.has_value()) {
203 list_processing_error = AutofillEntryDelete(autofill); 270 list_processing_error = AutofillEntryDelete(autofill);
204 } else { 271 } else {
205 DLOG(WARNING) 272 DLOG(WARNING)
206 << "Delete for old-style autofill profile being dropped!"; 273 << "Delete for old-style autofill profile being dropped!";
207 } 274 }
208 } break; 275 } break;
209 default: 276 default:
210 NOTREACHED() << "Unexpected sync change state."; 277 NOTREACHED() << "Unexpected sync change state.";
211 return SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " + 278 return SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " +
212 SyncChange::ChangeTypeToString(i->change_type()), 279 SyncChange::ChangeTypeToString(i->change_type()),
213 syncable::AUTOFILL); 280 syncable::AUTOFILL);
214 } 281 }
215 } 282 }
216 283
217 if (!SaveChangesToWebData(new_entries)) 284 if (!SaveChangesToWebData(new_entries))
218 return SyncError(FROM_HERE, "Failed to update webdata.", model_type()); 285 return SyncError(FROM_HERE, "Failed to update webdata.", model_type());
219 286
287 // Remove already expired data.
288 for (size_t i = 0; i < ignored_entries.size(); ++i) {
289 if (db_entries.get() &&
290 db_entries->find(ignored_entries[i].key()) != db_entries->end()) {
291 bool success = web_data_service_->GetDatabase()->GetAutofillTable()->
292 RemoveFormElement(ignored_entries[i].key().name(),
293 ignored_entries[i].key().value());
294 DCHECK(success);
295 }
296 }
297
220 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_); 298 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_);
221 299
222 return list_processing_error; 300 return list_processing_error;
223 } 301 }
224 302
225 void AutocompleteSyncableService::Observe(int type, 303 void AutocompleteSyncableService::Observe(int type,
226 const content::NotificationSource& source, 304 const content::NotificationSource& source,
227 const content::NotificationDetails& details) { 305 const content::NotificationDetails& details) {
228 DCHECK_EQ(chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, type); 306 DCHECK_EQ(chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, type);
229 307
(...skipping 27 matching lines...) Expand all
257 GetAutofillTable()->UpdateAutofillEntries(new_entries)) { 335 GetAutofillTable()->UpdateAutofillEntries(new_entries)) {
258 return false; 336 return false;
259 } 337 }
260 return true; 338 return true;
261 } 339 }
262 340
263 // Creates or updates an autocomplete entry based on |data|. 341 // Creates or updates an autocomplete entry based on |data|.
264 void AutocompleteSyncableService::CreateOrUpdateEntry( 342 void AutocompleteSyncableService::CreateOrUpdateEntry(
265 const SyncData& data, 343 const SyncData& data,
266 AutocompleteEntryMap* loaded_data, 344 AutocompleteEntryMap* loaded_data,
267 std::vector<AutofillEntry>* new_entries) { 345 std::vector<AutofillEntry>* new_entries,
346 std::vector<AutofillEntry>* ignored_entries) {
268 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); 347 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
269 const sync_pb::AutofillSpecifics& autofill_specifics( 348 const sync_pb::AutofillSpecifics& autofill_specifics(
270 specifics.autofill()); 349 specifics.autofill());
271 350
272 if (!autofill_specifics.has_value()) { 351 if (!autofill_specifics.has_value()) {
273 DLOG(WARNING) 352 DLOG(WARNING)
274 << "Add/Update for old-style autofill profile being dropped!"; 353 << "Add/Update for old-style autofill profile being dropped!";
275 return; 354 return;
276 } 355 }
277 356
278 AutofillKey key(autofill_specifics.name().c_str(), 357 AutofillKey key(autofill_specifics.name().c_str(),
279 autofill_specifics.value().c_str()); 358 autofill_specifics.value().c_str());
280 AutocompleteEntryMap::iterator it = loaded_data->find(key); 359 AutocompleteEntryMap::iterator it = loaded_data->find(key);
281 if (it == loaded_data->end()) { 360 if (it == loaded_data->end()) {
282 // New entry. 361 // New entry.
283 std::vector<base::Time> timestamps; 362 std::vector<base::Time> timestamps;
284 size_t timestamps_count = autofill_specifics.usage_timestamp_size(); 363 size_t timestamps_count = autofill_specifics.usage_timestamp_size();
285 timestamps.resize(timestamps_count); 364 timestamps.reserve(2);
286 for (size_t ts = 0; ts < timestamps_count; ++ts) { 365 if (timestamps_count) {
287 timestamps[ts] = base::Time::FromInternalValue( 366 timestamps.push_back(base::Time::FromInternalValue(
288 autofill_specifics.usage_timestamp(ts)); 367 autofill_specifics.usage_timestamp(0)));
289 } 368 }
290 new_entries->push_back(AutofillEntry(key, timestamps)); 369 if (timestamps_count > 1) {
370 timestamps.push_back(base::Time::FromInternalValue(
371 autofill_specifics.usage_timestamp(timestamps_count - 1)));
372 }
373 AutofillEntry new_entry(key, timestamps);
374 if (new_entry.IsExpired())
375 ignored_entries->push_back(new_entry);
376 else
377 new_entries->push_back(new_entry);
291 } else { 378 } else {
292 // Entry already present - merge if necessary. 379 // Entry already present - merge if necessary.
293 std::vector<base::Time> timestamps; 380 std::vector<base::Time> timestamps;
294 bool different = MergeTimestamps( 381 bool different = MergeTimestamps(
295 autofill_specifics, it->second.second->timestamps(), &timestamps); 382 autofill_specifics, it->second.second->timestamps(), &timestamps);
296 if (different) { 383 if (different) {
297 AutofillEntry new_entry(it->second.second->key(), timestamps); 384 AutofillEntry new_entry(it->second.second->key(), timestamps);
298 new_entries->push_back(new_entry); 385 if (new_entry.IsExpired()) {
299 386 ignored_entries->push_back(new_entry);
300 // Update the sync db if the list of timestamps have changed. 387 } else {
301 *(it->second.second) = new_entry; 388 new_entries->push_back(new_entry);
302 it->second.first = SyncChange::ACTION_UPDATE; 389 // Update the sync db if the list of timestamps have changed.
390 *(it->second.second) = new_entry;
391 it->second.first = SyncChange::ACTION_UPDATE;
392 }
303 } else { 393 } else {
304 loaded_data->erase(it); 394 loaded_data->erase(it);
305 } 395 }
306 } 396 }
307 } 397 }
308 398
309 // static 399 // static
310 void AutocompleteSyncableService::WriteAutofillEntry( 400 void AutocompleteSyncableService::WriteAutofillEntry(
311 const AutofillEntry& entry, sync_pb::EntitySpecifics* autofill_specifics) { 401 const AutofillEntry& entry, sync_pb::EntitySpecifics* autofill_specifics) {
312 sync_pb::AutofillSpecifics* autofill = 402 sync_pb::AutofillSpecifics* autofill =
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 } 441 }
352 AutofillEntry entry(change->key(), timestamps); 442 AutofillEntry entry(change->key(), timestamps);
353 SyncChange::SyncChangeType change_type = 443 SyncChange::SyncChangeType change_type =
354 (change->type() == AutofillChange::ADD) ? 444 (change->type() == AutofillChange::ADD) ?
355 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE; 445 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE;
356 new_changes.push_back(SyncChange(change_type, 446 new_changes.push_back(SyncChange(change_type,
357 CreateSyncData(entry))); 447 CreateSyncData(entry)));
358 break; 448 break;
359 } 449 }
360 case AutofillChange::REMOVE: { 450 case AutofillChange::REMOVE: {
361 std::vector<base::Time> timestamps; 451 if (keys_to_ignore_.find(change->key()) == keys_to_ignore_.end()) {
362 AutofillEntry entry(change->key(), timestamps); 452 std::vector<base::Time> timestamps;
363 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE, 453 AutofillEntry entry(change->key(), timestamps);
364 CreateSyncData(entry))); 454 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE,
455 CreateSyncData(entry)));
456 }
365 break; 457 break;
366 } 458 }
367 default: 459 default:
368 NOTREACHED(); 460 NOTREACHED();
369 break; 461 break;
370 } 462 }
371 } 463 }
372 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 464 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
373 if (error.IsSet()) { 465 if (error.IsSet()) {
374 DLOG(WARNING) << "[AUTOCOMPLETE SYNC]" 466 DLOG(WARNING) << "[AUTOCOMPLETE SYNC]"
375 << " Failed processing change:" 467 << " Failed processing change:"
376 << " Error:" << error.message(); 468 << " Error:" << error.message();
377 } 469 }
470 // |keys_to_ignore_| are only needed for the very first notification.
471 keys_to_ignore_.clear();
378 } 472 }
379 473
380 SyncData AutocompleteSyncableService::CreateSyncData( 474 SyncData AutocompleteSyncableService::CreateSyncData(
381 const AutofillEntry& entry) const { 475 const AutofillEntry& entry) const {
382 sync_pb::EntitySpecifics autofill_specifics; 476 sync_pb::EntitySpecifics autofill_specifics;
383 WriteAutofillEntry(entry, &autofill_specifics); 477 WriteAutofillEntry(entry, &autofill_specifics);
384 std::string tag(KeyToTag(UTF16ToUTF8(entry.key().name()), 478 std::string tag(KeyToTag(UTF16ToUTF8(entry.key().name()),
385 UTF16ToUTF8(entry.key().value()))); 479 UTF16ToUTF8(entry.key().value())));
386 return SyncData::CreateLocalData(tag, tag, autofill_specifics); 480 return SyncData::CreateLocalData(tag, tag, autofill_specifics);
387 } 481 }
388 482
389 // static 483 // static
390 std::string AutocompleteSyncableService::KeyToTag(const std::string& name, 484 std::string AutocompleteSyncableService::KeyToTag(const std::string& name,
391 const std::string& value) { 485 const std::string& value) {
392 std::string ns(kAutofillEntryNamespaceTag); 486 std::string ns(kAutofillEntryNamespaceTag);
393 return ns + net::EscapePath(name) + "|" + net::EscapePath(value); 487 return ns + net::EscapePath(name) + "|" + net::EscapePath(value);
394 } 488 }
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