Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: chrome/browser/sync/glue/autofill_change_processor2.cc

Issue 4683003: Sending the proto files for review to unblcok the server team Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 &timestamps)) {
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 &timestamps)) {
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
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/autofill_change_processor2.h ('k') | chrome/browser/sync/glue/autofill_model_associator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698