OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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_change_processor2.h" |
| 6 |
| 7 #include <string> |
| 8 #include <vector> |
| 9 |
| 10 #include "base/string_util.h" |
| 11 #include "base/utf_string_conversions.h" |
| 12 #include "chrome/browser/profile.h" |
| 13 #include "chrome/browser/autofill/personal_data_manager.h" |
| 14 #include "chrome/browser/sync/glue/autofill_model_associator.h" |
| 15 #include "chrome/browser/sync/glue/autofill_model_associator2.h" |
| 16 #include "chrome/browser/sync/profile_sync_service.h" |
| 17 #include "chrome/browser/webdata/autofill_change.h" |
| 18 #include "chrome/browser/webdata/web_data_service.h" |
| 19 #include "chrome/browser/webdata/web_database.h" |
| 20 #include "chrome/common/notification_service.h" |
| 21 |
| 22 namespace browser_sync { |
| 23 |
| 24 class AutofillModelAssociator2; |
| 25 struct AutofillChangeProcessor2::AutofillChangeRecord { |
| 26 sync_api::SyncManager::ChangeRecord::Action action_; |
| 27 int64 id_; |
| 28 sync_pb::AutofillSpecifics autofill_; |
| 29 AutofillChangeRecord(sync_api::SyncManager::ChangeRecord::Action action, |
| 30 int64 id, const sync_pb::AutofillSpecifics& autofill) |
| 31 : action_(action), |
| 32 id_(id), |
| 33 autofill_(autofill) { } |
| 34 }; |
| 35 |
| 36 AutofillChangeProcessor2::AutofillChangeProcessor2( |
| 37 AutofillModelAssociator2* model_associator, |
| 38 WebDatabase* web_database, |
| 39 PersonalDataManager* personal_data, |
| 40 UnrecoverableErrorHandler* error_handler) |
| 41 : ChangeProcessor(error_handler), |
| 42 model_associator_(model_associator), |
| 43 web_database_(web_database), |
| 44 personal_data_(personal_data), |
| 45 observing_(false) { |
| 46 DCHECK(model_associator); |
| 47 DCHECK(web_database); |
| 48 DCHECK(error_handler); |
| 49 DCHECK(personal_data); |
| 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 51 StartObserving(); |
| 52 } |
| 53 |
| 54 AutofillChangeProcessor2::~AutofillChangeProcessor2() {} |
| 55 |
| 56 void AutofillChangeProcessor2::Observe(NotificationType type, |
| 57 const NotificationSource& source, |
| 58 const NotificationDetails& details) { |
| 59 // Ensure this notification came from our web database. |
| 60 WebDataService* wds = Source<WebDataService>(source).ptr(); |
| 61 if (!wds || wds->GetDatabase() != web_database_) |
| 62 return; |
| 63 |
| 64 DCHECK(running()); |
| 65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 66 if (!observing_) |
| 67 return; |
| 68 |
| 69 sync_api::WriteTransaction trans(share_handle()); |
| 70 sync_api::ReadNode autofill_root(&trans); |
| 71 if (!autofill_root.InitByTagLookup(kAutofillTag)) { |
| 72 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 73 "Server did not create the top-level autofill node. " |
| 74 "We might be running against an out-of-date server."); |
| 75 return; |
| 76 } |
| 77 |
| 78 switch (type.value) { |
| 79 case NotificationType::AUTOFILL_ENTRIES_CHANGED: { |
| 80 AutofillChangeList* changes = Details<AutofillChangeList>(details).ptr(); |
| 81 ObserveAutofillEntriesChanged(changes, &trans, autofill_root); |
| 82 break; |
| 83 } |
| 84 case NotificationType::AUTOFILL_PROFILE_CHANGED: { |
| 85 AutofillProfileChange* change = |
| 86 Details<AutofillProfileChange>(details).ptr(); |
| 87 ObserveAutofillProfileChanged(change, &trans, autofill_root); |
| 88 break; |
| 89 } |
| 90 default: |
| 91 NOTREACHED() << "Invalid NotificationType."; |
| 92 } |
| 93 } |
| 94 |
| 95 void AutofillChangeProcessor2::ChangeProfileLabelIfAlreadyTaken( |
| 96 sync_api::BaseTransaction* trans, |
| 97 const string16& pre_update_label, |
| 98 AutoFillProfile* profile, |
| 99 std::string* tag) { |
| 100 DCHECK_EQ(AutofillModelAssociator2::ProfileLabelToTag(profile->Label()), |
| 101 *tag); |
| 102 sync_api::ReadNode read_node(trans); |
| 103 if (!pre_update_label.empty() && pre_update_label == profile->Label()) |
| 104 return; |
| 105 if (read_node.InitByClientTagLookup(syncable::AUTOFILL, *tag)) { |
| 106 // Handle the edge case of duplicate labels. |
| 107 string16 new_label(AutofillModelAssociator2::MakeUniqueLabel( |
| 108 profile->Label(), pre_update_label, trans)); |
| 109 if (new_label.empty()) { |
| 110 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 111 "No unique label; can't move aside"); |
| 112 return; |
| 113 } |
| 114 OverrideProfileLabel(new_label, profile, tag); |
| 115 } |
| 116 } |
| 117 |
| 118 void AutofillChangeProcessor2::OverrideProfileLabel( |
| 119 const string16& new_label, |
| 120 AutoFillProfile* profile_to_update, |
| 121 std::string* tag_to_update) { |
| 122 tag_to_update->assign(AutofillModelAssociator2::ProfileLabelToTag(new_label)); |
| 123 |
| 124 profile_to_update->set_label(new_label); |
| 125 if (!web_database_->UpdateAutoFillProfile(*profile_to_update)) { |
| 126 std::string err = "Failed to overwrite label for node "; |
| 127 err += UTF16ToUTF8(new_label); |
| 128 error_handler()->OnUnrecoverableError(FROM_HERE, err); |
| 129 return; |
| 130 } |
| 131 |
| 132 // Notify the PersonalDataManager that it's out of date. |
| 133 PostOptimisticRefreshTask(); |
| 134 } |
| 135 |
| 136 void AutofillChangeProcessor2::PostOptimisticRefreshTask() { |
| 137 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 138 new AutofillModelAssociator2::DoOptimisticRefreshTask( |
| 139 personal_data_)); |
| 140 } |
| 141 |
| 142 void AutofillChangeProcessor2::AddAutofillProfileSyncNode( |
| 143 sync_api::WriteTransaction* trans, const sync_api::BaseNode& autofill, |
| 144 const std::string& tag, const AutoFillProfile* profile) { |
| 145 sync_api::WriteNode sync_node(trans); |
| 146 if (!sync_node.InitUniqueByCreation(syncable::AUTOFILL, autofill, tag)) { |
| 147 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 148 "Failed to create autofill sync node."); |
| 149 return; |
| 150 } |
| 151 sync_node.SetTitle(UTF8ToWide(tag)); |
| 152 |
| 153 WriteAutofillProfile(*profile, &sync_node); |
| 154 model_associator_->Associate(&tag, sync_node.GetId()); |
| 155 } |
| 156 |
| 157 void AutofillChangeProcessor2::ObserveAutofillProfileChanged( |
| 158 AutofillProfileChange* change, sync_api::WriteTransaction* trans, |
| 159 const sync_api::ReadNode& autofill_root) { |
| 160 std::string tag(AutofillModelAssociator2::ProfileLabelToTag(change->key())); |
| 161 switch (change->type()) { |
| 162 case AutofillProfileChange::ADD: { |
| 163 scoped_ptr<AutoFillProfile> clone( |
| 164 static_cast<AutoFillProfile*>(change->profile()->Clone())); |
| 165 DCHECK_EQ(clone->Label(), change->key()); |
| 166 ChangeProfileLabelIfAlreadyTaken(trans, string16(), clone.get(), &tag); |
| 167 AddAutofillProfileSyncNode(trans, autofill_root, tag, clone.get()); |
| 168 break; |
| 169 } |
| 170 case AutofillProfileChange::UPDATE: { |
| 171 scoped_ptr<AutoFillProfile> clone( |
| 172 static_cast<AutoFillProfile*>(change->profile()->Clone())); |
| 173 std::string pre_update_tag = AutofillModelAssociator2::ProfileLabelToTag( |
| 174 change->pre_update_label()); |
| 175 DCHECK_EQ(clone->Label(), change->key()); |
| 176 sync_api::WriteNode sync_node(trans); |
| 177 ChangeProfileLabelIfAlreadyTaken(trans, change->pre_update_label(), |
| 178 clone.get(), &tag); |
| 179 if (pre_update_tag != tag) { |
| 180 // If the label changes, replace the node instead of updating it. |
| 181 RemoveSyncNode(pre_update_tag, trans); |
| 182 AddAutofillProfileSyncNode(trans, autofill_root, tag, clone.get()); |
| 183 return; |
| 184 } |
| 185 int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag); |
| 186 if (sync_api::kInvalidId == sync_id) { |
| 187 std::string err = "Unexpected notification for: " + tag; |
| 188 error_handler()->OnUnrecoverableError(FROM_HERE, err); |
| 189 return; |
| 190 } else { |
| 191 if (!sync_node.InitByIdLookup(sync_id)) { |
| 192 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 193 "Autofill node lookup failed."); |
| 194 return; |
| 195 } |
| 196 WriteAutofillProfile(*clone.get(), &sync_node); |
| 197 } |
| 198 break; |
| 199 } |
| 200 case AutofillProfileChange::REMOVE: { |
| 201 RemoveSyncNode(tag, trans); |
| 202 break; |
| 203 } |
| 204 } |
| 205 } |
| 206 |
| 207 void AutofillChangeProcessor2::ObserveAutofillEntriesChanged( |
| 208 AutofillChangeList* changes, sync_api::WriteTransaction* trans, |
| 209 const sync_api::ReadNode& autofill_root) { |
| 210 for (AutofillChangeList::iterator change = changes->begin(); |
| 211 change != changes->end(); ++change) { |
| 212 switch (change->type()) { |
| 213 case AutofillChange::ADD: |
| 214 { |
| 215 sync_api::WriteNode sync_node(trans); |
| 216 std::string tag = |
| 217 AutofillModelAssociator2::KeyToTag(change->key().name(), |
| 218 change->key().value()); |
| 219 if (!sync_node.InitUniqueByCreation(syncable::AUTOFILL, |
| 220 autofill_root, tag)) { |
| 221 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 222 "Failed to create autofill sync node."); |
| 223 return; |
| 224 } |
| 225 |
| 226 std::vector<base::Time> timestamps; |
| 227 if (!web_database_->GetAutofillTimestamps( |
| 228 change->key().name(), |
| 229 change->key().value(), |
| 230 ×tamps)) { |
| 231 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 232 "Failed to get timestamps."); |
| 233 return; |
| 234 } |
| 235 |
| 236 sync_node.SetTitle(UTF8ToWide(tag)); |
| 237 |
| 238 WriteAutofillEntry(AutofillEntry(change->key(), timestamps), |
| 239 &sync_node); |
| 240 model_associator_->Associate(&tag, sync_node.GetId()); |
| 241 } |
| 242 break; |
| 243 |
| 244 case AutofillChange::UPDATE: |
| 245 { |
| 246 sync_api::WriteNode sync_node(trans); |
| 247 std::string tag = AutofillModelAssociator2::KeyToTag( |
| 248 change->key().name(), change->key().value()); |
| 249 int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag); |
| 250 if (sync_api::kInvalidId == sync_id) { |
| 251 std::string err = "Unexpected notification for: " + |
| 252 UTF16ToUTF8(change->key().name()); |
| 253 error_handler()->OnUnrecoverableError(FROM_HERE, err); |
| 254 return; |
| 255 } else { |
| 256 if (!sync_node.InitByIdLookup(sync_id)) { |
| 257 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 258 "Autofill node lookup failed."); |
| 259 return; |
| 260 } |
| 261 } |
| 262 |
| 263 std::vector<base::Time> timestamps; |
| 264 if (!web_database_->GetAutofillTimestamps( |
| 265 change->key().name(), |
| 266 change->key().value(), |
| 267 ×tamps)) { |
| 268 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 269 "Failed to get timestamps."); |
| 270 return; |
| 271 } |
| 272 |
| 273 WriteAutofillEntry(AutofillEntry(change->key(), timestamps), |
| 274 &sync_node); |
| 275 } |
| 276 break; |
| 277 case AutofillChange::REMOVE: { |
| 278 std::string tag = AutofillModelAssociator2::KeyToTag( |
| 279 change->key().name(), change->key().value()); |
| 280 RemoveSyncNode(tag, trans); |
| 281 } |
| 282 break; |
| 283 } |
| 284 } |
| 285 } |
| 286 |
| 287 void AutofillChangeProcessor2::RemoveSyncNode(const std::string& tag, |
| 288 sync_api::WriteTransaction* trans) { |
| 289 sync_api::WriteNode sync_node(trans); |
| 290 int64 sync_id = model_associator_->GetSyncIdFromChromeId(tag); |
| 291 if (sync_api::kInvalidId == sync_id) { |
| 292 std::string err = "Unexpected notification for: " + tag; |
| 293 error_handler()->OnUnrecoverableError(FROM_HERE, err); |
| 294 return; |
| 295 } else { |
| 296 if (!sync_node.InitByIdLookup(sync_id)) { |
| 297 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 298 "Autofill node lookup failed."); |
| 299 return; |
| 300 } |
| 301 model_associator_->Disassociate(sync_node.GetId()); |
| 302 sync_node.Remove(); |
| 303 } |
| 304 } |
| 305 |
| 306 void AutofillChangeProcessor2::ApplyChangesFromSyncModel( |
| 307 const sync_api::BaseTransaction* trans, |
| 308 const sync_api::SyncManager::ChangeRecord* changes, |
| 309 int change_count) { |
| 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 311 if (!running()) |
| 312 return; |
| 313 StopObserving(); |
| 314 |
| 315 sync_api::ReadNode autofill_root(trans); |
| 316 if (!autofill_root.InitByTagLookup(kAutofillTag)) { |
| 317 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 318 "Autofill root node lookup failed."); |
| 319 return; |
| 320 } |
| 321 |
| 322 for (int i = 0; i < change_count; ++i) { |
| 323 sync_api::SyncManager::ChangeRecord::Action action(changes[i].action); |
| 324 if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE == action) { |
| 325 DCHECK(changes[i].specifics.HasExtension(sync_pb::autofill)) |
| 326 << "Autofill specifics data not present on delete!"; |
| 327 const sync_pb::AutofillSpecifics& autofill = |
| 328 changes[i].specifics.GetExtension(sync_pb::autofill); |
| 329 if (autofill.has_value() || autofill.has_profile()) { |
| 330 autofill_changes_.push_back(AutofillChangeRecord(changes[i].action, |
| 331 changes[i].id, |
| 332 autofill)); |
| 333 } else { |
| 334 NOTREACHED() << "Autofill specifics has no data!"; |
| 335 } |
| 336 continue; |
| 337 } |
| 338 |
| 339 // Handle an update or add. |
| 340 sync_api::ReadNode sync_node(trans); |
| 341 if (!sync_node.InitByIdLookup(changes[i].id)) { |
| 342 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 343 "Autofill node lookup failed."); |
| 344 return; |
| 345 } |
| 346 |
| 347 // Check that the changed node is a child of the autofills folder. |
| 348 DCHECK(autofill_root.GetId() == sync_node.GetParentId()); |
| 349 DCHECK(syncable::AUTOFILL == sync_node.GetModelType()); |
| 350 |
| 351 const sync_pb::AutofillSpecifics& autofill( |
| 352 sync_node.GetAutofillSpecifics()); |
| 353 int64 sync_id = sync_node.GetId(); |
| 354 if (autofill.has_value() || autofill.has_profile()) { |
| 355 autofill_changes_.push_back(AutofillChangeRecord(changes[i].action, |
| 356 sync_id, autofill)); |
| 357 } else { |
| 358 NOTREACHED() << "Autofill specifics has no data!"; |
| 359 } |
| 360 } |
| 361 |
| 362 StartObserving(); |
| 363 } |
| 364 |
| 365 void AutofillChangeProcessor2::CommitChangesFromSyncModel() { |
| 366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 367 if (!running()) |
| 368 return; |
| 369 StopObserving(); |
| 370 |
| 371 std::vector<AutofillEntry> new_entries; |
| 372 for (unsigned int i = 0; i < autofill_changes_.size(); i++) { |
| 373 // Handle deletions. |
| 374 if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE == |
| 375 autofill_changes_[i].action_) { |
| 376 if (autofill_changes_[i].autofill_.has_value()) { |
| 377 ApplySyncAutofillEntryDelete(autofill_changes_[i].autofill_); |
| 378 } else if (autofill_changes_[i].autofill_.has_profile()) { |
| 379 ApplySyncAutofillProfileDelete(autofill_changes_[i].autofill_.profile(), |
| 380 autofill_changes_[i].id_); |
| 381 } else { |
| 382 NOTREACHED() << "Autofill's CommitChanges received change with no" |
| 383 " data!"; |
| 384 } |
| 385 continue; |
| 386 } |
| 387 |
| 388 // Handle update/adds. |
| 389 if (autofill_changes_[i].autofill_.has_value()) { |
| 390 ApplySyncAutofillEntryChange(autofill_changes_[i].action_, |
| 391 autofill_changes_[i].autofill_, &new_entries, |
| 392 autofill_changes_[i].id_); |
| 393 } else if (autofill_changes_[i].autofill_.has_profile()) { |
| 394 ApplySyncAutofillProfileChange(autofill_changes_[i].action_, |
| 395 autofill_changes_[i].autofill_.profile(), |
| 396 autofill_changes_[i].id_); |
| 397 } else { |
| 398 NOTREACHED() << "Autofill's CommitChanges received change with no data!"; |
| 399 } |
| 400 } |
| 401 autofill_changes_.clear(); |
| 402 |
| 403 // Make changes |
| 404 if (!web_database_->UpdateAutofillEntries(new_entries)) { |
| 405 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 406 "Could not update autofill entries."); |
| 407 return; |
| 408 } |
| 409 |
| 410 PostOptimisticRefreshTask(); |
| 411 |
| 412 StartObserving(); |
| 413 } |
| 414 |
| 415 void AutofillChangeProcessor2::ApplySyncAutofillEntryDelete( |
| 416 const sync_pb::AutofillSpecifics& autofill) { |
| 417 if (!web_database_->RemoveFormElement( |
| 418 UTF8ToUTF16(autofill.name()), UTF8ToUTF16(autofill.value()))) { |
| 419 error_handler()->OnUnrecoverableError(FROM_HERE, |
| 420 "Could not remove autofill node."); |
| 421 return; |
| 422 } |
| 423 } |
| 424 |
| 425 void AutofillChangeProcessor2::ApplySyncAutofillEntryChange( |
| 426 sync_api::SyncManager::ChangeRecord::Action action, |
| 427 const sync_pb::AutofillSpecifics& autofill, |
| 428 std::vector<AutofillEntry>* new_entries, |
| 429 int64 sync_id) { |
| 430 DCHECK_NE(sync_api::SyncManager::ChangeRecord::ACTION_DELETE, action); |
| 431 |
| 432 std::vector<base::Time> timestamps; |
| 433 size_t timestamps_size = autofill.usage_timestamp_size(); |
| 434 for (size_t c = 0; c < timestamps_size; ++c) { |
| 435 timestamps.push_back( |
| 436 base::Time::FromInternalValue(autofill.usage_timestamp(c))); |
| 437 } |
| 438 AutofillKey k(UTF8ToUTF16(autofill.name()), UTF8ToUTF16(autofill.value())); |
| 439 AutofillEntry new_entry(k, timestamps); |
| 440 |
| 441 new_entries->push_back(new_entry); |
| 442 std::string tag(AutofillModelAssociator2::KeyToTag(k.name(), k.value())); |
| 443 if (action == sync_api::SyncManager::ChangeRecord::ACTION_ADD) |
| 444 model_associator_->Associate(&tag, sync_id); |
| 445 } |
| 446 |
| 447 void AutofillChangeProcessor2::ApplySyncAutofillProfileChange( |
| 448 sync_api::SyncManager::ChangeRecord::Action action, |
| 449 const sync_pb::AutofillProfileSpecifics& profile, |
| 450 int64 sync_id) { |
| 451 DCHECK_NE(sync_api::SyncManager::ChangeRecord::ACTION_DELETE, action); |
| 452 |
| 453 std::string tag(AutofillModelAssociator2::ProfileLabelToTag( |
| 454 UTF8ToUTF16(profile.label()))); |
| 455 switch (action) { |
| 456 case sync_api::SyncManager::ChangeRecord::ACTION_ADD: { |
| 457 PersonalDataManager* pdm = model_associator_->sync_service()-> |
| 458 profile()->GetPersonalDataManager(); |
| 459 scoped_ptr<AutoFillProfile> p( |
| 460 pdm->CreateNewEmptyAutoFillProfileForDBThread( |
| 461 UTF8ToUTF16(profile.label()))); |
| 462 AutofillModelAssociator2::OverwriteProfileWithServerData(p.get(), |
| 463 profile); |
| 464 |
| 465 model_associator_->Associate(&tag, sync_id); |
| 466 if (!web_database_->AddAutoFillProfile(*p.get())) { |
| 467 NOTREACHED() << "Couldn't add autofill profile: " << profile.label(); |
| 468 return; |
| 469 } |
| 470 break; |
| 471 } |
| 472 case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: { |
| 473 AutoFillProfile* p = NULL; |
| 474 string16 label = UTF8ToUTF16(profile.label()); |
| 475 if (!web_database_->GetAutoFillProfileForLabel(label, &p)) { |
| 476 NOTREACHED() << "Couldn't retrieve autofill profile: " << label; |
| 477 return; |
| 478 } |
| 479 AutofillModelAssociator2::OverwriteProfileWithServerData(p, profile); |
| 480 if (!web_database_->UpdateAutoFillProfile(*p)) { |
| 481 NOTREACHED() << "Couldn't update autofill profile: " << label; |
| 482 return; |
| 483 } |
| 484 delete p; |
| 485 break; |
| 486 } |
| 487 default: |
| 488 NOTREACHED(); |
| 489 } |
| 490 } |
| 491 |
| 492 void AutofillChangeProcessor2::ApplySyncAutofillProfileDelete( |
| 493 const sync_pb::AutofillProfileSpecifics& profile, |
| 494 int64 sync_id) { |
| 495 string16 label(UTF8ToUTF16(profile.label())); |
| 496 AutoFillProfile* ptr = NULL; |
| 497 bool get_success = web_database_->GetAutoFillProfileForLabel(label, &ptr); |
| 498 scoped_ptr<AutoFillProfile> p(ptr); |
| 499 if (!get_success) { |
| 500 NOTREACHED() << "Couldn't retrieve autofill profile: " << label; |
| 501 return; |
| 502 } |
| 503 if (!web_database_->RemoveAutoFillProfile(p->unique_id())) { |
| 504 NOTREACHED() << "Couldn't remove autofill profile: " << label; |
| 505 return; |
| 506 } |
| 507 model_associator_->Disassociate(sync_id); |
| 508 } |
| 509 |
| 510 void AutofillChangeProcessor2::StartImpl(Profile* profile) { |
| 511 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 512 observing_ = true; |
| 513 } |
| 514 |
| 515 void AutofillChangeProcessor2::StopImpl() { |
| 516 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 517 observing_ = false; |
| 518 } |
| 519 |
| 520 |
| 521 void AutofillChangeProcessor2::StartObserving() { |
| 522 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 523 notification_registrar_.Add(this, NotificationType::AUTOFILL_ENTRIES_CHANGED, |
| 524 NotificationService::AllSources()); |
| 525 notification_registrar_.Add(this, NotificationType::AUTOFILL_PROFILE_CHANGED, |
| 526 NotificationService::AllSources()); |
| 527 } |
| 528 |
| 529 void AutofillChangeProcessor2::StopObserving() { |
| 530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
| 531 notification_registrar_.RemoveAll(); |
| 532 } |
| 533 |
| 534 // static |
| 535 void AutofillChangeProcessor2::WriteAutofillEntry( |
| 536 const AutofillEntry& entry, |
| 537 sync_api::WriteNode* node) { |
| 538 sync_pb::AutofillSpecifics autofill; |
| 539 autofill.set_name(UTF16ToUTF8(entry.key().name())); |
| 540 autofill.set_value(UTF16ToUTF8(entry.key().value())); |
| 541 const std::vector<base::Time>& ts(entry.timestamps()); |
| 542 for (std::vector<base::Time>::const_iterator timestamp = ts.begin(); |
| 543 timestamp != ts.end(); ++timestamp) { |
| 544 autofill.add_usage_timestamp(timestamp->ToInternalValue()); |
| 545 } |
| 546 node->SetAutofillSpecifics(autofill); |
| 547 } |
| 548 |
| 549 // static |
| 550 void AutofillChangeProcessor2::WriteAutofillProfile( |
| 551 const AutoFillProfile& profile, sync_api::WriteNode* node) { |
| 552 sync_pb::AutofillSpecifics autofill; |
| 553 sync_pb::AutofillProfileSpecifics* s(autofill.mutable_profile()); |
| 554 s->set_label(UTF16ToUTF8(profile.Label())); |
| 555 s->set_name_first(UTF16ToUTF8( |
| 556 profile.GetFieldText(AutoFillType(NAME_FIRST)))); |
| 557 s->set_name_middle(UTF16ToUTF8( |
| 558 profile.GetFieldText(AutoFillType(NAME_MIDDLE)))); |
| 559 s->set_name_last(UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_LAST)))); |
| 560 s->set_address_home_line1( |
| 561 UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1)))); |
| 562 s->set_address_home_line2( |
| 563 UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2)))); |
| 564 s->set_address_home_city(UTF16ToUTF8(profile.GetFieldText( |
| 565 AutoFillType(ADDRESS_HOME_CITY)))); |
| 566 s->set_address_home_state(UTF16ToUTF8(profile.GetFieldText( |
| 567 AutoFillType(ADDRESS_HOME_STATE)))); |
| 568 s->set_address_home_country(UTF16ToUTF8(profile.GetFieldText( |
| 569 AutoFillType(ADDRESS_HOME_COUNTRY)))); |
| 570 s->set_address_home_zip(UTF16ToUTF8(profile.GetFieldText( |
| 571 AutoFillType(ADDRESS_HOME_ZIP)))); |
| 572 s->set_email_address(UTF16ToUTF8(profile.GetFieldText( |
| 573 AutoFillType(EMAIL_ADDRESS)))); |
| 574 s->set_company_name(UTF16ToUTF8(profile.GetFieldText( |
| 575 AutoFillType(COMPANY_NAME)))); |
| 576 s->set_phone_fax_whole_number(UTF16ToUTF8(profile.GetFieldText( |
| 577 AutoFillType(PHONE_FAX_WHOLE_NUMBER)))); |
| 578 s->set_phone_home_whole_number(UTF16ToUTF8(profile.GetFieldText( |
| 579 AutoFillType(PHONE_HOME_WHOLE_NUMBER)))); |
| 580 node->SetAutofillSpecifics(autofill); |
| 581 } |
| 582 |
| 583 } // namespace browser_sync |
OLD | NEW |