Chromium Code Reviews| Index: device/bluetooth/bluetooth_adapter_experimental_chromeos.cc |
| diff --git a/device/bluetooth/bluetooth_adapter_experimental_chromeos.cc b/device/bluetooth/bluetooth_adapter_experimental_chromeos.cc |
| index 8cdfb9618629b15a7c977c7fe4f889893e837602..eb8c1da7f084fe55c249d9853e68c1f1263a1486 100644 |
| --- a/device/bluetooth/bluetooth_adapter_experimental_chromeos.cc |
| +++ b/device/bluetooth/bluetooth_adapter_experimental_chromeos.cc |
| @@ -6,32 +6,77 @@ |
| #include <string> |
| +#include "base/bind.h" |
| +#include "base/logging.h" |
| +#include "chromeos/dbus/dbus_thread_manager.h" |
| +#include "chromeos/dbus/experimental_bluetooth_adapter_client.h" |
| +#include "chromeos/dbus/experimental_bluetooth_device_client.h" |
| +#include "device/bluetooth/bluetooth_device.h" |
| +#include "device/bluetooth/bluetooth_device_experimental_chromeos.h" |
| + |
| using device::BluetoothAdapter; |
| +using device::BluetoothDevice; |
| namespace chromeos { |
| BluetoothAdapterExperimentalChromeOS::BluetoothAdapterExperimentalChromeOS() |
| - : BluetoothAdapter(), |
| - weak_ptr_factory_(this) { |
| + : weak_ptr_factory_(this) { |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + AddObserver(this); |
| + DBusThreadManager::Get()->GetExperimentalBluetoothDeviceClient()-> |
| + AddObserver(this); |
| + |
| + std::vector<dbus::ObjectPath> object_paths = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetAdapters(); |
| + |
| + if (!object_paths.empty()) { |
| + VLOG(1) << object_paths.size() << " Bluetooth adapter(s) available."; |
| + SetAdapter(object_paths[0]); |
| + } |
| } |
| BluetoothAdapterExperimentalChromeOS::~BluetoothAdapterExperimentalChromeOS() { |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + RemoveObserver(this); |
| + DBusThreadManager::Get()->GetExperimentalBluetoothDeviceClient()-> |
| + RemoveObserver(this); |
| } |
| void BluetoothAdapterExperimentalChromeOS::AddObserver( |
| BluetoothAdapter::Observer* observer) { |
| + DCHECK(observer); |
| + observers_.AddObserver(observer); |
| } |
| void BluetoothAdapterExperimentalChromeOS::RemoveObserver( |
| BluetoothAdapter::Observer* observer) { |
| + DCHECK(observer); |
| + observers_.RemoveObserver(observer); |
| } |
| std::string BluetoothAdapterExperimentalChromeOS::GetAddress() const { |
| - return std::string(); |
| + if (object_path_.value().empty()) |
| + return std::string(); |
| + |
| + ExperimentalBluetoothAdapterClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_); |
| + DCHECK(properties); |
| + |
| + return properties->address.value(); |
| } |
| std::string BluetoothAdapterExperimentalChromeOS::GetName() const { |
| - return std::string(); |
| + if (object_path_.value().empty()) |
| + return std::string(); |
| + |
| + ExperimentalBluetoothAdapterClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_); |
| + DCHECK(properties); |
| + |
| + return properties->alias.value(); |
| } |
| bool BluetoothAdapterExperimentalChromeOS::IsInitialized() const { |
| @@ -39,33 +84,77 @@ bool BluetoothAdapterExperimentalChromeOS::IsInitialized() const { |
| } |
| bool BluetoothAdapterExperimentalChromeOS::IsPresent() const { |
| - return false; |
| + return !object_path_.value().empty(); |
| } |
| bool BluetoothAdapterExperimentalChromeOS::IsPowered() const { |
| - return false; |
| + if (object_path_.value().empty()) |
|
youngki
2013/04/16 15:26:56
Would it be more elegant if we reuse IsPresent() h
keybuk
2013/04/16 23:19:13
Done.
|
| + return false; |
| + |
| + ExperimentalBluetoothAdapterClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_); |
| + |
| + return properties->powered.value(); |
| } |
| -void BluetoothAdapterExperimentalChromeOS::SetPowered(bool powered, |
| - const base::Closure& callback, |
| - const ErrorCallback& error_callback) { |
| - error_callback.Run(); |
| +void BluetoothAdapterExperimentalChromeOS::SetPowered( |
| + bool powered, |
| + const base::Closure& callback, |
| + const ErrorCallback& error_callback) { |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_)->powered.Set( |
| + powered, |
| + base::Bind(&BluetoothAdapterExperimentalChromeOS::OnSetPowered, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + callback, error_callback)); |
|
youngki
2013/04/16 15:26:56
style nits: one argument per line.
keybuk
2013/04/16 23:19:13
Done.
|
| } |
| bool BluetoothAdapterExperimentalChromeOS::IsDiscovering() const { |
| - return false; |
| + if (object_path_.value().empty()) |
|
youngki
2013/04/16 15:26:56
Can we reuse IsPresent()?
if (!IsPresent())
ret
keybuk
2013/04/16 23:19:13
Done.
|
| + return false; |
| + |
| + ExperimentalBluetoothAdapterClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_); |
| + |
| + return properties->discovering.value(); |
| } |
| void BluetoothAdapterExperimentalChromeOS::StartDiscovering( |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) { |
| - error_callback.Run(); |
| + // BlueZ counts discovery sessions, and permits multiple sessions for a |
| + // single connection, so issue a StartDiscovery() call for every use |
| + // within Chromium for the right behavior. |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + StartDiscovery( |
| + object_path_, |
| + base::Bind( |
| + &BluetoothAdapterExperimentalChromeOS::OnStartDiscovery, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + callback), |
| + base::Bind( |
| + &BluetoothAdapterExperimentalChromeOS::OnStartDiscoveryError, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + error_callback)); |
| } |
| void BluetoothAdapterExperimentalChromeOS::StopDiscovering( |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) { |
| - error_callback.Run(); |
| + // Inform BlueZ to stop one of our open discovery sessions. |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + StopDiscovery( |
| + object_path_, |
| + base::Bind( |
| + &BluetoothAdapterExperimentalChromeOS::OnStopDiscovery, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + callback), |
| + base::Bind( |
| + &BluetoothAdapterExperimentalChromeOS::OnStopDiscoveryError, |
| + weak_ptr_factory_.GetWeakPtr(), |
| + error_callback)); |
| } |
| void BluetoothAdapterExperimentalChromeOS::ReadLocalOutOfBandPairingData( |
| @@ -74,4 +163,228 @@ void BluetoothAdapterExperimentalChromeOS::ReadLocalOutOfBandPairingData( |
| error_callback.Run(); |
| } |
| +void BluetoothAdapterExperimentalChromeOS::AdapterAdded( |
| + const dbus::ObjectPath& object_path) { |
| + if (object_path_.value().empty()) |
|
satorux1
2013/04/16 06:30:45
Did you mean:
if (!object_path_.value().empty())
keybuk
2013/04/16 23:19:13
No, this only sets the adapter if it *isn't* alrea
|
| + SetAdapter(object_path); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::AdapterRemoved( |
| + const dbus::ObjectPath& object_path) { |
| + if (object_path == object_path_) |
| + RemoveAdapter(); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::AdapterPropertyChanged( |
| + const dbus::ObjectPath& object_path, |
| + const std::string& property_name) { |
| + if (object_path != object_path_) |
| + return; |
| + |
| + ExperimentalBluetoothAdapterClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_); |
| + |
| + if (property_name == properties->powered.name()) |
| + PoweredChanged(properties->powered.value()); |
| + else if (property_name == properties->discovering.name()) |
| + DiscoveringChanged(properties->discovering.value()); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::DeviceAdded( |
| + const dbus::ObjectPath& object_path) { |
| + ExperimentalBluetoothDeviceClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothDeviceClient()-> |
| + GetProperties(object_path); |
| + if (properties->adapter.value() != object_path_) |
| + return; |
| + |
| + BluetoothDeviceExperimentalChromeOS* device_chromeos = |
| + new BluetoothDeviceExperimentalChromeOS(this, object_path); |
| + |
|
youngki
2013/04/16 15:26:56
Can we put DCHECK here that devices_[device_chrome
keybuk
2013/04/16 23:19:13
Done.
|
| + devices_[device_chromeos->GetAddress()] = device_chromeos; |
| + |
| + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| + DeviceAdded(this, device_chromeos)); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::DeviceRemoved( |
| + const dbus::ObjectPath& object_path) { |
| + for (DevicesMap::iterator iter = devices_.begin(); |
| + iter != devices_.end(); ++iter) { |
| + BluetoothDeviceExperimentalChromeOS* device_chromeos = |
| + static_cast<BluetoothDeviceExperimentalChromeOS*>(iter->second); |
| + if (device_chromeos->object_path() == object_path) { |
| + devices_.erase(iter); |
| + |
| + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| + DeviceRemoved(this, device_chromeos)); |
| + delete device_chromeos; |
| + return; |
| + } |
| + } |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::DevicePropertyChanged( |
| + const dbus::ObjectPath& object_path, |
| + const std::string& property_name) { |
| + BluetoothDeviceExperimentalChromeOS* device_chromeos = |
| + GetDeviceWithPath(object_path); |
| + if (!device_chromeos) |
| + return; |
| + |
| + ExperimentalBluetoothDeviceClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothDeviceClient()-> |
| + GetProperties(object_path); |
| + |
| + if (property_name == properties->bluetooth_class.name() || |
| + property_name == properties->alias.name() || |
| + property_name == properties->paired.name() || |
| + property_name == properties->connected.name() || |
| + property_name == properties->uuids.name()) { |
| + FOR_EACH_OBSERVER( |
| + BluetoothAdapter::Observer, observers_, |
| + DeviceChanged(this, static_cast<BluetoothDevice*>(device_chromeos))); |
|
youngki
2013/04/16 15:26:56
I don't think this cast is necessary since Bluetoo
keybuk
2013/04/16 23:19:13
Done.
|
| + } |
| +} |
| + |
| +BluetoothDeviceExperimentalChromeOS* |
| +BluetoothAdapterExperimentalChromeOS::GetDeviceWithPath( |
| + const dbus::ObjectPath& object_path) { |
| + for (DevicesMap::iterator iter = devices_.begin(); |
| + iter != devices_.end(); ++iter) { |
| + BluetoothDeviceExperimentalChromeOS* device_chromeos = |
| + static_cast<BluetoothDeviceExperimentalChromeOS*>(iter->second); |
| + if (device_chromeos->object_path() == object_path) |
| + return device_chromeos; |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::SetAdapter( |
| + const dbus::ObjectPath& object_path) |
| +{ |
| + DCHECK(object_path_.value().empty()); |
| + object_path_ = object_path; |
| + |
| + VLOG(1) << object_path_.value() << ": using adapter."; |
| + |
| + ExperimentalBluetoothAdapterClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_); |
| + |
| + PresentChanged(true); |
| + |
| + if (properties->powered.value() != false) |
|
youngki
2013/04/16 15:26:56
change it to if (properties->powered.value())
keybuk
2013/04/16 23:19:13
Done.
|
| + PoweredChanged(properties->powered.value()); |
|
youngki
2013/04/16 15:26:56
Also I think we should just make it PoweredChanged
keybuk
2013/04/16 23:19:13
Done.
|
| + if (properties->discovering.value() != false) |
|
youngki
2013/04/16 15:26:56
change it to if (properties->discovering.value())
keybuk
2013/04/16 23:19:13
Done.
|
| + DiscoveringChanged(properties->discovering.value()); |
|
youngki
2013/04/16 15:26:56
Change it to DiscoveringChanged(true) also.
keybuk
2013/04/16 23:19:13
Done.
|
| + |
| + std::vector<dbus::ObjectPath> device_paths = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothDeviceClient()-> |
| + GetDevicesForAdapter(object_path_); |
| + |
| + for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin(); |
| + iter != device_paths.end(); ++iter) { |
| + BluetoothDeviceExperimentalChromeOS* device_chromeos = |
| + new BluetoothDeviceExperimentalChromeOS(this, *iter); |
| + |
| + devices_[device_chromeos->GetAddress()] = device_chromeos; |
| + |
| + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| + DeviceAdded(this, device_chromeos)); |
| + } |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::RemoveAdapter() |
| +{ |
| + DCHECK(!object_path_.value().empty()); |
|
youngki
2013/04/16 15:26:56
DCHECK(IsPresent());
keybuk
2013/04/16 23:19:13
Done.
|
| + VLOG(1) << object_path_.value() << ": adapter removed."; |
| + |
| + ExperimentalBluetoothAdapterClient::Properties* properties = |
| + DBusThreadManager::Get()->GetExperimentalBluetoothAdapterClient()-> |
| + GetProperties(object_path_); |
| + |
| + object_path_ = dbus::ObjectPath(""); |
| + |
| + if (properties->powered.value() != false) |
|
youngki
2013/04/16 15:26:56
change it to if (properties->powered.value())
keybuk
2013/04/16 23:19:13
Done.
|
| + PoweredChanged(false); |
|
youngki
2013/04/16 15:26:56
Are you sure this logic is right? This looks to me
keybuk
2013/04/16 23:19:13
"if powered was on, the adapter is going buh-bye,
|
| + if (properties->discovering.value() != false) |
|
youngki
2013/04/16 15:26:56
change it to if (properties->discovering.value())
keybuk
2013/04/16 23:19:13
Done.
|
| + DiscoveringChanged(false); |
| + |
| + // Copy the devices list here and clear the original so that when we |
| + // send DeviceRemoved(), GetDevices() returns no devices. |
| + DevicesMap devices = devices_; |
| + devices_.clear(); |
| + |
| + for (DevicesMap::iterator iter = devices.begin(); |
| + iter != devices.end(); ++iter) { |
| + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| + DeviceRemoved(this, iter->second)); |
| + delete iter->second; |
| + } |
| + |
| + PresentChanged(false); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::PoweredChanged(bool powered) |
| +{ |
| + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| + AdapterPoweredChanged(this, powered)); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::DiscoveringChanged(bool discovering) |
| +{ |
| + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| + AdapterDiscoveringChanged(this, discovering)); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::PresentChanged(bool present) |
| +{ |
| + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| + AdapterPresentChanged(this, present)); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::OnSetPowered( |
| + const base::Closure& callback, |
| + const ErrorCallback& error_callback, |
| + bool success) |
| +{ |
|
satorux1
2013/04/16 06:30:45
nit: move { to the previous line
keybuk
2013/04/16 23:19:13
Done.
|
| + if (success) |
| + callback.Run(); |
| + else |
| + error_callback.Run(); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::OnStartDiscovery( |
| + const base::Closure& callback) { |
| + callback.Run(); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::OnStartDiscoveryError( |
| + const ErrorCallback& error_callback, |
| + const std::string& error_name, |
| + const std::string& error_message) |
| +{ |
|
satorux1
2013/04/16 06:30:45
ditto
keybuk
2013/04/16 23:19:13
Done.
|
| + LOG(WARNING) << object_path_.value() << ": Failed to start discovery: " |
| + << error_name << ": " << error_message; |
| + error_callback.Run(); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::OnStopDiscovery( |
| + const base::Closure& callback) { |
| + callback.Run(); |
| +} |
| + |
| +void BluetoothAdapterExperimentalChromeOS::OnStopDiscoveryError( |
| + const ErrorCallback& error_callback, |
| + const std::string& error_name, |
| + const std::string& error_message) |
| +{ |
|
satorux1
2013/04/16 06:30:45
ditto
keybuk
2013/04/16 23:19:13
Done.
|
| + LOG(WARNING) << object_path_.value() << ": Failed to stop discovery: " |
| + << error_name << ": " << error_message; |
| + error_callback.Run(); |
| +} |
| + |
| } // namespace chromeos |