[GCM] Investigatory CHECKs for crash in parsing stream
[chromium-blink-merge.git] / components / pairing / bluetooth_host_pairing_controller.cc
blobf30c3ec495b57881607187539d0e5858928a5a56
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 {
18 const int kReceiveSize = 16384;
21 namespace pairing_chromeos {
23 BluetoothHostPairingController::BluetoothHostPairingController()
24 : current_stage_(STAGE_NONE),
25 device_(NULL),
26 proto_decoder_(new ProtoDecoder(this)),
27 ptr_factory_(this) {
30 BluetoothHostPairingController::~BluetoothHostPairingController() {
31 if (adapter_.get())
32 adapter_->RemoveObserver(this);
35 void BluetoothHostPairingController::ChangeStage(Stage new_stage) {
36 if (current_stage_ == new_stage)
37 return;
38 current_stage_ = new_stage;
39 FOR_EACH_OBSERVER(Observer, observers_, PairingStageChanged(new_stage));
42 void BluetoothHostPairingController::SendHostStatus() {
43 pairing_api::HostStatus host_status;
45 host_status.set_api_version(kPairingAPIVersion);
46 if (!enrollment_domain_.empty())
47 host_status.mutable_parameters()->set_domain(enrollment_domain_);
49 // TODO(zork): Get these values from the UI. (http://crbug.com/405744)
50 host_status.mutable_parameters()->set_connectivity(
51 pairing_api::HostStatusParameters::CONNECTIVITY_CONNECTED);
52 host_status.mutable_parameters()->set_update_status(
53 pairing_api::HostStatusParameters::UPDATE_STATUS_UPDATED);
55 // TODO(zork): Get a list of other paired controllers.
56 // (http://crbug.com/405757)
58 int size = 0;
59 scoped_refptr<net::IOBuffer> io_buffer(
60 ProtoDecoder::SendHostStatus(host_status, &size));
62 controller_socket_->Send(
63 io_buffer, size,
64 base::Bind(&BluetoothHostPairingController::OnSendComplete,
65 ptr_factory_.GetWeakPtr()),
66 base::Bind(&BluetoothHostPairingController::OnSendError,
67 ptr_factory_.GetWeakPtr()));
70 void BluetoothHostPairingController::AbortWithError(
71 int code,
72 const std::string& message) {
73 if (controller_socket_.get()) {
74 pairing_api::Error error;
76 error.set_api_version(kPairingAPIVersion);
77 error.mutable_parameters()->set_code(PAIRING_ERROR_PAIRING_OR_ENROLLMENT);
78 error.mutable_parameters()->set_description(message);
80 int size = 0;
81 scoped_refptr<net::IOBuffer> io_buffer(
82 ProtoDecoder::SendError(error, &size));
84 controller_socket_->Send(
85 io_buffer, size,
86 base::Bind(&BluetoothHostPairingController::OnSendComplete,
87 ptr_factory_.GetWeakPtr()),
88 base::Bind(&BluetoothHostPairingController::OnSendError,
89 ptr_factory_.GetWeakPtr()));
91 Reset();
94 void BluetoothHostPairingController::Reset() {
95 if (controller_socket_.get()) {
96 controller_socket_->Close();
97 controller_socket_ = NULL;
100 if (service_socket_.get()) {
101 service_socket_->Close();
102 service_socket_ = NULL;
104 ChangeStage(STAGE_NONE);
107 void BluetoothHostPairingController::OnGetAdapter(
108 scoped_refptr<device::BluetoothAdapter> adapter) {
109 DCHECK(thread_checker_.CalledOnValidThread());
110 DCHECK(!adapter_.get());
111 adapter_ = adapter;
113 if (adapter_->IsPresent()) {
114 SetName();
115 } else {
116 // Set the name once the adapter is present.
117 adapter_->AddObserver(this);
121 void BluetoothHostPairingController::SetName() {
122 // Hash the bluetooth address and take the lower 2 bytes to create a human
123 // readable device name.
124 const uint32 device_id = base::Hash(adapter_->GetAddress()) & 0xFFFF;
125 device_name_ = base::StringPrintf("%s%04X", kDeviceNamePrefix, device_id);
127 adapter_->SetName(
128 device_name_,
129 base::Bind(&BluetoothHostPairingController::OnSetName,
130 ptr_factory_.GetWeakPtr()),
131 base::Bind(&BluetoothHostPairingController::OnSetError,
132 ptr_factory_.GetWeakPtr()));
135 void BluetoothHostPairingController::OnSetName() {
136 DCHECK(thread_checker_.CalledOnValidThread());
137 if (adapter_->IsPowered()) {
138 OnSetPowered();
139 } else {
140 adapter_->SetPowered(
141 true,
142 base::Bind(&BluetoothHostPairingController::OnSetPowered,
143 ptr_factory_.GetWeakPtr()),
144 base::Bind(&BluetoothHostPairingController::OnSetError,
145 ptr_factory_.GetWeakPtr()));
149 void BluetoothHostPairingController::OnSetPowered() {
150 DCHECK(thread_checker_.CalledOnValidThread());
151 adapter_->AddPairingDelegate(
152 this, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
154 device::BluetoothAdapter::ServiceOptions options;
155 options.name.reset(new std::string(kPairingServiceName));
157 adapter_->CreateRfcommService(
158 device::BluetoothUUID(kPairingServiceUUID), options,
159 base::Bind(&BluetoothHostPairingController::OnCreateService,
160 ptr_factory_.GetWeakPtr()),
161 base::Bind(&BluetoothHostPairingController::OnCreateServiceError,
162 ptr_factory_.GetWeakPtr()));
165 void BluetoothHostPairingController::OnCreateService(
166 scoped_refptr<device::BluetoothSocket> socket) {
167 DCHECK(thread_checker_.CalledOnValidThread());
168 service_socket_ = socket;
170 service_socket_->Accept(
171 base::Bind(&BluetoothHostPairingController::OnAccept,
172 ptr_factory_.GetWeakPtr()),
173 base::Bind(&BluetoothHostPairingController::OnAcceptError,
174 ptr_factory_.GetWeakPtr()));
176 adapter_->SetDiscoverable(
177 true,
178 base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
179 ptr_factory_.GetWeakPtr(), true),
180 base::Bind(&BluetoothHostPairingController::OnSetError,
181 ptr_factory_.GetWeakPtr()));
184 void BluetoothHostPairingController::OnAccept(
185 const device::BluetoothDevice* device,
186 scoped_refptr<device::BluetoothSocket> socket) {
187 DCHECK(thread_checker_.CalledOnValidThread());
188 adapter_->SetDiscoverable(
189 false,
190 base::Bind(&BluetoothHostPairingController::OnSetDiscoverable,
191 ptr_factory_.GetWeakPtr(), false),
192 base::Bind(&BluetoothHostPairingController::OnSetError,
193 ptr_factory_.GetWeakPtr()));
195 controller_socket_ = socket;
196 service_socket_ = NULL;
198 // TODO: Update Host. (http://crbug.com/405754)
199 SendHostStatus();
201 controller_socket_->Receive(
202 kReceiveSize,
203 base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
204 ptr_factory_.GetWeakPtr()),
205 base::Bind(&BluetoothHostPairingController::OnReceiveError,
206 ptr_factory_.GetWeakPtr()));
208 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
211 void BluetoothHostPairingController::OnSetDiscoverable(bool change_stage) {
212 DCHECK(thread_checker_.CalledOnValidThread());
213 if (change_stage) {
214 DCHECK_EQ(current_stage_, STAGE_NONE);
215 ChangeStage(STAGE_WAITING_FOR_CONTROLLER);
219 void BluetoothHostPairingController::OnSendComplete(int bytes_sent) {}
221 void BluetoothHostPairingController::OnReceiveComplete(
222 int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
223 DCHECK(thread_checker_.CalledOnValidThread());
224 proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
226 controller_socket_->Receive(
227 kReceiveSize,
228 base::Bind(&BluetoothHostPairingController::OnReceiveComplete,
229 ptr_factory_.GetWeakPtr()),
230 base::Bind(&BluetoothHostPairingController::OnReceiveError,
231 ptr_factory_.GetWeakPtr()));
234 void BluetoothHostPairingController::OnCreateServiceError(
235 const std::string& message) {
236 LOG(ERROR) << message;
237 ChangeStage(STAGE_INITIALIZATION_ERROR);
240 void BluetoothHostPairingController::OnSetError() {
241 adapter_->RemovePairingDelegate(this);
242 ChangeStage(STAGE_INITIALIZATION_ERROR);
245 void BluetoothHostPairingController::OnAcceptError(
246 const std::string& error_message) {
247 LOG(ERROR) << error_message;
248 Reset();
251 void BluetoothHostPairingController::OnSendError(
252 const std::string& error_message) {
253 LOG(ERROR) << error_message;
256 void BluetoothHostPairingController::OnReceiveError(
257 device::BluetoothSocket::ErrorReason reason,
258 const std::string& error_message) {
259 LOG(ERROR) << reason << ", " << error_message;
260 Reset();
263 void BluetoothHostPairingController::OnHostStatusMessage(
264 const pairing_api::HostStatus& message) {
265 NOTREACHED();
268 void BluetoothHostPairingController::OnConfigureHostMessage(
269 const pairing_api::ConfigureHost& message) {
270 FOR_EACH_OBSERVER(Observer, observers_,
271 ConfigureHost(message.parameters().accepted_eula(),
272 message.parameters().lang(),
273 message.parameters().timezone(),
274 message.parameters().send_reports(),
275 message.parameters().keyboard_layout()));
278 void BluetoothHostPairingController::OnPairDevicesMessage(
279 const pairing_api::PairDevices& message) {
280 DCHECK(thread_checker_.CalledOnValidThread());
281 if (current_stage_ != STAGE_WAITING_FOR_CREDENTIALS) {
282 AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorInvalidProtocol);
283 return;
286 ChangeStage(STAGE_ENROLLING);
287 FOR_EACH_OBSERVER(Observer, observers_,
288 EnrollHost(message.parameters().admin_access_token()));
291 void BluetoothHostPairingController::SetEnrollmentComplete(bool success) {
292 DCHECK_EQ(current_stage_, STAGE_ENROLLING);
293 DCHECK(thread_checker_.CalledOnValidThread());
294 if (success) {
295 ChangeStage(STAGE_PAIRING_DONE);
296 SendHostStatus();
297 } else {
298 AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorEnrollmentFailed);
302 void BluetoothHostPairingController::OnCompleteSetupMessage(
303 const pairing_api::CompleteSetup& message) {
304 DCHECK(thread_checker_.CalledOnValidThread());
305 if (current_stage_ != STAGE_PAIRING_DONE) {
306 AbortWithError(PAIRING_ERROR_PAIRING_OR_ENROLLMENT, kErrorInvalidProtocol);
307 return;
310 // TODO(zork): Handle adding another controller. (http://crbug.com/405757)
311 ChangeStage(STAGE_FINISHED);
314 void BluetoothHostPairingController::OnErrorMessage(
315 const pairing_api::Error& message) {
316 NOTREACHED();
319 void BluetoothHostPairingController::AdapterPresentChanged(
320 device::BluetoothAdapter* adapter,
321 bool present) {
322 DCHECK_EQ(adapter, adapter_.get());
323 if (present) {
324 adapter_->RemoveObserver(this);
325 SetName();
329 void BluetoothHostPairingController::AddObserver(Observer* observer) {
330 observers_.AddObserver(observer);
333 void BluetoothHostPairingController::RemoveObserver(Observer* observer) {
334 observers_.RemoveObserver(observer);
337 HostPairingController::Stage BluetoothHostPairingController::GetCurrentStage() {
338 return current_stage_;
341 void BluetoothHostPairingController::StartPairing() {
342 DCHECK_EQ(current_stage_, STAGE_NONE);
343 bool bluetooth_available =
344 device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
345 if (!bluetooth_available) {
346 ChangeStage(STAGE_INITIALIZATION_ERROR);
347 return;
350 device::BluetoothAdapterFactory::GetAdapter(
351 base::Bind(&BluetoothHostPairingController::OnGetAdapter,
352 ptr_factory_.GetWeakPtr()));
355 std::string BluetoothHostPairingController::GetDeviceName() {
356 return device_name_;
359 std::string BluetoothHostPairingController::GetConfirmationCode() {
360 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
361 return confirmation_code_;
364 std::string BluetoothHostPairingController::GetEnrollmentDomain() {
365 return enrollment_domain_;
368 void BluetoothHostPairingController::OnUpdateStatusChanged(
369 UpdateStatus update_status) {
370 // TODO(zork): Handling updating stages (http://crbug.com/405754).
373 void BluetoothHostPairingController::RequestPinCode(
374 device::BluetoothDevice* device) {
375 // Disallow unknown device.
376 device->RejectPairing();
379 void BluetoothHostPairingController::RequestPasskey(
380 device::BluetoothDevice* device) {
381 // Disallow unknown device.
382 device->RejectPairing();
385 void BluetoothHostPairingController::DisplayPinCode(
386 device::BluetoothDevice* device,
387 const std::string& pincode) {
388 // Disallow unknown device.
389 device->RejectPairing();
392 void BluetoothHostPairingController::DisplayPasskey(
393 device::BluetoothDevice* device,
394 uint32 passkey) {
395 // Disallow unknown device.
396 device->RejectPairing();
399 void BluetoothHostPairingController::KeysEntered(
400 device::BluetoothDevice* device,
401 uint32 entered) {
402 // Disallow unknown device.
403 device->RejectPairing();
406 void BluetoothHostPairingController::ConfirmPasskey(
407 device::BluetoothDevice* device,
408 uint32 passkey) {
409 confirmation_code_ = base::StringPrintf("%06d", passkey);
410 device->ConfirmPairing();
411 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
414 void BluetoothHostPairingController::AuthorizePairing(
415 device::BluetoothDevice* device) {
416 // Disallow unknown device.
417 device->RejectPairing();
420 } // namespace pairing_chromeos