OLD | NEW |
---|---|
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/guid.h" |
16 #include "chrome/browser/prefs/pref_service.h" | |
16 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
17 #include "chrome/browser/sync/engine/syncapi.h" | 18 #include "chrome/browser/sync/engine/syncapi.h" |
18 #include "chrome/browser/sync/glue/autofill_change_processor.h" | 19 #include "chrome/browser/sync/glue/autofill_change_processor.h" |
20 #include "chrome/browser/sync/glue/autofill_profile_model_associator.h" | |
21 #include "chrome/browser/sync/glue/do_optimistic_refresh_task.h" | |
19 #include "chrome/browser/sync/profile_sync_service.h" | 22 #include "chrome/browser/sync/profile_sync_service.h" |
20 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h" | 23 #include "chrome/browser/sync/protocol/autofill_specifics.pb.h" |
21 #include "chrome/browser/webdata/web_database.h" | 24 #include "chrome/browser/webdata/web_database.h" |
25 #include "chrome/common/pref_names.h" | |
22 #include "net/base/escape.h" | 26 #include "net/base/escape.h" |
23 | 27 |
24 using base::TimeTicks; | 28 using base::TimeTicks; |
25 | 29 |
26 namespace browser_sync { | 30 namespace browser_sync { |
27 | 31 |
28 const char kAutofillTag[] = "google_chrome_autofill"; | 32 const char kAutofillTag[] = "google_chrome_autofill"; |
29 const char kAutofillEntryNamespaceTag[] = "autofill_entry|"; | 33 const char kAutofillEntryNamespaceTag[] = "autofill_entry|"; |
30 | 34 |
31 struct AutofillModelAssociator::DataBundle { | 35 struct AutofillModelAssociator::DataBundle { |
32 std::set<AutofillKey> current_entries; | 36 std::set<AutofillKey> current_entries; |
33 std::vector<AutofillEntry> new_entries; | 37 std::vector<AutofillEntry> new_entries; |
34 std::set<string16> current_profiles; | 38 std::set<string16> current_profiles; |
35 std::vector<AutoFillProfile*> updated_profiles; | 39 std::vector<AutoFillProfile*> updated_profiles; |
36 std::vector<AutoFillProfile*> new_profiles; // We own these pointers. | 40 std::vector<AutoFillProfile*> new_profiles; // We own these pointers. |
37 ~DataBundle() { STLDeleteElements(&new_profiles); } | 41 ~DataBundle() { STLDeleteElements(&new_profiles); } |
38 }; | 42 }; |
39 | 43 |
40 AutofillModelAssociator::DoOptimisticRefreshTask::DoOptimisticRefreshTask( | |
41 PersonalDataManager* pdm) : pdm_(pdm) {} | |
42 | |
43 AutofillModelAssociator::DoOptimisticRefreshTask::~DoOptimisticRefreshTask() {} | |
44 | |
45 void AutofillModelAssociator::DoOptimisticRefreshTask::Run() { | |
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
47 pdm_->Refresh(); | |
48 } | |
49 | |
50 AutofillModelAssociator::AutofillModelAssociator( | 44 AutofillModelAssociator::AutofillModelAssociator( |
51 ProfileSyncService* sync_service, | 45 ProfileSyncService* sync_service, |
52 WebDatabase* web_database, | 46 WebDatabase* web_database, |
53 PersonalDataManager* personal_data) | 47 PersonalDataManager* personal_data) |
54 : sync_service_(sync_service), | 48 : sync_service_(sync_service), |
55 web_database_(web_database), | 49 web_database_(web_database), |
56 personal_data_(personal_data), | 50 personal_data_(personal_data), |
57 autofill_node_id_(sync_api::kInvalidId), | 51 autofill_node_id_(sync_api::kInvalidId), |
58 abort_association_pending_(false) { | 52 abort_association_pending_(false), |
53 number_of_entries_created_(0) { | |
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
60 DCHECK(sync_service_); | 55 DCHECK(sync_service_); |
61 DCHECK(web_database_); | 56 DCHECK(web_database_); |
62 DCHECK(personal_data_); | 57 DCHECK(personal_data_); |
63 } | 58 } |
64 | 59 |
65 AutofillModelAssociator::~AutofillModelAssociator() { | 60 AutofillModelAssociator::~AutofillModelAssociator() { |
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
67 } | 62 } |
68 | 63 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 } else { | 102 } else { |
108 sync_api::WriteNode node(write_trans); | 103 sync_api::WriteNode node(write_trans); |
109 if (!node.InitUniqueByCreation(syncable::AUTOFILL, | 104 if (!node.InitUniqueByCreation(syncable::AUTOFILL, |
110 autofill_root, tag)) { | 105 autofill_root, tag)) { |
111 LOG(ERROR) << "Failed to create autofill sync node."; | 106 LOG(ERROR) << "Failed to create autofill sync node."; |
112 return false; | 107 return false; |
113 } | 108 } |
114 node.SetTitle(UTF8ToWide(tag)); | 109 node.SetTitle(UTF8ToWide(tag)); |
115 AutofillChangeProcessor::WriteAutofillEntry(*ix, &node); | 110 AutofillChangeProcessor::WriteAutofillEntry(*ix, &node); |
116 Associate(&tag, node.GetId()); | 111 Associate(&tag, node.GetId()); |
112 number_of_entries_created_++; | |
117 } | 113 } |
118 | 114 |
119 current_entries->insert(ix->key()); | 115 current_entries->insert(ix->key()); |
120 } | 116 } |
121 return true; | 117 return true; |
122 } | 118 } |
123 | 119 |
124 bool AutofillModelAssociator::MakeNewAutofillProfileSyncNode( | |
125 sync_api::WriteTransaction* trans, const sync_api::BaseNode& autofill_root, | |
126 const std::string& tag, const AutoFillProfile& profile, int64* sync_id) { | |
127 sync_api::WriteNode node(trans); | |
128 if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) { | |
129 LOG(ERROR) << "Failed to create autofill sync node."; | |
130 return false; | |
131 } | |
132 node.SetTitle(UTF8ToWide(tag)); | |
133 AutofillChangeProcessor::WriteAutofillProfile(profile, &node); | |
134 *sync_id = node.GetId(); | |
135 return true; | |
136 } | |
137 | |
138 | |
139 bool AutofillModelAssociator::LoadAutofillData( | 120 bool AutofillModelAssociator::LoadAutofillData( |
140 std::vector<AutofillEntry>* entries, | 121 std::vector<AutofillEntry>* entries, |
141 std::vector<AutoFillProfile*>* profiles) { | 122 std::vector<AutoFillProfile*>* profiles) { |
142 if (IsAbortPending()) | 123 if (IsAbortPending()) |
143 return false; | 124 return false; |
144 if (!web_database_->GetAllAutofillEntries(entries)) | 125 if (!web_database_->GetAllAutofillEntries(entries)) |
145 return false; | 126 return false; |
146 | 127 |
147 if (IsAbortPending()) | 128 if (IsAbortPending()) |
148 return false; | 129 return false; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
198 // Since we're on the DB thread, we don't have to worry about updating | 179 // Since we're on the DB thread, we don't have to worry about updating |
199 // the autofill database after closing the write transaction, since | 180 // the autofill database after closing the write transaction, since |
200 // this is the only thread that writes to the database. We also don't have | 181 // this is the only thread that writes to the database. We also don't have |
201 // to worry about the sync model getting out of sync, because changes are | 182 // to worry about the sync model getting out of sync, because changes are |
202 // propogated to the ChangeProcessor on this thread. | 183 // propogated to the ChangeProcessor on this thread. |
203 if (!SaveChangesToWebData(bundle)) { | 184 if (!SaveChangesToWebData(bundle)) { |
204 LOG(ERROR) << "Failed to update autofill entries."; | 185 LOG(ERROR) << "Failed to update autofill entries."; |
205 return false; | 186 return false; |
206 } | 187 } |
207 | 188 |
189 if (sync_service_->backend()->GetAutofillMigrationState() != | |
190 syncable::MIGRATED) { | |
191 syncable::AutofillMigrationDebugInfo debug_info; | |
192 debug_info.autofill_entries_added_during_migration = | |
193 number_of_entries_created_; | |
194 sync_service_->backend()->SetAutofillMigrationDebugInfo( | |
195 syncable::AutofillMigrationDebugInfo::ENTRIES_ADDED, | |
196 debug_info); | |
197 } | |
198 | |
208 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 199 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
209 new DoOptimisticRefreshTask(personal_data_)); | 200 new DoOptimisticRefreshForAutofill(personal_data_)); |
210 return true; | 201 return true; |
211 } | 202 } |
212 | 203 |
213 bool AutofillModelAssociator::SaveChangesToWebData(const DataBundle& bundle) { | 204 bool AutofillModelAssociator::SaveChangesToWebData(const DataBundle& bundle) { |
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
215 | 206 |
216 if (IsAbortPending()) | 207 if (IsAbortPending()) |
217 return false; | 208 return false; |
218 | 209 |
219 if (bundle.new_entries.size() && | 210 if (bundle.new_entries.size() && |
(...skipping 17 matching lines...) Expand all Loading... | |
237 return true; | 228 return true; |
238 } | 229 } |
239 | 230 |
240 bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes( | 231 bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes( |
241 sync_api::WriteTransaction* write_trans, | 232 sync_api::WriteTransaction* write_trans, |
242 const sync_api::ReadNode& autofill_root, | 233 const sync_api::ReadNode& autofill_root, |
243 DataBundle* bundle, | 234 DataBundle* bundle, |
244 const std::vector<AutoFillProfile*>& all_profiles_from_db) { | 235 const std::vector<AutoFillProfile*>& all_profiles_from_db) { |
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
246 | 237 |
238 bool autofill_profile_not_migrated = HasNotMigratedYet(write_trans); | |
239 | |
240 if (MigrationLoggingEnabled() && | |
241 autofill_profile_not_migrated) { | |
242 VLOG(1) << "[AUTOFILL MIGRATION]" | |
243 << "Printing profiles from web db"; | |
244 | |
245 for (std::vector<AutoFillProfile*>::const_iterator ix = | |
246 all_profiles_from_db.begin(); ix != all_profiles_from_db.end(); ++ix) { | |
247 AutoFillProfile* p = *ix; | |
248 VLOG(1) << "[AUTOFILL MIGRATION] " | |
249 << UTF16ToUTF8(p->GetFieldText(AutoFillType(NAME_FIRST))) | |
tim (not reviewing)
2010/12/15 20:11:42
conversion shouldn't be necessary
lipalani
2010/12/15 21:28:15
Done.
| |
250 << UTF16ToUTF8(p->GetFieldText(AutoFillType(NAME_LAST))); | |
251 } | |
252 } | |
253 | |
254 if (MigrationLoggingEnabled() && autofill_profile_not_migrated) { | |
255 VLOG(1) << "[AUTOFILL MIGRATION]" | |
256 << "Iterating over sync db"; | |
257 } | |
258 | |
247 int64 sync_child_id = autofill_root.GetFirstChildId(); | 259 int64 sync_child_id = autofill_root.GetFirstChildId(); |
248 while (sync_child_id != sync_api::kInvalidId) { | 260 while (sync_child_id != sync_api::kInvalidId) { |
249 sync_api::ReadNode sync_child(write_trans); | 261 sync_api::ReadNode sync_child(write_trans); |
250 if (!sync_child.InitByIdLookup(sync_child_id)) { | 262 if (!sync_child.InitByIdLookup(sync_child_id)) { |
251 LOG(ERROR) << "Failed to fetch child node."; | 263 LOG(ERROR) << "Failed to fetch child node."; |
252 return false; | 264 return false; |
253 } | 265 } |
254 const sync_pb::AutofillSpecifics& autofill( | 266 const sync_pb::AutofillSpecifics& autofill( |
255 sync_child.GetAutofillSpecifics()); | 267 sync_child.GetAutofillSpecifics()); |
256 | 268 |
257 if (autofill.has_value()) { | 269 if (autofill.has_value()) { |
258 AddNativeEntryIfNeeded(autofill, bundle, sync_child); | 270 AddNativeEntryIfNeeded(autofill, bundle, sync_child); |
259 } else if (autofill.has_profile() && HasNotMigratedYet()) { | 271 } else if (autofill.has_profile()) { |
260 // Ignore autofill profiles if we are not upgrading. | 272 // Ignore autofill profiles if we are not upgrading. |
261 AddNativeProfileIfNeeded( | 273 if (autofill_profile_not_migrated) { |
262 autofill.profile(), | 274 if (MigrationLoggingEnabled()) { |
263 bundle, | 275 VLOG(1) << "[AUTOFILL MIGRATION] Looking for " |
264 sync_child, | 276 << autofill.profile().name_first() |
265 all_profiles_from_db); | 277 << autofill.profile().name_last(); |
278 } | |
279 AddNativeProfileIfNeeded( | |
280 autofill.profile(), | |
281 bundle, | |
282 sync_child, | |
283 all_profiles_from_db); | |
284 } | |
266 } else { | 285 } else { |
267 NOTREACHED() << "AutofillSpecifics has no autofill data!"; | 286 NOTREACHED() << "AutofillSpecifics has no autofill data!"; |
268 } | 287 } |
269 | 288 |
270 sync_child_id = sync_child.GetSuccessorId(); | 289 sync_child_id = sync_child.GetSuccessorId(); |
271 } | 290 } |
272 return true; | 291 return true; |
273 } | 292 } |
274 | 293 |
275 // Define the functor to be used as the predicate in find_if call. | 294 // Define the functor to be used as the predicate in find_if call. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 } | 344 } |
326 | 345 |
327 void AutofillModelAssociator::AddNativeProfileIfNeeded( | 346 void AutofillModelAssociator::AddNativeProfileIfNeeded( |
328 const sync_pb::AutofillProfileSpecifics& profile, | 347 const sync_pb::AutofillProfileSpecifics& profile, |
329 DataBundle* bundle, | 348 DataBundle* bundle, |
330 const sync_api::ReadNode& node, | 349 const sync_api::ReadNode& node, |
331 const std::vector<AutoFillProfile*>& all_profiles_from_db) { | 350 const std::vector<AutoFillProfile*>& all_profiles_from_db) { |
332 | 351 |
333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
334 | 353 |
335 scoped_ptr<AutoFillProfile> profile_in_web_db(FindCorrespondingNodeFromWebDB( | 354 AutoFillProfile* profile_in_web_db = FindCorrespondingNodeFromWebDB( |
336 profile, all_profiles_from_db)); | 355 profile, all_profiles_from_db); |
337 | 356 |
338 if (profile_in_web_db.get() != NULL) { | 357 if (profile_in_web_db != NULL) { |
358 if (MigrationLoggingEnabled()) { | |
359 VLOG(1) << "[AUTOFILL MIGRATION]" | |
360 << "Node found in web db. So associating"; | |
361 } | |
339 int64 sync_id = node.GetId(); | 362 int64 sync_id = node.GetId(); |
340 std::string guid = profile_in_web_db->guid(); | 363 std::string guid = profile_in_web_db->guid(); |
341 Associate(&guid, sync_id); | 364 Associate(&guid, sync_id); |
342 return; | 365 return; |
343 } else { // Create a new node. | 366 } else { // Create a new node. |
367 if (MigrationLoggingEnabled()) { | |
368 VLOG(1) << "[AUTOFILL MIGRATION]" | |
369 << "Node not found in web db so creating and associating"; | |
370 } | |
344 std::string guid = guid::GenerateGUID(); | 371 std::string guid = guid::GenerateGUID(); |
345 Associate(&guid, node.GetId()); | 372 Associate(&guid, node.GetId()); |
346 AutoFillProfile* p = new AutoFillProfile(guid); | 373 AutoFillProfile* p = new AutoFillProfile(guid); |
347 FillProfileWithServerData(p, profile); | 374 FillProfileWithServerData(p, profile); |
348 bundle->new_profiles.push_back(p); | 375 bundle->new_profiles.push_back(p); |
349 } | 376 } |
350 } | 377 } |
351 | 378 |
352 bool AutofillModelAssociator::DisassociateModels() { | 379 bool AutofillModelAssociator::DisassociateModels() { |
353 id_map_.clear(); | 380 id_map_.clear(); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff; | 529 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff; |
503 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff; | 530 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff; |
504 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff; | 531 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff; |
505 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number()) | 532 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number()) |
506 || diff; | 533 || diff; |
507 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number()) | 534 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number()) |
508 || diff; | 535 || diff; |
509 return diff; | 536 return diff; |
510 } | 537 } |
511 | 538 |
512 bool AutofillModelAssociator::HasNotMigratedYet() { | 539 bool AutofillModelAssociator::HasNotMigratedYet( |
513 return true; | 540 const sync_api::BaseTransaction* trans) { |
541 | |
542 // Now read the current value from the directory. | |
543 syncable::AutofillMigrationState autofill_migration_state = | |
tim (not reviewing)
2010/12/15 20:11:42
nit - indent is off.
lipalani
2010/12/15 21:28:15
Done.
| |
544 sync_service()->backend()->GetAutofillMigrationState(); | |
545 | |
546 DCHECK_NE(autofill_migration_state, syncable::NOT_DETERMINED); | |
547 | |
548 if (autofill_migration_state== syncable::NOT_DETERMINED) { | |
549 VLOG(1) << "Autofill migration state is not determined inside " | |
550 << " model associator"; | |
551 } | |
552 | |
553 if (autofill_migration_state == syncable::NOT_MIGRATED) { | |
554 return true; | |
555 } | |
556 | |
557 if (autofill_migration_state == syncable::INSUFFICIENT_INFO_TO_DETERMINE) { | |
558 if (MigrationLoggingEnabled()) { | |
559 VLOG(1) << "[AUTOFILL MIGRATION]" | |
560 << "current autofill migration state is insufficient info to" | |
561 << "Determine"; | |
562 } | |
563 sync_api::ReadNode autofill_profile_root_node(trans); | |
564 if (!autofill_profile_root_node.InitByTagLookup( | |
565 browser_sync::kAutofillProfileTag) || | |
566 autofill_profile_root_node.GetFirstChildId()== | |
567 static_cast<int64>(0)) { | |
568 sync_service()->backend()->SetAutofillMigrationState( | |
569 syncable::NOT_MIGRATED); | |
570 | |
571 if (MigrationLoggingEnabled()) { | |
572 VLOG(1) << "[AUTOFILL MIGRATION]" | |
573 << "Current autofill migration state is NOT Migrated becausse" | |
tim (not reviewing)
2010/12/15 20:11:42
couple typos: 'because' 'autofill' and 'present'
lipalani
2010/12/15 21:28:15
Done.
| |
574 << "legacy autofil root node is preseent whereas new " | |
575 << "Autofill profile root node is not present"; | |
576 } | |
577 return true; | |
578 } | |
579 | |
580 sync_service()->backend()->SetAutofillMigrationState(syncable::MIGRATED); | |
581 | |
582 if (MigrationLoggingEnabled()) { | |
583 VLOG(1) << "[AUTOFILL MIGRATION]" | |
584 << "Current autofill migration state is migrated"; | |
585 } | |
586 } | |
587 | |
588 return false; | |
514 } | 589 } |
515 | 590 |
591 bool AutofillModelAssociator::MigrationLoggingEnabled() { | |
592 // [TODO] enable logging via a command line flag. | |
593 return false; | |
594 } | |
516 } // namespace browser_sync | 595 } // namespace browser_sync |
596 | |
OLD | NEW |