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

Side by Side Diff: chrome/browser/sync/glue/autofill_model_associator.cc

Issue 1361002: Scope the WriteTransactions during model association so that we don't lock the UI thread (Closed)
Patch Set: Added comments, fixed a typo Created 10 years, 9 months 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
« no previous file with comments | « no previous file | chrome/browser/sync/glue/typed_url_change_processor.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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(), &timestamps)) { 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(), &timestamps)) {
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
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
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/sync/glue/typed_url_change_processor.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698