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