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

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

Issue 6878038: [Sync] Ensure we don't hold a transaction when we access password store. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rearrange Created 9 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/password_model_associator.h" 5 #include "chrome/browser/sync/glue/password_model_associator.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/stl_util-inl.h" 9 #include "base/stl_util-inl.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
(...skipping 27 matching lines...) Expand all
38 38
39 PasswordModelAssociator::~PasswordModelAssociator() {} 39 PasswordModelAssociator::~PasswordModelAssociator() {}
40 40
41 bool PasswordModelAssociator::AssociateModels() { 41 bool PasswordModelAssociator::AssociateModels() {
42 DCHECK(expected_loop_ == MessageLoop::current()); 42 DCHECK(expected_loop_ == MessageLoop::current());
43 { 43 {
44 base::AutoLock lock(abort_association_pending_lock_); 44 base::AutoLock lock(abort_association_pending_lock_);
45 abort_association_pending_ = false; 45 abort_association_pending_ = false;
46 } 46 }
47 47
48 sync_api::WriteTransaction trans(sync_service_->GetUserShare()); 48 // We must not be holding a transaction when we interact with the password
49 sync_api::ReadNode password_root(&trans); 49 // store, as it can post tasks to the UI thread which can itself be blocked
50 if (!password_root.InitByTagLookup(kPasswordTag)) { 50 // on our transaction, resulting in deadlock. (http://crbug.com/70658)
51 LOG(ERROR) << "Server did not create the top-level password node. We "
52 << "might be running against an out-of-date server.";
53 return false;
54 }
55
56 std::vector<webkit_glue::PasswordForm*> passwords; 51 std::vector<webkit_glue::PasswordForm*> passwords;
57 if (!password_store_->FillAutofillableLogins(&passwords) || 52 if (!password_store_->FillAutofillableLogins(&passwords) ||
58 !password_store_->FillBlacklistLogins(&passwords)) { 53 !password_store_->FillBlacklistLogins(&passwords)) {
59 STLDeleteElements(&passwords); 54 STLDeleteElements(&passwords);
60 LOG(ERROR) << "Could not get the password entries."; 55 LOG(ERROR) << "Could not get the password entries.";
61 return false; 56 return false;
62 } 57 }
63 58
64 std::set<std::string> current_passwords; 59 std::set<std::string> current_passwords;
65 PasswordVector new_passwords; 60 PasswordVector new_passwords;
66 PasswordVector updated_passwords; 61 PasswordVector updated_passwords;
62 {
63 sync_api::WriteTransaction trans(sync_service_->GetUserShare());
64 sync_api::ReadNode password_root(&trans);
65 if (!password_root.InitByTagLookup(kPasswordTag)) {
66 LOG(ERROR) << "Server did not create the top-level password node. We "
67 << "might be running against an out-of-date server.";
68 return false;
69 }
67 70
68 for (std::vector<webkit_glue::PasswordForm*>::iterator ix = passwords.begin(); 71 for (std::vector<webkit_glue::PasswordForm*>::iterator ix =
69 ix != passwords.end(); ++ix) { 72 passwords.begin();
70 if (IsAbortPending()) 73 ix != passwords.end(); ++ix) {
71 return false; 74 if (IsAbortPending())
72 std::string tag = MakeTag(**ix); 75 return false;
76 std::string tag = MakeTag(**ix);
73 77
74 sync_api::ReadNode node(&trans); 78 sync_api::ReadNode node(&trans);
75 if (node.InitByClientTagLookup(syncable::PASSWORDS, tag)) { 79 if (node.InitByClientTagLookup(syncable::PASSWORDS, tag)) {
76 const sync_pb::PasswordSpecificsData& password = 80 const sync_pb::PasswordSpecificsData& password =
77 node.GetPasswordSpecifics(); 81 node.GetPasswordSpecifics();
78 DCHECK_EQ(tag, MakeTag(password)); 82 DCHECK_EQ(tag, MakeTag(password));
79 83
80 webkit_glue::PasswordForm new_password; 84 webkit_glue::PasswordForm new_password;
81 85
82 if (MergePasswords(password, **ix, &new_password)) { 86 if (MergePasswords(password, **ix, &new_password)) {
83 sync_api::WriteNode write_node(&trans); 87 sync_api::WriteNode write_node(&trans);
84 if (!write_node.InitByClientTagLookup(syncable::PASSWORDS, tag)) { 88 if (!write_node.InitByClientTagLookup(syncable::PASSWORDS, tag)) {
89 STLDeleteElements(&passwords);
90 LOG(ERROR) << "Failed to edit password sync node.";
91 return false;
92 }
93 WriteToSyncNode(new_password, &write_node);
94 updated_passwords.push_back(new_password);
95 }
96
97 Associate(&tag, node.GetId());
98 } else {
99 sync_api::WriteNode node(&trans);
100 if (!node.InitUniqueByCreation(syncable::PASSWORDS,
101 password_root, tag)) {
85 STLDeleteElements(&passwords); 102 STLDeleteElements(&passwords);
86 LOG(ERROR) << "Failed to edit password sync node."; 103 LOG(ERROR) << "Failed to create password sync node.";
87 return false; 104 return false;
88 } 105 }
89 WriteToSyncNode(new_password, &write_node); 106
90 updated_passwords.push_back(new_password); 107 WriteToSyncNode(**ix, &node);
108
109 Associate(&tag, node.GetId());
91 } 110 }
92 111
93 Associate(&tag, node.GetId()); 112 current_passwords.insert(tag);
94 } else { 113 }
95 sync_api::WriteNode node(&trans); 114
96 if (!node.InitUniqueByCreation(syncable::PASSWORDS, 115 STLDeleteElements(&passwords);
97 password_root, tag)) { 116
98 STLDeleteElements(&passwords); 117 int64 sync_child_id = password_root.GetFirstChildId();
99 LOG(ERROR) << "Failed to create password sync node."; 118 while (sync_child_id != sync_api::kInvalidId) {
119 sync_api::ReadNode sync_child_node(&trans);
120 if (!sync_child_node.InitByIdLookup(sync_child_id)) {
121 LOG(ERROR) << "Failed to fetch child node.";
100 return false; 122 return false;
101 } 123 }
124 const sync_pb::PasswordSpecificsData& password =
125 sync_child_node.GetPasswordSpecifics();
126 std::string tag = MakeTag(password);
102 127
103 WriteToSyncNode(**ix, &node); 128 // The password only exists on the server. Add it to the local
129 // model.
130 if (current_passwords.find(tag) == current_passwords.end()) {
131 webkit_glue::PasswordForm new_password;
104 132
105 Associate(&tag, node.GetId()); 133 CopyPassword(password, &new_password);
134 Associate(&tag, sync_child_node.GetId());
135 new_passwords.push_back(new_password);
136 }
137
138 sync_child_id = sync_child_node.GetSuccessorId();
106 } 139 }
107
108 current_passwords.insert(tag);
109 } 140 }
110 141
111 STLDeleteElements(&passwords); 142 // We must not be holding a transaction when we interact with the password
112 143 // store, as it can post tasks to the UI thread which can itself be blocked
113 int64 sync_child_id = password_root.GetFirstChildId(); 144 // on our transaction, resulting in deadlock. (http://crbug.com/70658)
114 while (sync_child_id != sync_api::kInvalidId) {
115 sync_api::ReadNode sync_child_node(&trans);
116 if (!sync_child_node.InitByIdLookup(sync_child_id)) {
117 LOG(ERROR) << "Failed to fetch child node.";
118 return false;
119 }
120 const sync_pb::PasswordSpecificsData& password =
121 sync_child_node.GetPasswordSpecifics();
122 std::string tag = MakeTag(password);
123
124 // The password only exists on the server. Add it to the local
125 // model.
126 if (current_passwords.find(tag) == current_passwords.end()) {
127 webkit_glue::PasswordForm new_password;
128
129 CopyPassword(password, &new_password);
130 Associate(&tag, sync_child_node.GetId());
131 new_passwords.push_back(new_password);
132 }
133
134 sync_child_id = sync_child_node.GetSuccessorId();
135 }
136
137 if (!WriteToPasswordStore(&new_passwords, &updated_passwords, NULL)) { 145 if (!WriteToPasswordStore(&new_passwords, &updated_passwords, NULL)) {
138 LOG(ERROR) << "Failed to write passwords."; 146 LOG(ERROR) << "Failed to write passwords.";
139 return false; 147 return false;
140 } 148 }
141 149
142 return true; 150 return true;
143 } 151 }
144 152
145 bool PasswordModelAssociator::DeleteAllNodes( 153 bool PasswordModelAssociator::DeleteAllNodes(
146 sync_api::WriteTransaction* trans) { 154 sync_api::WriteTransaction* trans) {
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 const std::string& password_element, 400 const std::string& password_element,
393 const std::string& signon_realm) { 401 const std::string& signon_realm) {
394 return EscapePath(origin_url) + "|" + 402 return EscapePath(origin_url) + "|" +
395 EscapePath(username_element) + "|" + 403 EscapePath(username_element) + "|" +
396 EscapePath(username_value) + "|" + 404 EscapePath(username_value) + "|" +
397 EscapePath(password_element) + "|" + 405 EscapePath(password_element) + "|" +
398 EscapePath(signon_realm); 406 EscapePath(signon_realm);
399 } 407 }
400 408
401 } // namespace browser_sync 409 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/password_change_processor.cc ('k') | chrome/browser/sync/profile_sync_service_password_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698