1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "services/device/serial/serial_port_manager_impl.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/task/sequenced_task_runner.h"
14 #include "device/bluetooth/bluetooth_adapter_factory.h"
15 #include "services/device/public/cpp/serial/serial_switches.h"
16 #include "services/device/serial/bluetooth_serial_device_enumerator.h"
17 #include "services/device/serial/bluetooth_serial_port_impl.h"
18 #include "services/device/serial/serial_device_enumerator.h"
19 #include "services/device/serial/serial_port_impl.h"
25 void OnPortOpened(mojom::SerialPortManager::OpenPortCallback callback,
26 const scoped_refptr<base::TaskRunner>& task_runner,
27 mojo::PendingRemote<mojom::SerialPort> port) {
28 task_runner->PostTask(FROM_HERE,
29 base::BindOnce(std::move(callback), std::move(port)));
34 SerialPortManagerImpl::SerialPortManagerImpl(
35 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
36 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
37 : io_task_runner_(std::move(io_task_runner)),
38 ui_task_runner_(std::move(ui_task_runner)) {
39 DETACH_FROM_SEQUENCE(sequence_checker_);
42 SerialPortManagerImpl::~SerialPortManagerImpl() {
43 // Intentionally do not check sequence. See class comment doc for more info.
46 void SerialPortManagerImpl::Bind(
47 mojo::PendingReceiver<mojom::SerialPortManager> receiver) {
48 receivers_.Add(this, std::move(receiver));
51 void SerialPortManagerImpl::SetSerialEnumeratorForTesting(
52 std::unique_ptr<SerialDeviceEnumerator> fake_enumerator) {
53 DCHECK(fake_enumerator);
54 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
55 enumerator_ = std::move(fake_enumerator);
56 observed_enumerator_.AddObservation(enumerator_.get());
59 void SerialPortManagerImpl::SetBluetoothSerialEnumeratorForTesting(
60 std::unique_ptr<BluetoothSerialDeviceEnumerator>
61 fake_bluetooth_enumerator) {
62 DCHECK(fake_bluetooth_enumerator);
63 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
64 bluetooth_enumerator_ = std::move(fake_bluetooth_enumerator);
65 observed_enumerator_.AddObservation(bluetooth_enumerator_.get());
68 void SerialPortManagerImpl::SetClient(
69 mojo::PendingRemote<mojom::SerialPortManagerClient> client) {
70 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
71 clients_.Add(std::move(client));
74 void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) {
75 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
77 enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
78 observed_enumerator_.AddObservation(enumerator_.get());
80 auto devices = enumerator_->GetDevices();
81 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
82 switches::kEnableBluetoothSerialPortProfileInSerialApi)) {
83 if (!bluetooth_enumerator_) {
84 bluetooth_enumerator_ =
85 std::make_unique<BluetoothSerialDeviceEnumerator>(ui_task_runner_);
86 observed_enumerator_.AddObservation(bluetooth_enumerator_.get());
88 auto bluetooth_devices = bluetooth_enumerator_->GetDevices();
89 devices.insert(devices.end(),
90 std::make_move_iterator(bluetooth_devices.begin()),
91 std::make_move_iterator(bluetooth_devices.end()));
94 std::move(callback).Run(std::move(devices));
97 void SerialPortManagerImpl::OpenPort(
98 const base::UnguessableToken& token,
99 bool use_alternate_path,
100 device::mojom::SerialConnectionOptionsPtr options,
101 mojo::PendingRemote<mojom::SerialPortClient> client,
102 mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
103 OpenPortCallback callback) {
104 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
106 enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
107 observed_enumerator_.AddObservation(enumerator_.get());
109 absl::optional<base::FilePath> path =
110 enumerator_->GetPathFromToken(token, use_alternate_path);
112 io_task_runner_->PostTask(
114 base::BindOnce(&SerialPortImpl::Open, *path, std::move(options),
115 std::move(client), std::move(watcher), ui_task_runner_,
116 base::BindOnce(&OnPortOpened, std::move(callback),
117 base::SequencedTaskRunnerHandle::Get())));
121 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
122 switches::kEnableBluetoothSerialPortProfileInSerialApi)) {
123 if (!bluetooth_enumerator_) {
124 bluetooth_enumerator_ =
125 std::make_unique<BluetoothSerialDeviceEnumerator>(ui_task_runner_);
126 observed_enumerator_.AddObservation(bluetooth_enumerator_.get());
128 absl::optional<std::string> address =
129 bluetooth_enumerator_->GetAddressFromToken(token);
131 const BluetoothUUID service_class_id =
132 bluetooth_enumerator_->GetServiceClassIdFromToken(token);
133 ui_task_runner_->PostTask(
136 &SerialPortManagerImpl::OpenBluetoothSerialPortOnUI,
137 weak_factory_.GetWeakPtr(), *address, service_class_id,
138 std::move(options), std::move(client), std::move(watcher),
139 base::BindOnce(&OnPortOpened, std::move(callback),
140 base::SequencedTaskRunnerHandle::Get())));
145 std::move(callback).Run(mojo::NullRemote());
148 void SerialPortManagerImpl::OpenBluetoothSerialPortOnUI(
149 const std::string& address,
150 const BluetoothUUID& service_class_id,
151 mojom::SerialConnectionOptionsPtr options,
152 mojo::PendingRemote<mojom::SerialPortClient> client,
153 mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
154 BluetoothSerialPortImpl::OpenCallback callback) {
155 BluetoothSerialPortImpl::Open(bluetooth_enumerator_->GetAdapter(), address,
156 service_class_id, std::move(options),
157 std::move(client), std::move(watcher),
158 std::move(callback));
161 void SerialPortManagerImpl::OnPortAdded(const mojom::SerialPortInfo& port) {
162 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
163 for (auto& client : clients_)
164 client->OnPortAdded(port.Clone());
167 void SerialPortManagerImpl::OnPortRemoved(const mojom::SerialPortInfo& port) {
168 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
169 for (auto& client : clients_)
170 client->OnPortRemoved(port.Clone());
173 } // namespace device