Fix build break
[chromium-blink-merge.git] / device / bluetooth / bluetooth_device_chromeos.cc
blob0d87b18694a17de8966d7674aee1cba8e931c8e8
1 // Copyright (c) 2012 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.
5 #include "device/bluetooth/bluetooth_device_chromeos.h"
7 #include <map>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_vector.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/string16.h"
17 #include "base/string_util.h"
18 #include "base/values.h"
19 #include "chromeos/dbus/bluetooth_adapter_client.h"
20 #include "chromeos/dbus/bluetooth_agent_service_provider.h"
21 #include "chromeos/dbus/bluetooth_device_client.h"
22 #include "chromeos/dbus/bluetooth_input_client.h"
23 #include "chromeos/dbus/bluetooth_out_of_band_client.h"
24 #include "chromeos/dbus/dbus_thread_manager.h"
25 #include "chromeos/dbus/introspectable_client.h"
26 #include "dbus/bus.h"
27 #include "dbus/object_path.h"
28 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
29 #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h"
30 #include "device/bluetooth/bluetooth_service_record.h"
31 #include "device/bluetooth/bluetooth_service_record_chromeos.h"
32 #include "device/bluetooth/bluetooth_socket_chromeos.h"
33 #include "device/bluetooth/bluetooth_utils.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
36 using device::BluetoothDevice;
37 using device::BluetoothOutOfBandPairingData;
38 using device::BluetoothServiceRecord;
39 using device::BluetoothSocket;
41 namespace {
43 void DoNothingServiceRecordList(const BluetoothDevice::ServiceRecordList&) {}
45 } // namespace
47 namespace chromeos {
49 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS(
50 BluetoothAdapterChromeOS* adapter)
51 : BluetoothDevice(),
52 adapter_(adapter),
53 bluetooth_class_(0),
54 paired_(false),
55 connected_(false),
56 connectable_(true),
57 connecting_(false),
58 pairing_delegate_(NULL),
59 connecting_applications_counter_(0),
60 connecting_calls_(0),
61 service_records_loaded_(false),
62 weak_ptr_factory_(this) {
65 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
68 uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const {
69 return bluetooth_class_;
72 std::string BluetoothDeviceChromeOS::GetDeviceName() const {
73 return name_;
76 std::string BluetoothDeviceChromeOS::GetAddress() const {
77 return address_;
80 bool BluetoothDeviceChromeOS::IsPaired() const {
81 return paired_;
84 bool BluetoothDeviceChromeOS::IsConnected() const {
85 return connected_;
88 bool BluetoothDeviceChromeOS::IsConnectable() const {
89 return connectable_;
92 bool BluetoothDeviceChromeOS::IsConnecting() const {
93 return connecting_;
96 BluetoothDeviceChromeOS::ServiceList
97 BluetoothDeviceChromeOS::GetServices() const {
98 return service_uuids_;
101 void BluetoothDeviceChromeOS::GetServiceRecords(
102 const ServiceRecordsCallback& callback,
103 const ErrorCallback& error_callback) {
104 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
105 DiscoverServices(
106 object_path_,
107 "", // empty pattern to browse all services
108 base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback,
109 weak_ptr_factory_.GetWeakPtr(),
110 callback,
111 base::Bind(
112 &BluetoothDeviceChromeOS::OnGetServiceRecordsError,
113 weak_ptr_factory_.GetWeakPtr(),
114 callback,
115 error_callback)));
118 void BluetoothDeviceChromeOS::ProvidesServiceWithName(
119 const std::string& name,
120 const ProvidesServiceCallback& callback) {
121 GetServiceRecords(
122 base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameCallback,
123 weak_ptr_factory_.GetWeakPtr(),
124 name,
125 callback),
126 base::Bind(&BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback,
127 weak_ptr_factory_.GetWeakPtr(),
128 callback));
131 bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
132 return !pincode_callback_.is_null();
135 bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
136 return !passkey_callback_.is_null();
139 bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
140 return !confirmation_callback_.is_null();
143 void BluetoothDeviceChromeOS::Connect(
144 PairingDelegate* pairing_delegate,
145 const base::Closure& callback,
146 const ConnectErrorCallback& error_callback) {
147 // This is safe because Connect() and its callbacks are called in the same
148 // thread.
149 connecting_calls_++;
150 connecting_ = !!connecting_calls_;
151 // Set the decrement to be issued when either callback is called.
152 base::Closure wrapped_callback = base::Bind(
153 &BluetoothDeviceChromeOS::OnConnectCallbackCalled,
154 weak_ptr_factory_.GetWeakPtr(),
155 callback);
156 ConnectErrorCallback wrapped_error_callback = base::Bind(
157 &BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled,
158 weak_ptr_factory_.GetWeakPtr(),
159 error_callback);
161 if (IsPaired() || IsConnected()) {
162 // Connection to already paired or connected device.
163 ConnectApplications(wrapped_callback, wrapped_error_callback);
165 } else if (!pairing_delegate) {
166 // No pairing delegate supplied, initiate low-security connection only.
167 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
168 CreateDevice(adapter_->object_path_,
169 address_,
170 base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice,
171 weak_ptr_factory_.GetWeakPtr(),
172 wrapped_callback,
173 wrapped_error_callback),
174 base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError,
175 weak_ptr_factory_.GetWeakPtr(),
176 wrapped_error_callback));
177 } else {
178 // Initiate high-security connection with pairing.
179 DCHECK(!pairing_delegate_);
180 pairing_delegate_ = pairing_delegate;
182 // The agent path is relatively meaningless, we use the device address
183 // to generate it as we only support one pairing attempt at a time for
184 // a given bluetooth device.
185 DCHECK(agent_.get() == NULL);
187 std::string agent_path_basename;
188 ReplaceChars(address_, ":", "_", &agent_path_basename);
189 dbus::ObjectPath agent_path("/org/chromium/bluetooth_agent/" +
190 agent_path_basename);
192 dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
193 if (system_bus) {
194 agent_.reset(BluetoothAgentServiceProvider::Create(system_bus,
195 agent_path,
196 this));
197 } else {
198 agent_.reset(NULL);
201 VLOG(1) << "Pairing: " << address_;
202 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
203 CreatePairedDevice(
204 adapter_->object_path_,
205 address_,
206 agent_path,
207 bluetooth_agent::kDisplayYesNoCapability,
208 base::Bind(&BluetoothDeviceChromeOS::OnCreateDevice,
209 weak_ptr_factory_.GetWeakPtr(),
210 wrapped_callback,
211 wrapped_error_callback),
212 base::Bind(&BluetoothDeviceChromeOS::OnCreateDeviceError,
213 weak_ptr_factory_.GetWeakPtr(),
214 wrapped_error_callback));
218 void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
219 if (!agent_.get() || pincode_callback_.is_null())
220 return;
222 pincode_callback_.Run(SUCCESS, pincode);
223 pincode_callback_.Reset();
226 void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) {
227 if (!agent_.get() || passkey_callback_.is_null())
228 return;
230 passkey_callback_.Run(SUCCESS, passkey);
231 passkey_callback_.Reset();
234 void BluetoothDeviceChromeOS::ConfirmPairing() {
235 if (!agent_.get() || confirmation_callback_.is_null())
236 return;
238 confirmation_callback_.Run(SUCCESS);
239 confirmation_callback_.Reset();
242 void BluetoothDeviceChromeOS::RejectPairing() {
243 if (!agent_.get())
244 return;
246 if (!pincode_callback_.is_null()) {
247 pincode_callback_.Run(REJECTED, "");
248 pincode_callback_.Reset();
250 if (!passkey_callback_.is_null()) {
251 passkey_callback_.Run(REJECTED, 0);
252 passkey_callback_.Reset();
254 if (!confirmation_callback_.is_null()) {
255 confirmation_callback_.Run(REJECTED);
256 confirmation_callback_.Reset();
260 void BluetoothDeviceChromeOS::CancelPairing() {
261 bool have_callback = false;
262 if (agent_.get()) {
263 if (!pincode_callback_.is_null()) {
264 pincode_callback_.Run(CANCELLED, "");
265 pincode_callback_.Reset();
266 have_callback = true;
268 if (!passkey_callback_.is_null()) {
269 passkey_callback_.Run(CANCELLED, 0);
270 passkey_callback_.Reset();
271 have_callback = true;
273 if (!confirmation_callback_.is_null()) {
274 confirmation_callback_.Run(CANCELLED);
275 confirmation_callback_.Reset();
276 have_callback = true;
280 if (!have_callback) {
281 // User cancels the pairing process.
282 DBusThreadManager::Get()->GetBluetoothAdapterClient()->CancelDeviceCreation(
283 adapter_->object_path_,
284 address_,
285 base::Bind(&BluetoothDeviceChromeOS::OnCancelDeviceCreation,
286 weak_ptr_factory_.GetWeakPtr()));
288 pairing_delegate_ = NULL;
289 agent_.reset();
293 void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
294 const ErrorCallback& error_callback) {
295 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
296 Disconnect(object_path_,
297 base::Bind(&BluetoothDeviceChromeOS::DisconnectCallback,
298 weak_ptr_factory_.GetWeakPtr(),
299 callback,
300 error_callback));
304 void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
305 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
306 RemoveDevice(adapter_->object_path_,
307 object_path_,
308 base::Bind(&BluetoothDeviceChromeOS::ForgetCallback,
309 weak_ptr_factory_.GetWeakPtr(),
310 error_callback));
313 void BluetoothDeviceChromeOS::ConnectToService(const std::string& service_uuid,
314 const SocketCallback& callback) {
315 GetServiceRecords(
316 base::Bind(&BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback,
317 weak_ptr_factory_.GetWeakPtr(),
318 service_uuid,
319 callback),
320 base::Bind(
321 &BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback,
322 weak_ptr_factory_.GetWeakPtr(),
323 callback));
326 void BluetoothDeviceChromeOS::SetOutOfBandPairingData(
327 const BluetoothOutOfBandPairingData& data,
328 const base::Closure& callback,
329 const ErrorCallback& error_callback) {
330 DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
331 AddRemoteData(
332 object_path_,
333 address_,
334 data,
335 base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback,
336 weak_ptr_factory_.GetWeakPtr(),
337 callback,
338 error_callback));
341 void BluetoothDeviceChromeOS::ClearOutOfBandPairingData(
342 const base::Closure& callback,
343 const ErrorCallback& error_callback) {
344 DBusThreadManager::Get()->GetBluetoothOutOfBandClient()->
345 RemoveRemoteData(
346 object_path_,
347 address_,
348 base::Bind(&BluetoothDeviceChromeOS::OnRemoteDataCallback,
349 weak_ptr_factory_.GetWeakPtr(),
350 callback,
351 error_callback));
354 void BluetoothDeviceChromeOS::SetObjectPath(
355 const dbus::ObjectPath& object_path) {
356 DCHECK(object_path_ == dbus::ObjectPath(""));
357 object_path_ = object_path;
360 void BluetoothDeviceChromeOS::RemoveObjectPath() {
361 DCHECK(object_path_ != dbus::ObjectPath(""));
362 object_path_ = dbus::ObjectPath("");
365 void BluetoothDeviceChromeOS::Update(
366 const BluetoothDeviceClient::Properties* properties,
367 bool update_state) {
368 std::string address = properties->address.value();
369 std::string name = properties->name.value();
370 uint32 bluetooth_class = properties->bluetooth_class.value();
371 const std::vector<std::string>& uuids = properties->uuids.value();
373 if (!address.empty())
374 address_ = address;
375 if (!name.empty())
376 name_ = name;
377 if (bluetooth_class)
378 bluetooth_class_ = bluetooth_class;
379 if (!uuids.empty()) {
380 service_uuids_.clear();
381 service_uuids_.assign(uuids.begin(), uuids.end());
384 if (update_state) {
385 // When the device reconnects and we don't have any service records for it,
386 // try to update the cache or fail silently.
387 if (!service_records_loaded_ && !connected_ &&
388 properties->connected.value())
389 GetServiceRecords(base::Bind(&DoNothingServiceRecordList),
390 base::Bind(&base::DoNothing));
392 paired_ = properties->paired.value();
393 connected_ = properties->connected.value();
397 void BluetoothDeviceChromeOS::OnCreateDevice(
398 const base::Closure& callback,
399 const ConnectErrorCallback& error_callback,
400 const dbus::ObjectPath& device_path) {
401 VLOG(1) << "Connection successful: " << device_path.value();
402 if (object_path_.value().empty()) {
403 object_path_ = device_path;
404 } else {
405 LOG_IF(WARNING, object_path_ != device_path)
406 << "Conflicting device paths for objects, result gave: "
407 << device_path.value() << " but signal gave: "
408 << object_path_.value();
411 // Mark the device trusted so it can connect to us automatically, and
412 // we can connect after rebooting. This information is part of the
413 // pairing information of the device, and is unique to the combination
414 // of our bluetooth address and the device's bluetooth address. A
415 // different host needs a new pairing, so it's not useful to sync.
416 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
417 GetProperties(object_path_)->trusted.Set(
418 true,
419 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
420 weak_ptr_factory_.GetWeakPtr()));
422 // In parallel with the |trusted| property change, call GetServiceRecords to
423 // retrieve the SDP from the device and then, either on success or failure,
424 // call ConnectApplications.
425 GetServiceRecords(
426 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecords,
427 weak_ptr_factory_.GetWeakPtr(),
428 callback,
429 error_callback),
430 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError,
431 weak_ptr_factory_.GetWeakPtr(),
432 callback,
433 error_callback));
436 void BluetoothDeviceChromeOS::OnCreateDeviceError(
437 const ConnectErrorCallback& error_callback,
438 const std::string& error_name,
439 const std::string& error_message) {
440 // The default |error_code| is an unknown error.
441 ConnectErrorCode error_code = ERROR_UNKNOWN;
443 // Report any error in the log, even if we know the possible source of it.
444 LOG(WARNING) << "Connection failed (on CreatePairedDevice): "
445 << "\"" << name_ << "\" (" << address_ << "): "
446 << error_name << ": \"" << error_message << "\"";
448 // Determines the right error code from error_name, assuming the error name
449 // comes from CreatePairedDevice bluez function.
450 if (error_name == bluetooth_adapter::kErrorConnectionAttemptFailed) {
451 error_code = ERROR_FAILED;
452 } else if (error_name == bluetooth_adapter::kErrorAuthenticationFailed) {
453 error_code = ERROR_AUTH_FAILED;
454 } else if (error_name == bluetooth_adapter::kErrorAuthenticationRejected) {
455 error_code = ERROR_AUTH_REJECTED;
456 } else if (error_name == bluetooth_adapter::kErrorAuthenticationTimeout) {
457 error_code = ERROR_AUTH_TIMEOUT;
459 error_callback.Run(error_code);
462 void BluetoothDeviceChromeOS::CollectServiceRecordsCallback(
463 const ServiceRecordsCallback& callback,
464 const ErrorCallback& error_callback,
465 const dbus::ObjectPath& device_path,
466 const BluetoothDeviceClient::ServiceMap& service_map,
467 bool success) {
468 if (!success) {
469 error_callback.Run();
470 return;
473 // Update the cache. No other thread is executing a GetServiceRecords
474 // callback, so it is safe to delete the previous objects here.
475 service_records_.clear();
476 // TODO(deymo): Perhaps don't update the cache if the new SDP information is
477 // empty and we had something before. Some devices only answer this
478 // information while paired, and this callback could be called in any order if
479 // several calls to GetServiceRecords are made while initial pairing with the
480 // device. This requires more investigation.
481 for (BluetoothDeviceClient::ServiceMap::const_iterator i =
482 service_map.begin(); i != service_map.end(); ++i) {
483 service_records_.push_back(
484 new BluetoothServiceRecordChromeOS(address_, i->second));
486 service_records_loaded_ = true;
488 callback.Run(service_records_);
491 void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
492 LOG_IF(WARNING, !success) << "Failed to set device as trusted: " << address_;
495 void BluetoothDeviceChromeOS::OnInitialGetServiceRecords(
496 const base::Closure& callback,
497 const ConnectErrorCallback& error_callback,
498 const ServiceRecordList& list) {
499 // Connect application-layer protocols.
500 ConnectApplications(callback, error_callback);
503 void BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError(
504 const base::Closure& callback,
505 const ConnectErrorCallback& error_callback) {
506 // Ignore the error retrieving the service records and continue.
507 LOG(WARNING) << "Error retrieving SDP for " << address_ << " after pairing.";
508 // Connect application-layer protocols.
509 ConnectApplications(callback, error_callback);
512 void BluetoothDeviceChromeOS::OnGetServiceRecordsError(
513 const ServiceRecordsCallback& callback,
514 const ErrorCallback& error_callback) {
515 if (service_records_loaded_) {
516 callback.Run(service_records_);
517 } else {
518 error_callback.Run();
522 void BluetoothDeviceChromeOS::OnConnectCallbackCalled(
523 const base::Closure& callback) {
524 // Update the connecting status.
525 connecting_calls_--;
526 connecting_ = !!connecting_calls_;
527 callback.Run();
530 void BluetoothDeviceChromeOS::OnConnectErrorCallbackCalled(
531 const ConnectErrorCallback& error_callback,
532 enum ConnectErrorCode error_code) {
533 // Update the connecting status.
534 connecting_calls_--;
535 connecting_ = !!connecting_calls_;
536 error_callback.Run(error_code);
539 void BluetoothDeviceChromeOS::ConnectApplications(
540 const base::Closure& callback,
541 const ConnectErrorCallback& error_callback) {
542 // Introspect the device object to determine supported applications.
543 DBusThreadManager::Get()->GetIntrospectableClient()->
544 Introspect(bluetooth_device::kBluetoothDeviceServiceName,
545 object_path_,
546 base::Bind(&BluetoothDeviceChromeOS::OnIntrospect,
547 weak_ptr_factory_.GetWeakPtr(),
548 callback,
549 error_callback));
552 void BluetoothDeviceChromeOS::OnIntrospect(
553 const base::Closure& callback,
554 const ConnectErrorCallback& error_callback,
555 const std::string& service_name,
556 const dbus::ObjectPath& device_path,
557 const std::string& xml_data,
558 bool success) {
559 if (!success) {
560 LOG(WARNING) << "Failed to determine supported applications: " << address_;
561 error_callback.Run(ERROR_UNKNOWN);
562 return;
565 // The introspection data for the device object may list one or more
566 // additional D-Bus interfaces that BlueZ supports for this particular
567 // device. Send appropraite Connect calls for each of those interfaces
568 // to connect all of the application protocols for this device.
569 std::vector<std::string> interfaces =
570 IntrospectableClient::GetInterfacesFromIntrospectResult(xml_data);
572 DCHECK_EQ(0, connecting_applications_counter_);
573 connecting_applications_counter_ = 0;
574 for (std::vector<std::string>::iterator iter = interfaces.begin();
575 iter != interfaces.end(); ++iter) {
576 if (*iter == bluetooth_input::kBluetoothInputInterface) {
577 connecting_applications_counter_++;
578 // Supports Input interface.
579 DBusThreadManager::Get()->GetBluetoothInputClient()->
580 Connect(object_path_,
581 base::Bind(&BluetoothDeviceChromeOS::OnConnect,
582 weak_ptr_factory_.GetWeakPtr(),
583 callback,
584 *iter),
585 base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
586 weak_ptr_factory_.GetWeakPtr(),
587 error_callback, *iter));
591 // If OnConnect has been called for every call to Connect above, then this
592 // will decrement the counter to -1. In that case, call the callback
593 // directly as it has not been called by any of the OnConnect callbacks.
594 // This is safe because OnIntrospect and OnConnect run on the same thread.
595 connecting_applications_counter_--;
596 if (connecting_applications_counter_ == -1)
597 callback.Run();
600 void BluetoothDeviceChromeOS::OnConnect(const base::Closure& callback,
601 const std::string& interface_name,
602 const dbus::ObjectPath& device_path) {
603 VLOG(1) << "Application connection successful: " << device_path.value()
604 << ": " << interface_name;
606 connecting_applications_counter_--;
607 // |callback| should only be called once, meaning it cannot be called before
608 // all requests have been started. The extra decrement after all requests
609 // have been started, and the check for -1 instead of 0 below, insure only a
610 // single call to |callback| will occur (provided OnConnect and OnIntrospect
611 // run on the same thread, which is true).
612 if (connecting_applications_counter_ == -1) {
613 connecting_applications_counter_ = 0;
614 callback.Run();
618 void BluetoothDeviceChromeOS::OnConnectError(
619 const ConnectErrorCallback& error_callback,
620 const std::string& interface_name,
621 const dbus::ObjectPath& device_path,
622 const std::string& error_name,
623 const std::string& error_message) {
624 // The default |error_code| is an unknown error.
625 ConnectErrorCode error_code = ERROR_UNKNOWN;
627 // Report any error in the log, even if we know the possible source of it.
628 LOG(WARNING) << "Connection failed (on Connect): "
629 << interface_name << ": "
630 << "\"" << name_ << "\" (" << address_ << "): "
631 << error_name << ": \"" << error_message << "\"";
633 // Determines the right error code from error_name, assuming the error name
634 // comes from Connect bluez function.
635 if (error_name == bluetooth_adapter::kErrorFailed) {
636 error_code = ERROR_FAILED;
637 } else if (error_name == bluetooth_adapter::kErrorInProgress) {
638 error_code = ERROR_INPROGRESS;
639 } else if (error_name == bluetooth_adapter::kErrorNotSupported) {
640 error_code = ERROR_UNSUPPORTED_DEVICE;
643 error_callback.Run(error_code);
646 void BluetoothDeviceChromeOS::DisconnectCallback(
647 const base::Closure& callback,
648 const ErrorCallback& error_callback,
649 const dbus::ObjectPath& device_path,
650 bool success) {
651 DCHECK(device_path == object_path_);
652 if (success) {
653 VLOG(1) << "Disconnection successful: " << address_;
654 callback.Run();
655 } else {
656 if (connected_) {
657 LOG(WARNING) << "Disconnection failed: " << address_;
658 error_callback.Run();
659 } else {
660 VLOG(1) << "Disconnection failed on a already disconnected device: "
661 << address_;
662 callback.Run();
667 void BluetoothDeviceChromeOS::ForgetCallback(
668 const ErrorCallback& error_callback,
669 const dbus::ObjectPath& adapter_path,
670 bool success) {
671 // It's quite normal that this path never gets called on success; we use a
672 // weak pointer, and bluetoothd might send the DeviceRemoved signal before
673 // the method reply, in which case this object is deleted and the
674 // callback never takes place. Therefore don't do anything here for the
675 // success case.
676 if (!success) {
677 LOG(WARNING) << "Forget failed: " << address_;
678 error_callback.Run();
682 void BluetoothDeviceChromeOS::OnCancelDeviceCreation(
683 const dbus::ObjectPath& adapter_path,
684 bool success) {
685 if (!success)
686 LOG(WARNING) << "CancelDeviceCreation failed: " << address_;
689 void BluetoothDeviceChromeOS::SearchServicesForNameErrorCallback(
690 const ProvidesServiceCallback& callback) {
691 callback.Run(false);
694 void BluetoothDeviceChromeOS::SearchServicesForNameCallback(
695 const std::string& name,
696 const ProvidesServiceCallback& callback,
697 const ServiceRecordList& list) {
698 for (ServiceRecordList::const_iterator i = list.begin();
699 i != list.end(); ++i) {
700 if ((*i)->name() == name) {
701 callback.Run(true);
702 return;
705 callback.Run(false);
708 void BluetoothDeviceChromeOS::GetServiceRecordsForConnectErrorCallback(
709 const SocketCallback& callback) {
710 callback.Run(NULL);
713 void BluetoothDeviceChromeOS::GetServiceRecordsForConnectCallback(
714 const std::string& service_uuid,
715 const SocketCallback& callback,
716 const ServiceRecordList& list) {
717 for (ServiceRecordList::const_iterator i = list.begin();
718 i != list.end(); ++i) {
719 if ((*i)->uuid() == service_uuid) {
720 // If multiple service records are found, use the first one that works.
721 scoped_refptr<BluetoothSocket> socket(
722 BluetoothSocketChromeOS::CreateBluetoothSocket(**i));
723 if (socket.get() != NULL) {
724 callback.Run(socket);
725 return;
729 callback.Run(NULL);
732 void BluetoothDeviceChromeOS::OnRemoteDataCallback(
733 const base::Closure& callback,
734 const ErrorCallback& error_callback,
735 bool success) {
736 if (success)
737 callback.Run();
738 else
739 error_callback.Run();
742 void BluetoothDeviceChromeOS::DisconnectRequested(
743 const dbus::ObjectPath& object_path) {
744 DCHECK(object_path == object_path_);
747 void BluetoothDeviceChromeOS::Release() {
748 DCHECK(agent_.get());
749 VLOG(1) << "Release: " << address_;
751 DCHECK(pairing_delegate_);
752 pairing_delegate_->DismissDisplayOrConfirm();
753 pairing_delegate_ = NULL;
755 pincode_callback_.Reset();
756 passkey_callback_.Reset();
757 confirmation_callback_.Reset();
759 agent_.reset();
762 void BluetoothDeviceChromeOS::RequestPinCode(
763 const dbus::ObjectPath& device_path,
764 const PinCodeCallback& callback) {
765 DCHECK(agent_.get());
766 VLOG(1) << "RequestPinCode: " << device_path.value();
768 DCHECK(pairing_delegate_);
769 DCHECK(pincode_callback_.is_null());
770 pincode_callback_ = callback;
771 pairing_delegate_->RequestPinCode(this);
774 void BluetoothDeviceChromeOS::RequestPasskey(
775 const dbus::ObjectPath& device_path,
776 const PasskeyCallback& callback) {
777 DCHECK(agent_.get());
778 DCHECK(device_path == object_path_);
779 VLOG(1) << "RequestPasskey: " << device_path.value();
781 DCHECK(pairing_delegate_);
782 DCHECK(passkey_callback_.is_null());
783 passkey_callback_ = callback;
784 pairing_delegate_->RequestPasskey(this);
787 void BluetoothDeviceChromeOS::DisplayPinCode(
788 const dbus::ObjectPath& device_path,
789 const std::string& pincode) {
790 DCHECK(agent_.get());
791 DCHECK(device_path == object_path_);
792 VLOG(1) << "DisplayPinCode: " << device_path.value() << " " << pincode;
794 DCHECK(pairing_delegate_);
795 pairing_delegate_->DisplayPinCode(this, pincode);
798 void BluetoothDeviceChromeOS::DisplayPasskey(
799 const dbus::ObjectPath& device_path,
800 uint32 passkey) {
801 DCHECK(agent_.get());
802 DCHECK(device_path == object_path_);
803 VLOG(1) << "DisplayPasskey: " << device_path.value() << " " << passkey;
805 DCHECK(pairing_delegate_);
806 pairing_delegate_->DisplayPasskey(this, passkey);
809 void BluetoothDeviceChromeOS::RequestConfirmation(
810 const dbus::ObjectPath& device_path,
811 uint32 passkey,
812 const ConfirmationCallback& callback) {
813 DCHECK(agent_.get());
814 DCHECK(device_path == object_path_);
815 VLOG(1) << "RequestConfirmation: " << device_path.value() << " " << passkey;
817 DCHECK(pairing_delegate_);
818 DCHECK(confirmation_callback_.is_null());
819 confirmation_callback_ = callback;
820 pairing_delegate_->ConfirmPasskey(this, passkey);
823 void BluetoothDeviceChromeOS::Authorize(const dbus::ObjectPath& device_path,
824 const std::string& uuid,
825 const ConfirmationCallback& callback) {
826 DCHECK(agent_.get());
827 DCHECK(device_path == object_path_);
828 LOG(WARNING) << "Rejected authorization for service: " << uuid
829 << " requested from device: " << device_path.value();
830 callback.Run(REJECTED);
833 void BluetoothDeviceChromeOS::ConfirmModeChange(
834 Mode mode,
835 const ConfirmationCallback& callback) {
836 DCHECK(agent_.get());
837 LOG(WARNING) << "Rejected adapter-level mode change: " << mode
838 << " made on agent for device: " << address_;
839 callback.Run(REJECTED);
842 void BluetoothDeviceChromeOS::Cancel() {
843 DCHECK(agent_.get());
844 VLOG(1) << "Cancel: " << address_;
846 DCHECK(pairing_delegate_);
847 pairing_delegate_->DismissDisplayOrConfirm();
851 // static
852 BluetoothDeviceChromeOS* BluetoothDeviceChromeOS::Create(
853 BluetoothAdapterChromeOS* adapter) {
854 return new BluetoothDeviceChromeOS(adapter);
857 } // namespace chromeos