Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/sync/glue/autofill_profile_syncable_service.h" | |
| 6 | |
| 7 #include "base/tracked.h" | |
| 8 #include "base/utf_string_conversions.h" | |
| 9 #include "chrome/browser/sync/api/sync_error.h" | |
| 10 #include "chrome/browser/sync/glue/do_optimistic_refresh_task.h" | |
| 11 #include "chrome/browser/webdata/autofill_table.h" | |
| 12 #include "chrome/browser/webdata/web_database.h" | |
| 13 #include "chrome/common/chrome_notification_types.h" | |
| 14 #include "chrome/common/guid.h" | |
| 15 #include "content/common/notification_service.h" | |
| 16 | |
| 17 namespace browser_sync { | |
| 18 | |
| 19 const char kAutofillProfileTag[] = "google_chrome_autofill_profiles"; | |
| 20 | |
| 21 AutofillProfileSyncableService::AutofillProfileSyncableService( | |
| 22 WebDatabase* web_database, | |
| 23 PersonalDataManager* personal_data) | |
| 24 : web_database_(web_database), | |
| 25 personal_data_(personal_data), | |
| 26 sync_processor_(NULL), | |
| 27 number_of_profiles_created_(0) { | |
| 28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 29 DCHECK(web_database_); | |
| 30 DCHECK(personal_data_); | |
| 31 notification_registrar_.Add(this, | |
| 32 chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED, | |
| 33 NotificationService::AllSources()); | |
|
Ilya Sherman
2011/09/01 07:22:31
Are you sure this should be AllSources() rather th
dhollowa
2011/09/01 23:11:46
Yes, it seems like this code should only listen/re
GeorgeY
2011/09/02 04:34:12
That call is moved from original change processor,
| |
| 34 } | |
| 35 | |
| 36 AutofillProfileSyncableService::~AutofillProfileSyncableService() { | |
| 37 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
|
dhollowa
2011/09/01 23:11:46
It is fine to leave this here... but I believe it
GeorgeY
2011/09/02 04:34:12
Yes, could be changed to DCHECK(CalledOnValidThrea
| |
| 38 } | |
| 39 | |
| 40 AutofillProfileSyncableService::AutofillProfileSyncableService() | |
| 41 : web_database_(NULL), | |
| 42 personal_data_(NULL), | |
| 43 sync_processor_(NULL), | |
| 44 number_of_profiles_created_(0) { | |
| 45 notification_registrar_.Add(this, | |
| 46 chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED, | |
| 47 NotificationService::AllSources()); | |
|
Ilya Sherman
2011/09/01 07:22:31
Ditto.
GeorgeY
2011/09/02 04:34:12
Ditto.
| |
| 48 } | |
| 49 | |
| 50 bool AutofillProfileSyncableService::LoadAutofillData( | |
| 51 std::vector<AutofillProfile*>* profiles) const { | |
| 52 // const_cast it as GetAutofillProfiles() is a really const accessor, though | |
| 53 // not so declared. | |
|
Ilya Sherman
2011/09/01 07:22:31
nit: Can we propagate const properly rather than c
dhollowa
2011/09/01 23:11:46
+1
GeorgeY
2011/09/02 04:34:12
Didn't do it because:
#1. The internal state of db
| |
| 54 if (!const_cast<WebDatabase*>(web_database_)-> | |
|
dhollowa
2011/09/01 23:11:46
nit: how about simply:
return web_database_->...
dhollowa
2011/09/07 01:48:15
Ping.
GeorgeY
2011/09/07 20:55:07
sure
| |
| 55 GetAutofillTable()->GetAutofillProfiles(profiles)) | |
| 56 return false; | |
| 57 | |
| 58 return true; | |
| 59 } | |
| 60 | |
| 61 SyncError AutofillProfileSyncableService::MergeDataAndStartSyncing( | |
| 62 syncable::ModelType type, | |
| 63 const SyncDataList& initial_sync_data, | |
| 64 SyncChangeProcessor* sync_processor) { | |
| 65 DCHECK(CalledOnValidThread()); | |
| 66 DCHECK(sync_processor_ == NULL); | |
| 67 VLOG(1) << "Associating Autofill: MergeDataAndStartSyncing"; | |
| 68 | |
| 69 ScopedVector<AutofillProfile> profiles; | |
| 70 | |
| 71 if (!LoadAutofillData(&profiles.get())) { | |
| 72 return SyncError( | |
| 73 FROM_HERE, "Could not get the autofill data from WebDatabase.", | |
| 74 model_type()); | |
| 75 } | |
| 76 | |
| 77 if (VLOG_IS_ON(2)) { | |
| 78 VLOG(2) << "[AUTOFILL MIGRATION]" | |
| 79 << "Printing profiles from web db"; | |
| 80 | |
| 81 for (ScopedVector<AutofillProfile>::const_iterator ix = | |
| 82 profiles.begin(); ix != profiles.end(); ++ix) { | |
| 83 AutofillProfile* p = *ix; | |
| 84 VLOG(2) << "[AUTOFILL MIGRATION] " | |
| 85 << p->GetInfo(NAME_FIRST) | |
| 86 << p->GetInfo(NAME_LAST) | |
| 87 << p->guid(); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 sync_processor_ = sync_processor; | |
| 92 | |
| 93 GuidToProfileMap remaining_profiles; | |
| 94 CreateGuidToProfileMap(&profiles, &remaining_profiles); | |
| 95 | |
| 96 DataBundle bundle; | |
| 97 // Go through and check for all the profiles that sync already knows about. | |
| 98 for (SyncDataList::const_iterator sync_iter = initial_sync_data.begin(); | |
| 99 sync_iter != initial_sync_data.end(); | |
| 100 ++sync_iter) | |
| 101 CreateOrUpdateProfile(*sync_iter, &profiles, &remaining_profiles, &bundle); | |
|
dhollowa
2011/09/01 23:11:46
nit: style guide requires { } for multi-line for()
GeorgeY
2011/09/02 04:34:12
AFAIK, {} are required *only* if executing statem
dhollowa
2011/09/07 01:48:15
src/base/... is littered with examples of this. A
GeorgeY
2011/09/07 20:55:07
Have you checked the last code - it is already th
dhollowa
2011/09/07 21:10:24
It is helpful to the reviewer if you mark "Done".
GeorgeY
2011/09/07 23:26:24
Done. :)
| |
| 102 | |
| 103 if (!SaveChangesToWebData(bundle)) | |
| 104 return SyncError(FROM_HERE, "Failed to update webdata.", model_type()); | |
| 105 | |
| 106 SyncChangeList new_changes; | |
| 107 for (GuidToProfileMap::iterator i = remaining_profiles.begin(); | |
| 108 i != remaining_profiles.end(); ++i) { | |
| 109 new_changes.push_back( | |
| 110 CreateChange(SyncChange::ACTION_ADD, *(*(i->second)))); | |
| 111 } | |
| 112 | |
| 113 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); | |
| 114 | |
| 115 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 116 new DoOptimisticRefreshForAutofill(personal_data_)); | |
| 117 | |
| 118 return error; | |
| 119 } | |
| 120 | |
| 121 void AutofillProfileSyncableService::StopSyncing(syncable::ModelType type) { | |
| 122 DCHECK(CalledOnValidThread()); | |
| 123 DCHECK(sync_processor_ != NULL); | |
| 124 DCHECK_EQ(type, syncable::AUTOFILL_PROFILE); | |
| 125 | |
| 126 sync_processor_ = NULL; | |
| 127 } | |
| 128 | |
| 129 SyncDataList AutofillProfileSyncableService::GetAllSyncData( | |
| 130 syncable::ModelType type) const { | |
| 131 DCHECK(CalledOnValidThread()); | |
| 132 DCHECK(sync_processor_ != NULL); | |
| 133 DCHECK_EQ(type, syncable::AUTOFILL_PROFILE); | |
| 134 | |
| 135 SyncDataList current_data; | |
| 136 | |
| 137 ScopedVector<AutofillProfile> profiles; | |
| 138 | |
| 139 if (!LoadAutofillData(&profiles.get())) | |
| 140 return current_data; | |
| 141 | |
| 142 for (ScopedVector<AutofillProfile>::iterator i = profiles.begin(); | |
| 143 i != profiles.end(); ++i) { | |
| 144 sync_pb::EntitySpecifics specifics; | |
| 145 WriteAutofillProfile(*(*i), &specifics); | |
| 146 current_data.push_back(SyncData::CreateLocalData( | |
| 147 (*i)->guid(), (*i)->guid(), specifics)); | |
| 148 } | |
| 149 return current_data; | |
| 150 } | |
| 151 | |
| 152 SyncError AutofillProfileSyncableService::ProcessSyncChanges( | |
| 153 const tracked_objects::Location& from_here, | |
| 154 const SyncChangeList& change_list) { | |
| 155 DCHECK(CalledOnValidThread()); | |
| 156 DCHECK(sync_processor_ != NULL); | |
| 157 if (sync_processor_ == NULL) { | |
| 158 SyncError error(FROM_HERE, "Models not yet associated.", | |
| 159 syncable::AUTOFILL_PROFILE); | |
| 160 return error; | |
| 161 } | |
|
lipalani1
2011/09/01 05:06:02
I am concerned about the perf impact here Cam you
GeorgeY
2011/09/02 04:34:12
Done.
| |
| 162 | |
| 163 ScopedVector<AutofillProfile> profiles; | |
| 164 if (!LoadAutofillData(&profiles.get())) { | |
| 165 SyncError error(FROM_HERE, "Failed to read Web DB.", | |
| 166 syncable::AUTOFILL_PROFILE); | |
| 167 return error; | |
| 168 } | |
| 169 | |
| 170 GuidToProfileMap remaining_profiles; | |
| 171 CreateGuidToProfileMap(&profiles, &remaining_profiles); | |
| 172 | |
| 173 std::vector<std::string> profiles_to_delete; | |
| 174 DataBundle bundle; | |
| 175 | |
| 176 for (SyncChangeList::const_iterator i = change_list.begin(); | |
| 177 i != change_list.end(); ++i) { | |
| 178 DCHECK(i->IsValid()); | |
| 179 switch (i->change_type()) { | |
| 180 case SyncChange::ACTION_ADD: | |
| 181 case SyncChange::ACTION_UPDATE: | |
| 182 CreateOrUpdateProfile(i->sync_data(), &profiles, &remaining_profiles, | |
| 183 &bundle); | |
| 184 break; | |
| 185 case SyncChange::ACTION_DELETE: | |
| 186 bundle.profiles_to_delete.push_back( | |
| 187 i->sync_data().GetSpecifics(). | |
| 188 GetExtension(sync_pb::autofill_profile).guid()); | |
| 189 break; | |
| 190 default: | |
| 191 NOTREACHED() << "Unexpected sync change state."; | |
| 192 return SyncError(FROM_HERE, "ProcessSyncChanges failed on ChangeType " + | |
| 193 SyncChange::ChangeTypeToString(i->change_type()), | |
| 194 syncable::AUTOFILL_PROFILE); | |
| 195 } | |
| 196 } | |
| 197 | |
| 198 if (!SaveChangesToWebData(bundle)) | |
| 199 return SyncError(FROM_HERE, "Failed to update webdata.", model_type()); | |
| 200 | |
| 201 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 202 new DoOptimisticRefreshForAutofill(personal_data_)); | |
| 203 return SyncError(); | |
| 204 } | |
| 205 | |
| 206 void AutofillProfileSyncableService::Observe(int type, | |
| 207 const NotificationSource& source, | |
| 208 const NotificationDetails& details) { | |
| 209 DCHECK_EQ(type, chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED); | |
| 210 WebDataService* wds = Source<WebDataService>(source).ptr(); | |
| 211 | |
| 212 if (!wds || wds->GetDatabase() != web_database_) | |
| 213 return; | |
| 214 | |
| 215 AutofillProfileChange* change = Details<AutofillProfileChange>(details).ptr(); | |
| 216 | |
| 217 ActOnChange(change); | |
| 218 } | |
| 219 | |
| 220 // Helper to compare the local value and cloud value of a field, merge into | |
| 221 // the local value if they differ, and return whether the merge happened. | |
| 222 bool AutofillProfileSyncableService::MergeField(FormGroup* f, | |
| 223 AutofillFieldType t, | |
| 224 const std::string& specifics_field) { | |
| 225 if (UTF16ToUTF8(f->GetInfo(t)) == specifics_field) | |
| 226 return false; | |
| 227 f->SetInfo(t, UTF8ToUTF16(specifics_field)); | |
| 228 return true; | |
| 229 } | |
| 230 | |
| 231 // static | |
| 232 bool AutofillProfileSyncableService::OverwriteProfileWithServerData( | |
| 233 AutofillProfile* merge_into, | |
|
dhollowa
2011/09/01 20:17:49
Rename |merge_into| as |profile| and get rid of te
GeorgeY
2011/09/02 04:34:12
Done.
| |
| 234 const sync_pb::AutofillProfileSpecifics& specifics) { | |
| 235 bool diff = false; | |
| 236 AutofillProfile* p = merge_into; | |
| 237 const sync_pb::AutofillProfileSpecifics& s(specifics); | |
| 238 diff = MergeField(p, NAME_FIRST, s.name_first()) || diff; | |
| 239 diff = MergeField(p, NAME_LAST, s.name_last()) || diff; | |
| 240 diff = MergeField(p, NAME_MIDDLE, s.name_middle()) || diff; | |
| 241 diff = MergeField(p, ADDRESS_HOME_LINE1, s.address_home_line1()) || diff; | |
| 242 diff = MergeField(p, ADDRESS_HOME_LINE2, s.address_home_line2()) || diff; | |
| 243 diff = MergeField(p, ADDRESS_HOME_CITY, s.address_home_city()) || diff; | |
| 244 diff = MergeField(p, ADDRESS_HOME_STATE, s.address_home_state()) || diff; | |
| 245 diff = MergeField(p, ADDRESS_HOME_COUNTRY, s.address_home_country()) || diff; | |
| 246 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff; | |
| 247 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff; | |
| 248 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff; | |
| 249 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number()) | |
| 250 || diff; | |
| 251 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number()) | |
| 252 || diff; | |
| 253 return diff; | |
| 254 } | |
| 255 | |
| 256 SyncChange AutofillProfileSyncableService::CreateChange( | |
| 257 SyncChange::SyncChangeType action, | |
| 258 const AutofillProfile& profile) { | |
| 259 return SyncChange(action, CreateData(profile)); | |
| 260 } | |
| 261 | |
| 262 SyncChange AutofillProfileSyncableService::CreateDeleteChange( | |
| 263 const std::string& guid) { | |
| 264 AutofillProfile empty_profile(guid); | |
| 265 return SyncChange(SyncChange::ACTION_DELETE, CreateData(empty_profile)); | |
| 266 } | |
| 267 | |
| 268 SyncData AutofillProfileSyncableService::CreateData( | |
| 269 const AutofillProfile& profile) { | |
| 270 sync_pb::EntitySpecifics specifics; | |
| 271 WriteAutofillProfile(profile, &specifics); | |
| 272 return SyncData::CreateLocalData(profile.guid(), profile.guid(), specifics); | |
| 273 } | |
| 274 | |
| 275 // static | |
| 276 void AutofillProfileSyncableService::WriteAutofillProfile( | |
|
dhollowa
2011/09/01 20:17:49
nit: please reorder method to match the .h file.
GeorgeY
2011/09/02 04:34:12
Done.
| |
| 277 const AutofillProfile& profile, | |
| 278 sync_pb::EntitySpecifics* profile_specifics) { | |
| 279 sync_pb::AutofillProfileSpecifics* specifics = | |
| 280 profile_specifics->MutableExtension(sync_pb::autofill_profile); | |
| 281 | |
| 282 // This would get compiled out in official builds. The caller is expected to | |
| 283 // pass in a valid profile object with valid guid.(i.e., the caller might | |
| 284 // have to a DCHECK and log before calling. Having to check in 2 places is | |
| 285 // not optimal.) | |
| 286 DCHECK(guid::IsValidGUID(profile.guid())); | |
| 287 | |
| 288 specifics->set_guid(profile.guid()); | |
| 289 specifics->set_name_first(UTF16ToUTF8(profile.GetInfo(NAME_FIRST))); | |
| 290 specifics->set_name_middle(UTF16ToUTF8(profile.GetInfo(NAME_MIDDLE))); | |
| 291 specifics->set_name_last(UTF16ToUTF8(profile.GetInfo(NAME_LAST))); | |
| 292 specifics->set_address_home_line1( | |
| 293 UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE1))); | |
| 294 specifics->set_address_home_line2( | |
| 295 UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE2))); | |
| 296 specifics->set_address_home_city(UTF16ToUTF8(profile.GetInfo( | |
| 297 ADDRESS_HOME_CITY))); | |
| 298 specifics->set_address_home_state(UTF16ToUTF8(profile.GetInfo( | |
| 299 ADDRESS_HOME_STATE))); | |
| 300 specifics->set_address_home_country(UTF16ToUTF8(profile.GetInfo( | |
| 301 ADDRESS_HOME_COUNTRY))); | |
| 302 specifics->set_address_home_zip(UTF16ToUTF8(profile.GetInfo( | |
| 303 ADDRESS_HOME_ZIP))); | |
| 304 specifics->set_email_address(UTF16ToUTF8(profile.GetInfo(EMAIL_ADDRESS))); | |
| 305 specifics->set_company_name(UTF16ToUTF8(profile.GetInfo(COMPANY_NAME))); | |
| 306 specifics->set_phone_fax_whole_number(UTF16ToUTF8(profile.GetInfo( | |
| 307 PHONE_FAX_WHOLE_NUMBER))); | |
| 308 specifics->set_phone_home_whole_number(UTF16ToUTF8(profile.GetInfo( | |
| 309 PHONE_HOME_WHOLE_NUMBER))); | |
| 310 } | |
| 311 | |
| 312 void AutofillProfileSyncableService::CreateGuidToProfileMap( | |
| 313 ScopedVector<AutofillProfile>* profiles, GuidToProfileMap* profile_map) { | |
|
Ilya Sherman
2011/09/01 07:22:31
nit: |profiles| should probably be passed by const
GeorgeY
2011/09/02 04:34:12
Nope. I needed ::iterator, not ::const_iterator.
C
| |
| 314 DCHECK(profile_map); | |
| 315 profile_map->clear(); | |
| 316 for (ScopedVector<AutofillProfile>::iterator i = profiles->begin(); | |
| 317 i != profiles->end(); ++i) | |
| 318 (*profile_map)[(*i)->guid()] = i; | |
| 319 } | |
| 320 | |
| 321 bool AutofillProfileSyncableService::CreateOrUpdateProfile( | |
|
dhollowa
2011/09/01 23:11:46
The name of this function doesn't really reflect w
| |
| 322 const SyncData& data, ScopedVector<AutofillProfile>* profiles, | |
|
Ilya Sherman
2011/09/01 07:22:31
nit: |profiles| does not seem to be used in this f
GeorgeY
2011/09/02 04:34:12
Was left from older version - removed.
| |
| 323 GuidToProfileMap* profile_map, DataBundle *bundle) { | |
|
dhollowa
2011/09/01 20:17:49
nit: s/ */* /
GeorgeY
2011/09/02 04:34:12
Done.
| |
| 324 DCHECK(profiles); | |
| 325 DCHECK(profile_map); | |
| 326 DCHECK(bundle); | |
| 327 | |
| 328 DCHECK_EQ(syncable::AUTOFILL_PROFILE, data.GetDataType()); | |
| 329 | |
| 330 const sync_pb::EntitySpecifics& specifics = data.GetSpecifics(); | |
| 331 const sync_pb::AutofillProfileSpecifics& autofill_specifics( | |
| 332 specifics.GetExtension(sync_pb::autofill_profile)); | |
| 333 | |
| 334 bool added_new_profile = false; | |
| 335 | |
| 336 GuidToProfileMap::iterator it = profile_map->find( | |
| 337 autofill_specifics.guid()); | |
| 338 if (it != profile_map->end()) { | |
| 339 // Some profile that already present is synced. | |
| 340 if (OverwriteProfileWithServerData(*(it->second), autofill_specifics)) | |
| 341 bundle->updated_profiles.push_back(*(it->second)); | |
| 342 profile_map->erase(autofill_specifics.guid()); | |
| 343 } else { | |
| 344 // New profile synced. | |
| 345 AutofillProfile *p(new AutofillProfile(autofill_specifics.guid())); | |
|
dhollowa
2011/09/01 20:17:49
nit: s/ */* /
GeorgeY
2011/09/02 04:34:12
Done.
| |
| 346 OverwriteProfileWithServerData(p, autofill_specifics); | |
| 347 | |
| 348 // Check if profile appears under a different guid. | |
| 349 GuidToProfileMap::iterator i; | |
| 350 for (i = profile_map->begin(); i != profile_map->end(); ++i) { | |
| 351 if ((*(i->second))->Compare(*p) == 0) { | |
| 352 bundle->profiles_to_delete.push_back((*(i->second))->guid()); | |
| 353 VLOG(2) << "[AUTOFILL SYNC]" | |
| 354 << "Found in sync db but with a different guid: " | |
| 355 << UTF16ToUTF8((*(i->second))->GetInfo(NAME_FIRST)) | |
| 356 << UTF16ToUTF8((*(i->second))->GetInfo(NAME_LAST)) | |
| 357 << "New guid " << p->guid() << ". Profile to be deleted " | |
| 358 << (*(i->second))->guid(); | |
| 359 profile_map->erase(i); | |
|
lipalani1
2011/09/01 05:06:02
Profile is only erased from the map. Who is erasin
GeorgeY
2011/09/02 04:34:12
It is erased from web_db with a call to DataBundle
| |
| 360 break; | |
| 361 } | |
| 362 } | |
| 363 // Bundle takes ownership of new profiles only. | |
| 364 bundle->new_profiles.push_back(p); | |
| 365 added_new_profile = true; | |
|
Ilya Sherman
2011/09/01 07:22:31
I'm a little confused here: If the profile appear
GeorgeY
2011/09/02 04:34:12
We do not want to have multiple copies of a profil
| |
| 366 } | |
| 367 return added_new_profile; | |
| 368 } | |
| 369 | |
| 370 void AutofillProfileSyncableService::ActOnChange( | |
| 371 AutofillProfileChange* change) { | |
| 372 DCHECK(change->type() == AutofillProfileChange::REMOVE || change->profile()); | |
|
dhollowa
2011/09/01 23:11:46
This DCHECK is not quite accurate. Better would b
GeorgeY
2011/09/02 04:34:12
Further down we assert on any change that is not A
dhollowa
2011/09/07 01:48:15
Yes, but your checks wouldn't catch the case where
GeorgeY
2011/09/07 20:55:07
But that case is not and error - AFAIK, profile is
dhollowa
2011/09/07 21:10:24
That is not correct. See autofill_change.h:51
GeorgeY
2011/09/07 23:26:24
Done.
| |
| 373 DCHECK(sync_processor_); | |
| 374 SyncChangeList new_changes; | |
| 375 switch (change->type()) { | |
| 376 case AutofillProfileChange::ADD: | |
| 377 new_changes.push_back( | |
| 378 CreateChange(SyncChange::ACTION_ADD, *(change->profile()))); | |
|
dhollowa
2011/09/01 23:11:46
These CreateChange and CreateDeleteChange helpers
GeorgeY
2011/09/02 04:34:12
sure
| |
| 379 break; | |
| 380 case AutofillProfileChange::UPDATE: | |
| 381 new_changes.push_back( | |
| 382 CreateChange(SyncChange::ACTION_UPDATE, *(change->profile()))); | |
| 383 break; | |
| 384 case AutofillProfileChange::REMOVE: | |
| 385 new_changes.push_back(CreateDeleteChange(change->key())); | |
| 386 break; | |
| 387 default: | |
| 388 NOTREACHED(); | |
| 389 } | |
| 390 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); | |
| 391 if (error.IsSet()) { | |
|
lipalani1
2011/09/01 05:06:02
may be this is a vlog(warning)?
GeorgeY
2011/09/02 04:34:12
Sure.
| |
| 392 VLOG(2) << "[AUTOFILL SYNC]" | |
| 393 << " Failed processing change:" | |
| 394 << " Error:" << error.message() | |
| 395 << " Guid:" << change->profile()->guid(); | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 bool AutofillProfileSyncableService::SaveChangesToWebData( | |
| 400 const DataBundle& bundle) { | |
| 401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 402 | |
| 403 for (size_t i = 0; i < bundle.new_profiles.size(); i++) { | |
| 404 if (!web_database_->GetAutofillTable()->AddAutofillProfile( | |
| 405 *bundle.new_profiles[i])) | |
| 406 return false; | |
| 407 } | |
| 408 | |
| 409 for (size_t i = 0; i < bundle.updated_profiles.size(); i++) { | |
| 410 if (!web_database_->GetAutofillTable()->UpdateAutofillProfile( | |
| 411 *bundle.updated_profiles[i])) | |
| 412 return false; | |
| 413 } | |
| 414 | |
| 415 for (size_t i = 0; i< bundle.profiles_to_delete.size(); ++i) { | |
| 416 if (!web_database_->GetAutofillTable()->RemoveAutofillProfile( | |
| 417 bundle.profiles_to_delete[i])) | |
| 418 return false; | |
| 419 } | |
| 420 return true; | |
| 421 } | |
| 422 | |
| 423 AutofillProfileSyncableService::DataBundle::DataBundle() {} | |
| 424 | |
| 425 AutofillProfileSyncableService::DataBundle::~DataBundle() { | |
| 426 STLDeleteElements(&new_profiles); | |
| 427 } | |
| 428 | |
| 429 } // namespace browser_sync | |
| 430 | |
| OLD | NEW |