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