| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/chromeos/login/easy_unlock/easy_unlock_key_manager.h" | 5 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 11 #include "base/values.h" | 11 #include "base/values.h" |
| 12 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.
h" | 12 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.
h" |
| 13 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_
factory.h" | 13 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_
factory.h" |
| 14 | 14 |
| 15 namespace chromeos { | 15 namespace chromeos { |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 const char kKeyBluetoothAddress[] = "bluetoothAddress"; | 19 const char kKeyBluetoothAddress[] = "bluetoothAddress"; |
| 20 const char kKeyPermitRecord[] = "permitRecord"; | 20 const char kKeyPermitRecord[] = "permitRecord"; |
| 21 const char kKeyPermitId[] = "permitRecord.id"; | 21 const char kKeyPermitId[] = "permitRecord.id"; |
| 22 const char kKeyPermitPermitId[] = "permitRecord.permitId"; | 22 const char kKeyPermitPermitId[] = "permitRecord.permitId"; |
| 23 const char kKeyPermitData[] = "permitRecord.data"; | 23 const char kKeyPermitData[] = "permitRecord.data"; |
| 24 const char kKeyPermitType[] = "permitRecord.type"; | 24 const char kKeyPermitType[] = "permitRecord.type"; |
| 25 const char kKeyPsk[] = "psk"; | 25 const char kKeyPsk[] = "psk"; |
| 26 | 26 |
| 27 const char kKeyLabelPrefix[] = "easy-unlock-"; | 27 const char kKeyLabelPrefix[] = "easy-unlock-"; |
| 28 | 28 |
| 29 const char kPermitPermitIdFormat[] = "permit://google.com/easyunlock/v1/%s"; | 29 const char kPermitPermitIdFormat[] = "permit://google.com/easyunlock/v1/%s"; |
| 30 const char kPermitTypeLicence[] = "licence"; | 30 const char kPermitTypeLicence[] = "licence"; |
| 31 | 31 |
| 32 } // namespace | 32 } // namespace |
| 33 | 33 |
| 34 EasyUnlockKeyManager::EasyUnlockKeyManager() | 34 EasyUnlockKeyManager::EasyUnlockKeyManager() |
| 35 : write_queue_deleter_(&write_operation_queue_), | 35 : operation_id_(0), |
| 36 read_queue_deleter_(&read_operation_queue_), | |
| 37 weak_ptr_factory_(this) { | 36 weak_ptr_factory_(this) { |
| 38 } | 37 } |
| 39 | 38 |
| 40 EasyUnlockKeyManager::~EasyUnlockKeyManager() { | 39 EasyUnlockKeyManager::~EasyUnlockKeyManager() { |
| 40 STLDeleteContainerPairSecondPointers(get_keys_ops_.begin(), |
| 41 get_keys_ops_.end()); |
| 41 } | 42 } |
| 42 | 43 |
| 43 void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context, | 44 void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context, |
| 44 const base::ListValue& remote_devices, | 45 const base::ListValue& remote_devices, |
| 45 const RefreshKeysCallback& callback) { | 46 const RefreshKeysCallback& callback) { |
| 47 // Must have the secret. |
| 48 DCHECK(!user_context.GetKey()->GetSecret().empty()); |
| 49 |
| 46 base::Closure do_refresh_keys = base::Bind( | 50 base::Closure do_refresh_keys = base::Bind( |
| 47 &EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent, | 51 &EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent, |
| 48 weak_ptr_factory_.GetWeakPtr(), | 52 weak_ptr_factory_.GetWeakPtr(), |
| 49 user_context, | 53 user_context, |
| 50 base::Owned(remote_devices.DeepCopy()), | 54 base::Owned(remote_devices.DeepCopy()), |
| 51 callback); | 55 callback); |
| 52 | 56 |
| 53 EasyUnlockTpmKeyManager* tpm_key_manager = | 57 EasyUnlockTpmKeyManager* tpm_key_manager = |
| 54 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( | 58 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( |
| 55 user_context.GetUserID()); | 59 user_context.GetUserID()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 80 EasyUnlockTpmKeyManager* tpm_key_manager = | 84 EasyUnlockTpmKeyManager* tpm_key_manager = |
| 81 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( | 85 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( |
| 82 user_context.GetUserID()); | 86 user_context.GetUserID()); |
| 83 std::string tpm_public_key = | 87 std::string tpm_public_key = |
| 84 tpm_key_manager->GetPublicTpmKey(user_context.GetUserID()); | 88 tpm_key_manager->GetPublicTpmKey(user_context.GetUserID()); |
| 85 | 89 |
| 86 EasyUnlockDeviceKeyDataList devices; | 90 EasyUnlockDeviceKeyDataList devices; |
| 87 if (!RemoteDeviceListToDeviceDataList(*remote_devices, &devices)) | 91 if (!RemoteDeviceListToDeviceDataList(*remote_devices, &devices)) |
| 88 devices.clear(); | 92 devices.clear(); |
| 89 | 93 |
| 90 write_operation_queue_.push_back(new EasyUnlockRefreshKeysOperation( | 94 // Only one pending request. |
| 91 user_context, tpm_public_key, devices, | 95 DCHECK(!HasPendingOperations()); |
| 92 base::Bind(&EasyUnlockKeyManager::OnKeysRefreshed, | 96 create_keys_op_.reset(new EasyUnlockCreateKeysOperation( |
| 93 weak_ptr_factory_.GetWeakPtr(), callback))); | 97 user_context, |
| 94 RunNextOperation(); | 98 tpm_public_key, |
| 99 devices, |
| 100 base::Bind(&EasyUnlockKeyManager::OnKeysCreated, |
| 101 weak_ptr_factory_.GetWeakPtr(), |
| 102 devices.size(), |
| 103 callback))); |
| 104 create_keys_op_->Start(); |
| 105 } |
| 106 |
| 107 void EasyUnlockKeyManager::RemoveKeys(const UserContext& user_context, |
| 108 size_t start_index, |
| 109 const RemoveKeysCallback& callback) { |
| 110 // Must have the secret. |
| 111 DCHECK(!user_context.GetKey()->GetSecret().empty()); |
| 112 // Only one pending request. |
| 113 DCHECK(!HasPendingOperations()); |
| 114 |
| 115 remove_keys_op_.reset( |
| 116 new EasyUnlockRemoveKeysOperation( |
| 117 user_context, |
| 118 start_index, |
| 119 base::Bind(&EasyUnlockKeyManager::OnKeysRemoved, |
| 120 weak_ptr_factory_.GetWeakPtr(), |
| 121 callback))); |
| 122 remove_keys_op_->Start(); |
| 95 } | 123 } |
| 96 | 124 |
| 97 void EasyUnlockKeyManager::GetDeviceDataList( | 125 void EasyUnlockKeyManager::GetDeviceDataList( |
| 98 const UserContext& user_context, | 126 const UserContext& user_context, |
| 99 const GetDeviceDataListCallback& callback) { | 127 const GetDeviceDataListCallback& callback) { |
| 100 read_operation_queue_.push_back(new EasyUnlockGetKeysOperation( | 128 // Defer the get operation if there is pending write operations. |
| 101 user_context, base::Bind(&EasyUnlockKeyManager::OnKeysFetched, | 129 if (create_keys_op_ || remove_keys_op_) { |
| 102 weak_ptr_factory_.GetWeakPtr(), callback))); | 130 pending_ops_.push_back(base::Bind(&EasyUnlockKeyManager::GetDeviceDataList, |
| 103 RunNextOperation(); | 131 weak_ptr_factory_.GetWeakPtr(), |
| 132 user_context, |
| 133 callback)); |
| 134 return; |
| 135 } |
| 136 |
| 137 const int op_id = GetNextOperationId(); |
| 138 scoped_ptr<EasyUnlockGetKeysOperation> op(new EasyUnlockGetKeysOperation( |
| 139 user_context, |
| 140 base::Bind(&EasyUnlockKeyManager::OnKeysFetched, |
| 141 weak_ptr_factory_.GetWeakPtr(), |
| 142 op_id, |
| 143 callback))); |
| 144 op->Start(); |
| 145 get_keys_ops_[op_id] = op.release(); |
| 104 } | 146 } |
| 105 | 147 |
| 106 // static | 148 // static |
| 107 void EasyUnlockKeyManager::DeviceDataToRemoteDeviceDictionary( | 149 void EasyUnlockKeyManager::DeviceDataToRemoteDeviceDictionary( |
| 108 const std::string& user_id, | 150 const std::string& user_id, |
| 109 const EasyUnlockDeviceKeyData& data, | 151 const EasyUnlockDeviceKeyData& data, |
| 110 base::DictionaryValue* dict) { | 152 base::DictionaryValue* dict) { |
| 111 dict->SetString(kKeyBluetoothAddress, data.bluetooth_address); | 153 dict->SetString(kKeyBluetoothAddress, data.bluetooth_address); |
| 112 dict->SetString(kKeyPsk, data.psk); | 154 dict->SetString(kKeyPsk, data.psk); |
| 113 scoped_ptr<base::DictionaryValue> permit_record(new base::DictionaryValue); | 155 scoped_ptr<base::DictionaryValue> permit_record(new base::DictionaryValue); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 217 |
| 176 data_list->swap(parsed_devices); | 218 data_list->swap(parsed_devices); |
| 177 return true; | 219 return true; |
| 178 } | 220 } |
| 179 | 221 |
| 180 // static | 222 // static |
| 181 std::string EasyUnlockKeyManager::GetKeyLabel(size_t key_index) { | 223 std::string EasyUnlockKeyManager::GetKeyLabel(size_t key_index) { |
| 182 return base::StringPrintf("%s%zu", kKeyLabelPrefix, key_index); | 224 return base::StringPrintf("%s%zu", kKeyLabelPrefix, key_index); |
| 183 } | 225 } |
| 184 | 226 |
| 185 void EasyUnlockKeyManager::RunNextOperation() { | 227 bool EasyUnlockKeyManager::HasPendingOperations() const { |
| 186 if (pending_write_operation_ || pending_read_operation_) | 228 return create_keys_op_ || remove_keys_op_ || !get_keys_ops_.empty(); |
| 229 } |
| 230 |
| 231 int EasyUnlockKeyManager::GetNextOperationId() { |
| 232 return ++operation_id_; |
| 233 } |
| 234 |
| 235 void EasyUnlockKeyManager::RunNextPendingOp() { |
| 236 if (pending_ops_.empty()) |
| 187 return; | 237 return; |
| 188 | 238 |
| 189 if (!write_operation_queue_.empty()) { | 239 pending_ops_.front().Run(); |
| 190 pending_write_operation_ = make_scoped_ptr(write_operation_queue_.front()); | 240 pending_ops_.pop_front(); |
| 191 write_operation_queue_.pop_front(); | |
| 192 pending_write_operation_->Start(); | |
| 193 } else if (!read_operation_queue_.empty()) { | |
| 194 pending_read_operation_ = make_scoped_ptr(read_operation_queue_.front()); | |
| 195 read_operation_queue_.pop_front(); | |
| 196 pending_read_operation_->Start(); | |
| 197 } | |
| 198 } | 241 } |
| 199 | 242 |
| 200 void EasyUnlockKeyManager::OnKeysRefreshed(const RefreshKeysCallback& callback, | 243 void EasyUnlockKeyManager::OnKeysCreated( |
| 201 bool refresh_success) { | 244 size_t remove_start_index, |
| 245 const RefreshKeysCallback& callback, |
| 246 bool create_success) { |
| 247 scoped_ptr<EasyUnlockCreateKeysOperation> op = create_keys_op_.Pass(); |
| 202 if (!callback.is_null()) | 248 if (!callback.is_null()) |
| 203 callback.Run(refresh_success); | 249 callback.Run(create_success); |
| 204 | 250 |
| 205 DCHECK(pending_write_operation_); | 251 // Remove extra existing keys. |
| 206 pending_write_operation_.reset(); | 252 RemoveKeys(op->user_context(), remove_start_index, RemoveKeysCallback()); |
| 207 RunNextOperation(); | 253 } |
| 254 |
| 255 void EasyUnlockKeyManager::OnKeysRemoved(const RemoveKeysCallback& callback, |
| 256 bool remove_success) { |
| 257 scoped_ptr<EasyUnlockRemoveKeysOperation> op = remove_keys_op_.Pass(); |
| 258 if (!callback.is_null()) |
| 259 callback.Run(remove_success); |
| 260 |
| 261 if (!HasPendingOperations()) |
| 262 RunNextPendingOp(); |
| 208 } | 263 } |
| 209 | 264 |
| 210 void EasyUnlockKeyManager::OnKeysFetched( | 265 void EasyUnlockKeyManager::OnKeysFetched( |
| 266 int op_id, |
| 211 const GetDeviceDataListCallback& callback, | 267 const GetDeviceDataListCallback& callback, |
| 212 bool fetch_success, | 268 bool fetch_success, |
| 213 const EasyUnlockDeviceKeyDataList& fetched_data) { | 269 const EasyUnlockDeviceKeyDataList& fetched_data) { |
| 270 std::map<int, EasyUnlockGetKeysOperation*>::iterator it = |
| 271 get_keys_ops_.find(op_id); |
| 272 scoped_ptr<EasyUnlockGetKeysOperation> op; |
| 273 if (it != get_keys_ops_.end()) { |
| 274 op.reset(it->second); |
| 275 get_keys_ops_.erase(it); |
| 276 } else { |
| 277 NOTREACHED(); |
| 278 } |
| 279 |
| 214 if (!callback.is_null()) | 280 if (!callback.is_null()) |
| 215 callback.Run(fetch_success, fetched_data); | 281 callback.Run(fetch_success, fetched_data); |
| 216 | 282 |
| 217 DCHECK(pending_read_operation_); | 283 if (!HasPendingOperations()) |
| 218 pending_read_operation_.reset(); | 284 RunNextPendingOp(); |
| 219 RunNextOperation(); | |
| 220 } | 285 } |
| 221 | 286 |
| 222 } // namespace chromeos | 287 } // namespace chromeos |
| OLD | NEW |