OLD | NEW |
---|---|
(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 | |
OLD | NEW |