| 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 |