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 |