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

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: 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 : ptr_factory_(this),
27 current_stage_(STAGE_NONE),
28 got_initial_status_(false),
29 device_(NULL),
30 proto_decoder_(new ProtoDecoder(this)) {
31 }
achuithb 2014/08/20 21:52:32 Is this expected to be created and used on the UI
Zachary Kuznia 2014/08/21 00:42:07 Done.
32
33 BluetoothControllerPairingController::~BluetoothControllerPairingController() {
34 Reset();
35 }
36
37 void BluetoothControllerPairingController::ChangeStage(Stage new_stage) {
38 if (current_stage_ == new_stage)
39 return;
40 current_stage_ = new_stage;
41 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
42 PairingStageChanged(new_stage));
43 }
44
45 void BluetoothControllerPairingController::Reset() {
46 got_initial_status_ = false;
47 device_ = NULL;
48 discovery_session_.reset();
49
50 if (socket_) {
51 socket_->Close();
52 socket_ = NULL;
53 }
54
55 if (adapter_) {
56 adapter_->RemoveObserver(this);
57 adapter_ = NULL;
58 }
59 }
60
61 void BluetoothControllerPairingController::DeviceFound(
62 device::BluetoothDevice* device) {
63 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
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 std::set<std::string>::iterator ix =
76 discovered_devices_.find(device->GetAddress());
77 if (ix != discovered_devices_.end()) {
78 discovered_devices_.erase(ix);
79 FOR_EACH_OBSERVER(ControllerPairingController::Observer, observers_,
80 DiscoveredDevicesListChanged());
81 }
82 }
83
84 void BluetoothControllerPairingController::OnSetPowered() {
85 adapter_->StartDiscoverySession(
86 base::Bind(&BluetoothControllerPairingController::OnStartDiscoverySession,
87 ptr_factory_.GetWeakPtr()),
88 base::Bind(&BluetoothControllerPairingController::OnError,
89 ptr_factory_.GetWeakPtr()));
90 }
91
92 void BluetoothControllerPairingController::OnGetAdapter(
93 scoped_refptr<device::BluetoothAdapter> adapter) {
94 CHECK(!adapter_);
95 adapter_ = adapter;
96 adapter_->AddObserver(this);
97
98 if (adapter_->IsPowered()) {
99 OnSetPowered();
100 } else {
101 adapter_->SetPowered(
102 true,
103 base::Bind(&BluetoothControllerPairingController::OnSetPowered,
104 ptr_factory_.GetWeakPtr()),
105 base::Bind(&BluetoothControllerPairingController::OnError,
106 ptr_factory_.GetWeakPtr()));
107 }
108 }
109
110 void BluetoothControllerPairingController::OnStartDiscoverySession(
111 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
112 discovery_session_ = discovery_session.Pass();
113 ChangeStage(STAGE_DEVICES_DISCOVERY);
114
115 device::BluetoothAdapter::DeviceList device_list = adapter_->GetDevices();
116 for (device::BluetoothAdapter::DeviceList::iterator ix = device_list.begin();
117 ix != device_list.end(); ++ix) {
118 DeviceFound(*ix);
119 }
120 }
121
122 void BluetoothControllerPairingController::OnConnect() {
123 device_->ConnectToService(
124 device::BluetoothUUID(kPairingServiceUUID),
125 base::Bind(&BluetoothControllerPairingController::OnConnectToService,
126 ptr_factory_.GetWeakPtr()),
127 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
128 ptr_factory_.GetWeakPtr()));
129 }
130
131 void BluetoothControllerPairingController::OnConnectToService(
132 scoped_refptr<device::BluetoothSocket> socket) {
133 socket_ = socket;
134
135 socket_->Receive(
136 kReceiveSize,
137 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
138 ptr_factory_.GetWeakPtr()),
139 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
140 ptr_factory_.GetWeakPtr()));
141 }
142
143 void BluetoothControllerPairingController::OnSendComplete(int bytes_sent) {}
144
145 void BluetoothControllerPairingController::OnReceiveComplete(
146 int bytes, scoped_refptr<net::IOBuffer> io_buffer) {
147 proto_decoder_->DecodeIOBuffer(bytes, io_buffer);
148
149 socket_->Receive(
150 kReceiveSize,
151 base::Bind(&BluetoothControllerPairingController::OnReceiveComplete,
152 ptr_factory_.GetWeakPtr()),
153 base::Bind(&BluetoothControllerPairingController::OnReceiveError,
154 ptr_factory_.GetWeakPtr()));
155 }
156
157 void BluetoothControllerPairingController::OnError() {
158 ChangeStage(STAGE_DEVICE_NOT_FOUND);
achuithb 2014/08/20 21:52:32 Shouldn't we be logging something here? Why STAGE_
Zachary Kuznia 2014/08/21 00:42:07 Added TODO and explanation.
159 }
160
161 void BluetoothControllerPairingController::OnErrorWithMessage(
162 const std::string& message) {
163 LOG(ERROR) << message;
164 Reset();
achuithb 2014/08/20 21:52:31 Is this the best thing to do? What happens if we r
Zachary Kuznia 2014/08/21 00:42:06 Added TODO and explanation.
165 }
166
167 void BluetoothControllerPairingController::OnConnectError(
168 device::BluetoothDevice::ConnectErrorCode error_code) {
169 if (device_->IsPaired()) {
achuithb 2014/08/20 21:52:32 Could you add some comments here - why is connect
Zachary Kuznia 2014/08/21 00:42:06 Added comment.
170 // Connection error is fine, as long as pairing was successful.
171 OnConnect();
172 } else {
173 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR);
174 }
175 }
176
177 void BluetoothControllerPairingController::OnReceiveError(
178 device::BluetoothSocket::ErrorReason reason,
179 const std::string& error_message) {
180 LOG(ERROR) << reason << ", " << error_message;
181 Reset();
182 }
183
184 // ControllerPairingController:
achuithb 2014/08/20 21:52:32 Remove this comment
Zachary Kuznia 2014/08/21 00:42:06 Done.
185 void BluetoothControllerPairingController::AddObserver(
186 ControllerPairingController::Observer* observer) {
187 observers_.AddObserver(observer);
188 }
189
190 void BluetoothControllerPairingController::RemoveObserver(
191 ControllerPairingController::Observer* observer) {
192 observers_.RemoveObserver(observer);
193 }
194
195 ControllerPairingController::Stage
196 BluetoothControllerPairingController::GetCurrentStage() {
achuithb 2014/08/20 21:52:31 This should be current_stage() and defined in the
Zachary Kuznia 2014/08/21 00:42:06 This is virtual, as discussed.
197 return current_stage_;
198 }
199
200 void BluetoothControllerPairingController::StartPairing() {
201 DCHECK(current_stage_ == STAGE_NONE ||
202 current_stage_ == STAGE_DEVICE_NOT_FOUND ||
203 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
204 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
205 bool bluetooth_available =
achuithb 2014/08/20 21:52:32 This variable seems unnecessary - why not inline i
Zachary Kuznia 2014/08/21 00:42:06 Done.
206 device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
207 // TODO(zork): Add a stage for no bluetooth.
achuithb 2014/08/20 21:52:32 Let's add bug-ids for all TODOs.
Zachary Kuznia 2014/08/21 00:42:07 Done.
208 if (!bluetooth_available)
209 ChangeStage(STAGE_DEVICE_NOT_FOUND);
210
211 device::BluetoothAdapterFactory::GetAdapter(
212 base::Bind(&BluetoothControllerPairingController::OnGetAdapter,
213 ptr_factory_.GetWeakPtr()));
214
215 }
216
217 ControllerPairingController::DeviceIdList
218 BluetoothControllerPairingController::GetDiscoveredDevices() {
219 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
220 return DeviceIdList(discovered_devices_.begin(), discovered_devices_.end());
221 }
222
223 void BluetoothControllerPairingController::ChooseDeviceForPairing(
224 const std::string& device_id) {
225 DCHECK_EQ(current_stage_, STAGE_DEVICES_DISCOVERY);
226 CHECK(discovered_devices_.count(device_id));
achuithb 2014/08/20 21:52:31 Why CHECK?
Zachary Kuznia 2014/08/21 00:42:06 DCHECK now.
227 // TODO: Consider using stop instead of reset().
achuithb 2014/08/20 21:52:33 TODO(zork) + bug-id
Zachary Kuznia 2014/08/21 00:42:06 Done.
228 discovery_session_.reset();
229 device_ = adapter_->GetDevice(device_id);
230 if (device_) {
231 ChangeStage(STAGE_ESTABLISHING_CONNECTION);
232 if (device_->IsPaired()) {
233 OnConnect();
234 } else {
235 device_->Connect(
236 this,
237 base::Bind(&BluetoothControllerPairingController::OnConnect,
238 ptr_factory_.GetWeakPtr()),
239 base::Bind(&BluetoothControllerPairingController::OnConnectError,
240 ptr_factory_.GetWeakPtr()));
241 }
242 } else {
243 ChangeStage(STAGE_ESTABLISHING_CONNECTION_ERROR);
244 }
245 }
246
247 void BluetoothControllerPairingController::RepeatDiscovery() {
248 CHECK(current_stage_ == STAGE_DEVICE_NOT_FOUND ||
achuithb 2014/08/20 21:52:33 Why CHECK and not DCHECK?
Zachary Kuznia 2014/08/21 00:42:06 Done.
249 current_stage_ == STAGE_ESTABLISHING_CONNECTION_ERROR ||
250 current_stage_ == STAGE_HOST_ENROLLMENT_ERROR);
251 Reset();
252 StartPairing();
253 }
254
255 std::string BluetoothControllerPairingController::GetConfirmationCode() {
achuithb 2014/08/20 21:52:32 Return const std::string&
Zachary Kuznia 2014/08/21 00:42:07 This is virtual, as discussed.
256 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
257 DCHECK(!confirmation_code_.empty());
258 return confirmation_code_;
259 }
260
261 void BluetoothControllerPairingController::SetConfirmationCodeIsCorrect(
262 bool correct) {
263 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CODE_CONFIRMATION);
264 if (correct) {
265 device_->ConfirmPairing();
266 // Once pairing is confirmed, the connection will either be successful, or
267 // fail. Either case is acceptable as long as the devices are paired.
268 } else {
269 device_->RejectPairing();
270 device_ = NULL;
271 RepeatDiscovery();
272 }
273 }
274
275 void BluetoothControllerPairingController::OnAuthenticationDone(
276 const chromeos::UserContext& user_context,
277 content::BrowserContext* browser_context) {
278 DCHECK_EQ(current_stage_, STAGE_WAITING_FOR_CREDENTIALS);
279
280 // TODO: Get configuration from UI and send to Host
281
282 // TODO: Get proper credentials.
achuithb 2014/08/20 21:52:33 TODO(zork) + bug-id
Zachary Kuznia 2014/08/21 00:42:06 Done.
283 // For now, send a fake domain.
284 pairing_api::PairDevices pair_devices;
285 pair_devices.set_api_version(kPairingAPIVersion);
286 pair_devices.mutable_parameters()->set_admin_access_token(
287 kFakeEnrollmentDomain);
288
289 int size = 0;
290 scoped_refptr<net::IOBuffer> io_buffer(
291 ProtoDecoder::SendPairDevices(pair_devices, &size));
292
293 socket_->Send(
294 io_buffer, size,
295 base::Bind(&BluetoothControllerPairingController::OnSendComplete,
296 ptr_factory_.GetWeakPtr()),
297 base::Bind(&BluetoothControllerPairingController::OnErrorWithMessage,
298 ptr_factory_.GetWeakPtr()));
299 ChangeStage(STAGE_HOST_ENROLLMENT_IN_PROGRESS);
300 }
301
302 void BluetoothControllerPairingController::StartSession() {
303 DCHECK_EQ(current_stage_, STAGE_PAIRING_DONE);
304 ChangeStage(STAGE_FINISHED);
305 }
306
307 // ProtoDecoder::Observer:
achuithb 2014/08/20 21:52:32 Remove this comment
Zachary Kuznia 2014/08/21 00:42:06 Done.
308 void BluetoothControllerPairingController::OnHostStatusMessage(
309 const pairing_api::HostStatus& message) {
310 if (got_initial_status_) {
311 if (message.parameters().has_domain()) {
312 if (message.parameters().domain() == kFakeEnrollmentDomain) {
achuithb 2014/08/20 21:52:31 Where is this domain supposed to come from?
Zachary Kuznia 2014/08/21 00:42:06 Added a comment to explain.
313 pairing_api::CompleteSetup complete_setup;
314 complete_setup.set_api_version(kPairingAPIVersion);
315 // TODO: Get AddAnother from UI
achuithb 2014/08/20 21:52:32 TODO(zork) + bug-id
Zachary Kuznia 2014/08/21 00:42:06 Done.
316 complete_setup.mutable_parameters()->set_add_another(false);
317
318 int size = 0;
319 scoped_refptr<net::IOBuffer> io_buffer(
320 ProtoDecoder::SendCompleteSetup(complete_setup, &size));
321
322 socket_->Send(
323 io_buffer, size,
324 base::Bind(&BluetoothControllerPairingController::OnSendComplete,
325 ptr_factory_.GetWeakPtr()),
326 base::Bind(
327 &BluetoothControllerPairingController::OnErrorWithMessage,
achuithb 2014/08/20 21:52:31 Should we be retrying?
Zachary Kuznia 2014/08/21 00:42:06 No; if send fails, we'll have to restart the whole
328 ptr_factory_.GetWeakPtr()));
329 ChangeStage(STAGE_PAIRING_DONE);
330 } else {
331 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
332 }
333 } else {
334 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
335 }
336 } else {
337 got_initial_status_ = true;
338
339 // TODO: Check domain.
340
341 // TODO: Handling updating stages.
achuithb 2014/08/20 21:52:32 TODO(zork) + bug-id
Zachary Kuznia 2014/08/21 00:42:07 Done.
342 ChangeStage(STAGE_WAITING_FOR_CREDENTIALS);
343 }
344 }
345
346 void BluetoothControllerPairingController::OnConfigureHostMessage(
347 const pairing_api::ConfigureHost& message) {
348 NOTREACHED();
349 }
350
351 void BluetoothControllerPairingController::OnPairDevicesMessage(
352 const pairing_api::PairDevices& message) {
353 NOTREACHED();
354 }
355
356 void BluetoothControllerPairingController::OnCompleteSetupMessage(
357 const pairing_api::CompleteSetup& message) {
358 NOTREACHED();
359 }
360
361 void BluetoothControllerPairingController::OnErrorMessage(
362 const pairing_api::Error& message) {
363 LOG(ERROR) << message.parameters().code() << ", " <<
364 message.parameters().description();
365 ChangeStage(STAGE_HOST_ENROLLMENT_ERROR);
366 }
367
368 // device::BluetoothAdapter::Observer:
achuithb 2014/08/20 21:52:32 REmove this comment
Zachary Kuznia 2014/08/21 00:42:06 Done.
369 void BluetoothControllerPairingController::DeviceAdded(
370 device::BluetoothAdapter* adapter,
371 device::BluetoothDevice* device) {
372 DCHECK_EQ(adapter, adapter_.get());
373 DeviceFound(device);
374 }
375
376 void BluetoothControllerPairingController::DeviceRemoved(
377 device::BluetoothAdapter* adapter,
378 device::BluetoothDevice* device) {
379 DCHECK_EQ(adapter, adapter_.get());
380 DeviceLost(device);
381 }
382
383 // device::BluetoothDevice::PairingDelegate:
achuithb 2014/08/20 21:52:32 REmove this comment
Zachary Kuznia 2014/08/21 00:42:06 Done.
384 void BluetoothControllerPairingController::RequestPinCode(
385 device::BluetoothDevice* device) {
386 // Disallow unknown device.
387 device->RejectPairing();
388 }
389
390 void BluetoothControllerPairingController::RequestPasskey(
391 device::BluetoothDevice* device) {
392 // Disallow unknown device.
393 device->RejectPairing();
394 }
395
396 void BluetoothControllerPairingController::DisplayPinCode(
397 device::BluetoothDevice* device,
398 const std::string& pincode) {
399 // Disallow unknown device.
400 device->RejectPairing();
401 }
402
403 void BluetoothControllerPairingController::DisplayPasskey(
404 device::BluetoothDevice* device,
405 uint32 passkey) {
406 // Disallow unknown device.
407 device->RejectPairing();
408 }
409
410 void BluetoothControllerPairingController::KeysEntered(
411 device::BluetoothDevice* device,
412 uint32 entered) {
413 // Disallow unknown device.
414 device->RejectPairing();
415 }
416
417 void BluetoothControllerPairingController::ConfirmPasskey(
418 device::BluetoothDevice* device,
419 uint32 passkey) {
420 DCHECK_EQ(device, device_);
421 confirmation_code_ = base::StringPrintf("%06d", passkey);
422 ChangeStage(STAGE_WAITING_FOR_CODE_CONFIRMATION);
423 }
424
425 void BluetoothControllerPairingController::AuthorizePairing(
426 device::BluetoothDevice* device) {
427 // Disallow unknown device.
428 device->RejectPairing();
429 }
430
431 } // namespace pairing_chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698