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

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

Issue 9585020: Cull autofill entries older than 60 days. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: if (!RemoveFormElementForID(pair_id)) Created 8 years, 9 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/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/profiles/profile.h"
(...skipping 22 matching lines...) Expand all
33 bool MergeTimestamps(const sync_pb::AutofillSpecifics& autofill, 33 bool MergeTimestamps(const sync_pb::AutofillSpecifics& autofill,
34 const std::vector<base::Time>& timestamps, 34 const std::vector<base::Time>& timestamps,
35 std::vector<base::Time>* new_timestamps) { 35 std::vector<base::Time>* new_timestamps) {
36 DCHECK(new_timestamps); 36 DCHECK(new_timestamps);
37 std::set<base::Time> timestamp_union(timestamps.begin(), 37 std::set<base::Time> timestamp_union(timestamps.begin(),
38 timestamps.end()); 38 timestamps.end());
39 39
40 size_t timestamps_count = autofill.usage_timestamp_size(); 40 size_t timestamps_count = autofill.usage_timestamp_size();
41 41
42 bool different = timestamps.size() != timestamps_count; 42 bool different = timestamps.size() != timestamps_count;
43 for (size_t i = 0; i < timestamps_count; ++i) { 43 for (size_t i = 0; i < timestamps_count; ++i) {
Nicolas Zea 2012/03/26 18:23:55 This shouldn't union, but instead just check first
GeorgeY 2012/03/26 19:59:10 Done.
44 if (timestamp_union.insert(base::Time::FromInternalValue( 44 if (timestamp_union.insert(base::Time::FromInternalValue(
45 autofill.usage_timestamp(i))).second) { 45 autofill.usage_timestamp(i))).second) {
46 different = true; 46 different = true;
47 } 47 }
48 } 48 }
49 49
50 if (different) { 50 if (different) {
51 new_timestamps->insert(new_timestamps->begin(), 51 new_timestamps->insert(new_timestamps->begin(),
52 timestamp_union.begin(), 52 timestamp_union.begin(),
53 timestamp_union.end()); 53 timestamp_union.end());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 93
94 AutocompleteEntryMap new_db_entries; 94 AutocompleteEntryMap new_db_entries;
95 for (std::vector<AutofillEntry>::iterator it = entries.begin(); 95 for (std::vector<AutofillEntry>::iterator it = entries.begin();
96 it != entries.end(); ++it) { 96 it != entries.end(); ++it) {
97 new_db_entries[it->key()] = std::make_pair(SyncChange::ACTION_ADD, it); 97 new_db_entries[it->key()] = std::make_pair(SyncChange::ACTION_ADD, it);
98 } 98 }
99 99
100 sync_processor_.reset(sync_processor); 100 sync_processor_.reset(sync_processor);
101 101
102 std::vector<AutofillEntry> new_synced_entries; 102 std::vector<AutofillEntry> new_synced_entries;
103 std::vector<AutofillEntry> synced_expired_entries;
103 // Go through and check for all the entries that sync already knows about. 104 // Go through and check for all the entries that sync already knows about.
104 // CreateOrUpdateEntry() will remove entries that are same with the synced 105 // CreateOrUpdateEntry() will remove entries that are same with the synced
105 // ones from |new_db_entries|. 106 // ones from |new_db_entries|.
106 for (SyncDataList::const_iterator sync_iter = initial_sync_data.begin(); 107 for (SyncDataList::const_iterator sync_iter = initial_sync_data.begin();
107 sync_iter != initial_sync_data.end(); ++sync_iter) { 108 sync_iter != initial_sync_data.end(); ++sync_iter) {
108 CreateOrUpdateEntry(*sync_iter, &new_db_entries, &new_synced_entries); 109 CreateOrUpdateEntry(*sync_iter, &new_db_entries,
110 &new_synced_entries, &synced_expired_entries);
109 } 111 }
110 112
113 // Check if newly received items need culling.
114 bool need_to_cull_data = !synced_expired_entries.empty();
115
111 if (!SaveChangesToWebData(new_synced_entries)) 116 if (!SaveChangesToWebData(new_synced_entries))
112 return SyncError(FROM_HERE, "Failed to update webdata.", model_type()); 117 return SyncError(FROM_HERE, "Failed to update webdata.", model_type());
113 118
114 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_); 119 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_);
120 keys_to_ignore_.clear();
115 121
116 SyncChangeList new_changes; 122 SyncChangeList new_changes;
117 for (AutocompleteEntryMap::iterator i = new_db_entries.begin(); 123 for (AutocompleteEntryMap::iterator i = new_db_entries.begin();
118 i != new_db_entries.end(); ++i) { 124 i != new_db_entries.end(); ++i) {
119 new_changes.push_back( 125 // Sync back only the data that appeared after
120 SyncChange(i->second.first, CreateSyncData(*(i->second.second)))); 126 // |AutofillEntry::ExpirationTime()|.
127 if (!i->second.second->IsExpired()) {
128 new_changes.push_back(
129 SyncChange(i->second.first, CreateSyncData(*(i->second.second))));
130 } else {
131 need_to_cull_data = true;
132 // Key is not on the server and is too old, it will not ever be synced -
133 // delete it locally.
134 if (i->second.first == SyncChange::ACTION_ADD)
135 keys_to_ignore_.insert(i->first);
136 }
137 }
138
139 // Delete only the changes never synced to the db as they are too old.
Ilya Sherman 2012/03/23 22:44:45 nit: "synced to" -> "synced to" (extra space)
GeorgeY 2012/03/26 19:59:10 Done.
140 for (size_t i = 0; i < synced_expired_entries.size(); ++i) {
141 // Key is on the server and not local and is too old, we need to notify
142 // sync that it has expired.
143 if (keys_to_ignore_.find(synced_expired_entries[i].key()) ==
144 keys_to_ignore_.end()) {
145 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE,
146 CreateSyncData(synced_expired_entries[i])));
147 }
148 }
149
150 if (need_to_cull_data) {
151 // This will schedule deletion operation later on DB thread and we will
152 // be notified on the results of the deletion and deletes will be synced to
153 // the sync.
154 web_data_service_->RemoveExpiredFormElements();
121 } 155 }
122 156
123 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 157 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
124 158
125 return error; 159 return error;
126 } 160 }
127 161
128 void AutocompleteSyncableService::StopSyncing(syncable::ModelType type) { 162 void AutocompleteSyncableService::StopSyncing(syncable::ModelType type) {
129 DCHECK(CalledOnValidThread()); 163 DCHECK(CalledOnValidThread());
130 DCHECK_EQ(syncable::AUTOFILL, type); 164 DCHECK_EQ(syncable::AUTOFILL, type);
(...skipping 30 matching lines...) Expand all
161 if (!sync_processor_.get()) { 195 if (!sync_processor_.get()) {
162 SyncError error(FROM_HERE, "Models not yet associated.", 196 SyncError error(FROM_HERE, "Models not yet associated.",
163 syncable::AUTOFILL); 197 syncable::AUTOFILL);
164 return error; 198 return error;
165 } 199 }
166 200
167 // Data is loaded only if we get new ADD/UPDATE change. 201 // Data is loaded only if we get new ADD/UPDATE change.
168 std::vector<AutofillEntry> entries; 202 std::vector<AutofillEntry> entries;
169 scoped_ptr<AutocompleteEntryMap> db_entries; 203 scoped_ptr<AutocompleteEntryMap> db_entries;
170 std::vector<AutofillEntry> new_entries; 204 std::vector<AutofillEntry> new_entries;
205 std::vector<AutofillEntry> ignored_entries;
171 206
172 SyncError list_processing_error; 207 SyncError list_processing_error;
173 208
174 for (SyncChangeList::const_iterator i = change_list.begin(); 209 for (SyncChangeList::const_iterator i = change_list.begin();
175 i != change_list.end() && !list_processing_error.IsSet(); ++i) { 210 i != change_list.end() && !list_processing_error.IsSet(); ++i) {
176 DCHECK(i->IsValid()); 211 DCHECK(i->IsValid());
177 switch (i->change_type()) { 212 switch (i->change_type()) {
178 case SyncChange::ACTION_ADD: 213 case SyncChange::ACTION_ADD:
179 case SyncChange::ACTION_UPDATE: 214 case SyncChange::ACTION_UPDATE:
180 if (!db_entries.get()) { 215 if (!db_entries.get()) {
181 if (!LoadAutofillData(&entries)) { 216 if (!LoadAutofillData(&entries)) {
182 return SyncError( 217 return SyncError(
183 FROM_HERE, 218 FROM_HERE,
184 "Could not get the autocomplete data from WebDatabase.", 219 "Could not get the autocomplete data from WebDatabase.",
185 model_type()); 220 model_type());
186 } 221 }
187 db_entries.reset(new AutocompleteEntryMap); 222 db_entries.reset(new AutocompleteEntryMap);
188 for (std::vector<AutofillEntry>::iterator it = entries.begin(); 223 for (std::vector<AutofillEntry>::iterator it = entries.begin();
189 it != entries.end(); ++it) { 224 it != entries.end(); ++it) {
190 (*db_entries)[it->key()] = 225 (*db_entries)[it->key()] =
191 std::make_pair(SyncChange::ACTION_ADD, it); 226 std::make_pair(SyncChange::ACTION_ADD, it);
192 } 227 }
193 } 228 }
194 CreateOrUpdateEntry(i->sync_data(), db_entries.get(), &new_entries); 229 CreateOrUpdateEntry(i->sync_data(), db_entries.get(),
230 &new_entries, &ignored_entries);
195 break; 231 break;
196 case SyncChange::ACTION_DELETE: { 232 case SyncChange::ACTION_DELETE: {
197 DCHECK(i->sync_data().GetSpecifics().has_autofill()) 233 DCHECK(i->sync_data().GetSpecifics().has_autofill())
198 << "Autofill specifics data not present on delete!"; 234 << "Autofill specifics data not present on delete!";
199 const sync_pb::AutofillSpecifics& autofill = 235 const sync_pb::AutofillSpecifics& autofill =
200 i->sync_data().GetSpecifics().autofill(); 236 i->sync_data().GetSpecifics().autofill();
201 if (autofill.has_value()) { 237 if (autofill.has_value()) {
202 list_processing_error = AutofillEntryDelete(autofill); 238 list_processing_error = AutofillEntryDelete(autofill);
203 } else { 239 } else {
204 DLOG(WARNING) 240 DLOG(WARNING)
205 << "Delete for old-style autofill profile being dropped!"; 241 << "Delete for old-style autofill profile being dropped!";
206 } 242 }
207 } break; 243 } break;
208 default: 244 default:
209 NOTREACHED() << "Unexpected sync change state."; 245 NOTREACHED() << "Unexpected sync change state.";
210 return SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " + 246 return SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " +
211 SyncChange::ChangeTypeToString(i->change_type()), 247 SyncChange::ChangeTypeToString(i->change_type()),
212 syncable::AUTOFILL); 248 syncable::AUTOFILL);
213 } 249 }
214 } 250 }
215 251
216 if (!SaveChangesToWebData(new_entries)) 252 if (!SaveChangesToWebData(new_entries))
217 return SyncError(FROM_HERE, "Failed to update webdata.", model_type()); 253 return SyncError(FROM_HERE, "Failed to update webdata.", model_type());
218 254
255 // Remove already expired data.
256 for (size_t i = 0; i < ignored_entries.size(); ++i) {
257 if (db_entries.get() &&
258 db_entries->find(ignored_entries[i].key()) != db_entries->end()) {
259 if (!web_data_service_->GetDatabase()->GetAutofillTable()->
260 RemoveFormElement(ignored_entries[i].key().name(),
261 ignored_entries[i].key().value())) {
262 NOTREACHED();
263 }
Ilya Sherman 2012/03/23 22:44:45 nit: Up to you, but I think this would be a little
GeorgeY 2012/03/26 19:59:10 Done.
264 }
265 }
266
219 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_); 267 WebDataService::NotifyOfMultipleAutofillChanges(web_data_service_);
220 268
221 return list_processing_error; 269 return list_processing_error;
222 } 270 }
223 271
224 void AutocompleteSyncableService::Observe(int type, 272 void AutocompleteSyncableService::Observe(int type,
225 const content::NotificationSource& source, 273 const content::NotificationSource& source,
226 const content::NotificationDetails& details) { 274 const content::NotificationDetails& details) {
227 DCHECK_EQ(chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, type); 275 DCHECK_EQ(chrome::NOTIFICATION_AUTOFILL_ENTRIES_CHANGED, type);
228 276
(...skipping 27 matching lines...) Expand all
256 GetAutofillTable()->UpdateAutofillEntries(new_entries)) { 304 GetAutofillTable()->UpdateAutofillEntries(new_entries)) {
257 return false; 305 return false;
258 } 306 }
259 return true; 307 return true;
260 } 308 }
261 309
262 // Creates or updates an autocomplete entry based on |data|. 310 // Creates or updates an autocomplete entry based on |data|.
263 void AutocompleteSyncableService::CreateOrUpdateEntry( 311 void AutocompleteSyncableService::CreateOrUpdateEntry(
264 const SyncData& data, 312 const SyncData& data,
265 AutocompleteEntryMap* loaded_data, 313 AutocompleteEntryMap* loaded_data,
266 std::vector<AutofillEntry>* new_entries) { 314 std::vector<AutofillEntry>* new_entries,
315 std::vector<AutofillEntry>* ignored_entries) {
267 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); 316 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics();
268 const sync_pb::AutofillSpecifics& autofill_specifics( 317 const sync_pb::AutofillSpecifics& autofill_specifics(
269 specifics.autofill()); 318 specifics.autofill());
270 319
271 if (!autofill_specifics.has_value()) { 320 if (!autofill_specifics.has_value()) {
272 DLOG(WARNING) 321 DLOG(WARNING)
273 << "Add/Update for old-style autofill profile being dropped!"; 322 << "Add/Update for old-style autofill profile being dropped!";
274 return; 323 return;
275 } 324 }
276 325
277 AutofillKey key(autofill_specifics.name().c_str(), 326 AutofillKey key(autofill_specifics.name().c_str(),
278 autofill_specifics.value().c_str()); 327 autofill_specifics.value().c_str());
279 AutocompleteEntryMap::iterator it = loaded_data->find(key); 328 AutocompleteEntryMap::iterator it = loaded_data->find(key);
280 if (it == loaded_data->end()) { 329 if (it == loaded_data->end()) {
281 // New entry. 330 // New entry.
282 std::vector<base::Time> timestamps; 331 std::vector<base::Time> timestamps;
283 size_t timestamps_count = autofill_specifics.usage_timestamp_size(); 332 size_t timestamps_count = autofill_specifics.usage_timestamp_size();
284 timestamps.resize(timestamps_count); 333 timestamps.resize(timestamps_count);
285 for (size_t ts = 0; ts < timestamps_count; ++ts) { 334 for (size_t ts = 0; ts < timestamps_count; ++ts) {
286 timestamps[ts] = base::Time::FromInternalValue( 335 timestamps[ts] = base::Time::FromInternalValue(
287 autofill_specifics.usage_timestamp(ts)); 336 autofill_specifics.usage_timestamp(ts));
Nicolas Zea 2012/03/26 18:23:55 this should probably only look at the first and la
GeorgeY 2012/03/26 19:59:10 Done.
288 } 337 }
289 new_entries->push_back(AutofillEntry(key, timestamps)); 338 AutofillEntry new_entry(key, timestamps);
339 if (new_entry.IsExpired())
340 ignored_entries->push_back(new_entry);
341 else
342 new_entries->push_back(new_entry);
290 } else { 343 } else {
291 // Entry already present - merge if necessary. 344 // Entry already present - merge if necessary.
292 std::vector<base::Time> timestamps; 345 std::vector<base::Time> timestamps;
293 bool different = MergeTimestamps( 346 bool different = MergeTimestamps(
294 autofill_specifics, it->second.second->timestamps(), &timestamps); 347 autofill_specifics, it->second.second->timestamps(), &timestamps);
295 if (different) { 348 if (different) {
296 AutofillEntry new_entry(it->second.second->key(), timestamps); 349 AutofillEntry new_entry(it->second.second->key(), timestamps);
297 new_entries->push_back(new_entry); 350 if (new_entry.IsExpired())
351 ignored_entries->push_back(new_entry);
352 else
353 new_entries->push_back(new_entry);
298 354
299 // Update the sync db if the list of timestamps have changed. 355 // Update the sync db if the list of timestamps have changed.
300 *(it->second.second) = new_entry; 356 *(it->second.second) = new_entry;
301 it->second.first = SyncChange::ACTION_UPDATE; 357 it->second.first = SyncChange::ACTION_UPDATE;
302 } else { 358 } else {
303 loaded_data->erase(it); 359 loaded_data->erase(it);
304 } 360 }
305 } 361 }
306 } 362 }
307 363
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 } 406 }
351 AutofillEntry entry(change->key(), timestamps); 407 AutofillEntry entry(change->key(), timestamps);
352 SyncChange::SyncChangeType change_type = 408 SyncChange::SyncChangeType change_type =
353 (change->type() == AutofillChange::ADD) ? 409 (change->type() == AutofillChange::ADD) ?
354 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE; 410 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE;
355 new_changes.push_back(SyncChange(change_type, 411 new_changes.push_back(SyncChange(change_type,
356 CreateSyncData(entry))); 412 CreateSyncData(entry)));
357 break; 413 break;
358 } 414 }
359 case AutofillChange::REMOVE: { 415 case AutofillChange::REMOVE: {
360 std::vector<base::Time> timestamps; 416 if (keys_to_ignore_.find(change->key()) == keys_to_ignore_.end()) {
361 AutofillEntry entry(change->key(), timestamps); 417 std::vector<base::Time> timestamps;
362 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE, 418 AutofillEntry entry(change->key(), timestamps);
363 CreateSyncData(entry))); 419 new_changes.push_back(SyncChange(SyncChange::ACTION_DELETE,
420 CreateSyncData(entry)));
421 }
364 break; 422 break;
365 } 423 }
366 default: 424 default:
367 NOTREACHED(); 425 NOTREACHED();
368 break; 426 break;
369 } 427 }
370 } 428 }
371 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); 429 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
372 if (error.IsSet()) { 430 if (error.IsSet()) {
373 DLOG(WARNING) << "[AUTOCOMPLETE SYNC]" 431 DLOG(WARNING) << "[AUTOCOMPLETE SYNC]"
374 << " Failed processing change:" 432 << " Failed processing change:"
375 << " Error:" << error.message(); 433 << " Error:" << error.message();
376 } 434 }
435 // |keys_to_ignore_| are only needed for the very first notification.
436 keys_to_ignore_.clear();
377 } 437 }
378 438
379 SyncData AutocompleteSyncableService::CreateSyncData( 439 SyncData AutocompleteSyncableService::CreateSyncData(
380 const AutofillEntry& entry) const { 440 const AutofillEntry& entry) const {
381 sync_pb::EntitySpecifics autofill_specifics; 441 sync_pb::EntitySpecifics autofill_specifics;
382 WriteAutofillEntry(entry, &autofill_specifics); 442 WriteAutofillEntry(entry, &autofill_specifics);
383 std::string tag(KeyToTag(UTF16ToUTF8(entry.key().name()), 443 std::string tag(KeyToTag(UTF16ToUTF8(entry.key().name()),
384 UTF16ToUTF8(entry.key().value()))); 444 UTF16ToUTF8(entry.key().value())));
385 return SyncData::CreateLocalData(tag, tag, autofill_specifics); 445 return SyncData::CreateLocalData(tag, tag, autofill_specifics);
386 } 446 }
387 447
388 // static 448 // static
389 std::string AutocompleteSyncableService::KeyToTag(const std::string& name, 449 std::string AutocompleteSyncableService::KeyToTag(const std::string& name,
390 const std::string& value) { 450 const std::string& value) {
391 std::string ns(kAutofillEntryNamespaceTag); 451 std::string ns(kAutofillEntryNamespaceTag);
392 return ns + net::EscapePath(name) + "|" + net::EscapePath(value); 452 return ns + net::EscapePath(name) + "|" + net::EscapePath(value);
393 } 453 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698