Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: components/pairing/bluetooth_controller_pairing_controller.cc

Issue 469613002: Add bluetooth host and controller delegates for pairing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Code review fixes Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 char* kFakeEnrollmentDomain = "http://fake.com";
20 const int kReceiveSize = 16384;
21 }
22
23 namespace pairing_chromeos {
24
25 BluetoothControllerPairingController::BluetoothControllerPairingController()
26 : current_stage_(STAGE_NONE),
27 got_initial_status_(false),
28 proto_decoder_(new ProtoDecoder(this)),
29 ptr_factory_(this) {
30 }
31
32 BluetoothControllerPairingController::~BluetoothControllerPairingController() {
33 Reset();
34 }
35
36 device::BluetoothDevice* BluetoothControllerPairingController::GetController() {
37 DCHECK(!controller_device_id_.empty());
38 device::BluetoothDevice* device = adapter_->GetDevice(controller_device_id_);
39 if (!device) {
40 LOG(ERROR) << "Lost connection to controller.";
41 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR);
42 }
43
44 return device;
45 }
46
47 void BluetoothControllerPairingController::ChangeStage(Stage new_stage) {
48 if (current_stage_ == new_stage)
49 return;
50 current_stage_ = new_stage;
51 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
52 PairingStageChanged(new_stage));
53 }
54
55 void BluetoothControllerPairingController::Reset() {
56 got_initial_status_ = false;
57 controller_device_id_.clear();
58 discovery_session_.reset();
59
60 if (socket_) {
61 socket_->Close();
62 socket_ = NULL;
63 }
64
65 if (adapter_) {
66 adapter_->RemoveObserver(this);
67 adapter_ = NULL;
68 }
69 }
70
71 void BluetoothControllerPairingController::DeviceFound(
72 device::BluetoothDevice* device) {
73 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
74 DCHECK(thread_checker_.CalledOnValidThread());
75 if (StartsWith(device->GetName(), base::ASCIIToUTF16(kDeviceNamePrefix),
76 false)) {
77 discovered_devices_.insert(device->GetAddress());
78 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
79 DiscoveredDevicesListChanged());
80 }
81 }
82
83 void BluetoothControllerPairingController::DeviceLost(
84 device::BluetoothDevice* device) {
85 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
86 DCHECK(thread_checker_.CalledOnValidThread());
87 std::set<std::string>::iterator ix =
88 discovered_devices_.find(device->GetAddress());
89 if (ix != discovered_devices_.end()) {
90 discovered_devices_.erase(ix);
91 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
92 DiscoveredDevicesListChanged());
93 }
94 }
95
96 void BluetoothControllerPairingController::OnSetPowered() {
97 DCHECK(thread_checker_.CalledOnValidThread());
98 adapter_->StartDiscoverySession(
99 base::Bind(&BluetoothControllerPairingController::OnStartDiscoverySession,
100 ptr_factory_.GetWeakPtr()),
101 base::Bind(&BluetoothControllerPairingController::OnError,
102 ptr_factory_.GetWeakPtr()));
103 }
104
105 void BluetoothControllerPairingController::OnGetAdapter(
106 scoped_refptr<device::BluetoothAdapter> adapter) {
107 DCHECK(thread_checker_.CalledOnValidThread());
108 DCHECK(!adapter_);
109 adapter_ = adapter;
110 adapter_->AddObserver(this);
111
112 if (adapter_->IsPowered()) {
113 OnSetPowered();
114 } else {
115 adapter_->SetPowered(
116 true,
117 base::Bind(&BluetoothControllerPairingController::OnSetPowered,
118 ptr_factory_.GetWeakPtr()),
119 base::Bind(&BluetoothControllerPairingController::OnError,
120 ptr_factory_.GetWeakPtr()));
121 }
122 }
123
124 void BluetoothControllerPairingController::OnStartDiscoverySession(
125 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
126 DCHECK(thread_checker_.CalledOnValidThread());
127 discovery_session_ = discovery_session.Pass();
128 ChangeStage(STAGE_DEVICES_DISCOVERY);
129
130 device::BluetoothAdapter::DeviceList device_list = adapter_->GetDevices();
131 for (device::BluetoothAdapter::DeviceList::iterator ix = device_list.begin();
132 ix != device_list.end(); ++ix) {
133 DeviceFound(*ix);
134 }
135 }
136
137 void BluetoothControllerPairingController::OnConnect() {
138 DCHECK(thread_checker_.CalledOnValidThread());
139 device::BluetoothDevice* device = GetController();
140 if (!device)
achuithb 2014/08/26 19:41:06 Nit: Might just read better to do if (device) {
Zachary Kuznia 2014/08/26 19:47:35 Done.
141 return;
142
143 device->ConnectToService(
144 device::BluetoothUUID(kPairingServiceUUID),
145 base::Bind(&BluetoothControllerPairingController::OnConnectToService,
146 ptr_factory_.GetWeakPtr()),
147 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
148 ptr_factory_.GetWeakPtr()));
149 }
150
151 void BluetoothControllerPairingController::OnConnectToService(
152 scoped_refptr<device::BluetoothSocket> socket) {
153 DCHECK(thread_checker_.CalledOnValidThread());
154 socket_ = socket;
155
156 socket_->Receive(
157 kReceiveSize,
158 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
159 ptr_factory_.GetWeakPtr()),
160 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
161 ptr_factory_.GetWeakPtr()));
162 }
163
164 void BluetoothControllerPairingController::OnSendComplete(int bytes_sent) {}
165
166 void BluetoothControllerPairingController::OnReceiveComplete(
167 int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
168 DCHECK(thread_checker_.CalledOnValidThread());
169 proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
170
171 socket_->Receive(
172 kReceiveSize,
173 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
174 ptr_factory_.GetWeakPtr()),
175 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
176 ptr_factory_.GetWeakPtr()));
177 }
178
179 void BluetoothControllerPairingController::OnError() {
180 // TODO(zork): Add a stage for initialization error. (http://crbug.com/405744)
181 LOG(ERROR) << "Pairing initialization failed";
182 Reset();
183 }
184
185 void BluetoothControllerPairingController::OnErrorWithMessage(
186 const std::string& message) {
187 // TODO(zork): Add a stage for initialization error. (http://crbug.com/405744)
188 LOG(ERROR) << message;
189 Reset();
190 }
191
192 void BluetoothControllerPairingController::OnConnectError(
193 device::BluetoothDevice::ConnectErrorCode error_code) {
194 DCHECK(thread_checker_.CalledOnValidThread());
195 device::BluetoothDevice* device = GetController();
196
197 if (device && device->IsPaired()) {
198 // The connection attempt is only used to start the pairing between the
199 // devices. If the connection fails, it's not a problem as long as pairing
200 // was successful.
201 OnConnect();
202 }
203 }
204
205 void BluetoothControllerPairingController::OnReceiveError(
206 device::BluetoothSocket::ErrorReason reason,
207 const std::string& error_message) {
208 LOG(ERROR) << reason << ", " << error_message;
209 Reset();
210 }
211
212 void BluetoothControllerPairingController::AddObserver(
213 ControllerPairingController::Observer* observer) {
214 observers_.AddObserver(observer);
215 }
216
217 void BluetoothControllerPairingController::RemoveObserver(
218 ControllerPairingController::Observer* observer) {
219 observers_.RemoveObserver(observer);
220 }
221
222 ControllerPairingController::Stage
223 BluetoothControllerPairingController::GetCurrentStage() {
224 return current_stage_;
225 }
226
227 void BluetoothControllerPairingController::StartPairing() {
228 DCHECK(thread_checker_.CalledOnValidThread());
229 DCHECK(current_stage_ == STAGE_NONE ||
230 current_stage_ == STAGE_DEVICE_NOT_FOUND ||
231 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
232 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
233 // TODO(zork): Add a stage for no bluetooth. (http://crbug.com/405744)
234 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
235 ChangeStage(STAGE_DEVICE_NOT_FOUND);
236 return;
237 }
238
239 device::BluetoothAdapterFactory::GetAdapter(
240 base::Bind(&BluetoothControllerPairingController::OnGetAdapter,
241 ptr_factory_.GetWeakPtr()));
242
243 }
244
245 ControllerPairingController::DeviceIdList
246 BluetoothControllerPairingController::GetDiscoveredDevices() {
247 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
248 return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end());
249 }
250
251 void BluetoothControllerPairingController::ChooseDeviceForPairing(
252 const std::string& device_id) {
253 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
254 DCHECK(discovered_devices_.count(device_id));
255 discovery_session_.reset();
256 controller_device_id_ = device_id;
257
258 device::BluetoothDevice* device = GetController();
259
260 if (device) {
261 ChangeStage(STAGE_ESTABLISHING_CONNECTION);
262 if (device->IsPaired()) {
263 OnConnect();
264 } else {
265 device->Connect(
266 this,
267 base::Bind(&BluetoothControllerPairingController::OnConnect,
268 ptr_factory_.GetWeakPtr()),
269 base::Bind(&BluetoothControllerPairingController::OnConnectError,
270 ptr_factory_.GetWeakPtr()));
271 }
272 }
273 }
274
275 void BluetoothControllerPairingController::RepeatDiscovery() {
276 DCHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND ||
277 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
278 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
279 Reset();
280 StartPairing();
281 }
282
283 std::string BluetoothControllerPairingController::GetConfirmationCode() {
284 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
285 DCHECK(!confirmation_code_.empty());
286 return confirmation_code_;
287 }
288
289 void BluetoothControllerPairingController::SetConfirmationCodeIsCorrect(
290 bool correct) {
291 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
292
293 device::BluetoothDevice* device = GetController();
294 if (!device)
295 return;
296
297 if (correct) {
298 device->ConfirmPairing();
299 // Once pairing is confirmed, the connection will either be successful, or
300 // fail. Either case is acceptable as long as the devices are paired.
301 } else {
302 device->RejectPairing();
303 controller_device_id_.clear();
304 RepeatDiscovery();
305 }
306 }
307
308 void BluetoothControllerPairingController::OnAuthenticationDone(
309 const chromeos::UserContext& user_context,
310 content::BrowserContext* browser_context) {
311 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CREDENTIALS);
312
313 // TODO(zork): Get configuration from UI and send to Host.
314 // (http://crbug.com/405744)
315
316 // TODO(zork): Get proper credentials. (http://crbug.com/405744)
317 // For now, send a fake domain.
318 pairing_api::PairDevices pair_devices;
319 pair_devices.set_api_version(kPairingAPIVersion);
320 pair_devices.mutable_parameters()->set_admin_access_token(
321 kFakeEnrollmentDomain);
322
323 int size = 0;
324 scoped_refptr<net::IOBuffer> io_buffer(
325 ProtoDecoder::SendPairDevices(pair_devices, &size));
326
327 socket_->Send(
328 io_buffer, size,
329 base::Bind(&BluetoothControllerPairingController::OnSendComplete,
330 ptr_factory_.GetWeakPtr()),
331 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
332 ptr_factory_.GetWeakPtr()));
333 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS);
334 }
335
336 void BluetoothControllerPairingController::StartSession() {
337 DCHECK_EQ(current_stage_, STAGE_PAIRING_DONE);
338 ChangeStage(STAGE_FINISHED);
339 }
340
341 // ProtoDecoder::Observer:
342 void BluetoothControllerPairingController::OnHostStatusMessage(
343 const pairing_api::HostStatus& message) {
344 if (got_initial_status_) {
345 if (message.parameters().has_domain()) {
346 // TODO(zork): Remove this if we don't actually need the domain for UI.
347 // (http://crbug.com/405761)
348 if (message.parameters().domain() == kFakeEnrollmentDomain) {
349 pairing_api::CompleteSetup complete_setup;
350 complete_setup.set_api_version(kPairingAPIVersion);
351 // TODO(zork): Get AddAnother from UI (http://crbug.com/405757)
352 complete_setup.mutable_parameters()->set_add_another(false);
353
354 int size = 0;
355 scoped_refptr<net::IOBuffer> io_buffer(
356 ProtoDecoder::SendCompleteSetup(complete_setup, &size));
357
358 socket_->Send(
359 io_buffer, size,
360 base::Bind(&BluetoothControllerPairingController::OnSendComplete,
361 ptr_factory_.GetWeakPtr()),
362 base::Bind(
363 &BluetoothControllerPairingController::OnErrorWithMessage,
364 ptr_factory_.GetWeakPtr()));
365 ChangeStage(STAGE_PAIRING_DONE);
366 } else {
367 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
368 }
369 } else {
370 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
371 }
372 } else {
373 got_initial_status_ = true;
374
375 // TODO(zork): Check domain. (http://crbug.com/405761)
376
377 // TODO(zork): Handling updating stages (http://crbug.com/405754).
378 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
379 }
380 }
381
382 void BluetoothControllerPairingController::OnConfigureHostMessage(
383 const pairing_api::ConfigureHost& message) {
384 NOTREACHED();
385 }
386
387 void BluetoothControllerPairingController::OnPairDevicesMessage(
388 const pairing_api::PairDevices& message) {
389 NOTREACHED();
390 }
391
392 void BluetoothControllerPairingController::OnCompleteSetupMessage(
393 const pairing_api::CompleteSetup& message) {
394 NOTREACHED();
395 }
396
397 void BluetoothControllerPairingController::OnErrorMessage(
398 const pairing_api::Error& message) {
399 LOG(ERROR) << message.parameters().code() << ", " <<
400 message.parameters().description();
401 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
402 }
403
404 void BluetoothControllerPairingController::DeviceAdded(
405 device::BluetoothAdapter* adapter,
406 device::BluetoothDevice* device) {
407 DCHECK_EQ(adapter, adapter_.get());
408 DeviceFound(device);
409 }
410
411 void BluetoothControllerPairingController::DeviceRemoved(
412 device::BluetoothAdapter* adapter,
413 device::BluetoothDevice* device) {
414 DCHECK_EQ(adapter, adapter_.get());
415 DeviceLost(device);
416 }
417
418 void BluetoothControllerPairingController::RequestPinCode(
419 device::BluetoothDevice* device) {
420 // Disallow unknown device.
421 device->RejectPairing();
422 }
423
424 void BluetoothControllerPairingController::RequestPasskey(
425 device::BluetoothDevice* device) {
426 // Disallow unknown device.
427 device->RejectPairing();
428 }
429
430 void BluetoothControllerPairingController::DisplayPinCode(
431 device::BluetoothDevice* device,
432 const std::string& pincode) {
433 // Disallow unknown device.
434 device->RejectPairing();
435 }
436
437 void BluetoothControllerPairingController::DisplayPasskey(
438 device::BluetoothDevice* device,
439 uint32 passkey) {
440 // Disallow unknown device.
441 device->RejectPairing();
442 }
443
444 void BluetoothControllerPairingController::KeysEntered(
445 device::BluetoothDevice* device,
446 uint32 entered) {
447 // Disallow unknown device.
448 device->RejectPairing();
449 }
450
451 void BluetoothControllerPairingController::ConfirmPasskey(
452 device::BluetoothDevice* device,
453 uint32 passkey) {
454 confirmation_code_ = base::StringPrintf("%06d", passkey);
455 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
456 }
457
458 void BluetoothControllerPairingController::AuthorizePairing(
459 device::BluetoothDevice* device) {
460 // Disallow unknown device.
461 device->RejectPairing();
462 }
463
464 } // namespace pairing_chromeos
OLDNEW
« no previous file with comments | « components/pairing/bluetooth_controller_pairing_controller.h ('k') | components/pairing/bluetooth_host_pairing_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698