Fix closure compiler errors in options.
[chromium-blink-merge.git] / components / pairing / bluetooth_host_pairing_controller.cc
blob5a8c8aab255b192e6d909dfb3b07586a3700c3b4
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_host_pairing_controller.h"
7 #include "base/bind.h"
8 #include "base/hash.h"
9 #include "base/logging.h"
10 #include "base/strings/stringprintf.h"
11 #include "components/pairing/bluetooth_pairing_constants.h"
12 #include "components/pairing/pairing_api.pb.h"
13 #include "components/pairing/proto_decoder.h"
14 #include "device/bluetooth/bluetooth_adapter_factory.h"
15 #include "net/base/io_buffer.h"
17 namespace pairing_chromeos {
19 namespace {
20 const int kReceiveSize = 16384;
22 pairing_api::HostStatusParameters::UpdateStatus PairingApiUpdateStatus(
23 HostPairingController::UpdateStatus update_status) {
24 switch(update_status) {
25 case HostPairingController::UPDATE_STATUS_UNKNOWN:
26 return pairing_api::HostStatusParameters::UPDATE_STATUS_UNKNOWN;
27 case HostPairingController::UPDATE_STATUS_UPDATING:
28 return pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATING;
29 case HostPairingController::UPDATE_STATUS_REBOOTING:
30 return pairing_api::HostStatusParameters::UPDATE_STATUS_REBOOTING;
31 case HostPairingController::UPDATE_STATUS_UPDATED:
32 return pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATED;
33 default:
34 NOTREACHED();
35 return pairing_api::HostStatusParameters::UPDATE_STATUS_UNKNOWN;
39 pairing_api::HostStatusParameters::EnrollmentStatus PairingApiEnrollmentStatus(
40 HostPairingController::EnrollmentStatus enrollment_status) {
41 switch(enrollment_status) {
42 case HostPairingController::ENROLLMENT_STATUS_UNKNOWN:
43 return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_UNKNOWN;
44 case HostPairingController::ENROLLMENT_STATUS_ENROLLING:
45 return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_ENROLLING;
46 case HostPairingController::ENROLLMENT_STATUS_FAILURE:
47 return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_FAILURE;
48 case HostPairingController::ENROLLMENT_STATUS_SUCCESS:
49 return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_SUCCESS;
50 default:
51 NOTREACHED();
52 return pairing_api::HostStatusParameters::ENROLLMENT_STATUS_UNKNOWN;
56 } // namespace
58 BluetoothHostPairingController::BluetoothHostPairingController()
59 : current_stage_(STAGE_NONE),
60 update_status_(UPDATE_STATUS_UNKNOWN),
61 enrollment_status_(ENROLLMENT_STATUS_UNKNOWN),
62 device_(NULL),
63 proto_decoder_(new ProtoDecoder(this)),
64 ptr_factory_(this) {
67 BluetoothHostPairingController::~BluetoothHostPairingController() {
68 if (adapter_.get()) {
69 if (adapter_->IsDiscoverable()) {
70 adapter_->SetDiscoverable(false, base::Closure(), base::Closure());
72 adapter_->RemoveObserver(this);
73 adapter_ = NULL;
77 void BluetoothHostPairingController::ChangeStage(Stage new_stage) {
78 if (current_stage_ == new_stage)
79 return;
80 VLOG(1) << "ChangeStage " << new_stage;
81 current_stage_ = new_stage;
82 FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage));
85 void BluetoothHostPairingController::SendHostStatus() {
86 pairing_api::HostStatus host_status;
88 host_status.set_api_version(kPairingAPIVersion);
89 if (!enrollment_domain_.empty())
90 host_status.mutable_parameters()->set_domain(enrollment_domain_);
92 // TODO(zork): Get these values from the UI. (http://crbug.com/405744)
93 host_status.mutable_parameters()->set_connectivity(
94 pairing_api::HostStatusParameters::CONNECTIVITY_CONNECTED);
95 host_status.mutable_parameters()->set_update_status(
96 PairingApiUpdateStatus(update_status_));
97 host_status.mutable_parameters()->set_enrollment_status(
98 PairingApiEnrollmentStatus(enrollment_status_));
100 // TODO(zork): Get a list of other paired controllers.
101 // (http://crbug.com/405757)
103 int size = 0;
104 scoped_refptr<net::IOBuffer> io_buffer(
105 ProtoDecoder::SendHostStatus(host_status, &size));
107 controller_socket_->Send(
108 io_buffer, size,
109 base::Bind(&BluetoothHostPairingController::OnSendComplete,
110 ptr_factory_.GetWeakPtr()),
111 base::Bind(&BluetoothHostPairingController::OnSendError,
112 ptr_factory_.GetWeakPtr()));
115 void BluetoothHostPairingController::AbortWithError(
116 int code,
117 const std::string& message) {
118 if (controller_socket_.get()) {
119 pairing_api::Error error;
121 error.set_api_version(kPairingAPIVersion);
122 error.mutable_parameters()->set_code(PAIRING_ERROR_PAIRING_OR_ENROLLMENT);
123 error.mutable_parameters()->set_description(message);
125 int size = 0;
126 scoped_refptr<net::IOBuffer> io_buffer(
127 ProtoDecoder::SendError(error, &size));
129 controller_socket_->Send(
130 io_buffer, size,
131 base::Bind(&BluetoothHostPairingController::OnSendComplete,
132 ptr_factory_.GetWeakPtr()),
133 base::Bind(&BluetoothHostPairingController::OnSendError,
134 ptr_factory_.GetWeakPtr()));
136 Reset();
139 void BluetoothHostPairingController::Reset() {
140 if (controller_socket_.get()) {
141 controller_socket_->Close();
142 controller_socket_ = NULL;
145 if (service_socket_.get()) {
146 service_socket_->Close();
147 service_socket_ = NULL;
149 ChangeStage(STAGE_NONE);
152 void BluetoothHostPairingController::OnGetAdapter(
153 scoped_refptr<device::BluetoothAdapter> adapter) {
154 DCHECK(thread_checker_.CalledOnValidThread());
155 DCHECK(!adapter_.get());
156 adapter_ = adapter;
158 if (adapter_->IsPresent()) {
159 SetName();
160 } else {
161 // Set the name once the adapter is present.
162 adapter_->AddObserver(this);
166 void BluetoothHostPairingController::SetName() {
167 // Hash the bluetooth address and take the lower 2 bytes to create a human
168 // readable device name.
169 const uint32 device_id = base::Hash(adapter_->GetAddress()) & 0xFFFF;
170 device_name_ = base::StringPrintf("%s%04X", kDeviceNamePrefix, device_id);
172 adapter_->SetName(
173 device_name_,
174 base::Bind(&BluetoothHostPairingController::OnSetName,
175 ptr_factory_.GetWeakPtr()),
176 base::Bind(&BluetoothHostPairingController::OnSetError,
177 ptr_factory_.GetWeakPtr()));
180 void BluetoothHostPairingController::OnSetName() {
181 DCHECK(thread_checker_.CalledOnValidThread());
182 if (adapter_->IsPowered()) {
183 OnSetPowered();
184 } else {
185 adapter_->SetPowered(
186 true,
187 base::Bind(&BluetoothHostPairingController::OnSetPowered,
188 ptr_factory_.GetWeakPtr()),
189 base::Bind(&BluetoothHostPairingController::OnSetError,
190 ptr_factory_.GetWeakPtr()));
194 void BluetoothHostPairingController::OnSetPowered() {
195 DCHECK(thread_checker_.CalledOnValidThread());
196 adapter_->AddPairingDelegate(
197 this, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
199 device::BluetoothAdapter::ServiceOptions options;
200 options.name.reset(new std::string(kPairingServiceName));
202 adapter_->CreateRfcommService(
203 device::BluetoothUUID(kPairingServiceUUID), options,
204 base::Bind(&BluetoothHostPairingController::OnCreateService,
205 ptr_factory_.GetWeakPtr()),
206 base::Bind(&BluetoothHostPairingController::OnCreateServiceError,
207 ptr_factory_.GetWeakPtr()));
210 void BluetoothHostPairingController::OnCreateService(
211 scoped_refptr<device::BluetoothSocket> socket) {
212 DCHECK(thread_checker_.CalledOnValidThread());
213 service_socket_ = socket;
215 service_socket_->Accept(
216 base::Bind(&BluetoothHostPairingController::OnAccept,
217 ptr_factory_.GetWeakPtr()),
218 base::Bind(&BluetoothHostPairingController::OnAcceptError,
219 ptr_factory_.GetWeakPtr()));
221 adapter_->SetDiscoverable(
222 true,
223 base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
224 ptr_factory_.GetWeakPtr(), true),
225 base::Bind(&BluetoothHostPairingController::OnSetError,
226 ptr_factory_.GetWeakPtr()));
229 void BluetoothHostPairingController::OnAccept(
230 const device::BluetoothDevice* device,
231 scoped_refptr<device::BluetoothSocket> socket) {
232 DCHECK(thread_checker_.CalledOnValidThread());
233 adapter_->SetDiscoverable(
234 false,
235 base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
236 ptr_factory_.GetWeakPtr(), false),
237 base::Bind(&BluetoothHostPairingController::OnSetError,
238 ptr_factory_.GetWeakPtr()));
240 controller_socket_ = socket;
241 service_socket_ = NULL;
243 SendHostStatus();
245 controller_socket_->Receive(
246 kReceiveSize,
247 base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
248 ptr_factory_.GetWeakPtr()),
249 base::Bind(&BluetoothHostPairingController::OnReceiveError,
250 ptr_factory_.GetWeakPtr()));
253 void BluetoothHostPairingController::OnSetDiscoverable(bool change_stage) {
254 DCHECK(thread_checker_.CalledOnValidThread());
255 if (change_stage) {
256 DCHECK_EQ(current_stage_, STAGE_NONE);
257 ChangeStage(STAGE_WAITING_FOR_CONTROLLER);
261 void BluetoothHostPairingController::OnSendComplete(int bytes_sent) {}
263 void BluetoothHostPairingController::OnReceiveComplete(
264 int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
265 DCHECK(thread_checker_.CalledOnValidThread());
266 proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
268 controller_socket_->Receive(
269 kReceiveSize,
270 base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
271 ptr_factory_.GetWeakPtr()),
272 base::Bind(&BluetoothHostPairingController::OnReceiveError,
273 ptr_factory_.GetWeakPtr()));
276 void BluetoothHostPairingController::OnCreateServiceError(
277 const std::string& message) {
278 LOG(ERROR) << message;
279 ChangeStage(STAGE_INITIALIZATION_ERROR);
282 void BluetoothHostPairingController::OnSetError() {
283 adapter_->RemovePairingDelegate(this);
284 ChangeStage(STAGE_INITIALIZATION_ERROR);
287 void BluetoothHostPairingController::OnAcceptError(
288 const std::string& error_message) {
289 LOG(ERROR) << error_message;
292 void BluetoothHostPairingController::OnSendError(
293 const std::string& error_message) {
294 LOG(ERROR) << error_message;
297 void BluetoothHostPairingController::OnReceiveError(
298 device::BluetoothSocket::ErrorReason reason,
299 const std::string& error_message) {
300 LOG(ERROR) << reason << ", " << error_message;
303 void BluetoothHostPairingController::OnHostStatusMessage(
304 const pairing_api::HostStatus& message) {
305 NOTREACHED();
308 void BluetoothHostPairingController::OnConfigureHostMessage(
309 const pairing_api::ConfigureHost& message) {
310 FOR_EACH_OBSERVER(Observer, observers_,
311 ConfigureHost(message.parameters().accepted_eula(),
312 message.parameters().lang(),
313 message.parameters().timezone(),
314 message.parameters().send_reports(),
315 message.parameters().keyboard_layout()));
318 void BluetoothHostPairingController::OnPairDevicesMessage(
319 const pairing_api::PairDevices& message) {
320 DCHECK(thread_checker_.CalledOnValidThread());
321 ChangeStage(STAGE_ENROLLING);
322 FOR_EACH_OBSERVER(Observer, observers_,
323 EnrollHost(message.parameters().admin_access_token()));
326 void BluetoothHostPairingController::OnCompleteSetupMessage(
327 const pairing_api::CompleteSetup& message) {
328 DCHECK(thread_checker_.CalledOnValidThread());
329 if (current_stage_ != STAGE_ENROLLMENT_SUCCESS) {
330 AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorInvalidProtocol);
331 return;
334 // TODO(zork): Handle adding another controller. (http://crbug.com/405757)
335 ChangeStage(STAGE_FINISHED);
338 void BluetoothHostPairingController::OnErrorMessage(
339 const pairing_api::Error& message) {
340 NOTREACHED();
343 void BluetoothHostPairingController::AdapterPresentChanged(
344 device::BluetoothAdapter* adapter,
345 bool present) {
346 DCHECK_EQ(adapter, adapter_.get());
347 if (present) {
348 adapter_->RemoveObserver(this);
349 SetName();
353 void BluetoothHostPairingController::AddObserver(Observer* observer) {
354 observers_.AddObserver(observer);
357 void BluetoothHostPairingController::RemoveObserver(Observer* observer) {
358 observers_.RemoveObserver(observer);
361 HostPairingController::Stage BluetoothHostPairingController::GetCurrentStage() {
362 return current_stage_;
365 void BluetoothHostPairingController::StartPairing() {
366 DCHECK_EQ(current_stage_, STAGE_NONE);
367 bool bluetooth_available =
368 device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
369 if (!bluetooth_available) {
370 ChangeStage(STAGE_INITIALIZATION_ERROR);
371 return;
374 device::BluetoothAdapterFactory::GetAdapter(
375 base::Bind(&BluetoothHostPairingController::OnGetAdapter,
376 ptr_factory_.GetWeakPtr()));
379 std::string BluetoothHostPairingController::GetDeviceName() {
380 return device_name_;
383 std::string BluetoothHostPairingController::GetConfirmationCode() {
384 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
385 return confirmation_code_;
388 std::string BluetoothHostPairingController::GetEnrollmentDomain() {
389 return enrollment_domain_;
392 void BluetoothHostPairingController::OnUpdateStatusChanged(
393 UpdateStatus update_status) {
394 update_status_ = update_status;
395 if (update_status == UPDATE_STATUS_UPDATED)
396 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
397 SendHostStatus();
400 void BluetoothHostPairingController::OnEnrollmentStatusChanged(
401 EnrollmentStatus enrollment_status) {
402 DCHECK_EQ(current_stage_, STAGE_ENROLLING);
403 DCHECK(thread_checker_.CalledOnValidThread());
405 enrollment_status_ = enrollment_status;
406 if (enrollment_status == ENROLLMENT_STATUS_SUCCESS) {
407 ChangeStage(STAGE_ENROLLMENT_SUCCESS);
408 } else if (enrollment_status == ENROLLMENT_STATUS_FAILURE) {
409 AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT,
410 kErrorEnrollmentFailed);
412 SendHostStatus();
415 void BluetoothHostPairingController::RequestPinCode(
416 device::BluetoothDevice* device) {
417 // Disallow unknown device.
418 device->RejectPairing();
421 void BluetoothHostPairingController::RequestPasskey(
422 device::BluetoothDevice* device) {
423 // Disallow unknown device.
424 device->RejectPairing();
427 void BluetoothHostPairingController::DisplayPinCode(
428 device::BluetoothDevice* device,
429 const std::string& pincode) {
430 // Disallow unknown device.
431 device->RejectPairing();
434 void BluetoothHostPairingController::DisplayPasskey(
435 device::BluetoothDevice* device,
436 uint32 passkey) {
437 // Disallow unknown device.
438 device->RejectPairing();
441 void BluetoothHostPairingController::KeysEntered(
442 device::BluetoothDevice* device,
443 uint32 entered) {
444 // Disallow unknown device.
445 device->RejectPairing();
448 void BluetoothHostPairingController::ConfirmPasskey(
449 device::BluetoothDevice* device,
450 uint32 passkey) {
451 // If a new connection is occurring, reset the stage. This can occur if the
452 // pairing times out, or a new controller connects.
453 if (current_stage_ == STAGE_WAITING_FOR_CODE_CONFIRMATION)
454 ChangeStage(STAGE_WAITING_FOR_CONTROLLER);
456 confirmation_code_ = base::StringPrintf("%06d", passkey);
457 device->ConfirmPairing();
458 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
461 void BluetoothHostPairingController::AuthorizePairing(
462 device::BluetoothDevice* device) {
463 // Disallow unknown device.
464 device->RejectPairing();
467 } // namespace pairing_chromeos