OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 "chrome/browser/chromeos/dbus/bluetooth_adapter_client.h" |
| 6 |
| 7 #include <map> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/stl_util.h" |
| 12 #include "chrome/browser/chromeos/system/runtime_environment.h" |
| 13 #include "dbus/bus.h" |
| 14 #include "dbus/message.h" |
| 15 #include "dbus/object_proxy.h" |
| 16 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 17 |
| 18 namespace chromeos { |
| 19 |
| 20 // The BluetoothAdapterClient implementation used in production. |
| 21 class BluetoothAdapterClientImpl: public BluetoothAdapterClient { |
| 22 public: |
| 23 explicit BluetoothAdapterClientImpl(dbus::Bus* bus) |
| 24 : weak_ptr_factory_(this), |
| 25 bus_(bus) { |
| 26 VLOG(1) << "BluetoothAdapterClientImpl ctor"; |
| 27 } |
| 28 |
| 29 virtual ~BluetoothAdapterClientImpl() { |
| 30 proxies_.clear(); |
| 31 } |
| 32 |
| 33 // BluetoothAdapterClient override. |
| 34 virtual void AddObserver(Observer* observer, const std::string& path) { |
| 35 VLOG(1) << "AddObserver: " << path; |
| 36 CHECK(observer != NULL); |
| 37 observers_.AddObserver(observer); |
| 38 AddObjectProxyForPath(path); |
| 39 } |
| 40 |
| 41 // BluetoothAdapterClient override. |
| 42 virtual void RemoveObserver(Observer* observer, const std::string& path) { |
| 43 VLOG(1) << "RemoveObserver: " << path; |
| 44 CHECK(observer != NULL); |
| 45 observers_.RemoveObserver(observer); |
| 46 RemoveObjectProxyForPath(path); |
| 47 } |
| 48 |
| 49 // BluetoothAdapterClient override. |
| 50 virtual void StartDiscovery(const std::string& path) { |
| 51 VLOG(1) << "StartDiscovery: " << path; |
| 52 |
| 53 dbus::MethodCall method_call( |
| 54 bluetooth_adapter::kBluetoothAdapterInterface, |
| 55 bluetooth_adapter::kStartDiscovery); |
| 56 |
| 57 ProxyMap::iterator it = proxies_.find(path); |
| 58 if (it == proxies_.end()) { |
| 59 LOG(ERROR) << "Couldn't find proxy for path " << path; |
| 60 return; |
| 61 } |
| 62 dbus::ObjectProxy* adapter_proxy = |
| 63 static_cast<dbus::ObjectProxy*>(it->second); |
| 64 CHECK(adapter_proxy != NULL); |
| 65 |
| 66 adapter_proxy->CallMethod( |
| 67 &method_call, |
| 68 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 69 base::Bind(&BluetoothAdapterClientImpl::OnStartDiscovery, |
| 70 weak_ptr_factory_.GetWeakPtr(), path)); |
| 71 } |
| 72 |
| 73 // BluetoothAdapterClient override. |
| 74 virtual void StopDiscovery(const std::string& path) { |
| 75 VLOG(1) << "StopDiscovery: " << path; |
| 76 |
| 77 dbus::MethodCall method_call( |
| 78 bluetooth_adapter::kBluetoothAdapterInterface, |
| 79 bluetooth_adapter::kStopDiscovery); |
| 80 |
| 81 ProxyMap::iterator it = proxies_.find(path); |
| 82 if (it == proxies_.end()) { |
| 83 LOG(ERROR) << "Couldn't find proxy for path " << path; |
| 84 return; |
| 85 } |
| 86 dbus::ObjectProxy* adapter_proxy = |
| 87 static_cast<dbus::ObjectProxy*>(it->second); |
| 88 CHECK(adapter_proxy != NULL); |
| 89 |
| 90 adapter_proxy->CallMethod( |
| 91 &method_call, |
| 92 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 93 base::Bind(&BluetoothAdapterClientImpl::OnStopDiscovery, |
| 94 weak_ptr_factory_.GetWeakPtr(), path)); |
| 95 } |
| 96 |
| 97 private: |
| 98 // Gets a dbus object proxy for an adapter with dbus path |path| and stores it |
| 99 // in our |proxies_| map. |
| 100 void AddObjectProxyForPath(const std::string& path) { |
| 101 VLOG(1) << "AddObjectProxyForPath: " << path; |
| 102 |
| 103 CHECK(bus_ != NULL); |
| 104 dbus::ObjectProxy* adapter_proxy = bus_->GetObjectProxy( |
| 105 bluetooth_adapter::kBluetoothAdapterServiceName, path); |
| 106 CHECK(adapter_proxy != NULL); |
| 107 |
| 108 proxies_[path] = adapter_proxy; |
| 109 |
| 110 adapter_proxy->ConnectToSignal( |
| 111 bluetooth_adapter::kBluetoothAdapterInterface, |
| 112 bluetooth_adapter::kPropertyChangedSignal, |
| 113 base::Bind(&BluetoothAdapterClientImpl::PropertyChangedReceived, |
| 114 weak_ptr_factory_.GetWeakPtr(), path), |
| 115 base::Bind(&BluetoothAdapterClientImpl::PropertyChangedConnected, |
| 116 weak_ptr_factory_.GetWeakPtr(), path)); |
| 117 |
| 118 adapter_proxy->ConnectToSignal( |
| 119 bluetooth_adapter::kBluetoothAdapterInterface, |
| 120 bluetooth_adapter::kDeviceFoundSignal, |
| 121 base::Bind(&BluetoothAdapterClientImpl::DeviceFoundReceived, |
| 122 weak_ptr_factory_.GetWeakPtr(), path), |
| 123 base::Bind(&BluetoothAdapterClientImpl::DeviceFoundConnected, |
| 124 weak_ptr_factory_.GetWeakPtr(), path)); |
| 125 |
| 126 adapter_proxy->ConnectToSignal( |
| 127 bluetooth_adapter::kBluetoothAdapterInterface, |
| 128 bluetooth_adapter::kDeviceDisappearedSignal, |
| 129 base::Bind(&BluetoothAdapterClientImpl::DeviceDisappearedReceived, |
| 130 weak_ptr_factory_.GetWeakPtr(), path), |
| 131 base::Bind(&BluetoothAdapterClientImpl::DeviceDisappearedConnected, |
| 132 weak_ptr_factory_.GetWeakPtr(), path)); |
| 133 } |
| 134 |
| 135 // Removes the dbus object proxy for the adapter with dbus path |path| from |
| 136 // our |proxies_| map. |
| 137 void RemoveObjectProxyForPath(const std::string& path) { |
| 138 VLOG(1) << "RemoveObjectProxyForPath: " << path; |
| 139 ProxyMap::iterator it = proxies_.find(path); |
| 140 if (it != proxies_.end()) { |
| 141 proxies_.erase(it); |
| 142 } |
| 143 } |
| 144 |
| 145 // Called by dbus:: when a PropertyChanged signal is received. |
| 146 void PropertyChangedReceived(const std::string& path, dbus::Signal* signal) { |
| 147 CHECK(signal != NULL); |
| 148 dbus::MessageReader reader(signal); |
| 149 std::string name; |
| 150 if (!reader.PopString(&name)) { |
| 151 LOG(ERROR) << path |
| 152 << ": PropertyChanged signal has incorrect parameters: " |
| 153 << signal->ToString(); |
| 154 return; |
| 155 } |
| 156 |
| 157 if (name != bluetooth_adapter::kDiscoveringProperty) { |
| 158 VLOG(1) << path << ": PropertyChanged: " << name; |
| 159 // We don't care. |
| 160 return; |
| 161 } |
| 162 |
| 163 bool discovering; |
| 164 if (!reader.PopVariantOfBool(&discovering)) { |
| 165 LOG(ERROR) << path |
| 166 << ": PropertyChanged signal has incorrect parameters: " |
| 167 << signal->ToString(); |
| 168 return; |
| 169 } |
| 170 VLOG(1) << path << ": PropertyChanged: Discovering = " << discovering; |
| 171 |
| 172 FOR_EACH_OBSERVER(Observer, observers_, |
| 173 DiscoveringPropertyChanged(path, discovering)); |
| 174 } |
| 175 |
| 176 // Called by dbus:: when the PropertyChanged signal is initially connected. |
| 177 void PropertyChangedConnected(const std::string& path, |
| 178 const std::string& interface_name, |
| 179 const std::string& signal_name, |
| 180 bool success) { |
| 181 LOG_IF(WARNING, !success) << path |
| 182 << ": Failed to connect to PropertyChanged signal."; |
| 183 } |
| 184 |
| 185 // Called by dbus:: when a DeviceFound signal is received. |
| 186 void DeviceFoundReceived(const std::string& path, dbus::Signal* signal) { |
| 187 CHECK(signal != NULL); |
| 188 dbus::MessageReader reader(signal); |
| 189 std::string address; |
| 190 if (!reader.PopString(&address)) { |
| 191 LOG(ERROR) << path << ": DeviceFound signal has incorrect parameters: " |
| 192 << signal->ToString(); |
| 193 return; |
| 194 } |
| 195 VLOG(1) << path << ": Device found: " << address; |
| 196 |
| 197 DictionaryValue device_properties; |
| 198 if (!reader.PopArrayOfDictEntries(&device_properties)) { |
| 199 LOG(ERROR) << path << ": DeviceFound signal has incorrect parameters: " |
| 200 << signal->ToString(); |
| 201 return; |
| 202 } |
| 203 |
| 204 FOR_EACH_OBSERVER(Observer, observers_, DeviceFound(path, address, |
| 205 device_properties)); |
| 206 } |
| 207 |
| 208 // Called by dbus:: when the DeviceFound signal is initially connected. |
| 209 void DeviceFoundConnected(const std::string& path, |
| 210 const std::string& interface_name, |
| 211 const std::string& signal_name, |
| 212 bool success) { |
| 213 LOG_IF(WARNING, !success) << path |
| 214 << ": Failed to connect to DeviceFound signal."; |
| 215 } |
| 216 |
| 217 // Called by dbus:: when a DeviceDisappeared signal is received. |
| 218 void DeviceDisappearedReceived(const std::string& path, |
| 219 dbus::Signal* signal) { |
| 220 CHECK(signal != NULL); |
| 221 dbus::MessageReader reader(signal); |
| 222 std::string address; |
| 223 if (!reader.PopString(&address)) { |
| 224 LOG(ERROR) << path |
| 225 << ": DeviceDisappeared signal has incorrect parameters: " |
| 226 << signal->ToString(); |
| 227 return; |
| 228 } |
| 229 VLOG(1) << path << ": Device disappeared: " << address; |
| 230 FOR_EACH_OBSERVER(Observer, observers_, DeviceDisappeared(path, address)); |
| 231 } |
| 232 |
| 233 // Called by dbus:: when the DeviceDisappeared signal is initially connected. |
| 234 void DeviceDisappearedConnected(const std::string& path, |
| 235 const std::string& interface_name, |
| 236 const std::string& signal_name, |
| 237 bool success) { |
| 238 LOG_IF(WARNING, !success) << path |
| 239 << ": Failed to connect to DeviceDisappeared signal."; |
| 240 } |
| 241 |
| 242 // Called when a response for StartDiscovery() is received. |
| 243 void OnStartDiscovery(const std::string& path, dbus::Response* response) { |
| 244 VLOG(1) << "OnStartDiscovery: " << path; |
| 245 CHECK(response != NULL); |
| 246 } |
| 247 |
| 248 // Called when a response for StopDiscovery() is received. |
| 249 void OnStopDiscovery(const std::string& path, dbus::Response* response) { |
| 250 VLOG(1) << "OnStopDiscovery: " << path; |
| 251 CHECK(response != NULL); |
| 252 } |
| 253 |
| 254 // Weak pointer factory for generating 'this' pointers that might live longer |
| 255 // than we do. |
| 256 base::WeakPtrFactory<BluetoothAdapterClientImpl> weak_ptr_factory_; |
| 257 |
| 258 dbus::Bus* bus_; |
| 259 |
| 260 // We maintain a collection of dbus object proxies, one for each adapter. |
| 261 typedef std::map<const std::string, dbus::ObjectProxy*> ProxyMap; |
| 262 ProxyMap proxies_; |
| 263 |
| 264 // List of observers interested in event notifications from us. |
| 265 ObserverList<Observer> observers_; |
| 266 |
| 267 DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClientImpl); |
| 268 }; |
| 269 |
| 270 // The BluetoothAdapterClient implementation used on Linux desktop, which does |
| 271 // nothing. |
| 272 class BluetoothAdapterClientStubImpl : public BluetoothAdapterClient { |
| 273 public: |
| 274 // BluetoothAdapterClient override. |
| 275 virtual void AddObserver(Observer* observer, const std::string& path) { |
| 276 VLOG(1) << "AddObserver: " << path; |
| 277 } |
| 278 |
| 279 // BluetoothAdapterClient override. |
| 280 virtual void RemoveObserver(Observer* observer, const std::string& path) { |
| 281 VLOG(1) << "RemoveObserver: " << path; |
| 282 } |
| 283 |
| 284 // BluetoothAdapterClient override. |
| 285 virtual void StartDiscovery(const std::string& path) { |
| 286 VLOG(1) << "StartDiscovery: " << path; |
| 287 } |
| 288 |
| 289 // BluetoothAdapterClient override. |
| 290 virtual void StopDiscovery(const std::string& path) { |
| 291 VLOG(1) << "StopDiscovery: " << path; |
| 292 } |
| 293 }; |
| 294 |
| 295 BluetoothAdapterClient::BluetoothAdapterClient() { |
| 296 } |
| 297 |
| 298 BluetoothAdapterClient::~BluetoothAdapterClient() { |
| 299 } |
| 300 |
| 301 BluetoothAdapterClient* BluetoothAdapterClient::Create(dbus::Bus* bus) { |
| 302 if (system::runtime_environment::IsRunningOnChromeOS()) { |
| 303 return new BluetoothAdapterClientImpl(bus); |
| 304 } else { |
| 305 return new BluetoothAdapterClientStubImpl(); |
| 306 } |
| 307 } |
| 308 |
| 309 } // namespace chromeos |
OLD | NEW |