OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |