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" |
24 #include "chrome/browser/sync/syncable/syncable.h" | |
21 #include "chrome/browser/webdata/web_database.h" | 25 #include "chrome/browser/webdata/web_database.h" |
26 #include "chrome/common/pref_names.h" | |
22 #include "net/base/escape.h" | 27 #include "net/base/escape.h" |
23 | 28 |
24 using base::TimeTicks; | 29 using base::TimeTicks; |
25 | 30 |
26 namespace browser_sync { | 31 namespace browser_sync { |
27 | 32 |
28 const char kAutofillTag[] = "google_chrome_autofill"; | 33 const char kAutofillTag[] = "google_chrome_autofill"; |
29 const char kAutofillEntryNamespaceTag[] = "autofill_entry|"; | 34 const char kAutofillEntryNamespaceTag[] = "autofill_entry|"; |
30 | 35 |
31 struct AutofillModelAssociator::DataBundle { | 36 struct AutofillModelAssociator::DataBundle { |
32 std::set<AutofillKey> current_entries; | 37 std::set<AutofillKey> current_entries; |
33 std::vector<AutofillEntry> new_entries; | 38 std::vector<AutofillEntry> new_entries; |
34 std::set<string16> current_profiles; | 39 std::set<string16> current_profiles; |
35 std::vector<AutoFillProfile*> updated_profiles; | 40 std::vector<AutoFillProfile*> updated_profiles; |
36 std::vector<AutoFillProfile*> new_profiles; // We own these pointers. | 41 std::vector<AutoFillProfile*> new_profiles; // We own these pointers. |
37 ~DataBundle() { STLDeleteElements(&new_profiles); } | 42 ~DataBundle() { STLDeleteElements(&new_profiles); } |
38 }; | 43 }; |
39 | 44 |
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( | 45 AutofillModelAssociator::AutofillModelAssociator( |
51 ProfileSyncService* sync_service, | 46 ProfileSyncService* sync_service, |
52 WebDatabase* web_database, | 47 WebDatabase* web_database, |
53 PersonalDataManager* personal_data) | 48 PersonalDataManager* personal_data) |
54 : sync_service_(sync_service), | 49 : sync_service_(sync_service), |
55 web_database_(web_database), | 50 web_database_(web_database), |
56 personal_data_(personal_data), | 51 personal_data_(personal_data), |
57 autofill_node_id_(sync_api::kInvalidId), | 52 autofill_node_id_(sync_api::kInvalidId), |
58 abort_association_pending_(false) { | 53 autofill_migration_state_(syncable::Directory::PersistedKernelInfo::NOT_DE TERMINED), |
54 abort_association_pending_(false), | |
55 number_of_entries_created_(0) { | |
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
60 DCHECK(sync_service_); | 57 DCHECK(sync_service_); |
61 DCHECK(web_database_); | 58 DCHECK(web_database_); |
62 DCHECK(personal_data_); | 59 DCHECK(personal_data_); |
63 } | 60 } |
64 | 61 |
65 AutofillModelAssociator::~AutofillModelAssociator() { | 62 AutofillModelAssociator::~AutofillModelAssociator() { |
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
67 } | 64 } |
68 | 65 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 } else { | 104 } else { |
108 sync_api::WriteNode node(write_trans); | 105 sync_api::WriteNode node(write_trans); |
109 if (!node.InitUniqueByCreation(syncable::AUTOFILL, | 106 if (!node.InitUniqueByCreation(syncable::AUTOFILL, |
110 autofill_root, tag)) { | 107 autofill_root, tag)) { |
111 LOG(ERROR) << "Failed to create autofill sync node."; | 108 LOG(ERROR) << "Failed to create autofill sync node."; |
112 return false; | 109 return false; |
113 } | 110 } |
114 node.SetTitle(UTF8ToWide(tag)); | 111 node.SetTitle(UTF8ToWide(tag)); |
115 AutofillChangeProcessor::WriteAutofillEntry(*ix, &node); | 112 AutofillChangeProcessor::WriteAutofillEntry(*ix, &node); |
116 Associate(&tag, node.GetId()); | 113 Associate(&tag, node.GetId()); |
114 number_of_entries_created_++; | |
117 } | 115 } |
118 | 116 |
119 current_entries->insert(ix->key()); | 117 current_entries->insert(ix->key()); |
120 } | 118 } |
121 return true; | 119 return true; |
122 } | 120 } |
123 | 121 |
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( | 122 bool AutofillModelAssociator::LoadAutofillData( |
140 std::vector<AutofillEntry>* entries, | 123 std::vector<AutofillEntry>* entries, |
141 std::vector<AutoFillProfile*>* profiles) { | 124 std::vector<AutoFillProfile*>* profiles) { |
142 if (IsAbortPending()) | 125 if (IsAbortPending()) |
143 return false; | 126 return false; |
144 if (!web_database_->GetAllAutofillEntries(entries)) | 127 if (!web_database_->GetAllAutofillEntries(entries)) |
145 return false; | 128 return false; |
146 | 129 |
147 if (IsAbortPending()) | 130 if (IsAbortPending()) |
148 return false; | 131 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 | 181 // 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 | 182 // 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 | 183 // 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 | 184 // to worry about the sync model getting out of sync, because changes are |
202 // propogated to the ChangeProcessor on this thread. | 185 // propogated to the ChangeProcessor on this thread. |
203 if (!SaveChangesToWebData(bundle)) { | 186 if (!SaveChangesToWebData(bundle)) { |
204 LOG(ERROR) << "Failed to update autofill entries."; | 187 LOG(ERROR) << "Failed to update autofill entries."; |
205 return false; | 188 return false; |
206 } | 189 } |
207 | 190 |
191 if (sync_service_->backend()->GetAutofillMigrationState() != | |
192 syncable::Directory::PersistedKernelInfo::MIGRATED) { | |
193 syncable::AutofillMigrationDebugInfo debug_info; | |
tim (not reviewing)
2010/12/10 22:16:02
indent here or line above looks off
lipalani
2010/12/11 00:12:36
Done.
| |
194 debug_info.autofill_entries_added_during_migration = | |
195 number_of_entries_created_; | |
tim (not reviewing)
2010/12/10 22:16:02
4 spaces indent
lipalani
2010/12/11 00:12:36
Done.
| |
196 sync_service_->backend()->SetAutofillMigrationDebugInfo( | |
197 syncable::AutofillMigrationDebugInfo::ENTRIES_ADDED, | |
tim (not reviewing)
2010/12/10 22:16:02
4 spaces indent
lipalani
2010/12/11 00:12:36
Done.
| |
198 debug_info); | |
199 } | |
200 | |
208 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 201 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
209 new DoOptimisticRefreshTask(personal_data_)); | 202 new DoOptimisticRefreshForAutofill(personal_data_)); |
210 return true; | 203 return true; |
211 } | 204 } |
212 | 205 |
213 bool AutofillModelAssociator::SaveChangesToWebData(const DataBundle& bundle) { | 206 bool AutofillModelAssociator::SaveChangesToWebData(const DataBundle& bundle) { |
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
215 | 208 |
216 if (IsAbortPending()) | 209 if (IsAbortPending()) |
217 return false; | 210 return false; |
218 | 211 |
219 if (bundle.new_entries.size() && | 212 if (bundle.new_entries.size() && |
(...skipping 17 matching lines...) Expand all Loading... | |
237 return true; | 230 return true; |
238 } | 231 } |
239 | 232 |
240 bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes( | 233 bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes( |
241 sync_api::WriteTransaction* write_trans, | 234 sync_api::WriteTransaction* write_trans, |
242 const sync_api::ReadNode& autofill_root, | 235 const sync_api::ReadNode& autofill_root, |
243 DataBundle* bundle, | 236 DataBundle* bundle, |
244 const std::vector<AutoFillProfile*>& all_profiles_from_db) { | 237 const std::vector<AutoFillProfile*>& all_profiles_from_db) { |
245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
246 | 239 |
240 bool autofill_profile_not_migrated = HasNotMigratedYet(write_trans); | |
241 | |
247 int64 sync_child_id = autofill_root.GetFirstChildId(); | 242 int64 sync_child_id = autofill_root.GetFirstChildId(); |
248 while (sync_child_id != sync_api::kInvalidId) { | 243 while (sync_child_id != sync_api::kInvalidId) { |
249 sync_api::ReadNode sync_child(write_trans); | 244 sync_api::ReadNode sync_child(write_trans); |
250 if (!sync_child.InitByIdLookup(sync_child_id)) { | 245 if (!sync_child.InitByIdLookup(sync_child_id)) { |
251 LOG(ERROR) << "Failed to fetch child node."; | 246 LOG(ERROR) << "Failed to fetch child node."; |
252 return false; | 247 return false; |
253 } | 248 } |
254 const sync_pb::AutofillSpecifics& autofill( | 249 const sync_pb::AutofillSpecifics& autofill( |
255 sync_child.GetAutofillSpecifics()); | 250 sync_child.GetAutofillSpecifics()); |
256 | 251 |
257 if (autofill.has_value()) { | 252 if (autofill.has_value()) { |
258 AddNativeEntryIfNeeded(autofill, bundle, sync_child); | 253 AddNativeEntryIfNeeded(autofill, bundle, sync_child); |
259 } else if (autofill.has_profile() && HasNotMigratedYet()) { | 254 } else if (autofill.has_profile()) { |
260 // Ignore autofill profiles if we are not upgrading. | 255 // Ignore autofill profiles if we are not upgrading. |
261 AddNativeProfileIfNeeded( | 256 if (autofill_profile_not_migrated) { |
262 autofill.profile(), | 257 AddNativeProfileIfNeeded( |
263 bundle, | 258 autofill.profile(), |
264 sync_child, | 259 bundle, |
265 all_profiles_from_db); | 260 sync_child, |
261 all_profiles_from_db); | |
262 } | |
266 } else { | 263 } else { |
267 NOTREACHED() << "AutofillSpecifics has no autofill data!"; | 264 NOTREACHED() << "AutofillSpecifics has no autofill data!"; |
268 } | 265 } |
269 | 266 |
270 sync_child_id = sync_child.GetSuccessorId(); | 267 sync_child_id = sync_child.GetSuccessorId(); |
271 } | 268 } |
272 return true; | 269 return true; |
273 } | 270 } |
274 | 271 |
275 // Define the functor to be used as the predicate in find_if call. | 272 // 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 } | 322 } |
326 | 323 |
327 void AutofillModelAssociator::AddNativeProfileIfNeeded( | 324 void AutofillModelAssociator::AddNativeProfileIfNeeded( |
328 const sync_pb::AutofillProfileSpecifics& profile, | 325 const sync_pb::AutofillProfileSpecifics& profile, |
329 DataBundle* bundle, | 326 DataBundle* bundle, |
330 const sync_api::ReadNode& node, | 327 const sync_api::ReadNode& node, |
331 const std::vector<AutoFillProfile*>& all_profiles_from_db) { | 328 const std::vector<AutoFillProfile*>& all_profiles_from_db) { |
332 | 329 |
333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
334 | 331 |
335 scoped_ptr<AutoFillProfile> profile_in_web_db(FindCorrespondingNodeFromWebDB( | 332 AutoFillProfile* profile_in_web_db = FindCorrespondingNodeFromWebDB( |
tim (not reviewing)
2010/12/10 22:16:02
why no scoped_ptr?
lipalani
2010/12/11 00:12:36
The pointer we are getting is part of the vector a
| |
336 profile, all_profiles_from_db)); | 333 profile, all_profiles_from_db); |
337 | 334 |
338 if (profile_in_web_db.get() != NULL) { | 335 if (profile_in_web_db != NULL) { |
339 int64 sync_id = node.GetId(); | 336 int64 sync_id = node.GetId(); |
340 std::string guid = profile_in_web_db->guid(); | 337 std::string guid = profile_in_web_db->guid(); |
341 Associate(&guid, sync_id); | 338 Associate(&guid, sync_id); |
342 return; | 339 return; |
343 } else { // Create a new node. | 340 } else { // Create a new node. |
344 std::string guid = guid::GenerateGUID(); | 341 std::string guid = guid::GenerateGUID(); |
345 Associate(&guid, node.GetId()); | 342 Associate(&guid, node.GetId()); |
346 AutoFillProfile* p = new AutoFillProfile(guid); | 343 AutoFillProfile* p = new AutoFillProfile(guid); |
347 FillProfileWithServerData(p, profile); | 344 FillProfileWithServerData(p, profile); |
348 bundle->new_profiles.push_back(p); | 345 bundle->new_profiles.push_back(p); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff; | 499 diff = MergeField(p, ADDRESS_HOME_ZIP, s.address_home_zip()) || diff; |
503 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff; | 500 diff = MergeField(p, EMAIL_ADDRESS, s.email_address()) || diff; |
504 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff; | 501 diff = MergeField(p, COMPANY_NAME, s.company_name()) || diff; |
505 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number()) | 502 diff = MergeField(p, PHONE_FAX_WHOLE_NUMBER, s.phone_fax_whole_number()) |
506 || diff; | 503 || diff; |
507 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number()) | 504 diff = MergeField(p, PHONE_HOME_WHOLE_NUMBER, s.phone_home_whole_number()) |
508 || diff; | 505 || diff; |
509 return diff; | 506 return diff; |
510 } | 507 } |
511 | 508 |
512 bool AutofillModelAssociator::HasNotMigratedYet() { | 509 bool AutofillModelAssociator::HasNotMigratedYet( |
513 return true; | 510 const sync_api::BaseTransaction* trans) { |
511 | |
lipalani
2010/12/09 19:45:25
get rid of the variable.
lipalani
2010/12/11 00:12:36
we need the transaction variable. this comment was
| |
512 // If state is migrated in our cached variable return true. We dont have | |
513 // to check against the directory as it will not change. | |
514 if (autofill_migration_state_ == | |
515 syncable::Directory::PersistedKernelInfo::MIGRATED) { | |
516 return false; | |
517 } | |
518 | |
519 // Now read the current value from the directory. | |
520 autofill_migration_state_ = | |
521 sync_service()->backend()->GetAutofillMigrationState(); | |
522 | |
lipalani
2010/12/09 19:45:25
add a redirect comment.
lipalani
2010/12/11 00:12:36
Done.
| |
523 DCHECK_NE(autofill_migration_state_, | |
524 syncable::Directory::PersistedKernelInfo::NOT_DETERMINED); | |
525 if (autofill_migration_state_ == | |
526 syncable::Directory::PersistedKernelInfo::NOT_MIGRATED) { | |
527 return true; | |
528 } | |
529 | |
530 if (autofill_migration_state_ == | |
531 syncable::Directory::PersistedKernelInfo::INSUFFICIENT_INFO_TO_DETERMINE) { | |
532 sync_api::ReadNode autofill_profile_root_node(trans); | |
533 if (!autofill_profile_root_node.InitByTagLookup( | |
534 browser_sync::kAutofillProfileTag) || | |
535 autofill_profile_root_node.GetFirstChildId()== | |
536 static_cast<int64>(0)) { | |
537 sync_service()->backend()->SetAutofillMigrationState( | |
538 syncable::Directory::PersistedKernelInfo::NOT_MIGRATED); | |
539 return true; | |
540 } | |
541 | |
542 sync_service()->backend()->SetAutofillMigrationState( | |
543 syncable::Directory::PersistedKernelInfo::MIGRATED); | |
544 | |
545 autofill_migration_state_ = | |
546 syncable::Directory::PersistedKernelInfo::MIGRATED; | |
547 } | |
548 | |
549 return false; | |
550 | |
514 } | 551 } |
552 } // namespace browser_sync | |
515 | 553 |
516 } // namespace browser_sync | |
OLD | NEW |