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 |