| 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/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/profile.h" | 10 #include "chrome/browser/profile.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 LOG(INFO) << "Associating Autofill Models"; | 36 LOG(INFO) << "Associating Autofill Models"; |
| 37 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 37 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 38 | 38 |
| 39 // TODO(zork): Attempt to load the model association from storage. | 39 // TODO(zork): Attempt to load the model association from storage. |
| 40 std::vector<AutofillEntry> entries; | 40 std::vector<AutofillEntry> entries; |
| 41 if (!web_database_->GetAllAutofillEntries(&entries)) { | 41 if (!web_database_->GetAllAutofillEntries(&entries)) { |
| 42 LOG(ERROR) << "Could not get the autofill entries."; | 42 LOG(ERROR) << "Could not get the autofill entries."; |
| 43 return false; | 43 return false; |
| 44 } | 44 } |
| 45 | 45 |
| 46 sync_api::WriteTransaction trans( | |
| 47 sync_service_->backend()->GetUserShareHandle()); | |
| 48 sync_api::ReadNode autofill_root(&trans); | |
| 49 if (!autofill_root.InitByTagLookup(kAutofillTag)) { | |
| 50 error_handler_->OnUnrecoverableError(); | |
| 51 LOG(ERROR) << "Server did not create the top-level autofill node. We " | |
| 52 << "might be running against an out-of-date server."; | |
| 53 return false; | |
| 54 } | |
| 55 | |
| 56 std::set<AutofillKey> current_entries; | 46 std::set<AutofillKey> current_entries; |
| 57 std::vector<AutofillEntry> new_entries; | 47 std::vector<AutofillEntry> new_entries; |
| 58 | 48 |
| 59 for (std::vector<AutofillEntry>::iterator ix = entries.begin(); | 49 { |
| 60 ix != entries.end(); ++ix) { | 50 sync_api::WriteTransaction trans( |
| 61 if (id_map_.find(ix->key()) != id_map_.end()) { | 51 sync_service_->backend()->GetUserShareHandle()); |
| 62 // It seems that name/value pairs are not unique in the web database. | 52 sync_api::ReadNode autofill_root(&trans); |
| 63 // As a result, we have to filter out duplicates here. This is probably | 53 if (!autofill_root.InitByTagLookup(kAutofillTag)) { |
| 64 // a bug in the database. | 54 error_handler_->OnUnrecoverableError(); |
| 65 continue; | 55 LOG(ERROR) << "Server did not create the top-level autofill node. We " |
| 56 << "might be running against an out-of-date server."; |
| 57 return false; |
| 66 } | 58 } |
| 67 | 59 |
| 68 std::string tag = KeyToTag(ix->key().name(), ix->key().value()); | 60 for (std::vector<AutofillEntry>::iterator ix = entries.begin(); |
| 61 ix != entries.end(); ++ix) { |
| 62 if (id_map_.find(ix->key()) != id_map_.end()) { |
| 63 // It seems that name/value pairs are not unique in the web database. |
| 64 // As a result, we have to filter out duplicates here. This is probably |
| 65 // a bug in the database. |
| 66 continue; |
| 67 } |
| 69 | 68 |
| 70 sync_api::ReadNode node(&trans); | 69 std::string tag = KeyToTag(ix->key().name(), ix->key().value()); |
| 71 if (node.InitByClientTagLookup(syncable::AUTOFILL, tag)) { | |
| 72 const sync_pb::AutofillSpecifics& autofill(node.GetAutofillSpecifics()); | |
| 73 DCHECK_EQ(tag, KeyToTag(UTF8ToUTF16(autofill.name()), | |
| 74 UTF8ToUTF16(autofill.value()))); | |
| 75 | 70 |
| 76 std::vector<base::Time> timestamps; | 71 sync_api::ReadNode node(&trans); |
| 77 if (MergeTimestamps(autofill, ix->timestamps(), ×tamps)) { | 72 if (node.InitByClientTagLookup(syncable::AUTOFILL, tag)) { |
| 78 AutofillEntry new_entry(ix->key(), timestamps); | 73 const sync_pb::AutofillSpecifics& autofill(node.GetAutofillSpecifics()); |
| 79 new_entries.push_back(new_entry); | 74 DCHECK_EQ(tag, KeyToTag(UTF8ToUTF16(autofill.name()), |
| 75 UTF8ToUTF16(autofill.value()))); |
| 80 | 76 |
| 81 sync_api::WriteNode write_node(&trans); | 77 std::vector<base::Time> timestamps; |
| 82 if (!write_node.InitByClientTagLookup(syncable::AUTOFILL, tag)) { | 78 if (MergeTimestamps(autofill, ix->timestamps(), ×tamps)) { |
| 83 LOG(ERROR) << "Failed to write autofill sync node."; | 79 AutofillEntry new_entry(ix->key(), timestamps); |
| 80 new_entries.push_back(new_entry); |
| 81 |
| 82 sync_api::WriteNode write_node(&trans); |
| 83 if (!write_node.InitByClientTagLookup(syncable::AUTOFILL, tag)) { |
| 84 LOG(ERROR) << "Failed to write autofill sync node."; |
| 85 return false; |
| 86 } |
| 87 AutofillChangeProcessor::WriteAutofill(&write_node, new_entry); |
| 88 } |
| 89 |
| 90 Associate(&(ix->key()), node.GetId()); |
| 91 } else { |
| 92 sync_api::WriteNode node(&trans); |
| 93 if (!node.InitUniqueByCreation(syncable::AUTOFILL, |
| 94 autofill_root, tag)) { |
| 95 LOG(ERROR) << "Failed to create autofill sync node."; |
| 84 error_handler_->OnUnrecoverableError(); | 96 error_handler_->OnUnrecoverableError(); |
| 85 return false; | 97 return false; |
| 86 } | 98 } |
| 87 AutofillChangeProcessor::WriteAutofill(&write_node, new_entry); | 99 node.SetTitle(UTF16ToWide(ix->key().name() + ix->key().value())); |
| 100 AutofillChangeProcessor::WriteAutofill(&node, *ix); |
| 101 Associate(&(ix->key()), node.GetId()); |
| 88 } | 102 } |
| 89 | 103 |
| 90 Associate(&(ix->key()), node.GetId()); | 104 current_entries.insert(ix->key()); |
| 91 } else { | 105 } |
| 92 sync_api::WriteNode node(&trans); | 106 |
| 93 if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) { | 107 int64 sync_child_id = autofill_root.GetFirstChildId(); |
| 94 LOG(ERROR) << "Failed to create autofill sync node."; | 108 while (sync_child_id != sync_api::kInvalidId) { |
| 109 sync_api::ReadNode sync_child_node(&trans); |
| 110 if (!sync_child_node.InitByIdLookup(sync_child_id)) { |
| 111 LOG(ERROR) << "Failed to fetch child node."; |
| 95 error_handler_->OnUnrecoverableError(); | 112 error_handler_->OnUnrecoverableError(); |
| 96 return false; | 113 return false; |
| 97 } | 114 } |
| 98 node.SetTitle(UTF16ToWide(ix->key().name() + ix->key().value())); | 115 const sync_pb::AutofillSpecifics& autofill( |
| 99 AutofillChangeProcessor::WriteAutofill(&node, *ix); | 116 sync_child_node.GetAutofillSpecifics()); |
| 100 Associate(&(ix->key()), node.GetId()); | 117 AutofillKey key(UTF8ToUTF16(autofill.name()), |
| 118 UTF8ToUTF16(autofill.value())); |
| 119 |
| 120 if (current_entries.find(key) == current_entries.end()) { |
| 121 std::vector<base::Time> timestamps; |
| 122 int timestamps_count = autofill.usage_timestamp_size(); |
| 123 for (int c = 0; c < timestamps_count; ++c) { |
| 124 timestamps.push_back(base::Time::FromInternalValue( |
| 125 autofill.usage_timestamp(c))); |
| 126 } |
| 127 Associate(&key, sync_child_node.GetId()); |
| 128 new_entries.push_back(AutofillEntry(key, timestamps)); |
| 129 } |
| 130 |
| 131 sync_child_id = sync_child_node.GetSuccessorId(); |
| 101 } | 132 } |
| 102 | |
| 103 current_entries.insert(ix->key()); | |
| 104 } | 133 } |
| 105 | 134 |
| 106 int64 sync_child_id = autofill_root.GetFirstChildId(); | 135 // Since we're on the DB thread, we don't have to worry about updating |
| 107 while (sync_child_id != sync_api::kInvalidId) { | 136 // the autofill database after closing the write transaction, since |
| 108 sync_api::ReadNode sync_child_node(&trans); | 137 // this is the only thread that writes to the database. We also don't have |
| 109 if (!sync_child_node.InitByIdLookup(sync_child_id)) { | 138 // to worry about the sync model getting out of sync, because changes are |
| 110 LOG(ERROR) << "Failed to fetch child node."; | 139 // propogated to the ChangeProcessor on this thread. |
| 111 error_handler_->OnUnrecoverableError(); | |
| 112 return false; | |
| 113 } | |
| 114 const sync_pb::AutofillSpecifics& autofill( | |
| 115 sync_child_node.GetAutofillSpecifics()); | |
| 116 AutofillKey key(UTF8ToUTF16(autofill.name()), | |
| 117 UTF8ToUTF16(autofill.value())); | |
| 118 | |
| 119 if (current_entries.find(key) == current_entries.end()) { | |
| 120 std::vector<base::Time> timestamps; | |
| 121 int timestamps_count = autofill.usage_timestamp_size(); | |
| 122 for (int c = 0; c < timestamps_count; ++c) { | |
| 123 timestamps.push_back(base::Time::FromInternalValue( | |
| 124 autofill.usage_timestamp(c))); | |
| 125 } | |
| 126 Associate(&key, sync_child_node.GetId()); | |
| 127 new_entries.push_back(AutofillEntry(key, timestamps)); | |
| 128 } | |
| 129 | |
| 130 sync_child_id = sync_child_node.GetSuccessorId(); | |
| 131 } | |
| 132 | |
| 133 if (new_entries.size() && | 140 if (new_entries.size() && |
| 134 !web_database_->UpdateAutofillEntries(new_entries)) { | 141 !web_database_->UpdateAutofillEntries(new_entries)) { |
| 135 LOG(ERROR) << "Failed to update autofill entries."; | 142 LOG(ERROR) << "Failed to update autofill entries."; |
| 136 error_handler_->OnUnrecoverableError(); | 143 error_handler_->OnUnrecoverableError(); |
| 137 return false; | 144 return false; |
| 138 } | 145 } |
| 139 | 146 |
| 140 return true; | 147 return true; |
| 141 } | 148 } |
| 142 | 149 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 | 246 |
| 240 if (different) { | 247 if (different) { |
| 241 new_timestamps->insert(new_timestamps->begin(), | 248 new_timestamps->insert(new_timestamps->begin(), |
| 242 timestamp_union.begin(), | 249 timestamp_union.begin(), |
| 243 timestamp_union.end()); | 250 timestamp_union.end()); |
| 244 } | 251 } |
| 245 return different; | 252 return different; |
| 246 } | 253 } |
| 247 | 254 |
| 248 } // namespace browser_sync | 255 } // namespace browser_sync |
| OLD | NEW |