Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / pairing / bluetooth_controller_pairing_controller.cc
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.
4
5 #include "components/pairing/bluetooth_controller_pairing_controller.h"
6
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"
17
18 namespace {
19 const int kReceiveSize = 16384;
20 }
21
22 namespace pairing_chromeos {
23
24 BluetoothControllerPairingController::BluetoothControllerPairingController()
25     : current_stage_(STAGE_NONE),
26       got_initial_status_(false),
27       proto_decoder_(new ProtoDecoder(this)),
28       ptr_factory_(this) {
29 }
30
31 BluetoothControllerPairingController::~BluetoothControllerPairingController() {
32   Reset();
33 }
34
35 device::BluetoothDevice* BluetoothControllerPairingController::GetController() {
36   DCHECK(!controller_device_id_.empty());
37   device::BluetoothDevice* device = adapter_->GetDevice(controller_device_id_);
38   if (!device) {
39     LOG(ERROR) << "Lost connection to controller.";
40     ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR);
41   }
42
43   return device;
44 }
45
46 void BluetoothControllerPairingController::ChangeStage(Stage new_stage) {
47   if (current_stage_ == new_stage)
48     return;
49   current_stage_ = new_stage;
50   FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
51                     PairingStageChanged(new_stage));
52 }
53
54 void BluetoothControllerPairingController::Reset() {
55   got_initial_status_ = false;
56   controller_device_id_.clear();
57   discovery_session_.reset();
58
59   if (socket_.get()) {
60     socket_->Close();
61     socket_ = NULL;
62   }
63
64   if (adapter_.get()) {
65     adapter_->RemoveObserver(this);
66     adapter_ = NULL;
67   }
68 }
69
70 void BluetoothControllerPairingController::DeviceFound(
71     device::BluetoothDevice* device) {
72   DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
73   DCHECK(thread_checker_.CalledOnValidThread());
74   if (StartsWith(device->GetName(), base::ASCIIToUTF16(kDeviceNamePrefix),
75                  false)) {
76     discovered_devices_.insert(device->GetAddress());
77     FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
78                       DiscoveredDevicesListChanged());
79   }
80 }
81
82 void BluetoothControllerPairingController::DeviceLost(
83     device::BluetoothDevice* device) {
84   DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
85   DCHECK(thread_checker_.CalledOnValidThread());
86   std::set<std::string>::iterator ix =
87       discovered_devices_.find(device->GetAddress());
88   if (ix != discovered_devices_.end()) {
89     discovered_devices_.erase(ix);
90     FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
91                       DiscoveredDevicesListChanged());
92   }
93 }
94
95 void BluetoothControllerPairingController::SendBuffer(
96     scoped_refptr<net::IOBuffer> io_buffer, int size) {
97   socket_->Send(
98       io_buffer, size,
99       base::Bind(&BluetoothControllerPairingController::OnSendComplete,
100                  ptr_factory_.GetWeakPtr()),
101       base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
102                  ptr_factory_.GetWeakPtr()));
103 }
104
105 void BluetoothControllerPairingController::OnSetPowered() {
106   DCHECK(thread_checker_.CalledOnValidThread());
107   adapter_->StartDiscoverySession(
108       base::Bind(&BluetoothControllerPairingController::OnStartDiscoverySession,
109                  ptr_factory_.GetWeakPtr()),
110       base::Bind(&BluetoothControllerPairingController::OnError,
111                  ptr_factory_.GetWeakPtr()));
112 }
113
114 void BluetoothControllerPairingController::OnGetAdapter(
115     scoped_refptr<device::BluetoothAdapter> adapter) {
116   DCHECK(thread_checker_.CalledOnValidThread());
117   DCHECK(!adapter_.get());
118   adapter_ = adapter;
119   adapter_->AddObserver(this);
120
121   if (adapter_->IsPowered()) {
122     OnSetPowered();
123   } else {
124     adapter_->SetPowered(
125         true,
126         base::Bind(&BluetoothControllerPairingController::OnSetPowered,
127                    ptr_factory_.GetWeakPtr()),
128         base::Bind(&BluetoothControllerPairingController::OnError,
129                    ptr_factory_.GetWeakPtr()));
130   }
131 }
132
133 void BluetoothControllerPairingController::OnStartDiscoverySession(
134     scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
135   DCHECK(thread_checker_.CalledOnValidThread());
136   discovery_session_ = discovery_session.Pass();
137   ChangeStage(STAGE_DEVICES_DISCOVERY);
138
139   device::BluetoothAdapter::DeviceList device_list = adapter_->GetDevices();
140   for (device::BluetoothAdapter::DeviceList::iterator ix = device_list.begin();
141        ix != device_list.end(); ++ix) {
142     DeviceFound(*ix);
143   }
144 }
145
146 void BluetoothControllerPairingController::OnConnect() {
147   DCHECK(thread_checker_.CalledOnValidThread());
148   device::BluetoothDevice* device = GetController();
149   if (device) {
150     device->ConnectToService(
151         device::BluetoothUUID(kPairingServiceUUID),
152         base::Bind(&BluetoothControllerPairingController::OnConnectToService,
153                    ptr_factory_.GetWeakPtr()),
154         base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
155                    ptr_factory_.GetWeakPtr()));
156   }
157 }
158
159 void BluetoothControllerPairingController::OnConnectToService(
160     scoped_refptr<device::BluetoothSocket> socket) {
161   DCHECK(thread_checker_.CalledOnValidThread());
162   socket_ = socket;
163
164   socket_->Receive(
165       kReceiveSize,
166       base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
167                  ptr_factory_.GetWeakPtr()),
168       base::Bind(&BluetoothControllerPairingController::OnReceiveError,
169                  ptr_factory_.GetWeakPtr()));
170 }
171
172 void BluetoothControllerPairingController::OnSendComplete(int bytes_sent) {}
173
174 void BluetoothControllerPairingController::OnReceiveComplete(
175     int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
176   DCHECK(thread_checker_.CalledOnValidThread());
177   proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
178
179   socket_->Receive(
180       kReceiveSize,
181       base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
182                  ptr_factory_.GetWeakPtr()),
183       base::Bind(&BluetoothControllerPairingController::OnReceiveError,
184                  ptr_factory_.GetWeakPtr()));
185 }
186
187 void BluetoothControllerPairingController::OnError() {
188   LOG(ERROR) << "Pairing initialization failed";
189   ChangeStage(STAGE_INITIALIZATION_ERROR);
190   Reset();
191 }
192
193 void BluetoothControllerPairingController::OnErrorWithMessage(
194     const std::string& message) {
195   LOG(ERROR) << message;
196   ChangeStage(STAGE_INITIALIZATION_ERROR);
197   Reset();
198 }
199
200 void BluetoothControllerPairingController::OnConnectError(
201     device::BluetoothDevice::ConnectErrorCode error_code) {
202   DCHECK(thread_checker_.CalledOnValidThread());
203   device::BluetoothDevice* device = GetController();
204
205   if (device && device->IsPaired()) {
206     // The connection attempt is only used to start the pairing between the
207     // devices.  If the connection fails, it's not a problem as long as pairing
208     // was successful.
209     OnConnect();
210   }
211 }
212
213 void BluetoothControllerPairingController::OnReceiveError(
214     device::BluetoothSocket::ErrorReason reason,
215     const std::string& error_message) {
216   LOG(ERROR) << reason << ", " << error_message;
217   Reset();
218 }
219
220 void BluetoothControllerPairingController::AddObserver(
221     ControllerPairingController::Observer* observer) {
222   observers_.AddObserver(observer);
223 }
224
225 void BluetoothControllerPairingController::RemoveObserver(
226     ControllerPairingController::Observer* observer) {
227   observers_.RemoveObserver(observer);
228 }
229
230 ControllerPairingController::Stage
231 BluetoothControllerPairingController::GetCurrentStage() {
232   return current_stage_;
233 }
234
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;
244   }
245
246   device::BluetoothAdapterFactory::GetAdapter(
247       base::Bind(&BluetoothControllerPairingController::OnGetAdapter,
248                  ptr_factory_.GetWeakPtr()));
249
250 }
251
252 ControllerPairingController::DeviceIdList
253 BluetoothControllerPairingController::GetDiscoveredDevices() {
254   DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
255   return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end());
256 }
257
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;
264
265   device::BluetoothDevice* device = GetController();
266
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()));
278     }
279   }
280 }
281
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();
288 }
289
290 std::string BluetoothControllerPairingController::GetConfirmationCode() {
291   DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
292   DCHECK(!confirmation_code_.empty());
293   return confirmation_code_;
294 }
295
296 void BluetoothControllerPairingController::SetConfirmationCodeIsCorrect(
297     bool correct) {
298   DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
299
300   device::BluetoothDevice* device = GetController();
301   if (!device)
302     return;
303
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();
312   }
313 }
314
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
322   pairing_api::ConfigureHost host_config;
323   host_config.set_api_version(kPairingAPIVersion);
324   host_config.mutable_parameters()->set_accepted_eula(accepted_eula);
325   host_config.mutable_parameters()->set_lang(lang);
326   host_config.mutable_parameters()->set_timezone(timezone);
327   host_config.mutable_parameters()->set_send_reports(send_reports);
328   host_config.mutable_parameters()->set_keyboard_layout(keyboard_layout);
329
330   int size = 0;
331   scoped_refptr<net::IOBuffer> io_buffer(
332       ProtoDecoder::SendConfigureHost(host_config, &size));
333
334   SendBuffer(io_buffer, size);
335 }
336
337 void BluetoothControllerPairingController::OnAuthenticationDone(
338     const std::string& domain,
339     const std::string& auth_token) {
340   DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CREDENTIALS);
341
342   pairing_api::PairDevices pair_devices;
343   pair_devices.set_api_version(kPairingAPIVersion);
344   pair_devices.mutable_parameters()->set_admin_access_token(auth_token);
345
346   int size = 0;
347   scoped_refptr<net::IOBuffer> io_buffer(
348       ProtoDecoder::SendPairDevices(pair_devices, &size));
349
350   SendBuffer(io_buffer, size);
351   ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS);
352 }
353
354 void BluetoothControllerPairingController::StartSession() {
355   DCHECK_EQ(current_stage_, STAGE_PAIRING_DONE);
356   ChangeStage(STAGE_FINISHED);
357 }
358
359 // ProtoDecoder::Observer:
360 void BluetoothControllerPairingController::OnHostStatusMessage(
361     const pairing_api::HostStatus& message) {
362   if (got_initial_status_) {
363     // TODO(zork): Check that the domain matches. (http://crbug.com/405761)
364     // TODO(zork): Handling updating stages (http://crbug.com/405754).
365     pairing_api::CompleteSetup complete_setup;
366     complete_setup.set_api_version(kPairingAPIVersion);
367     // TODO(zork): Get AddAnother from UI (http://crbug.com/405757)
368     complete_setup.mutable_parameters()->set_add_another(false);
369
370     int size = 0;
371     scoped_refptr<net::IOBuffer> io_buffer(
372         ProtoDecoder::SendCompleteSetup(complete_setup, &size));
373
374     SendBuffer(io_buffer, size);
375     ChangeStage(STAGE_PAIRING_DONE);
376   } else {
377     got_initial_status_ = true;
378
379     // TODO(zork): Check domain. (http://crbug.com/405761)
380     ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
381   }
382 }
383
384 void BluetoothControllerPairingController::OnConfigureHostMessage(
385     const pairing_api::ConfigureHost& message) {
386   NOTREACHED();
387 }
388
389 void BluetoothControllerPairingController::OnPairDevicesMessage(
390     const pairing_api::PairDevices& message) {
391   NOTREACHED();
392 }
393
394 void BluetoothControllerPairingController::OnCompleteSetupMessage(
395     const pairing_api::CompleteSetup& message) {
396   NOTREACHED();
397 }
398
399 void BluetoothControllerPairingController::OnErrorMessage(
400     const pairing_api::Error& message) {
401   LOG(ERROR) << message.parameters().code() << ", " <<
402       message.parameters().description();
403   ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
404 }
405
406 void BluetoothControllerPairingController::DeviceAdded(
407     device::BluetoothAdapter* adapter,
408     device::BluetoothDevice* device) {
409   DCHECK_EQ(adapter, adapter_.get());
410   DeviceFound(device);
411 }
412
413 void BluetoothControllerPairingController::DeviceRemoved(
414     device::BluetoothAdapter* adapter,
415     device::BluetoothDevice* device) {
416   DCHECK_EQ(adapter, adapter_.get());
417   DeviceLost(device);
418 }
419
420 void BluetoothControllerPairingController::RequestPinCode(
421     device::BluetoothDevice* device) {
422   // Disallow unknown device.
423   device->RejectPairing();
424 }
425
426 void BluetoothControllerPairingController::RequestPasskey(
427     device::BluetoothDevice* device) {
428   // Disallow unknown device.
429   device->RejectPairing();
430 }
431
432 void BluetoothControllerPairingController::DisplayPinCode(
433     device::BluetoothDevice* device,
434     const std::string& pincode) {
435   // Disallow unknown device.
436   device->RejectPairing();
437 }
438
439 void BluetoothControllerPairingController::DisplayPasskey(
440     device::BluetoothDevice* device,
441     uint32 passkey) {
442   // Disallow unknown device.
443   device->RejectPairing();
444 }
445
446 void BluetoothControllerPairingController::KeysEntered(
447     device::BluetoothDevice* device,
448     uint32 entered) {
449   // Disallow unknown device.
450   device->RejectPairing();
451 }
452
453 void BluetoothControllerPairingController::ConfirmPasskey(
454     device::BluetoothDevice* device,
455     uint32 passkey) {
456   confirmation_code_ = base::StringPrintf("%06d", passkey);
457   ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
458 }
459
460 void BluetoothControllerPairingController::AuthorizePairing(
461     device::BluetoothDevice* device) {
462   // Disallow unknown device.
463   device->RejectPairing();
464 }
465
466 }  // namespace pairing_chromeos