File: remote_device_life_cycle_impl.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (148 lines) | stat: -rw-r--r-- 5,520 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/components/proximity_auth/remote_device_life_cycle_impl.h"

#include <memory>

#include "base/functional/bind.h"
#include "base/task/single_thread_task_runner.h"
#include "chromeos/ash/components/multidevice/logging/logging.h"
#include "chromeos/ash/components/proximity_auth/messenger_impl.h"
#include "chromeos/ash/services/secure_channel/public/cpp/client/secure_channel_client.h"
#include "chromeos/ash/services/secure_channel/public/cpp/shared/connection_priority.h"

namespace proximity_auth {

namespace {

const char kSmartLockFeatureName[] = "easy_unlock";

}  // namespace

RemoteDeviceLifeCycleImpl::RemoteDeviceLifeCycleImpl(
    ash::multidevice::RemoteDeviceRef remote_device,
    std::optional<ash::multidevice::RemoteDeviceRef> local_device,
    ash::secure_channel::SecureChannelClient* secure_channel_client)
    : remote_device_(remote_device),
      local_device_(local_device),
      secure_channel_client_(secure_channel_client),
      state_(RemoteDeviceLifeCycle::State::STOPPED) {}

RemoteDeviceLifeCycleImpl::~RemoteDeviceLifeCycleImpl() {}

void RemoteDeviceLifeCycleImpl::Start() {
  PA_LOG(VERBOSE) << "Life cycle for " << remote_device_.name() << " started.";
  DCHECK(state_ == RemoteDeviceLifeCycle::State::STOPPED);
  FindConnection();
}

ash::multidevice::RemoteDeviceRef RemoteDeviceLifeCycleImpl::GetRemoteDevice()
    const {
  return remote_device_;
}

ash::secure_channel::ClientChannel* RemoteDeviceLifeCycleImpl::GetChannel()
    const {
  if (channel_)
    return channel_.get();
  if (messenger_)
    return messenger_->GetChannel();
  return nullptr;
}

RemoteDeviceLifeCycle::State RemoteDeviceLifeCycleImpl::GetState() const {
  return state_;
}

Messenger* RemoteDeviceLifeCycleImpl::GetMessenger() {
  return messenger_.get();
}

void RemoteDeviceLifeCycleImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void RemoteDeviceLifeCycleImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

void RemoteDeviceLifeCycleImpl::TransitionToState(
    RemoteDeviceLifeCycle::State new_state) {
  PA_LOG(VERBOSE) << "Life cycle transition: " << state_ << " => " << new_state;
  RemoteDeviceLifeCycle::State old_state = state_;
  state_ = new_state;
  for (auto& observer : observers_)
    observer.OnLifeCycleStateChanged(old_state, new_state);
}

void RemoteDeviceLifeCycleImpl::FindConnection() {
  connection_attempt_ = secure_channel_client_->ListenForConnectionFromDevice(
      remote_device_, *local_device_, kSmartLockFeatureName,
      ash::secure_channel::ConnectionMedium::kBluetoothLowEnergy,
      ash::secure_channel::ConnectionPriority::kHigh);
  connection_attempt_->SetDelegate(this);

  TransitionToState(RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
}

void RemoteDeviceLifeCycleImpl::CreateMessenger() {
  DCHECK(state_ == RemoteDeviceLifeCycle::State::AUTHENTICATING);

  messenger_ = std::make_unique<MessengerImpl>(std::move(channel_));
  messenger_->AddObserver(this);

  TransitionToState(RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
}

void RemoteDeviceLifeCycleImpl::OnConnectionAttemptFailure(
    ash::secure_channel::mojom::ConnectionAttemptFailureReason reason) {
  connection_attempt_.reset();

  if (reason == ash::secure_channel::mojom::ConnectionAttemptFailureReason::
                    ADAPTER_DISABLED ||
      reason == ash::secure_channel::mojom::ConnectionAttemptFailureReason::
                    ADAPTER_NOT_PRESENT) {
    // Transition to state STOPPED, and wait for Bluetooth to become powered.
    // If it does, UnlockManager will start RemoteDeviceLifeCycle again.
    PA_LOG(WARNING) << "Life cycle for "
                    << remote_device_.GetTruncatedDeviceIdForLogs()
                    << " stopped because Bluetooth is not available.";
    TransitionToState(RemoteDeviceLifeCycle::State::STOPPED);
  } else {
    // TODO(crbug.com/41474905): Improve the name AUTHENTICATION_FAILED (it can
    // encompass errors other than authentication failures) and create a metric
    // with buckets corresponding to the ConnectionAttemptFailureReason.
    PA_LOG(ERROR) << "Failed to authenticate with remote device: "
                  << remote_device_.GetTruncatedDeviceIdForLogs()
                  << ", for reason: " << reason << ". Giving up.";
    TransitionToState(RemoteDeviceLifeCycle::State::AUTHENTICATION_FAILED);
  }
}

void RemoteDeviceLifeCycleImpl::OnConnection(
    std::unique_ptr<ash::secure_channel::ClientChannel> channel) {
  DCHECK(state_ == RemoteDeviceLifeCycle::State::FINDING_CONNECTION);
  TransitionToState(RemoteDeviceLifeCycle::State::AUTHENTICATING);

  channel_ = std::move(channel);

  // Create the MessengerImpl asynchronously. |messenger_| registers itself as
  // an observer of |channel_|, so creating it synchronously would trigger
  // |OnSendCompleted()| as an observer call for |messenger_|.
  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindOnce(&RemoteDeviceLifeCycleImpl::CreateMessenger,
                                weak_ptr_factory_.GetWeakPtr()));
}

void RemoteDeviceLifeCycleImpl::OnDisconnected() {
  DCHECK(state_ == RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);

  messenger_->RemoveObserver(this);
  messenger_.reset();

  FindConnection();
}

}  // namespace proximity_auth