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/stl_util.h" | 9 #include "base/memory/scoped_ptr.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 : operation_id_(0), | 35 : write_queue_deleter_(&write_operation_queue_), |
| 36 read_queue_deleter_(&read_operation_queue_), |
36 weak_ptr_factory_(this) { | 37 weak_ptr_factory_(this) { |
37 } | 38 } |
38 | 39 |
39 EasyUnlockKeyManager::~EasyUnlockKeyManager() { | 40 EasyUnlockKeyManager::~EasyUnlockKeyManager() { |
40 STLDeleteContainerPairSecondPointers(get_keys_ops_.begin(), | |
41 get_keys_ops_.end()); | |
42 } | 41 } |
43 | 42 |
44 void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context, | 43 void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context, |
45 const base::ListValue& remote_devices, | 44 const base::ListValue& remote_devices, |
46 const RefreshKeysCallback& callback) { | 45 const RefreshKeysCallback& callback) { |
47 // Must have the secret. | |
48 DCHECK(!user_context.GetKey()->GetSecret().empty()); | |
49 | |
50 base::Closure do_refresh_keys = base::Bind( | 46 base::Closure do_refresh_keys = base::Bind( |
51 &EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent, | 47 &EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent, |
52 weak_ptr_factory_.GetWeakPtr(), | 48 weak_ptr_factory_.GetWeakPtr(), |
53 user_context, | 49 user_context, |
54 base::Owned(remote_devices.DeepCopy()), | 50 base::Owned(remote_devices.DeepCopy()), |
55 callback); | 51 callback); |
56 | 52 |
57 EasyUnlockTpmKeyManager* tpm_key_manager = | 53 EasyUnlockTpmKeyManager* tpm_key_manager = |
58 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( | 54 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( |
59 user_context.GetUserID()); | 55 user_context.GetUserID()); |
(...skipping 24 matching lines...) Expand all Loading... |
84 EasyUnlockTpmKeyManager* tpm_key_manager = | 80 EasyUnlockTpmKeyManager* tpm_key_manager = |
85 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( | 81 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser( |
86 user_context.GetUserID()); | 82 user_context.GetUserID()); |
87 std::string tpm_public_key = | 83 std::string tpm_public_key = |
88 tpm_key_manager->GetPublicTpmKey(user_context.GetUserID()); | 84 tpm_key_manager->GetPublicTpmKey(user_context.GetUserID()); |
89 | 85 |
90 EasyUnlockDeviceKeyDataList devices; | 86 EasyUnlockDeviceKeyDataList devices; |
91 if (!RemoteDeviceListToDeviceDataList(*remote_devices, &devices)) | 87 if (!RemoteDeviceListToDeviceDataList(*remote_devices, &devices)) |
92 devices.clear(); | 88 devices.clear(); |
93 | 89 |
94 // Only one pending request. | 90 write_operation_queue_.push_back(new EasyUnlockRefreshKeysOperation( |
95 DCHECK(!HasPendingOperations()); | 91 user_context, tpm_public_key, devices, |
96 create_keys_op_.reset(new EasyUnlockCreateKeysOperation( | 92 base::Bind(&EasyUnlockKeyManager::OnKeysRefreshed, |
97 user_context, | 93 weak_ptr_factory_.GetWeakPtr(), callback))); |
98 tpm_public_key, | 94 RunNextOperation(); |
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(); | |
123 } | 95 } |
124 | 96 |
125 void EasyUnlockKeyManager::GetDeviceDataList( | 97 void EasyUnlockKeyManager::GetDeviceDataList( |
126 const UserContext& user_context, | 98 const UserContext& user_context, |
127 const GetDeviceDataListCallback& callback) { | 99 const GetDeviceDataListCallback& callback) { |
128 // Defer the get operation if there is pending write operations. | 100 read_operation_queue_.push_back(new EasyUnlockGetKeysOperation( |
129 if (create_keys_op_ || remove_keys_op_) { | 101 user_context, base::Bind(&EasyUnlockKeyManager::OnKeysFetched, |
130 pending_ops_.push_back(base::Bind(&EasyUnlockKeyManager::GetDeviceDataList, | 102 weak_ptr_factory_.GetWeakPtr(), callback))); |
131 weak_ptr_factory_.GetWeakPtr(), | 103 RunNextOperation(); |
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(); | |
146 } | 104 } |
147 | 105 |
148 // static | 106 // static |
149 void EasyUnlockKeyManager::DeviceDataToRemoteDeviceDictionary( | 107 void EasyUnlockKeyManager::DeviceDataToRemoteDeviceDictionary( |
150 const std::string& user_id, | 108 const std::string& user_id, |
151 const EasyUnlockDeviceKeyData& data, | 109 const EasyUnlockDeviceKeyData& data, |
152 base::DictionaryValue* dict) { | 110 base::DictionaryValue* dict) { |
153 dict->SetString(kKeyBluetoothAddress, data.bluetooth_address); | 111 dict->SetString(kKeyBluetoothAddress, data.bluetooth_address); |
154 dict->SetString(kKeyPsk, data.psk); | 112 dict->SetString(kKeyPsk, data.psk); |
155 scoped_ptr<base::DictionaryValue> permit_record(new base::DictionaryValue); | 113 scoped_ptr<base::DictionaryValue> permit_record(new base::DictionaryValue); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 | 175 |
218 data_list->swap(parsed_devices); | 176 data_list->swap(parsed_devices); |
219 return true; | 177 return true; |
220 } | 178 } |
221 | 179 |
222 // static | 180 // static |
223 std::string EasyUnlockKeyManager::GetKeyLabel(size_t key_index) { | 181 std::string EasyUnlockKeyManager::GetKeyLabel(size_t key_index) { |
224 return base::StringPrintf("%s%zu", kKeyLabelPrefix, key_index); | 182 return base::StringPrintf("%s%zu", kKeyLabelPrefix, key_index); |
225 } | 183 } |
226 | 184 |
227 bool EasyUnlockKeyManager::HasPendingOperations() const { | 185 void EasyUnlockKeyManager::RunNextOperation() { |
228 return create_keys_op_ || remove_keys_op_ || !get_keys_ops_.empty(); | 186 if (pending_write_operation_ || pending_read_operation_) |
| 187 return; |
| 188 |
| 189 if (!write_operation_queue_.empty()) { |
| 190 pending_write_operation_ = make_scoped_ptr(write_operation_queue_.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 } |
229 } | 198 } |
230 | 199 |
231 int EasyUnlockKeyManager::GetNextOperationId() { | 200 void EasyUnlockKeyManager::OnKeysRefreshed(const RefreshKeysCallback& callback, |
232 return ++operation_id_; | 201 bool refresh_success) { |
233 } | 202 if (!callback.is_null()) |
| 203 callback.Run(refresh_success); |
234 | 204 |
235 void EasyUnlockKeyManager::RunNextPendingOp() { | 205 DCHECK(pending_write_operation_); |
236 if (pending_ops_.empty()) | 206 pending_write_operation_.reset(); |
237 return; | 207 RunNextOperation(); |
238 | |
239 pending_ops_.front().Run(); | |
240 pending_ops_.pop_front(); | |
241 } | |
242 | |
243 void EasyUnlockKeyManager::OnKeysCreated( | |
244 size_t remove_start_index, | |
245 const RefreshKeysCallback& callback, | |
246 bool create_success) { | |
247 scoped_ptr<EasyUnlockCreateKeysOperation> op = create_keys_op_.Pass(); | |
248 if (!callback.is_null()) | |
249 callback.Run(create_success); | |
250 | |
251 // Remove extra existing keys. | |
252 RemoveKeys(op->user_context(), remove_start_index, RemoveKeysCallback()); | |
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(); | |
263 } | 208 } |
264 | 209 |
265 void EasyUnlockKeyManager::OnKeysFetched( | 210 void EasyUnlockKeyManager::OnKeysFetched( |
266 int op_id, | |
267 const GetDeviceDataListCallback& callback, | 211 const GetDeviceDataListCallback& callback, |
268 bool fetch_success, | 212 bool fetch_success, |
269 const EasyUnlockDeviceKeyDataList& fetched_data) { | 213 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 | |
280 if (!callback.is_null()) | 214 if (!callback.is_null()) |
281 callback.Run(fetch_success, fetched_data); | 215 callback.Run(fetch_success, fetched_data); |
282 | 216 |
283 if (!HasPendingOperations()) | 217 DCHECK(pending_read_operation_); |
284 RunNextPendingOp(); | 218 pending_read_operation_.reset(); |
| 219 RunNextOperation(); |
285 } | 220 } |
286 | 221 |
287 } // namespace chromeos | 222 } // namespace chromeos |
OLD | NEW |