Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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(), ×tamps); | 382 autofill_specifics, it->second.second->timestamps(), ×tamps); |
| 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 Loading... | |
| 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 } |
| OLD | NEW |