| 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_model_associator.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/autofill_profile_change_processor.h" | |
| 11 #include "chrome/browser/sync/glue/do_optimistic_refresh_task.h" | |
| 12 #include "chrome/browser/sync/internal_api/read_node.h" | |
| 13 #include "chrome/browser/sync/internal_api/read_transaction.h" | |
| 14 #include "chrome/browser/sync/internal_api/write_node.h" | |
| 15 #include "chrome/browser/sync/internal_api/write_transaction.h" | |
| 16 #include "chrome/browser/sync/profile_sync_service.h" | |
| 17 #include "chrome/browser/webdata/autofill_table.h" | |
| 18 #include "chrome/browser/webdata/web_database.h" | |
| 19 #include "chrome/common/guid.h" | |
| 20 | |
| 21 using sync_api::ReadNode; | |
| 22 namespace browser_sync { | |
| 23 | |
| 24 const char kAutofillProfileTag[] = "google_chrome_autofill_profiles"; | |
| 25 | |
| 26 AutofillProfileModelAssociator::AutofillProfileModelAssociator( | |
| 27 ProfileSyncService* sync_service, | |
| 28 WebDatabase* web_database, | |
| 29 PersonalDataManager* personal_data) | |
| 30 : sync_service_(sync_service), | |
| 31 web_database_(web_database), | |
| 32 personal_data_(personal_data), | |
| 33 autofill_node_id_(sync_api::kInvalidId), | |
| 34 abort_association_pending_(false), | |
| 35 number_of_profiles_created_(0) { | |
| 36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 37 DCHECK(sync_service_); | |
| 38 DCHECK(web_database_); | |
| 39 DCHECK(personal_data_); | |
| 40 } | |
| 41 | |
| 42 AutofillProfileModelAssociator::~AutofillProfileModelAssociator() { | |
| 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 44 } | |
| 45 | |
| 46 AutofillProfileModelAssociator::AutofillProfileModelAssociator() | |
| 47 : sync_service_(NULL), | |
| 48 web_database_(NULL), | |
| 49 personal_data_(NULL), | |
| 50 autofill_node_id_(0), | |
| 51 abort_association_pending_(false), | |
| 52 number_of_profiles_created_(0) { | |
| 53 } | |
| 54 | |
| 55 bool AutofillProfileModelAssociator::TraverseAndAssociateChromeAutofillProfiles( | |
| 56 sync_api::WriteTransaction* write_trans, | |
| 57 const sync_api::ReadNode& autofill_root, | |
| 58 const std::vector<AutofillProfile*>& all_profiles_from_db, | |
| 59 std::set<std::string>* current_profiles, | |
| 60 std::vector<AutofillProfile*>* updated_profiles, | |
| 61 std::vector<AutofillProfile*>* new_profiles, | |
| 62 std::vector<std::string>* profiles_to_delete) { | |
| 63 | |
| 64 if (VLOG_IS_ON(2)) { | |
| 65 VLOG(2) << "[AUTOFILL MIGRATION]" | |
| 66 << "Printing profiles from web db"; | |
| 67 | |
| 68 for (std::vector<AutofillProfile*>::const_iterator ix = | |
| 69 all_profiles_from_db.begin(); ix != all_profiles_from_db.end(); ++ix) { | |
| 70 AutofillProfile* p = *ix; | |
| 71 VLOG(2) << "[AUTOFILL MIGRATION] " | |
| 72 << p->GetInfo(NAME_FIRST) | |
| 73 << p->GetInfo(NAME_LAST) | |
| 74 << p->guid(); | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 VLOG(1) << "[AUTOFILL MIGRATION]" | |
| 79 << "Looking for the above data in sync db.."; | |
| 80 | |
| 81 // Alias the all_profiles_from_db so we fit in 80 characters | |
| 82 const std::vector<AutofillProfile*>& profiles(all_profiles_from_db); | |
| 83 for (std::vector<AutofillProfile*>::const_iterator ix = profiles.begin(); | |
| 84 ix != profiles.end(); | |
| 85 ++ix) { | |
| 86 std::string guid((*ix)->guid()); | |
| 87 if (guid::IsValidGUID(guid) == false) { | |
| 88 DCHECK(false) << "Guid in the web db is invalid " << guid; | |
| 89 continue; | |
| 90 } | |
| 91 | |
| 92 ReadNode node(write_trans); | |
| 93 if (node.InitByClientTagLookup(syncable::AUTOFILL_PROFILE, guid) && | |
| 94 // The following check is to ensure the given sync node is not already | |
| 95 // associated with another profile. That could happen if the user has | |
| 96 // the same profile duplicated. | |
| 97 current_profiles->find(guid) == current_profiles->end()) { | |
| 98 VLOG(2) << "[AUTOFILL MIGRATION]" | |
| 99 << " Found in sync db: " | |
| 100 << (*ix)->GetInfo(NAME_FIRST) | |
| 101 << (*ix)->GetInfo(NAME_LAST) | |
| 102 << (*ix)->guid() | |
| 103 << " so associating with node id " << node.GetId(); | |
| 104 const sync_pb::AutofillProfileSpecifics& autofill( | |
| 105 node.GetAutofillProfileSpecifics()); | |
| 106 if (OverwriteProfileWithServerData(*ix, autofill)) { | |
| 107 updated_profiles->push_back(*ix); | |
| 108 } | |
| 109 Associate(&guid, node.GetId()); | |
| 110 current_profiles->insert(guid); | |
| 111 } else { | |
| 112 MakeNewAutofillProfileSyncNodeIfNeeded(write_trans, | |
| 113 autofill_root, | |
| 114 (**ix), | |
| 115 new_profiles, | |
| 116 current_profiles, | |
| 117 profiles_to_delete); | |
| 118 } | |
| 119 } | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 bool AutofillProfileModelAssociator::GetSyncIdForTaggedNode( | |
| 124 const std::string& tag, | |
| 125 int64* sync_id) { | |
| 126 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 127 sync_api::ReadNode sync_node(&trans); | |
| 128 if (!sync_node.InitByTagLookup(tag.c_str())) | |
| 129 return false; | |
| 130 *sync_id = sync_node.GetId(); | |
| 131 return true; | |
| 132 } | |
| 133 | |
| 134 bool AutofillProfileModelAssociator::LoadAutofillData( | |
| 135 std::vector<AutofillProfile*>* profiles) { | |
| 136 if (IsAbortPending()) | |
| 137 return false; | |
| 138 | |
| 139 if (!web_database_->GetAutofillTable()->GetAutofillProfiles(profiles)) | |
| 140 return false; | |
| 141 | |
| 142 return true; | |
| 143 } | |
| 144 | |
| 145 bool AutofillProfileModelAssociator::AssociateModels(SyncError* error) { | |
| 146 VLOG(1) << "Associating Autofill Models"; | |
| 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 148 { | |
| 149 base::AutoLock lock(abort_association_pending_lock_); | |
| 150 abort_association_pending_ = false; | |
| 151 } | |
| 152 | |
| 153 ScopedVector<AutofillProfile> profiles; | |
| 154 | |
| 155 if (!LoadAutofillData(&profiles.get())) { | |
| 156 error->Reset(FROM_HERE, | |
| 157 "Could not get the autofill data from WebDatabase.", | |
| 158 model_type()); | |
| 159 return false; | |
| 160 } | |
| 161 | |
| 162 VLOG(1) << "[AUTOFILL MIGRATION]" | |
| 163 << " Now associating to the new autofill profile model associator" | |
| 164 << " root node"; | |
| 165 DataBundle bundle; | |
| 166 { | |
| 167 // The write transaction lock is held inside this block. | |
| 168 // We do all the web db operations outside this block. | |
| 169 sync_api::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 170 | |
| 171 sync_api::ReadNode autofill_root(&trans); | |
| 172 if (!autofill_root.InitByTagLookup(kAutofillProfileTag)) { | |
| 173 error->Reset(FROM_HERE, | |
| 174 "Server did not create the top-level autofill node. We " | |
| 175 "might be running against an out-of-date server.", | |
| 176 model_type()); | |
| 177 return false; | |
| 178 } | |
| 179 | |
| 180 if (!TraverseAndAssociateChromeAutofillProfiles(&trans, autofill_root, | |
| 181 profiles.get(), &bundle.current_profiles, | |
| 182 &bundle.updated_profiles, | |
| 183 &bundle.new_profiles, | |
| 184 &bundle.profiles_to_delete) || | |
| 185 !TraverseAndAssociateAllSyncNodes(&trans, autofill_root, &bundle)) { | |
| 186 error->Reset(FROM_HERE, | |
| 187 "Failed to associate all sync nodes.", | |
| 188 model_type()); | |
| 189 return false; | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 if (!SaveChangesToWebData(bundle)) { | |
| 194 error->Reset(FROM_HERE, "Failed to update webdata.", model_type()); | |
| 195 return false; | |
| 196 } | |
| 197 | |
| 198 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 199 new DoOptimisticRefreshForAutofill(personal_data_)); | |
| 200 return true; | |
| 201 } | |
| 202 | |
| 203 bool AutofillProfileModelAssociator::DisassociateModels(SyncError* error) { | |
| 204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 205 id_map_.clear(); | |
| 206 id_map_inverse_.clear(); | |
| 207 return true; | |
| 208 } | |
| 209 | |
| 210 // Helper to compare the local value and cloud value of a field, merge into | |
| 211 // the local value if they differ, and return whether the merge happened. | |
| 212 bool AutofillProfileModelAssociator::MergeField(FormGroup* f, | |
| 213 AutofillFieldType t, | |
| 214 const std::string& specifics_field) { | |
| 215 if (UTF16ToUTF8(f->GetInfo(t)) == specifics_field) | |
| 216 return false; | |
| 217 f->SetInfo(t, UTF8ToUTF16(specifics_field)); | |
| 218 return true; | |
| 219 } | |
| 220 bool AutofillProfileModelAssociator::SyncModelHasUserCreatedNodes( | |
| 221 bool *has_nodes) { | |
| 222 CHECK_NE(has_nodes, reinterpret_cast<bool*>(NULL)); | |
| 223 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 224 | |
| 225 sync_api::ReadNode node(&trans); | |
| 226 | |
| 227 if (!node.InitByTagLookup(kAutofillProfileTag)) { | |
| 228 LOG(ERROR) << "Sever did not create a top level node" | |
| 229 << "Out of data server or autofill type not enabled"; | |
| 230 return false; | |
| 231 } | |
| 232 | |
| 233 *has_nodes = sync_api::kInvalidId != node.GetFirstChildId(); | |
| 234 return true; | |
| 235 } | |
| 236 // static | |
| 237 bool AutofillProfileModelAssociator::OverwriteProfileWithServerData( | |
| 238 AutofillProfile* merge_into, | |
| 239 const sync_pb::AutofillProfileSpecifics& specifics) { | |
| 240 bool diff = false; | |
| 241 AutofillProfile* p = merge_into; | |
| 242 const sync_pb::AutofillProfileSpecifics& s(specifics); | |
| 243 diff = MergeField(p, NAME_FIRST, s.name_first()) || diff; | |
| 244 diff = MergeField(p, NAME_LAST, s.name_last()) || diff; | |
| 245 diff = MergeField(p, NAME_MIDDLE, s.name_middle()) || diff; | |
| 246 diff = MergeField(p, ADDRESS_HOME_LINE1, s.address_home_line1()) || diff; | |
| 247 diff = MergeField(p, ADDRESS_HOME_LINE2, s.address_home_line2()) || diff; | |
| 248 diff = MergeField(p, ADDRESS_HOME_CITY, s.address_home_city()) || diff; | |
| 249 diff = MergeField(p, ADDRESS_HOME_STATE, s.address_home_state()) || diff; | |
| 250 diff = MergeField(p, ADDRESS_HOME_COUNTRY, s.address_home_country()) || diff; | |
| 251 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff; | |
| 252 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff; | |
| 253 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff; | |
| 254 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number()) | |
| 255 || diff; | |
| 256 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number()) | |
| 257 || diff; | |
| 258 return diff; | |
| 259 } | |
| 260 | |
| 261 | |
| 262 int64 AutofillProfileModelAssociator::FindSyncNodeWithProfile( | |
| 263 sync_api::WriteTransaction* trans, | |
| 264 const sync_api::BaseNode& autofill_root, | |
| 265 const AutofillProfile& profile_from_db, | |
| 266 std::set<std::string>* current_profiles) { | |
| 267 int64 sync_child_id = autofill_root.GetFirstChildId(); | |
| 268 while (sync_child_id != sync_api::kInvalidId) { | |
| 269 ReadNode read_node(trans); | |
| 270 AutofillProfile p; | |
| 271 if (!read_node.InitByIdLookup(sync_child_id)) { | |
| 272 LOG(ERROR) << "unable to find the id given by getfirst child " << | |
| 273 sync_child_id; | |
| 274 return sync_api::kInvalidId; | |
| 275 } | |
| 276 const sync_pb::AutofillProfileSpecifics& autofill_specifics( | |
| 277 read_node.GetAutofillProfileSpecifics()); | |
| 278 | |
| 279 // This find should be fast as the set uses tree. | |
| 280 if (current_profiles->find(autofill_specifics.guid()) | |
| 281 == current_profiles->end()) { | |
| 282 OverwriteProfileWithServerData(&p, autofill_specifics); | |
| 283 if (p.Compare(profile_from_db) == 0) { | |
| 284 return sync_child_id; | |
| 285 } | |
| 286 } | |
| 287 sync_child_id = read_node.GetSuccessorId(); | |
| 288 } | |
| 289 | |
| 290 return sync_api::kInvalidId; | |
| 291 } | |
| 292 bool AutofillProfileModelAssociator::MakeNewAutofillProfileSyncNodeIfNeeded( | |
| 293 sync_api::WriteTransaction* trans, | |
| 294 const sync_api::BaseNode& autofill_root, | |
| 295 const AutofillProfile& profile, | |
| 296 std::vector<AutofillProfile*>* new_profiles, | |
| 297 std::set<std::string>* current_profiles, | |
| 298 std::vector<std::string>* profiles_to_delete) { | |
| 299 | |
| 300 int64 sync_node_id = FindSyncNodeWithProfile(trans, | |
| 301 autofill_root, | |
| 302 profile, | |
| 303 current_profiles); | |
| 304 if (sync_node_id != sync_api::kInvalidId) { | |
| 305 // In case of duplicates throw away the local profile and apply the | |
| 306 // server profile.(The only difference between the 2 profiles are the guids) | |
| 307 profiles_to_delete->push_back(profile.guid()); | |
| 308 sync_api::ReadNode read_node(trans); | |
| 309 if (!read_node.InitByIdLookup(sync_node_id)) { | |
| 310 LOG(ERROR); | |
| 311 return false; | |
| 312 } | |
| 313 const sync_pb::AutofillProfileSpecifics& autofill_specifics( | |
| 314 read_node.GetAutofillProfileSpecifics()); | |
| 315 if (guid::IsValidGUID(autofill_specifics.guid()) == false) { | |
| 316 NOTREACHED() << "Guid in the web db is invalid " << | |
| 317 autofill_specifics.guid(); | |
| 318 return false; | |
| 319 } | |
| 320 AutofillProfile* p = new AutofillProfile(autofill_specifics.guid()); | |
| 321 OverwriteProfileWithServerData(p, autofill_specifics); | |
| 322 new_profiles->push_back(p); | |
| 323 std::string guid = autofill_specifics.guid(); | |
| 324 Associate(&guid, sync_node_id); | |
| 325 current_profiles->insert(autofill_specifics.guid()); | |
| 326 VLOG(2) << "[AUTOFILL MIGRATION]" | |
| 327 << "Found in sync db but with a different guid: " | |
| 328 << UTF16ToUTF8(profile.GetInfo(NAME_FIRST)) | |
| 329 << UTF16ToUTF8(profile.GetInfo(NAME_LAST)) | |
| 330 << "New guid " << autofill_specifics.guid() << " sync node id " | |
| 331 << sync_node_id << " so associating. Profile to be deleted " | |
| 332 << profile.guid(); | |
| 333 } else { | |
| 334 sync_api::WriteNode node(trans); | |
| 335 | |
| 336 // The profile.guid() is expected to be a valid guid. The caller is expected | |
| 337 // to pass in a valid profile object with a valid guid. Having to check in | |
| 338 // 2 places(the caller and here) is not optimal. | |
| 339 if (!node.InitUniqueByCreation( | |
| 340 syncable::AUTOFILL_PROFILE, autofill_root, profile.guid())) { | |
| 341 LOG(ERROR) << "Failed to create autofill sync node."; | |
| 342 return false; | |
| 343 } | |
| 344 node.SetTitle(UTF8ToWide(profile.guid())); | |
| 345 VLOG(2) << "[AUTOFILL MIGRATION]" | |
| 346 << "NOT Found in sync db " | |
| 347 << UTF16ToUTF8(profile.GetInfo(NAME_FIRST)) | |
| 348 << UTF16ToUTF8(profile.GetInfo(NAME_LAST)) | |
| 349 << profile.guid() | |
| 350 << " so creating a new sync node. Sync node id " | |
| 351 << node.GetId(); | |
| 352 AutofillProfileChangeProcessor::WriteAutofillProfile(profile, &node); | |
| 353 current_profiles->insert(profile.guid()); | |
| 354 std::string guid = profile.guid(); | |
| 355 Associate(&guid, node.GetId()); | |
| 356 number_of_profiles_created_++; | |
| 357 } | |
| 358 return true; | |
| 359 } | |
| 360 | |
| 361 bool AutofillProfileModelAssociator::TraverseAndAssociateAllSyncNodes( | |
| 362 sync_api::WriteTransaction* write_trans, | |
| 363 const sync_api::ReadNode& autofill_root, | |
| 364 DataBundle* bundle) { | |
| 365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 366 VLOG(1) << "[AUTOFILL MIGRATION] " | |
| 367 << " Iterating over sync nodes of autofill profile root node"; | |
| 368 | |
| 369 int64 sync_child_id = autofill_root.GetFirstChildId(); | |
| 370 while (sync_child_id != sync_api::kInvalidId) { | |
| 371 ReadNode sync_child(write_trans); | |
| 372 if (!sync_child.InitByIdLookup(sync_child_id)) { | |
| 373 LOG(ERROR) << "Failed to fetch child node."; | |
| 374 return false; | |
| 375 } | |
| 376 const sync_pb::AutofillProfileSpecifics& autofill( | |
| 377 sync_child.GetAutofillProfileSpecifics()); | |
| 378 | |
| 379 AddNativeProfileIfNeeded(autofill, bundle, sync_child); | |
| 380 | |
| 381 sync_child_id = sync_child.GetSuccessorId(); | |
| 382 } | |
| 383 return true; | |
| 384 } | |
| 385 | |
| 386 void AutofillProfileModelAssociator::AddNativeProfileIfNeeded( | |
| 387 const sync_pb::AutofillProfileSpecifics& profile, | |
| 388 DataBundle* bundle, | |
| 389 const sync_api::ReadNode& node) { | |
| 390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 391 | |
| 392 VLOG(2) << "[AUTOFILL MIGRATION] " | |
| 393 << "Trying to lookup " | |
| 394 << profile.name_first() | |
| 395 << " " | |
| 396 << profile.name_last() | |
| 397 << "sync node id " << node.GetId() | |
| 398 << " Guid " << profile.guid() | |
| 399 << " in the web db"; | |
| 400 | |
| 401 if (guid::IsValidGUID(profile.guid()) == false) { | |
| 402 DCHECK(false) << "Guid in the sync db is invalid " << profile.guid(); | |
| 403 return; | |
| 404 } | |
| 405 | |
| 406 if (bundle->current_profiles.find(profile.guid()) == | |
| 407 bundle->current_profiles.end()) { | |
| 408 std::string guid(profile.guid()); | |
| 409 Associate(&guid, node.GetId()); | |
| 410 AutofillProfile* p = new AutofillProfile(profile.guid()); | |
| 411 OverwriteProfileWithServerData(p, profile); | |
| 412 bundle->new_profiles.push_back(p); | |
| 413 VLOG(2) << "[AUTOFILL MIGRATION] " | |
| 414 << " Did not find one so creating it on web db"; | |
| 415 } else { | |
| 416 VLOG(2) << "[AUTOFILL MIGRATION] " | |
| 417 << " Found it on web db. Moving on "; | |
| 418 } | |
| 419 } | |
| 420 | |
| 421 bool AutofillProfileModelAssociator::SaveChangesToWebData( | |
| 422 const DataBundle& bundle) { | |
| 423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 424 | |
| 425 if (IsAbortPending()) | |
| 426 return false; | |
| 427 | |
| 428 for (size_t i = 0; i < bundle.new_profiles.size(); i++) { | |
| 429 if (IsAbortPending()) | |
| 430 return false; | |
| 431 if (!web_database_->GetAutofillTable()->AddAutofillProfile( | |
| 432 *bundle.new_profiles[i])) | |
| 433 return false; | |
| 434 } | |
| 435 | |
| 436 for (size_t i = 0; i < bundle.updated_profiles.size(); i++) { | |
| 437 if (IsAbortPending()) | |
| 438 return false; | |
| 439 if (!web_database_->GetAutofillTable()->UpdateAutofillProfile( | |
| 440 *bundle.updated_profiles[i])) | |
| 441 return false; | |
| 442 } | |
| 443 | |
| 444 for (size_t i = 0; i< bundle.profiles_to_delete.size(); ++i) { | |
| 445 if (IsAbortPending()) | |
| 446 return false; | |
| 447 if (!web_database_->GetAutofillTable()->RemoveAutofillProfile( | |
| 448 bundle.profiles_to_delete[i])) | |
| 449 return false; | |
| 450 } | |
| 451 return true; | |
| 452 } | |
| 453 | |
| 454 bool AutofillProfileModelAssociator::InitSyncNodeFromChromeId( | |
| 455 const std::string& node_id, | |
| 456 sync_api::BaseNode* sync_node) { | |
| 457 return false; | |
| 458 } | |
| 459 | |
| 460 void AutofillProfileModelAssociator::Associate( | |
| 461 const std::string* autofill, | |
| 462 int64 sync_id) { | |
| 463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 464 DCHECK_NE(sync_api::kInvalidId, sync_id); | |
| 465 DCHECK(id_map_.find(*autofill) == id_map_.end()); | |
| 466 DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); | |
| 467 id_map_[*autofill] = sync_id; | |
| 468 id_map_inverse_[sync_id] = *autofill; | |
| 469 } | |
| 470 | |
| 471 void AutofillProfileModelAssociator::Disassociate(int64 sync_id) { | |
| 472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | |
| 473 SyncIdToAutofillMap::iterator iter = id_map_inverse_.find(sync_id); | |
| 474 if (iter == id_map_inverse_.end()) | |
| 475 return; | |
| 476 CHECK(id_map_.erase(iter->second)); | |
| 477 id_map_inverse_.erase(iter); | |
| 478 } | |
| 479 | |
| 480 int64 AutofillProfileModelAssociator::GetSyncIdFromChromeId( | |
| 481 const std::string& autofill) { | |
| 482 AutofillToSyncIdMap::const_iterator iter = id_map_.find(autofill); | |
| 483 return iter == id_map_.end() ? sync_api::kInvalidId : iter->second; | |
| 484 } | |
| 485 | |
| 486 void AutofillProfileModelAssociator::AbortAssociation() { | |
| 487 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 488 base::AutoLock lock(abort_association_pending_lock_); | |
| 489 abort_association_pending_ = true; | |
| 490 } | |
| 491 | |
| 492 const std::string* AutofillProfileModelAssociator::GetChromeNodeFromSyncId( | |
| 493 int64 sync_id) { | |
| 494 SyncIdToAutofillMap::const_iterator iter = id_map_inverse_.find(sync_id); | |
| 495 return iter == id_map_inverse_.end() ? NULL : &(iter->second); | |
| 496 } | |
| 497 | |
| 498 bool AutofillProfileModelAssociator::IsAbortPending() { | |
| 499 base::AutoLock lock(abort_association_pending_lock_); | |
| 500 return abort_association_pending_; | |
| 501 } | |
| 502 | |
| 503 AutofillProfileModelAssociator::DataBundle::DataBundle() {} | |
| 504 | |
| 505 AutofillProfileModelAssociator::DataBundle::~DataBundle() { | |
| 506 STLDeleteElements(&new_profiles); | |
| 507 } | |
| 508 | |
| 509 bool AutofillProfileModelAssociator::CryptoReadyIfNecessary() { | |
| 510 // We only access the cryptographer while holding a transaction. | |
| 511 sync_api::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 512 syncable::ModelTypeSet encrypted_types; | |
| 513 encrypted_types = sync_api::GetEncryptedTypes(&trans); | |
| 514 return encrypted_types.count(syncable::AUTOFILL_PROFILE) == 0 || | |
| 515 sync_service_->IsCryptographerReady(&trans); | |
| 516 } | |
| 517 | |
| 518 } // namespace browser_sync | |
| OLD | NEW |