// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chromeos/dbus/bluetooth_manager_client.h" #include #include "base/bind.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "chromeos/dbus/bluetooth_property.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_path.h" #include "dbus/object_proxy.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { BluetoothManagerClient::Properties::Properties( dbus::ObjectProxy* object_proxy, const PropertyChangedCallback& callback) : BluetoothPropertySet(object_proxy, bluetooth_manager::kBluetoothManagerInterface, callback) { RegisterProperty(bluetooth_manager::kAdaptersProperty, &adapters); } BluetoothManagerClient::Properties::~Properties() { } // The BluetoothManagerClient implementation used in production. class BluetoothManagerClientImpl : public BluetoothManagerClient { public: explicit BluetoothManagerClientImpl(dbus::Bus* bus) : object_proxy_(NULL), weak_ptr_factory_(this) { // Create the object proxy. DCHECK(bus); object_proxy_ = bus->GetObjectProxy( bluetooth_manager::kBluetoothManagerServiceName, dbus::ObjectPath(bluetooth_manager::kBluetoothManagerServicePath)); object_proxy_->ConnectToSignal( bluetooth_manager::kBluetoothManagerInterface, bluetooth_manager::kAdapterAddedSignal, base::Bind(&BluetoothManagerClientImpl::AdapterAddedReceived, weak_ptr_factory_.GetWeakPtr()), base::Bind(&BluetoothManagerClientImpl::AdapterAddedConnected, weak_ptr_factory_.GetWeakPtr())); object_proxy_->ConnectToSignal( bluetooth_manager::kBluetoothManagerInterface, bluetooth_manager::kAdapterRemovedSignal, base::Bind(&BluetoothManagerClientImpl::AdapterRemovedReceived, weak_ptr_factory_.GetWeakPtr()), base::Bind(&BluetoothManagerClientImpl::AdapterRemovedConnected, weak_ptr_factory_.GetWeakPtr())); object_proxy_->ConnectToSignal( bluetooth_manager::kBluetoothManagerInterface, bluetooth_manager::kDefaultAdapterChangedSignal, base::Bind(&BluetoothManagerClientImpl::DefaultAdapterChangedReceived, weak_ptr_factory_.GetWeakPtr()), base::Bind(&BluetoothManagerClientImpl::DefaultAdapterChangedConnected, weak_ptr_factory_.GetWeakPtr())); // Create the properties structure. properties_ = new Properties( object_proxy_, base::Bind(&BluetoothManagerClientImpl::OnPropertyChanged, weak_ptr_factory_.GetWeakPtr())); properties_->ConnectSignals(); properties_->GetAll(); } virtual ~BluetoothManagerClientImpl() { // Clean up the Properties structure. delete properties_; } // BluetoothManagerClient override. virtual void AddObserver(Observer* observer) OVERRIDE { DCHECK(observer); observers_.AddObserver(observer); } // BluetoothManagerClient override. virtual void RemoveObserver(Observer* observer) OVERRIDE { DCHECK(observer); observers_.RemoveObserver(observer); } // BluetoothManagerClient override. virtual Properties* GetProperties() OVERRIDE { return properties_; } // BluetoothManagerClient override. virtual void DefaultAdapter(const AdapterCallback& callback) OVERRIDE { dbus::MethodCall method_call( bluetooth_manager::kBluetoothManagerInterface, bluetooth_manager::kDefaultAdapter); DCHECK(object_proxy_); object_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&BluetoothManagerClientImpl::OnDefaultAdapter, weak_ptr_factory_.GetWeakPtr(), callback)); } // BluetoothManagerClient override. virtual void FindAdapter(const std::string& address, const AdapterCallback& callback) OVERRIDE { dbus::MethodCall method_call( bluetooth_manager::kBluetoothManagerInterface, bluetooth_manager::kFindAdapter); dbus::MessageWriter writer(&method_call); writer.AppendString(address); DCHECK(object_proxy_); object_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&BluetoothManagerClientImpl::OnFindAdapter, weak_ptr_factory_.GetWeakPtr(), callback)); } private: // Called by BluetoothPropertySet when a property value is changed, // either by result of a signal or response to a GetAll() or Get() // call. Informs observers. void OnPropertyChanged(const std::string& property_name) { FOR_EACH_OBSERVER(BluetoothManagerClient::Observer, observers_, ManagerPropertyChanged(property_name)); } // Called by dbus:: when an AdapterAdded signal is received. void AdapterAddedReceived(dbus::Signal* signal) { DCHECK(signal); dbus::MessageReader reader(signal); dbus::ObjectPath object_path; if (!reader.PopObjectPath(&object_path)) { LOG(WARNING) << "AdapterAdded signal has incorrect parameters: " << signal->ToString(); return; } VLOG(1) << "Adapter added: " << object_path.value(); FOR_EACH_OBSERVER(Observer, observers_, AdapterAdded(object_path)); } // Called by dbus:: when the AdapterAdded signal is initially connected. void AdapterAddedConnected(const std::string& interface_name, const std::string& signal_name, bool success) { LOG_IF(WARNING, !success) << "Failed to connect to AdapterAdded signal."; } // Called by dbus:: when an AdapterRemoved signal is received. void AdapterRemovedReceived(dbus::Signal* signal) { DCHECK(signal); dbus::MessageReader reader(signal); dbus::ObjectPath object_path; if (!reader.PopObjectPath(&object_path)) { LOG(WARNING) << "AdapterRemoved signal has incorrect parameters: " << signal->ToString(); return; } VLOG(1) << "Adapter removed: " << object_path.value(); FOR_EACH_OBSERVER(Observer, observers_, AdapterRemoved(object_path)); } // Called by dbus:: when the AdapterRemoved signal is initially connected. void AdapterRemovedConnected(const std::string& interface_name, const std::string& signal_name, bool success) { LOG_IF(WARNING, !success) << "Failed to connect to AdapterRemoved signal."; } // Called by dbus:: when a DefaultAdapterChanged signal is received. void DefaultAdapterChangedReceived(dbus::Signal* signal) { DCHECK(signal); dbus::MessageReader reader(signal); dbus::ObjectPath object_path; if (!reader.PopObjectPath(&object_path)) { LOG(WARNING) << "DefaultAdapterChanged signal has incorrect parameters: " << signal->ToString(); return; } VLOG(1) << "Default adapter changed: " << object_path.value(); FOR_EACH_OBSERVER(Observer, observers_, DefaultAdapterChanged(object_path)); } // Called by dbus:: when the DefaultAdapterChanged signal is initially // connected. void DefaultAdapterChangedConnected(const std::string& interface_name, const std::string& signal_name, bool success) { LOG_IF(WARNING, !success) << "Failed to connect to DefaultAdapterChanged signal."; } // Called when a response for DefaultAdapter() is received. void OnDefaultAdapter(const AdapterCallback& callback, dbus::Response* response) { // Parse response. bool success = false; dbus::ObjectPath object_path; if (response != NULL) { dbus::MessageReader reader(response); if (!reader.PopObjectPath(&object_path)) { LOG(WARNING) << "DefaultAdapter response has incorrect parameters: " << response->ToString(); } else { success = true; } } else { LOG(WARNING) << "Failed to get default adapter."; } // Notify client. callback.Run(object_path, success); } // Called when a response for FindAdapter() is received. void OnFindAdapter(const AdapterCallback& callback, dbus::Response* response) { // Parse response. bool success = false; dbus::ObjectPath object_path; if (response != NULL) { dbus::MessageReader reader(response); if (!reader.PopObjectPath(&object_path)) { LOG(WARNING) << "FindAdapter response has incorrect parameters: " << response->ToString(); } else { success = true; } } else { LOG(WARNING) << "Failed to find adapter."; } // Notify client. callback.Run(object_path, success); } // D-Bus proxy for BlueZ Manager interface. dbus::ObjectProxy* object_proxy_; // Properties for BlueZ Manager interface. Properties* properties_; // List of observers interested in event notifications from us. ObserverList observers_; // Weak pointer factory for generating 'this' pointers that might live longer // than we do. // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed. base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BluetoothManagerClientImpl); }; // The BluetoothManagerClient implementation used on Linux desktop, which does // nothing. class BluetoothManagerClientStubImpl : public BluetoothManagerClient { public: struct Properties : public BluetoothManagerClient::Properties { explicit Properties(const PropertyChangedCallback& callback) : BluetoothManagerClient::Properties(NULL, callback) { } virtual ~Properties() { } virtual void Get(dbus::PropertyBase* property, dbus::PropertySet::GetCallback callback) OVERRIDE { VLOG(1) << "Get " << property->name(); callback.Run(false); } virtual void GetAll() OVERRIDE { VLOG(1) << "GetAll"; } virtual void Set(dbus::PropertyBase* property, dbus::PropertySet::SetCallback callback) OVERRIDE { VLOG(1) << "Set " << property->name(); callback.Run(false); } }; BluetoothManagerClientStubImpl() { properties_.reset(new Properties(base::Bind( &BluetoothManagerClientStubImpl::OnPropertyChanged, base::Unretained(this)))); std::vector adapters; adapters.push_back(dbus::ObjectPath("/fake/hci0")); properties_->adapters.ReplaceValue(adapters); } // BluetoothManagerClient override. virtual void AddObserver(Observer* observer) OVERRIDE { observers_.AddObserver(observer); } // BluetoothManagerClient override. virtual void RemoveObserver(Observer* observer) OVERRIDE { observers_.RemoveObserver(observer); } // BluetoothManagerClient override. virtual Properties* GetProperties() OVERRIDE { VLOG(1) << "GetProperties"; return properties_.get(); } // BluetoothManagerClient override. virtual void DefaultAdapter(const AdapterCallback& callback) OVERRIDE { VLOG(1) << "DefaultAdapter."; callback.Run(dbus::ObjectPath("/fake/hci0"), true); } // BluetoothManagerClient override. virtual void FindAdapter(const std::string& address, const AdapterCallback& callback) OVERRIDE { VLOG(1) << "FindAdapter: " << address; if (address == "hci0") callback.Run(dbus::ObjectPath("/fake/hci0"), true); else callback.Run(dbus::ObjectPath(), false); } private: void OnPropertyChanged(const std::string& property_name) { FOR_EACH_OBSERVER(BluetoothManagerClient::Observer, observers_, ManagerPropertyChanged(property_name)); } // List of observers interested in event notifications from us. ObserverList observers_; // Static properties we return. scoped_ptr properties_; }; BluetoothManagerClient::BluetoothManagerClient() { } BluetoothManagerClient::~BluetoothManagerClient() { } BluetoothManagerClient* BluetoothManagerClient::Create( DBusClientImplementationType type, dbus::Bus* bus) { if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) return new BluetoothManagerClientImpl(bus); DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); return new BluetoothManagerClientStubImpl(); } } // namespace chromeos