Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / components / pairing / bluetooth_controller_pairing_controller.cc
blob3d8cb6a85dc9ee3135ff6b8f8ebc4d8dfbfd292e
1 // Copyright 2014 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.
5 #include "components/pairing/bluetooth_controller_pairing_controller.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "components/pairing/bluetooth_pairing_constants.h"
13 #include "components/pairing/pairing_api.pb.h"
14 #include "device/bluetooth/bluetooth_adapter_factory.h"
15 #include "device/bluetooth/bluetooth_discovery_session.h"
16 #include "net/base/io_buffer.h"
18 namespace {
19 const int kReceiveSize = 16384;
22 namespace pairing_chromeos {
24 BluetoothControllerPairingController::BluetoothControllerPairingController()
25 : current_stage_(STAGE_NONE),
26 proto_decoder_(new ProtoDecoder(this)),
27 ptr_factory_(this) {
30 BluetoothControllerPairingController::~BluetoothControllerPairingController() {
31 Reset();
34 device::BluetoothDevice* BluetoothControllerPairingController::GetController() {
35 DCHECK(!controller_device_id_.empty());
36 device::BluetoothDevice* device = adapter_->GetDevice(controller_device_id_);
37 if (!device) {
38 LOG(ERROR) << "Lost connection to controller.";
39 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR);
42 return device;
45 void BluetoothControllerPairingController::ChangeStage(Stage new_stage) {
46 if (current_stage_ == new_stage)
47 return;
48 VLOG(1) << "ChangeStage " << new_stage;
49 current_stage_ = new_stage;
50 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
51 PairingStageChanged(new_stage));
54 void BluetoothControllerPairingController::Reset() {
55 controller_device_id_.clear();
56 discovery_session_.reset();
58 if (socket_.get()) {
59 socket_->Close();
60 socket_ = NULL;
63 if (adapter_.get()) {
64 adapter_->RemoveObserver(this);
65 adapter_ = NULL;
69 void BluetoothControllerPairingController::DeviceFound(
70 device::BluetoothDevice* device) {
71 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
72 DCHECK(thread_checker_.CalledOnValidThread());
73 if (base::StartsWith(device->GetName(), base::ASCIIToUTF16(kDeviceNamePrefix),
74 base::CompareCase::INSENSITIVE_ASCII)) {
75 discovered_devices_.insert(device->GetAddress());
76 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
77 DiscoveredDevicesListChanged());
81 void BluetoothControllerPairingController::DeviceLost(
82 device::BluetoothDevice* device) {
83 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
84 DCHECK(thread_checker_.CalledOnValidThread());
85 std::set<std::string>::iterator ix =
86 discovered_devices_.find(device->GetAddress());
87 if (ix != discovered_devices_.end()) {
88 discovered_devices_.erase(ix);
89 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
90 DiscoveredDevicesListChanged());
94 void BluetoothControllerPairingController::SendBuffer(
95 scoped_refptr<net::IOBuffer> io_buffer, int size) {
96 socket_->Send(
97 io_buffer, size,
98 base::Bind(&BluetoothControllerPairingController::OnSendComplete,
99 ptr_factory_.GetWeakPtr()),
100 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
101 ptr_factory_.GetWeakPtr()));
104 void BluetoothControllerPairingController::OnSetPowered() {
105 DCHECK(thread_checker_.CalledOnValidThread());
106 adapter_->StartDiscoverySession(
107 base::Bind(&BluetoothControllerPairingController::OnStartDiscoverySession,
108 ptr_factory_.GetWeakPtr()),
109 base::Bind(&BluetoothControllerPairingController::OnError,
110 ptr_factory_.GetWeakPtr()));
113 void BluetoothControllerPairingController::OnGetAdapter(
114 scoped_refptr<device::BluetoothAdapter> adapter) {
115 DCHECK(thread_checker_.CalledOnValidThread());
116 DCHECK(!adapter_.get());
117 adapter_ = adapter;
118 adapter_->AddObserver(this);
120 if (adapter_->IsPowered()) {
121 OnSetPowered();
122 } else {
123 adapter_->SetPowered(
124 true,
125 base::Bind(&BluetoothControllerPairingController::OnSetPowered,
126 ptr_factory_.GetWeakPtr()),
127 base::Bind(&BluetoothControllerPairingController::OnError,
128 ptr_factory_.GetWeakPtr()));
132 void BluetoothControllerPairingController::OnStartDiscoverySession(
133 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
134 DCHECK(thread_checker_.CalledOnValidThread());
135 discovery_session_ = discovery_session.Pass();
136 ChangeStage(STAGE_DEVICES_DISCOVERY);
138 for (const auto& device : adapter_->GetDevices())
139 DeviceFound(device);
142 void BluetoothControllerPairingController::OnConnect() {
143 DCHECK(thread_checker_.CalledOnValidThread());
144 device::BluetoothDevice* device = GetController();
145 if (device) {
146 device->ConnectToService(
147 device::BluetoothUUID(kPairingServiceUUID),
148 base::Bind(&BluetoothControllerPairingController::OnConnectToService,
149 ptr_factory_.GetWeakPtr()),
150 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
151 ptr_factory_.GetWeakPtr()));
155 void BluetoothControllerPairingController::OnConnectToService(
156 scoped_refptr<device::BluetoothSocket> socket) {
157 DCHECK(thread_checker_.CalledOnValidThread());
158 socket_ = socket;
160 socket_->Receive(
161 kReceiveSize,
162 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
163 ptr_factory_.GetWeakPtr()),
164 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
165 ptr_factory_.GetWeakPtr()));
166 ChangeStage(STAGE_PAIRING_DONE);
169 void BluetoothControllerPairingController::OnSendComplete(int bytes_sent) {}
171 void BluetoothControllerPairingController::OnReceiveComplete(
172 int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
173 DCHECK(thread_checker_.CalledOnValidThread());
174 proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
176 socket_->Receive(
177 kReceiveSize,
178 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
179 ptr_factory_.GetWeakPtr()),
180 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
181 ptr_factory_.GetWeakPtr()));
184 void BluetoothControllerPairingController::OnError() {
185 LOG(ERROR) << "Pairing initialization failed";
186 ChangeStage(STAGE_INITIALIZATION_ERROR);
187 Reset();
190 void BluetoothControllerPairingController::OnErrorWithMessage(
191 const std::string& message) {
192 LOG(ERROR) << message;
193 ChangeStage(STAGE_INITIALIZATION_ERROR);
194 Reset();
197 void BluetoothControllerPairingController::OnConnectError(
198 device::BluetoothDevice::ConnectErrorCode error_code) {
199 DCHECK(thread_checker_.CalledOnValidThread());
200 device::BluetoothDevice* device = GetController();
202 if (device && device->IsPaired()) {
203 // The connection attempt is only used to start the pairing between the
204 // devices. If the connection fails, it's not a problem as long as pairing
205 // was successful.
206 OnConnect();
207 } else {
208 // This can happen if the confirmation dialog times out.
209 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR);
213 void BluetoothControllerPairingController::OnReceiveError(
214 device::BluetoothSocket::ErrorReason reason,
215 const std::string& error_message) {
216 LOG(ERROR) << reason << ", " << error_message;
217 Reset();
220 void BluetoothControllerPairingController::AddObserver(
221 ControllerPairingController::Observer* observer) {
222 observers_.AddObserver(observer);
225 void BluetoothControllerPairingController::RemoveObserver(
226 ControllerPairingController::Observer* observer) {
227 observers_.RemoveObserver(observer);
230 ControllerPairingController::Stage
231 BluetoothControllerPairingController::GetCurrentStage() {
232 return current_stage_;
235 void BluetoothControllerPairingController::StartPairing() {
236 DCHECK(thread_checker_.CalledOnValidThread());
237 DCHECK(current_stage_ == STAGE_NONE ||
238 current_stage_ == STAGE_DEVICE_NOT_FOUND ||
239 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
240 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
241 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
242 ChangeStage(STAGE_INITIALIZATION_ERROR);
243 return;
246 device::BluetoothAdapterFactory::GetAdapter(
247 base::Bind(&BluetoothControllerPairingController::OnGetAdapter,
248 ptr_factory_.GetWeakPtr()));
252 ControllerPairingController::DeviceIdList
253 BluetoothControllerPairingController::GetDiscoveredDevices() {
254 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
255 return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end());
258 void BluetoothControllerPairingController::ChooseDeviceForPairing(
259 const std::string& device_id) {
260 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
261 DCHECK(discovered_devices_.count(device_id));
262 discovery_session_.reset();
263 controller_device_id_ = device_id;
265 device::BluetoothDevice* device = GetController();
267 if (device) {
268 ChangeStage(STAGE_ESTABLISHING_CONNECTION);
269 if (device->IsPaired()) {
270 OnConnect();
271 } else {
272 device->Connect(
273 this,
274 base::Bind(&BluetoothControllerPairingController::OnConnect,
275 ptr_factory_.GetWeakPtr()),
276 base::Bind(&BluetoothControllerPairingController::OnConnectError,
277 ptr_factory_.GetWeakPtr()));
282 void BluetoothControllerPairingController::RepeatDiscovery() {
283 DCHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND ||
284 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
285 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
286 Reset();
287 StartPairing();
290 std::string BluetoothControllerPairingController::GetConfirmationCode() {
291 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
292 DCHECK(!confirmation_code_.empty());
293 return confirmation_code_;
296 void BluetoothControllerPairingController::SetConfirmationCodeIsCorrect(
297 bool correct) {
298 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
300 device::BluetoothDevice* device = GetController();
301 if (!device)
302 return;
304 if (correct) {
305 device->ConfirmPairing();
306 // Once pairing is confirmed, the connection will either be successful, or
307 // fail. Either case is acceptable as long as the devices are paired.
308 } else {
309 device->RejectPairing();
310 controller_device_id_.clear();
311 RepeatDiscovery();
315 void BluetoothControllerPairingController::SetHostConfiguration(
316 bool accepted_eula,
317 const std::string& lang,
318 const std::string& timezone,
319 bool send_reports,
320 const std::string& keyboard_layout) {
321 VLOG(1) << "SetHostConfiguration lang=" << lang
322 << ", timezone=" << timezone
323 << ", keyboard_layout=" << keyboard_layout;
325 pairing_api::ConfigureHost host_config;
326 host_config.set_api_version(kPairingAPIVersion);
327 host_config.mutable_parameters()->set_accepted_eula(accepted_eula);
328 host_config.mutable_parameters()->set_lang(lang);
329 host_config.mutable_parameters()->set_timezone(timezone);
330 host_config.mutable_parameters()->set_send_reports(send_reports);
331 host_config.mutable_parameters()->set_keyboard_layout(keyboard_layout);
333 int size = 0;
334 scoped_refptr<net::IOBuffer> io_buffer(
335 ProtoDecoder::SendConfigureHost(host_config, &size));
337 SendBuffer(io_buffer, size);
340 void BluetoothControllerPairingController::OnAuthenticationDone(
341 const std::string& domain,
342 const std::string& auth_token) {
343 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CREDENTIALS);
345 pairing_api::PairDevices pair_devices;
346 pair_devices.set_api_version(kPairingAPIVersion);
347 pair_devices.mutable_parameters()->set_admin_access_token(auth_token);
349 int size = 0;
350 scoped_refptr<net::IOBuffer> io_buffer(
351 ProtoDecoder::SendPairDevices(pair_devices, &size));
353 SendBuffer(io_buffer, size);
354 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS);
357 void BluetoothControllerPairingController::StartSession() {
358 DCHECK_EQ(current_stage_, STAGE_HOST_ENROLLMENT_SUCCESS);
359 ChangeStage(STAGE_FINISHED);
362 void BluetoothControllerPairingController::OnHostStatusMessage(
363 const pairing_api::HostStatus& message) {
364 pairing_api::HostStatusParameters::UpdateStatus update_status =
365 message.parameters().update_status();
366 pairing_api::HostStatusParameters::EnrollmentStatus enrollment_status =
367 message.parameters().enrollment_status();
368 VLOG(1) << "OnHostStatusMessage, update_status=" << update_status;
369 // TODO(zork): Check domain. (http://crbug.com/405761)
370 if (enrollment_status ==
371 pairing_api::HostStatusParameters::ENROLLMENT_STATUS_SUCCESS) {
372 // TODO(achuith, zork): Need to ensure that controller has also successfully
373 // enrolled.
374 CompleteSetup();
375 } else if (update_status ==
376 pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATING) {
377 ChangeStage(STAGE_HOST_UPDATE_IN_PROGRESS);
378 } else if (update_status ==
379 pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATED) {
380 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
384 void BluetoothControllerPairingController::CompleteSetup() {
385 pairing_api::CompleteSetup complete_setup;
386 complete_setup.set_api_version(kPairingAPIVersion);
387 // TODO(zork): Get AddAnother from UI (http://crbug.com/405757)
388 complete_setup.mutable_parameters()->set_add_another(false);
390 int size = 0;
391 scoped_refptr<net::IOBuffer> io_buffer(
392 ProtoDecoder::SendCompleteSetup(complete_setup, &size));
394 SendBuffer(io_buffer, size);
395 ChangeStage(STAGE_HOST_ENROLLMENT_SUCCESS);
398 void BluetoothControllerPairingController::OnConfigureHostMessage(
399 const pairing_api::ConfigureHost& message) {
400 NOTREACHED();
403 void BluetoothControllerPairingController::OnPairDevicesMessage(
404 const pairing_api::PairDevices& message) {
405 NOTREACHED();
408 void BluetoothControllerPairingController::OnCompleteSetupMessage(
409 const pairing_api::CompleteSetup& message) {
410 NOTREACHED();
413 void BluetoothControllerPairingController::OnErrorMessage(
414 const pairing_api::Error& message) {
415 LOG(ERROR) << message.parameters().code() << ", " <<
416 message.parameters().description();
417 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
420 void BluetoothControllerPairingController::OnAddNetworkMessage(
421 const pairing_api::AddNetwork& message) {
422 NOTREACHED();
425 void BluetoothControllerPairingController::DeviceAdded(
426 device::BluetoothAdapter* adapter,
427 device::BluetoothDevice* device) {
428 DCHECK_EQ(adapter, adapter_.get());
429 DeviceFound(device);
432 void BluetoothControllerPairingController::DeviceRemoved(
433 device::BluetoothAdapter* adapter,
434 device::BluetoothDevice* device) {
435 DCHECK_EQ(adapter, adapter_.get());
436 DeviceLost(device);
439 void BluetoothControllerPairingController::RequestPinCode(
440 device::BluetoothDevice* device) {
441 // Disallow unknown device.
442 device->RejectPairing();
445 void BluetoothControllerPairingController::RequestPasskey(
446 device::BluetoothDevice* device) {
447 // Disallow unknown device.
448 device->RejectPairing();
451 void BluetoothControllerPairingController::DisplayPinCode(
452 device::BluetoothDevice* device,
453 const std::string& pincode) {
454 // Disallow unknown device.
455 device->RejectPairing();
458 void BluetoothControllerPairingController::DisplayPasskey(
459 device::BluetoothDevice* device,
460 uint32 passkey) {
461 // Disallow unknown device.
462 device->RejectPairing();
465 void BluetoothControllerPairingController::KeysEntered(
466 device::BluetoothDevice* device,
467 uint32 entered) {
468 // Disallow unknown device.
469 device->RejectPairing();
472 void BluetoothControllerPairingController::ConfirmPasskey(
473 device::BluetoothDevice* device,
474 uint32 passkey) {
475 confirmation_code_ = base::StringPrintf("%06d", passkey);
476 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
479 void BluetoothControllerPairingController::AuthorizePairing(
480 device::BluetoothDevice* device) {
481 // Disallow unknown device.
482 device->RejectPairing();
485 } // namespace pairing_chromeos