Index: chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc |
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc |
index a33cc5206c2e07128348c707dfc0fe4a6eefa07e..33750f140b8cebac23f52221b0fc5310c1e76dec 100644 |
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc |
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc |
@@ -6,7 +6,7 @@ |
#include "base/bind.h" |
#include "base/logging.h" |
-#include "base/memory/scoped_ptr.h" |
+#include "base/stl_util.h" |
#include "base/strings/stringprintf.h" |
#include "base/values.h" |
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h" |
@@ -32,17 +32,21 @@ |
} // namespace |
EasyUnlockKeyManager::EasyUnlockKeyManager() |
- : write_queue_deleter_(&write_operation_queue_), |
- read_queue_deleter_(&read_operation_queue_), |
+ : operation_id_(0), |
weak_ptr_factory_(this) { |
} |
EasyUnlockKeyManager::~EasyUnlockKeyManager() { |
+ STLDeleteContainerPairSecondPointers(get_keys_ops_.begin(), |
+ get_keys_ops_.end()); |
} |
void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context, |
const base::ListValue& remote_devices, |
const RefreshKeysCallback& callback) { |
+ // Must have the secret. |
+ DCHECK(!user_context.GetKey()->GetSecret().empty()); |
+ |
base::Closure do_refresh_keys = base::Bind( |
&EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent, |
weak_ptr_factory_.GetWeakPtr(), |
@@ -87,20 +91,58 @@ |
if (!RemoteDeviceListToDeviceDataList(*remote_devices, &devices)) |
devices.clear(); |
- write_operation_queue_.push_back(new EasyUnlockRefreshKeysOperation( |
- user_context, tpm_public_key, devices, |
- base::Bind(&EasyUnlockKeyManager::OnKeysRefreshed, |
- weak_ptr_factory_.GetWeakPtr(), callback))); |
- RunNextOperation(); |
+ // Only one pending request. |
+ DCHECK(!HasPendingOperations()); |
+ create_keys_op_.reset(new EasyUnlockCreateKeysOperation( |
+ user_context, |
+ tpm_public_key, |
+ devices, |
+ base::Bind(&EasyUnlockKeyManager::OnKeysCreated, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ devices.size(), |
+ callback))); |
+ create_keys_op_->Start(); |
+} |
+ |
+void EasyUnlockKeyManager::RemoveKeys(const UserContext& user_context, |
+ size_t start_index, |
+ const RemoveKeysCallback& callback) { |
+ // Must have the secret. |
+ DCHECK(!user_context.GetKey()->GetSecret().empty()); |
+ // Only one pending request. |
+ DCHECK(!HasPendingOperations()); |
+ |
+ remove_keys_op_.reset( |
+ new EasyUnlockRemoveKeysOperation( |
+ user_context, |
+ start_index, |
+ base::Bind(&EasyUnlockKeyManager::OnKeysRemoved, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ callback))); |
+ remove_keys_op_->Start(); |
} |
void EasyUnlockKeyManager::GetDeviceDataList( |
const UserContext& user_context, |
const GetDeviceDataListCallback& callback) { |
- read_operation_queue_.push_back(new EasyUnlockGetKeysOperation( |
- user_context, base::Bind(&EasyUnlockKeyManager::OnKeysFetched, |
- weak_ptr_factory_.GetWeakPtr(), callback))); |
- RunNextOperation(); |
+ // Defer the get operation if there is pending write operations. |
+ if (create_keys_op_ || remove_keys_op_) { |
+ pending_ops_.push_back(base::Bind(&EasyUnlockKeyManager::GetDeviceDataList, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ user_context, |
+ callback)); |
+ return; |
+ } |
+ |
+ const int op_id = GetNextOperationId(); |
+ scoped_ptr<EasyUnlockGetKeysOperation> op(new EasyUnlockGetKeysOperation( |
+ user_context, |
+ base::Bind(&EasyUnlockKeyManager::OnKeysFetched, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ op_id, |
+ callback))); |
+ op->Start(); |
+ get_keys_ops_[op_id] = op.release(); |
} |
// static |
@@ -182,41 +224,64 @@ |
return base::StringPrintf("%s%zu", kKeyLabelPrefix, key_index); |
} |
-void EasyUnlockKeyManager::RunNextOperation() { |
- if (pending_write_operation_ || pending_read_operation_) |
+bool EasyUnlockKeyManager::HasPendingOperations() const { |
+ return create_keys_op_ || remove_keys_op_ || !get_keys_ops_.empty(); |
+} |
+ |
+int EasyUnlockKeyManager::GetNextOperationId() { |
+ return ++operation_id_; |
+} |
+ |
+void EasyUnlockKeyManager::RunNextPendingOp() { |
+ if (pending_ops_.empty()) |
return; |
- if (!write_operation_queue_.empty()) { |
- pending_write_operation_ = make_scoped_ptr(write_operation_queue_.front()); |
- write_operation_queue_.pop_front(); |
- pending_write_operation_->Start(); |
- } else if (!read_operation_queue_.empty()) { |
- pending_read_operation_ = make_scoped_ptr(read_operation_queue_.front()); |
- read_operation_queue_.pop_front(); |
- pending_read_operation_->Start(); |
- } |
-} |
- |
-void EasyUnlockKeyManager::OnKeysRefreshed(const RefreshKeysCallback& callback, |
- bool refresh_success) { |
+ pending_ops_.front().Run(); |
+ pending_ops_.pop_front(); |
+} |
+ |
+void EasyUnlockKeyManager::OnKeysCreated( |
+ size_t remove_start_index, |
+ const RefreshKeysCallback& callback, |
+ bool create_success) { |
+ scoped_ptr<EasyUnlockCreateKeysOperation> op = create_keys_op_.Pass(); |
if (!callback.is_null()) |
- callback.Run(refresh_success); |
- |
- DCHECK(pending_write_operation_); |
- pending_write_operation_.reset(); |
- RunNextOperation(); |
+ callback.Run(create_success); |
+ |
+ // Remove extra existing keys. |
+ RemoveKeys(op->user_context(), remove_start_index, RemoveKeysCallback()); |
+} |
+ |
+void EasyUnlockKeyManager::OnKeysRemoved(const RemoveKeysCallback& callback, |
+ bool remove_success) { |
+ scoped_ptr<EasyUnlockRemoveKeysOperation> op = remove_keys_op_.Pass(); |
+ if (!callback.is_null()) |
+ callback.Run(remove_success); |
+ |
+ if (!HasPendingOperations()) |
+ RunNextPendingOp(); |
} |
void EasyUnlockKeyManager::OnKeysFetched( |
+ int op_id, |
const GetDeviceDataListCallback& callback, |
bool fetch_success, |
const EasyUnlockDeviceKeyDataList& fetched_data) { |
+ std::map<int, EasyUnlockGetKeysOperation*>::iterator it = |
+ get_keys_ops_.find(op_id); |
+ scoped_ptr<EasyUnlockGetKeysOperation> op; |
+ if (it != get_keys_ops_.end()) { |
+ op.reset(it->second); |
+ get_keys_ops_.erase(it); |
+ } else { |
+ NOTREACHED(); |
+ } |
+ |
if (!callback.is_null()) |
callback.Run(fetch_success, fetched_data); |
- DCHECK(pending_read_operation_); |
- pending_read_operation_.reset(); |
- RunNextOperation(); |
+ if (!HasPendingOperations()) |
+ RunNextPendingOp(); |
} |
} // namespace chromeos |