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

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