| Index: components/pairing/bluetooth_host_pairing_controller.cc
|
| diff --git a/components/pairing/bluetooth_host_pairing_controller.cc b/components/pairing/bluetooth_host_pairing_controller.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..fc229a14c1a7def1448408212d50ed6b68ed57da
|
| --- /dev/null
|
| +++ b/components/pairing/bluetooth_host_pairing_controller.cc
|
| @@ -0,0 +1,379 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "components/pairing/bluetooth_host_pairing_controller.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/logging.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "components/pairing/bluetooth_pairing_constants.h"
|
| +#include "components/pairing/pairing_api.pb.h"
|
| +#include "components/pairing/proto_decoder.h"
|
| +#include "device/bluetooth/bluetooth_adapter_factory.h"
|
| +#include "net/base/io_buffer.h"
|
| +
|
| +namespace {
|
| +const int kReceiveSize = 16384;
|
| +}
|
| +
|
| +namespace pairing_chromeos {
|
| +
|
| +BluetoothHostPairingController::BluetoothHostPairingController()
|
| + : current_stage_(STAGE_NONE),
|
| + device_(NULL),
|
| + proto_decoder_(new ProtoDecoder(this)),
|
| + ptr_factory_(this) {
|
| +}
|
| +
|
| +BluetoothHostPairingController::~BluetoothHostPairingController() {}
|
| +
|
| +void BluetoothHostPairingController::ChangeStage(Stage new_stage) {
|
| + if (current_stage_ == new_stage)
|
| + return;
|
| + current_stage_ = new_stage;
|
| + FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage));
|
| +}
|
| +
|
| +void BluetoothHostPairingController::SendHostStatus() {
|
| + pairing_api::HostStatus host_status;
|
| +
|
| + host_status.set_api_version(kPairingAPIVersion);
|
| + if (!enrollment_domain_.empty())
|
| + host_status.mutable_parameters()->set_domain(enrollment_domain_);
|
| +
|
| + // TODO(zork): Get these values from the UI. (http://crbug.com/405744)
|
| + host_status.mutable_parameters()->set_connectivity(
|
| + pairing_api::HostStatusParameters::CONNECTIVITY_CONNECTED);
|
| + host_status.mutable_parameters()->set_update_status(
|
| + pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATED);
|
| +
|
| + // TODO(zork): Get a list of other paired controllers.
|
| + // (http://crbug.com/405757)
|
| +
|
| + int size = 0;
|
| + scoped_refptr<net::IOBuffer> io_buffer(
|
| + ProtoDecoder::SendHostStatus(host_status, &size));
|
| +
|
| + controller_socket_->Send(
|
| + io_buffer, size,
|
| + base::Bind(&BluetoothHostPairingController::OnSendComplete,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnSendError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void BluetoothHostPairingController::AbortWithError(
|
| + int code,
|
| + const std::string& message) {
|
| + if (controller_socket_) {
|
| + pairing_api::Error error;
|
| +
|
| + error.set_api_version(kPairingAPIVersion);
|
| + error.mutable_parameters()->set_code(PAIRING_ERROR_PAIRING_OR_ENROLLMENT);
|
| + error.mutable_parameters()->set_description(message);
|
| +
|
| + int size = 0;
|
| + scoped_refptr<net::IOBuffer> io_buffer(
|
| + ProtoDecoder::SendError(error, &size));
|
| +
|
| + controller_socket_->Send(
|
| + io_buffer, size,
|
| + base::Bind(&BluetoothHostPairingController::OnSendComplete,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnSendError,
|
| + ptr_factory_.GetWeakPtr()));
|
| + }
|
| + Reset();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::Reset() {
|
| + if (controller_socket_) {
|
| + controller_socket_->Close();
|
| + controller_socket_ = NULL;
|
| + }
|
| +
|
| + if (service_socket_) {
|
| + service_socket_->Close();
|
| + service_socket_ = NULL;
|
| + }
|
| + ChangeStage(STAGE_NONE);
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnGetAdapter(
|
| + scoped_refptr<device::BluetoothAdapter> adapter) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(!adapter_);
|
| + adapter_ = adapter;
|
| +
|
| + // TODO(zork): Make the device name prettier. (http://crbug.com/405774)
|
| + device_name_ = base::StringPrintf("%s%s", kDeviceNamePrefix,
|
| + adapter_->GetAddress().c_str());
|
| + adapter_->SetName(
|
| + device_name_,
|
| + base::Bind(&BluetoothHostPairingController::OnSetName,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnSetError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnSetName() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (adapter_->IsPowered()) {
|
| + OnSetPowered();
|
| + } else {
|
| + adapter_->SetPowered(
|
| + true,
|
| + base::Bind(&BluetoothHostPairingController::OnSetPowered,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnSetError,
|
| + ptr_factory_.GetWeakPtr()));
|
| + }
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnSetPowered() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + adapter_->AddPairingDelegate(
|
| + this, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
|
| +
|
| + device::BluetoothAdapter::ServiceOptions options;
|
| + options.name.reset(new std::string(kPairingServiceName));
|
| +
|
| + adapter_->CreateRfcommService(
|
| + device::BluetoothUUID(kPairingServiceUUID), options,
|
| + base::Bind(&BluetoothHostPairingController::OnCreateService,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnCreateServiceError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnCreateService(
|
| + scoped_refptr<device::BluetoothSocket> socket) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + service_socket_ = socket;
|
| +
|
| + service_socket_->Accept(
|
| + base::Bind(&BluetoothHostPairingController::OnAccept,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnAcceptError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +
|
| + adapter_->SetDiscoverable(
|
| + true,
|
| + base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
|
| + ptr_factory_.GetWeakPtr(), true),
|
| + base::Bind(&BluetoothHostPairingController::OnSetError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnAccept(
|
| + const device::BluetoothDevice* device,
|
| + scoped_refptr<device::BluetoothSocket> socket) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + adapter_->SetDiscoverable(
|
| + false,
|
| + base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
|
| + ptr_factory_.GetWeakPtr(), false),
|
| + base::Bind(&BluetoothHostPairingController::OnSetError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +
|
| + controller_socket_ = socket;
|
| + service_socket_ = NULL;
|
| +
|
| + // TODO: Update Host. (http://crbug.com/405754)
|
| + SendHostStatus();
|
| +
|
| + controller_socket_->Receive(
|
| + kReceiveSize,
|
| + base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnReceiveError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +
|
| + ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnSetDiscoverable(bool change_stage) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (change_stage) {
|
| + DCHECK_EQ(current_stage_, STAGE_NONE);
|
| + ChangeStage(STAGE_WAITING_FOR_CONTROLLER);
|
| + }
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnSendComplete(int bytes_sent) {}
|
| +
|
| +void BluetoothHostPairingController::OnReceiveComplete(
|
| + int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
|
| +
|
| + controller_socket_->Receive(
|
| + kReceiveSize,
|
| + base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
|
| + ptr_factory_.GetWeakPtr()),
|
| + base::Bind(&BluetoothHostPairingController::OnReceiveError,
|
| + ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnCreateServiceError(
|
| + const std::string& message) {
|
| + LOG(ERROR) << message;
|
| + // TODO(zork): Add a stage for initialization error. (http://crbug.com/405744)
|
| + ChangeStage(STAGE_NONE);
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnSetError() {
|
| + adapter_->RemovePairingDelegate(this);
|
| + // TODO(zork): Add a stage for initialization error. (http://crbug.com/405744)
|
| + ChangeStage(STAGE_NONE);
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnAcceptError(
|
| + const std::string& error_message) {
|
| + LOG(ERROR) << error_message;
|
| + Reset();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnSendError(
|
| + const std::string& error_message) {
|
| + LOG(ERROR) << error_message;
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnReceiveError(
|
| + device::BluetoothSocket::ErrorReason reason,
|
| + const std::string& error_message) {
|
| + LOG(ERROR) << reason << ", " << error_message;
|
| + Reset();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnHostStatusMessage(
|
| + const pairing_api::HostStatus& message) {
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnConfigureHostMessage(
|
| + const pairing_api::ConfigureHost& message) {
|
| + // TODO(zork): Add event to API to handle this case. (http://crbug.com/405744)
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnPairDevicesMessage(
|
| + const pairing_api::PairDevices& message) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (current_stage_ != STAGE_WAITING_FOR_CREDENTIALS) {
|
| + AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorInvalidProtocol);
|
| + return;
|
| + }
|
| +
|
| + ChangeStage(STAGE_ENROLLING);
|
| + // TODO(zork,achuith): Enroll device, send error on error.
|
| + // (http://crbug.com/374990)
|
| + // For now, test domain is sent in the access token.
|
| + enrollment_domain_ = message.parameters().admin_access_token();
|
| + ChangeStage(STAGE_PAIRING_DONE);
|
| + SendHostStatus();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnCompleteSetupMessage(
|
| + const pairing_api::CompleteSetup& message) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (current_stage_ != STAGE_PAIRING_DONE) {
|
| + AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorInvalidProtocol);
|
| + return;
|
| + }
|
| +
|
| + // TODO(zork): Handle adding another controller. (http://crbug.com/405757)
|
| + ChangeStage(STAGE_FINISHED);
|
| +}
|
| +
|
| +void BluetoothHostPairingController::OnErrorMessage(
|
| + const pairing_api::Error& message) {
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::AddObserver(Observer* observer) {
|
| + observers_.AddObserver(observer);
|
| +}
|
| +
|
| +void BluetoothHostPairingController::RemoveObserver(Observer* observer) {
|
| + observers_.RemoveObserver(observer);
|
| +}
|
| +
|
| +HostPairingController::Stage BluetoothHostPairingController::GetCurrentStage() {
|
| + return current_stage_;
|
| +}
|
| +
|
| +void BluetoothHostPairingController::StartPairing() {
|
| + DCHECK_EQ(current_stage_, STAGE_NONE);
|
| + bool bluetooth_available =
|
| + device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
|
| + // TODO(zork): Add a stage for initialization error. (http://crbug.com/405744)
|
| + if (!bluetooth_available)
|
| + return;
|
| +
|
| + device::BluetoothAdapterFactory::GetAdapter(
|
| + base::Bind(&BluetoothHostPairingController::OnGetAdapter,
|
| + ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +std::string BluetoothHostPairingController::GetDeviceName() {
|
| + return device_name_;
|
| +}
|
| +
|
| +std::string BluetoothHostPairingController::GetConfirmationCode() {
|
| + DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
|
| + return confirmation_code_;
|
| +}
|
| +
|
| +std::string BluetoothHostPairingController::GetEnrollmentDomain() {
|
| + return enrollment_domain_;
|
| +}
|
| +
|
| +void BluetoothHostPairingController::RequestPinCode(
|
| + device::BluetoothDevice* device) {
|
| + // Disallow unknown device.
|
| + device->RejectPairing();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::RequestPasskey(
|
| + device::BluetoothDevice* device) {
|
| + // Disallow unknown device.
|
| + device->RejectPairing();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::DisplayPinCode(
|
| + device::BluetoothDevice* device,
|
| + const std::string& pincode) {
|
| + // Disallow unknown device.
|
| + device->RejectPairing();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::DisplayPasskey(
|
| + device::BluetoothDevice* device,
|
| + uint32 passkey) {
|
| + // Disallow unknown device.
|
| + device->RejectPairing();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::KeysEntered(
|
| + device::BluetoothDevice* device,
|
| + uint32 entered) {
|
| + // Disallow unknown device.
|
| + device->RejectPairing();
|
| +}
|
| +
|
| +void BluetoothHostPairingController::ConfirmPasskey(
|
| + device::BluetoothDevice* device,
|
| + uint32 passkey) {
|
| + confirmation_code_ = base::StringPrintf("%06d", passkey);
|
| + device->ConfirmPairing();
|
| + ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
|
| +}
|
| +
|
| +void BluetoothHostPairingController::AuthorizePairing(
|
| + device::BluetoothDevice* device) {
|
| + // Disallow unknown device.
|
| + device->RejectPairing();
|
| +}
|
| +
|
| +} // namespace pairing_chromeos
|
|
|