remote_device_life_cycle_impl.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/components/proximity_auth/remote_device_life_cycle_impl.h"
  5. #include <memory>
  6. #include "ash/components/multidevice/logging/logging.h"
  7. #include "ash/components/proximity_auth/messenger_impl.h"
  8. #include "ash/services/secure_channel/public/cpp/client/secure_channel_client.h"
  9. #include "ash/services/secure_channel/public/cpp/shared/connection_priority.h"
  10. #include "base/bind.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. namespace proximity_auth {
  13. namespace {
  14. const char kSmartLockFeatureName[] = "easy_unlock";
  15. } // namespace
  16. RemoteDeviceLifeCycleImpl::RemoteDeviceLifeCycleImpl(
  17. ash::multidevice::RemoteDeviceRef remote_device,
  18. absl::optional<ash::multidevice::RemoteDeviceRef> local_device,
  19. ash::secure_channel::SecureChannelClient* secure_channel_client)
  20. : remote_device_(remote_device),
  21. local_device_(local_device),
  22. secure_channel_client_(secure_channel_client),
  23. state_(RemoteDeviceLifeCycle::State::STOPPED) {}
  24. RemoteDeviceLifeCycleImpl::~RemoteDeviceLifeCycleImpl() {}
  25. void RemoteDeviceLifeCycleImpl::Start() {
  26. PA_LOG(VERBOSE) << "Life cycle for " << remote_device_.name() << " started.";
  27. DCHECK(state_ == RemoteDeviceLifeCycle::State::STOPPED);
  28. FindConnection();
  29. }
  30. ash::multidevice::RemoteDeviceRef RemoteDeviceLifeCycleImpl::GetRemoteDevice()
  31. const {
  32. return remote_device_;
  33. }
  34. ash::secure_channel::ClientChannel* RemoteDeviceLifeCycleImpl::GetChannel()
  35. const {
  36. if (channel_)
  37. return channel_.get();
  38. if (messenger_)
  39. return messenger_->GetChannel();
  40. return nullptr;
  41. }
  42. RemoteDeviceLifeCycle::State RemoteDeviceLifeCycleImpl::GetState() const {
  43. return state_;
  44. }
  45. Messenger* RemoteDeviceLifeCycleImpl::GetMessenger() {
  46. return messenger_.get();
  47. }
  48. void RemoteDeviceLifeCycleImpl::AddObserver(Observer* observer) {
  49. observers_.AddObserver(observer);
  50. }
  51. void RemoteDeviceLifeCycleImpl::RemoveObserver(Observer* observer) {
  52. observers_.RemoveObserver(observer);
  53. }
  54. void RemoteDeviceLifeCycleImpl::TransitionToState(
  55. RemoteDeviceLifeCycle::State new_state) {
  56. PA_LOG(VERBOSE) << "Life cycle transition: " << state_ << " => " << new_state;
  57. RemoteDeviceLifeCycle::State old_state = state_;
  58. state_ = new_state;
  59. for (auto& observer : observers_)
  60. observer.OnLifeCycleStateChanged(old_state, new_state);
  61. }
  62. void RemoteDeviceLifeCycleImpl::FindConnection() {
  63. connection_attempt_ = secure_channel_client_->ListenForConnectionFromDevice(
  64. remote_device_, *local_device_, kSmartLockFeatureName,
  65. ash::secure_channel::ConnectionMedium::kBluetoothLowEnergy,
  66. ash::secure_channel::ConnectionPriority::kHigh);
  67. connection_attempt_->SetDelegate(this);
  68. TransitionToState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
  69. }
  70. void RemoteDeviceLifeCycleImpl::CreateMessenger() {
  71. DCHECK(state_ == RemoteDeviceLifeCycle::State::AUTHENTICATING);
  72. messenger_ = std::make_unique<MessengerImpl>(std::move(channel_));
  73. messenger_->AddObserver(this);
  74. TransitionToState(RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
  75. }
  76. void RemoteDeviceLifeCycleImpl::OnConnectionAttemptFailure(
  77. ash::secure_channel::mojom::ConnectionAttemptFailureReason reason) {
  78. connection_attempt_.reset();
  79. if (reason == ash::secure_channel::mojom::ConnectionAttemptFailureReason::
  80. ADAPTER_DISABLED ||
  81. reason == ash::secure_channel::mojom::ConnectionAttemptFailureReason::
  82. ADAPTER_NOT_PRESENT) {
  83. // Transition to state STOPPED, and wait for Bluetooth to become powered.
  84. // If it does, UnlockManager will start RemoteDeviceLifeCycle again.
  85. PA_LOG(WARNING) << "Life cycle for "
  86. << remote_device_.GetTruncatedDeviceIdForLogs()
  87. << " stopped because Bluetooth is not available.";
  88. TransitionToState(RemoteDeviceLifeCycle::State::STOPPED);
  89. } else {
  90. // TODO(crbug.com/991644): Improve the name AUTHENTICATION_FAILED (it can
  91. // encompass errors other than authentication failures) and create a metric
  92. // with buckets corresponding to the ConnectionAttemptFailureReason.
  93. PA_LOG(ERROR) << "Failed to authenticate with remote device: "
  94. << remote_device_.GetTruncatedDeviceIdForLogs()
  95. << ", for reason: " << reason << ". Giving up.";
  96. TransitionToState(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED);
  97. }
  98. }
  99. void RemoteDeviceLifeCycleImpl::OnConnection(
  100. std::unique_ptr<ash::secure_channel::ClientChannel> channel) {
  101. DCHECK(state_ == RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
  102. TransitionToState(RemoteDeviceLifeCycle::State::AUTHENTICATING);
  103. channel_ = std::move(channel);
  104. // Create the MessengerImpl asynchronously. |messenger_| registers itself as
  105. // an observer of |channel_|, so creating it synchronously would trigger
  106. // |OnSendCompleted()| as an observer call for |messenger_|.
  107. base::ThreadTaskRunnerHandle::Get()->PostTask(
  108. FROM_HERE, base::BindOnce(&RemoteDeviceLifeCycleImpl::CreateMessenger,
  109. weak_ptr_factory_.GetWeakPtr()));
  110. }
  111. void RemoteDeviceLifeCycleImpl::OnDisconnected() {
  112. DCHECK(state_ == RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
  113. messenger_->RemoveObserver(this);
  114. messenger_.reset();
  115. FindConnection();
  116. }
  117. } // namespace proximity_auth