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

Side by Side Diff: chrome/browser/sync/glue/autofill_model_associator.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
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 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/sync/glue/autofill_model_associator.h" 5 #include "chrome/browser/sync/glue/autofill_model_associator.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/task.h" 9 #include "base/task.h"
10 #include "base/time.h" 10 #include "base/time.h"
11 #include "base/string_number_conversions.h" 11 #include "base/string_number_conversions.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "chrome/browser/autofill/autofill_profile.h" 13 #include "chrome/browser/autofill/autofill_profile.h"
14 #include "chrome/browser/browser_thread.h" 14 #include "chrome/browser/browser_thread.h"
15 #include "chrome/browser/guid.h"
15 #include "chrome/browser/profile.h" 16 #include "chrome/browser/profile.h"
16 #include "chrome/browser/sync/engine/syncapi.h" 17 #include "chrome/browser/sync/engine/syncapi.h"
17 #include "chrome/browser/sync/glue/autofill_change_processor.h" 18 #include "chrome/browser/sync/glue/autofill_change_processor.h"
18 #include "chrome/browser/sync/profile_sync_service.h" 19 #include "chrome/browser/sync/profile_sync_service.h"
19 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h" 20 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
20 #include "chrome/browser/webdata/web_database.h" 21 #include "chrome/browser/webdata/web_database.h"
21 #include "net/base/escape.h" 22 #include "net/base/escape.h"
22 23
23 using base::TimeTicks; 24 using base::TimeTicks;
24 25
25 namespace browser_sync { 26 namespace browser_sync {
26 27
27 const char kAutofillTag[] = "google_chrome_autofill"; 28 const char kAutofillTag[] = "google_chrome_autofill";
28 const char kAutofillEntryNamespaceTag[] = "autofill_entry|"; 29 const char kAutofillEntryNamespaceTag[] = "autofill_entry|";
29 const char kAutofillProfileNamespaceTag[] = "autofill_profile|";
30
31 static const int kMaxNumAttemptsToFindUniqueLabel = 100;
32 30
33 struct AutofillModelAssociator::DataBundle { 31 struct AutofillModelAssociator::DataBundle {
34 std::set<AutofillKey> current_entries; 32 std::set<AutofillKey> current_entries;
35 std::vector<AutofillEntry> new_entries; 33 std::vector<AutofillEntry> new_entries;
36 std::set<string16> current_profiles; 34 std::set<string16> current_profiles;
37 std::vector<AutoFillProfile*> updated_profiles; 35 std::vector<AutoFillProfile*> updated_profiles;
38 std::vector<AutoFillProfile*> new_profiles; // We own these pointers. 36 std::vector<AutoFillProfile*> new_profiles; // We own these pointers.
39 ~DataBundle() { STLDeleteElements(&new_profiles); } 37 ~DataBundle() { STLDeleteElements(&new_profiles); }
40 }; 38 };
41 39
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 node.SetTitle(UTF8ToWide(tag)); 114 node.SetTitle(UTF8ToWide(tag));
117 AutofillChangeProcessor::WriteAutofillEntry(*ix, &node); 115 AutofillChangeProcessor::WriteAutofillEntry(*ix, &node);
118 Associate(&tag, node.GetId()); 116 Associate(&tag, node.GetId());
119 } 117 }
120 118
121 current_entries->insert(ix->key()); 119 current_entries->insert(ix->key());
122 } 120 }
123 return true; 121 return true;
124 } 122 }
125 123
126 bool AutofillModelAssociator::TraverseAndAssociateChromeAutoFillProfiles(
127 sync_api::WriteTransaction* write_trans,
128 const sync_api::ReadNode& autofill_root,
129 const std::vector<AutoFillProfile*>& all_profiles_from_db,
130 std::set<string16>* current_profiles,
131 std::vector<AutoFillProfile*>* updated_profiles) {
132 const std::vector<AutoFillProfile*>& profiles = all_profiles_from_db;
133 for (std::vector<AutoFillProfile*>::const_iterator ix = profiles.begin();
134 ix != profiles.end(); ++ix) {
135 string16 label((*ix)->Label());
136 std::string tag(ProfileLabelToTag(label));
137
138 sync_api::ReadNode node(write_trans);
139 if (node.InitByClientTagLookup(syncable::AUTOFILL, tag)) {
140 const sync_pb::AutofillSpecifics& autofill(node.GetAutofillSpecifics());
141 DCHECK(autofill.has_profile());
142 DCHECK_EQ(ProfileLabelToTag(UTF8ToUTF16(autofill.profile().label())),
143 tag);
144 int64 sync_id = node.GetId();
145 if (id_map_.find(tag) != id_map_.end()) {
146 // We just looked up something we already associated. Move aside.
147 label = MakeUniqueLabel(label, string16(), write_trans);
148 if (label.empty()) {
149 return false;
150 }
151 tag = ProfileLabelToTag(label);
152 // TODO(dhollowa): Replace with |AutoFillProfile::set_guid|.
153 // http://crbug.com/58813
154 (*ix)->set_label(label);
155 if (!MakeNewAutofillProfileSyncNode(write_trans, autofill_root,
156 tag, **ix, &sync_id)) {
157 return false;
158 }
159 updated_profiles->push_back(*ix);
160 } else {
161 // Overwrite local with cloud state.
162 if (OverwriteProfileWithServerData(*ix, autofill.profile()))
163 updated_profiles->push_back(*ix);
164 sync_id = node.GetId();
165 }
166
167 Associate(&tag, sync_id);
168 } else {
169 int64 id;
170 if (!MakeNewAutofillProfileSyncNode(write_trans, autofill_root,
171 tag, **ix, &id)) {
172 return false;
173 }
174 Associate(&tag, id);
175 }
176 current_profiles->insert(label);
177 }
178 return true;
179 }
180
181 // static
182 string16 AutofillModelAssociator::MakeUniqueLabel(
183 const string16& non_unique_label,
184 const string16& existing_unique_label,
185 sync_api::BaseTransaction* trans) {
186 if (!non_unique_label.empty() && non_unique_label == existing_unique_label) {
187 return existing_unique_label;
188 }
189 int unique_id = 1; // Priming so we start by appending "2".
190 while (unique_id++ < kMaxNumAttemptsToFindUniqueLabel) {
191 string16 suffix(base::IntToString16(unique_id));
192 string16 unique_label = non_unique_label + suffix;
193 if (unique_label == existing_unique_label)
194 return unique_label; // We'll use the one we already have.
195 sync_api::ReadNode node(trans);
196 if (node.InitByClientTagLookup(syncable::AUTOFILL,
197 ProfileLabelToTag(unique_label))) {
198 continue;
199 }
200 return unique_label;
201 }
202
203 LOG(ERROR) << "Couldn't create unique tag for autofill node. Srsly?!";
204 return string16();
205 }
206
207 bool AutofillModelAssociator::MakeNewAutofillProfileSyncNode( 124 bool AutofillModelAssociator::MakeNewAutofillProfileSyncNode(
208 sync_api::WriteTransaction* trans, const sync_api::BaseNode& autofill_root, 125 sync_api::WriteTransaction* trans, const sync_api::BaseNode& autofill_root,
209 const std::string& tag, const AutoFillProfile& profile, int64* sync_id) { 126 const std::string& tag, const AutoFillProfile& profile, int64* sync_id) {
210 sync_api::WriteNode node(trans); 127 sync_api::WriteNode node(trans);
211 if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) { 128 if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) {
212 LOG(ERROR) << "Failed to create autofill sync node."; 129 LOG(ERROR) << "Failed to create autofill sync node.";
213 return false; 130 return false;
214 } 131 }
215 node.SetTitle(UTF8ToWide(tag)); 132 node.SetTitle(UTF8ToWide(tag));
216 AutofillChangeProcessor::WriteAutofillProfile(profile, &node); 133 AutofillChangeProcessor::WriteAutofillProfile(profile, &node);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 sync_service_->backend()->GetUserShareHandle()); 175 sync_service_->backend()->GetUserShareHandle());
259 176
260 sync_api::ReadNode autofill_root(&trans); 177 sync_api::ReadNode autofill_root(&trans);
261 if (!autofill_root.InitByTagLookup(kAutofillTag)) { 178 if (!autofill_root.InitByTagLookup(kAutofillTag)) {
262 LOG(ERROR) << "Server did not create the top-level autofill node. We " 179 LOG(ERROR) << "Server did not create the top-level autofill node. We "
263 << "might be running against an out-of-date server."; 180 << "might be running against an out-of-date server.";
264 return false; 181 return false;
265 } 182 }
266 183
267 if (!TraverseAndAssociateChromeAutofillEntries(&trans, autofill_root, 184 if (!TraverseAndAssociateChromeAutofillEntries(&trans, autofill_root,
268 entries, &bundle.current_entries, &bundle.new_entries) || 185 entries, &bundle.current_entries, &bundle.new_entries)) {
269 !TraverseAndAssociateChromeAutoFillProfiles(&trans, autofill_root, 186 return false;
270 profiles.get(), &bundle.current_profiles, 187 }
271 &bundle.updated_profiles) || 188 if(IsUpgrading()) {
272 !TraverseAndAssociateAllSyncNodes(&trans, autofill_root, &bundle)) { 189 if(!TraverseAndAssociateAllSyncNodes(
273 return false; 190 &trans,
191 autofill_root,
192 &bundle,
193 profiles.get())) {
194 return false;
195 }
274 } 196 }
275 } 197 }
276 198
277 // Since we're on the DB thread, we don't have to worry about updating 199 // Since we're on the DB thread, we don't have to worry about updating
278 // the autofill database after closing the write transaction, since 200 // the autofill database after closing the write transaction, since
279 // this is the only thread that writes to the database. We also don't have 201 // this is the only thread that writes to the database. We also don't have
280 // to worry about the sync model getting out of sync, because changes are 202 // to worry about the sync model getting out of sync, because changes are
281 // propogated to the ChangeProcessor on this thread. 203 // propogated to the ChangeProcessor on this thread.
282 if (!SaveChangesToWebData(bundle)) { 204 if (!SaveChangesToWebData(bundle)) {
283 LOG(ERROR) << "Failed to update autofill entries."; 205 LOG(ERROR) << "Failed to update autofill entries.";
(...skipping 28 matching lines...) Expand all
312 return false; 234 return false;
313 if (!web_database_->UpdateAutoFillProfile(*bundle.updated_profiles[i])) 235 if (!web_database_->UpdateAutoFillProfile(*bundle.updated_profiles[i]))
314 return false; 236 return false;
315 } 237 }
316 return true; 238 return true;
317 } 239 }
318 240
319 bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes( 241 bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes(
320 sync_api::WriteTransaction* write_trans, 242 sync_api::WriteTransaction* write_trans,
321 const sync_api::ReadNode& autofill_root, 243 const sync_api::ReadNode& autofill_root,
322 DataBundle* bundle) { 244 DataBundle* bundle,
245 std::vector<AutoFillProfile*>& all_profiles_from_db) {
323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
324 247
325 int64 sync_child_id = autofill_root.GetFirstChildId(); 248 int64 sync_child_id = autofill_root.GetFirstChildId();
326 while (sync_child_id != sync_api::kInvalidId) { 249 while (sync_child_id != sync_api::kInvalidId) {
327 sync_api::ReadNode sync_child(write_trans); 250 sync_api::ReadNode sync_child(write_trans);
328 if (!sync_child.InitByIdLookup(sync_child_id)) { 251 if (!sync_child.InitByIdLookup(sync_child_id)) {
329 LOG(ERROR) << "Failed to fetch child node."; 252 LOG(ERROR) << "Failed to fetch child node.";
330 return false; 253 return false;
331 } 254 }
332 const sync_pb::AutofillSpecifics& autofill( 255 const sync_pb::AutofillSpecifics& autofill(
333 sync_child.GetAutofillSpecifics()); 256 sync_child.GetAutofillSpecifics());
334 257
335 if (autofill.has_value()) 258 if (autofill.has_value())
336 AddNativeEntryIfNeeded(autofill, bundle, sync_child); 259 AddNativeEntryIfNeeded(autofill, bundle, sync_child);
337 else if (autofill.has_profile()) 260 else if (autofill.has_profile()) {
338 AddNativeProfileIfNeeded(autofill.profile(), bundle, sync_child); 261 DCHECK(IsUpgrading());
262 AddNativeProfileIfNeeded(
263 autofill.profile(),
264 bundle, sync_child,
265 all_profiles_from_db);
266 }
339 else 267 else
340 NOTREACHED() << "AutofillSpecifics has no autofill data!"; 268 NOTREACHED() << "AutofillSpecifics has no autofill data!";
341 269
342 sync_child_id = sync_child.GetSuccessorId(); 270 sync_child_id = sync_child.GetSuccessorId();
343 } 271 }
344 return true; 272 return true;
345 } 273 }
346 274
275 // [TODO] fix the p1 and p2.
276 bool CompareAutofillProfiles(const AutoFillProfile& p1,
277 const AutoFillProfile& p2)
278 {
279 if(p1.Compare(p2) == 0)
280 return true;
281 else return false;
282 }
283
284 // Define the functor to be used as the predicate in find_if call.
285 struct CompareProfiles :
286 public std::binary_function<AutoFillProfile*,
287 AutoFillProfile*,
288 bool> {
289 bool operator() (AutoFillProfile* p1, AutoFillProfile* p2) const {
290 return CompareAutofillProfiles(*p1, *p2);
291 }
292
293 };
294
295 AutoFillProfile* AutofillModelAssociator::FindCorrespondingNodeFromWebDB(
296 const sync_pb::AutofillProfileSpecifics& profile,
297 const std::vector<AutoFillProfile*>& all_profiles_from_db) {
298
299 static std::string guid(guid::GenerateGUID());
300 AutoFillProfile p;
301 p.set_guid(guid);
302 if(!OverwriteProfileWithServerData(&p, profile))
303 {
304 // Not a big deal. We encountered an error. Just say this profile does not
305 // exist.
306 LOG(ERROR) << " Profile could not be associated";
307 return NULL;
308 }
309
310 // Now instantiate the functor and call find_if.
311 std::vector<AutoFillProfile*>::const_iterator ix =
312 std::find_if(all_profiles_from_db.begin(),
313 all_profiles_from_db.end(),
314 std::bind2nd(CompareProfiles(), &p));
315
316 return (ix == all_profiles_from_db.end()) ? NULL : *ix;
317 }
318
347 void AutofillModelAssociator::AddNativeEntryIfNeeded( 319 void AutofillModelAssociator::AddNativeEntryIfNeeded(
348 const sync_pb::AutofillSpecifics& autofill, DataBundle* bundle, 320 const sync_pb::AutofillSpecifics& autofill, DataBundle* bundle,
349 const sync_api::ReadNode& node) { 321 const sync_api::ReadNode& node) {
350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
351 AutofillKey key(UTF8ToUTF16(autofill.name()), UTF8ToUTF16(autofill.value())); 323 AutofillKey key(UTF8ToUTF16(autofill.name()), UTF8ToUTF16(autofill.value()));
352 324
353 if (bundle->current_entries.find(key) == bundle->current_entries.end()) { 325 if (bundle->current_entries.find(key) == bundle->current_entries.end()) {
354 std::vector<base::Time> timestamps; 326 std::vector<base::Time> timestamps;
355 int timestamps_count = autofill.usage_timestamp_size(); 327 int timestamps_count = autofill.usage_timestamp_size();
356 for (int c = 0; c < timestamps_count; ++c) { 328 for (int c = 0; c < timestamps_count; ++c) {
357 timestamps.push_back(base::Time::FromInternalValue( 329 timestamps.push_back(base::Time::FromInternalValue(
358 autofill.usage_timestamp(c))); 330 autofill.usage_timestamp(c)));
359 } 331 }
360 std::string tag(KeyToTag(key.name(), key.value())); 332 std::string tag(KeyToTag(key.name(), key.value()));
361 Associate(&tag, node.GetId()); 333 Associate(&tag, node.GetId());
362 bundle->new_entries.push_back(AutofillEntry(key, timestamps)); 334 bundle->new_entries.push_back(AutofillEntry(key, timestamps));
363 } 335 }
364 } 336 }
365 337
366 void AutofillModelAssociator::AddNativeProfileIfNeeded( 338 void AutofillModelAssociator::AddNativeProfileIfNeeded(
367 const sync_pb::AutofillProfileSpecifics& profile, DataBundle* bundle, 339 const sync_pb::AutofillProfileSpecifics& profile,
368 const sync_api::ReadNode& node) { 340 DataBundle* bundle,
341 const sync_api::ReadNode& node,
342 std::vector<AutoFillProfile*>& all_profiles_from_db) {
343
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
370 if (bundle->current_profiles.find(UTF8ToUTF16(profile.label())) == 345
371 bundle->current_profiles.end()) { 346 scoped_ptr<AutoFillProfile> profile_in_web_db(FindCorrespondingNodeFromWebDB(
372 std::string tag(ProfileLabelToTag(UTF8ToUTF16(profile.label()))); 347 profile, all_profiles_from_db));
373 Associate(&tag, node.GetId()); 348
374 AutoFillProfile* p = personal_data_-> 349 if(profile_in_web_db.get() != NULL) {
375 CreateNewEmptyAutoFillProfileForDBThread(UTF8ToUTF16(profile.label())); 350 int64 sync_id = node.GetId();
351 Associate(&(profile_in_web_db->guid()), sync_id);
352 return;
353 } else { // Create a new node.
354 std::string guid = guid::GenerateGUID();
355 Associate(&guid, node.GetId());
356 AutoFillProfile* p = new AutoFillProfile(guid);
376 OverwriteProfileWithServerData(p, profile); 357 OverwriteProfileWithServerData(p, profile);
377 bundle->new_profiles.push_back(p); 358 bundle->new_profiles.push_back(p);
378 } 359 }
379 } 360 }
380 361
381 bool AutofillModelAssociator::DisassociateModels() { 362 bool AutofillModelAssociator::DisassociateModels() {
363
382 id_map_.clear(); 364 id_map_.clear();
383 id_map_inverse_.clear(); 365 id_map_inverse_.clear();
384 return true; 366 return true;
385 } 367 }
386 368
387 bool AutofillModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) { 369 bool AutofillModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) {
388 DCHECK(has_nodes); 370 DCHECK(has_nodes);
389 *has_nodes = false; 371 *has_nodes = false;
390 int64 autofill_sync_id; 372 int64 autofill_sync_id;
391 if (!GetSyncIdForTaggedNode(kAutofillTag, &autofill_sync_id)) { 373 if (!GetSyncIdForTaggedNode(kAutofillTag, &autofill_sync_id)) {
(...skipping 18 matching lines...) Expand all
410 } 392 }
411 393
412 void AutofillModelAssociator::AbortAssociation() { 394 void AutofillModelAssociator::AbortAssociation() {
413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 AutoLock lock(abort_association_pending_lock_); 396 AutoLock lock(abort_association_pending_lock_);
415 abort_association_pending_ = true; 397 abort_association_pending_ = true;
416 } 398 }
417 399
418 const std::string* 400 const std::string*
419 AutofillModelAssociator::GetChromeNodeFromSyncId(int64 sync_id) { 401 AutofillModelAssociator::GetChromeNodeFromSyncId(int64 sync_id) {
420 return NULL; 402 SyncIdToAutofillMap::const_iterator iter = id_map_inverse_.find(sync_id);
403 return iter == id_map_inverse_.end() ? NULL : &(iter->second);
421 } 404 }
422 405
423 bool AutofillModelAssociator::InitSyncNodeFromChromeId( 406 bool AutofillModelAssociator::InitSyncNodeFromChromeId(
424 std::string node_id, 407 std::string node_id,
425 sync_api::BaseNode* sync_node) { 408 sync_api::BaseNode* sync_node) {
426 return false; 409 return false;
427 } 410 }
428 411
429 int64 AutofillModelAssociator::GetSyncIdFromChromeId( 412 int64 AutofillModelAssociator::GetSyncIdFromChromeId(
430 const std::string autofill) { 413 const std::string autofill) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 452
470 // static 453 // static
471 std::string AutofillModelAssociator::KeyToTag(const string16& name, 454 std::string AutofillModelAssociator::KeyToTag(const string16& name,
472 const string16& value) { 455 const string16& value) {
473 std::string ns(kAutofillEntryNamespaceTag); 456 std::string ns(kAutofillEntryNamespaceTag);
474 return ns + EscapePath(UTF16ToUTF8(name)) + "|" + 457 return ns + EscapePath(UTF16ToUTF8(name)) + "|" +
475 EscapePath(UTF16ToUTF8(value)); 458 EscapePath(UTF16ToUTF8(value));
476 } 459 }
477 460
478 // static 461 // static
479 std::string AutofillModelAssociator::ProfileLabelToTag(const string16& label) {
480 std::string ns(kAutofillProfileNamespaceTag);
481 return ns + EscapePath(UTF16ToUTF8(label));
482 }
483
484 // static
485 bool AutofillModelAssociator::MergeTimestamps( 462 bool AutofillModelAssociator::MergeTimestamps(
486 const sync_pb::AutofillSpecifics& autofill, 463 const sync_pb::AutofillSpecifics& autofill,
487 const std::vector<base::Time>& timestamps, 464 const std::vector<base::Time>& timestamps,
488 std::vector<base::Time>* new_timestamps) { 465 std::vector<base::Time>* new_timestamps) {
489 DCHECK(new_timestamps); 466 DCHECK(new_timestamps);
490 std::set<base::Time> timestamp_union(timestamps.begin(), 467 std::set<base::Time> timestamp_union(timestamps.begin(),
491 timestamps.end()); 468 timestamps.end());
492 469
493 size_t timestamps_count = autofill.usage_timestamp_size(); 470 size_t timestamps_count = autofill.usage_timestamp_size();
494 471
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff; 513 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff;
537 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff; 514 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff;
538 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff; 515 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff;
539 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number()) 516 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number())
540 || diff; 517 || diff;
541 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number()) 518 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number())
542 || diff; 519 || diff;
543 return diff; 520 return diff;
544 } 521 }
545 522
523 bool AutofillModelAssociator::IsUpgrading()
524 {
525 return true;
526 }
527
546 } // namespace browser_sync 528 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/autofill_model_associator.h ('k') | chrome/browser/sync/glue/autofill_model_associator2.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698