diff options
author | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-06 01:54:36 +0000 |
---|---|---|
committer | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-06 01:54:36 +0000 |
commit | 64e199254481d6132c3a7ccdf9b3a743bff86a88 (patch) | |
tree | c10cdf03cbde8439d1d8a7070a6c7f9fdf10f517 /chromeos | |
parent | 81a476c9ce1088345db02cf1647399d0e673d487 (diff) | |
download | chromium_src-64e199254481d6132c3a7ccdf9b3a743bff86a88.zip chromium_src-64e199254481d6132c3a7ccdf9b3a743bff86a88.tar.gz chromium_src-64e199254481d6132c3a7ccdf9b3a743bff86a88.tar.bz2 |
Move files inside chrome/browser/chromeos/dbus to chromeos/dbus
Move files in chrome/browser/chromeos/dbus/ to chromeos/dbus
Add chromeos/dbus/DEPS
Add chromeos.gyp:chromeos_test_support and chromeos.gyp:chromeos_unittests
Add CHROMEOS_EXPORT to classes
Move power related proto targets to chromeos.gyp
Rewrite and sort #includes
BUG=119583
TEST=component chromeos build success, checkdeps success
Review URL: https://chromiumcodereview.appspot.com/9838085
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131065 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
92 files changed, 11531 insertions, 1 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index bf6bd00..0dccb66 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -12,12 +12,169 @@ 'type': '<(component)', 'dependencies': [ '../base/base.gyp:base', + '../build/linux/system.gyp:dbus', + '../dbus/dbus.gyp:dbus', + '../net/net.gyp:net', + 'power_state_control_proto', + 'power_supply_properties_proto', ], 'sources': [ 'chromeos_export.h', + 'dbus/blocking_method_caller.cc', + 'dbus/blocking_method_caller.h', + 'dbus/bluetooth_adapter_client.cc', + 'dbus/bluetooth_adapter_client.h', + 'dbus/bluetooth_agent_service_provider.cc', + 'dbus/bluetooth_agent_service_provider.h', + 'dbus/bluetooth_device_client.cc', + 'dbus/bluetooth_device_client.h', + 'dbus/bluetooth_input_client.cc', + 'dbus/bluetooth_input_client.h', + 'dbus/bluetooth_manager_client.cc', + 'dbus/bluetooth_manager_client.h', + 'dbus/bluetooth_node_client.cc', + 'dbus/bluetooth_node_client.h', + 'dbus/bluetooth_property.cc', + 'dbus/bluetooth_property.h', + 'dbus/cashew_client.cc', + 'dbus/cashew_client.h', + 'dbus/cros_disks_client.cc', + 'dbus/cros_disks_client.h', + 'dbus/cryptohome_client.cc', + 'dbus/cryptohome_client.h', + 'dbus/dbus_client_implementation_type.h', + 'dbus/dbus_method_call_status.h', + 'dbus/dbus_thread_manager.cc', + 'dbus/dbus_thread_manager.h', + 'dbus/debug_daemon_client.cc', + 'dbus/debug_daemon_client.h', + 'dbus/cryptohome_client.h', + 'dbus/flimflam_ipconfig_client.cc', + 'dbus/flimflam_ipconfig_client.h', + 'dbus/flimflam_client_helper.cc', + 'dbus/flimflam_client_helper.h', + 'dbus/flimflam_network_client.cc', + 'dbus/flimflam_network_client.h', + 'dbus/flimflam_profile_client.cc', + 'dbus/flimflam_profile_client.h', + 'dbus/image_burner_client.cc', + 'dbus/image_burner_client.h', + 'dbus/introspectable_client.cc', + 'dbus/introspectable_client.h', + 'dbus/power_manager_client.cc', + 'dbus/power_manager_client.h', 'dbus/power_supply_status.cc', 'dbus/power_supply_status.h', + 'dbus/session_manager_client.cc', + 'dbus/session_manager_client.h', + 'dbus/speech_synthesizer_client.cc', + 'dbus/speech_synthesizer_client.h', + 'dbus/update_engine_client.cc', + 'dbus/update_engine_client.h', ], }, - ] + { + # This target contains mocks that can be used to write unit tests. + 'target_name': 'chromeos_test_support', + 'type': 'static_library', + 'dependencies': [ + '../build/linux/system.gyp:dbus', + '../testing/gmock.gyp:gmock', + 'chromeos', + ], + 'sources': [ + 'dbus/mock_bluetooth_adapter_client.cc', + 'dbus/mock_bluetooth_adapter_client.h', + 'dbus/mock_bluetooth_device_client.cc', + 'dbus/mock_bluetooth_device_client.h', + 'dbus/mock_bluetooth_input_client.cc', + 'dbus/mock_bluetooth_input_client.h', + 'dbus/mock_bluetooth_manager_client.cc', + 'dbus/mock_bluetooth_manager_client.h', + 'dbus/mock_bluetooth_node_client.cc', + 'dbus/mock_bluetooth_node_client.h', + 'dbus/mock_cros_disks_client.cc', + 'dbus/mock_cros_disks_client.h', + 'dbus/mock_cashew_client.cc', + 'dbus/mock_cashew_client.h', + 'dbus/mock_cryptohome_client.cc', + 'dbus/mock_cryptohome_client.h', + 'dbus/mock_dbus_thread_manager.cc', + 'dbus/mock_dbus_thread_manager.h', + 'dbus/mock_debug_daemon_client.cc', + 'dbus/mock_debug_daemon_client.h', + 'dbus/mock_flimflam_ipconfig_client.cc', + 'dbus/mock_flimflam_ipconfig_client.h', + 'dbus/mock_flimflam_network_client.cc', + 'dbus/mock_flimflam_network_client.h', + 'dbus/mock_flimflam_profile_client.cc', + 'dbus/mock_flimflam_profile_client.h', + 'dbus/mock_image_burner_client.cc', + 'dbus/mock_image_burner_client.h', + 'dbus/mock_introspectable_client.cc', + 'dbus/mock_introspectable_client.h', + 'dbus/mock_power_manager_client.cc', + 'dbus/mock_power_manager_client.h', + 'dbus/mock_session_manager_client.cc', + 'dbus/mock_session_manager_client.h', + 'dbus/mock_speech_synthesizer_client.cc', + 'dbus/mock_speech_synthesizer_client.h', + 'dbus/mock_update_engine_client.cc', + 'dbus/mock_update_engine_client.h', + ], + 'include_dirs': [ + '..', + ], + }, + { + 'target_name': 'chromeos_unittests', + 'type': 'executable', + 'dependencies': [ + '../base/base.gyp:run_all_unittests', + '../base/base.gyp:test_support_base', + '../build/linux/system.gyp:dbus', + '../dbus/dbus.gyp:dbus_test_support', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', + 'chromeos_test_support', + ], + 'sources': [ + 'dbus/blocking_method_caller_unittest.cc', + 'dbus/flimflam_client_unittest_base.cc', + 'dbus/flimflam_client_unittest_base.h', + 'dbus/flimflam_network_client_unittest.cc', + ], + 'include_dirs': [ + '..', + ], + }, + { + # Protobuf compiler / generator for the PowerSupplyProperties protocol + # buffer. + 'target_name': 'power_state_control_proto', + 'type': 'static_library', + 'sources': [ + '../third_party/cros_system_api/dbus/power_state_control.proto', + ], + 'variables': { + 'proto_in_dir': '../third_party/cros_system_api/dbus/', + 'proto_out_dir': 'chromeos/dbus', + }, + 'includes': ['../build/protoc.gypi'], + }, + { + # Protobuf compiler / generator for the PowerSupplyProperties protocol + # buffer. + 'target_name': 'power_supply_properties_proto', + 'type': 'static_library', + 'sources': [ + '../third_party/cros_system_api/dbus/power_supply_properties.proto', + ], + 'variables': { + 'proto_in_dir': '../third_party/cros_system_api/dbus/', + 'proto_out_dir': 'chromeos/dbus', + }, + 'includes': ['../build/protoc.gypi'], + }, + ], } diff --git a/chromeos/dbus/DEPS b/chromeos/dbus/DEPS new file mode 100644 index 0000000..d6abdda --- /dev/null +++ b/chromeos/dbus/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+dbus", +] diff --git a/chromeos/dbus/blocking_method_caller.cc b/chromeos/dbus/blocking_method_caller.cc new file mode 100644 index 0000000..182f0cf --- /dev/null +++ b/chromeos/dbus/blocking_method_caller.cc @@ -0,0 +1,67 @@ +// 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/blocking_method_caller.h" + +#include "base/bind.h" +#include "dbus/bus.h" +#include "dbus/object_proxy.h" + +namespace chromeos { + +namespace { + +// A utility class to ensure the WaitableEvent is signaled. +class WaitableEventSignaler { + public: + explicit WaitableEventSignaler(base::WaitableEvent* event) : event_(event) {} + + ~WaitableEventSignaler() { + event_->Signal(); + } + + private: + base::WaitableEvent* event_; +}; + +// This function is a part of CallMethodAndBlock implementation. +void CallMethodAndBlockInternal( + dbus::Response** response, + WaitableEventSignaler* signaler, + dbus::ObjectProxy* proxy, + dbus::MethodCall* method_call) { + *response = proxy->CallMethodAndBlock( + method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); +} + +} // namespace + +BlockingMethodCaller::BlockingMethodCaller(dbus::Bus* bus, + dbus::ObjectProxy* proxy) + : bus_(bus), + proxy_(proxy), + on_blocking_method_call_(false /* manual_reset */, + false /* initially_signaled */) { +} + +BlockingMethodCaller::~BlockingMethodCaller() { +} + +dbus::Response* BlockingMethodCaller::CallMethodAndBlock( + dbus::MethodCall* method_call) { + WaitableEventSignaler* signaler = + new WaitableEventSignaler(&on_blocking_method_call_); + dbus::Response* response = NULL; + bus_->PostTaskToDBusThread( + FROM_HERE, + base::Bind(&CallMethodAndBlockInternal, + &response, + base::Owned(signaler), + base::Unretained(proxy_), + method_call)); + on_blocking_method_call_.Wait(); + return response; +} + +} // namespace chromeos diff --git a/chromeos/dbus/blocking_method_caller.h b/chromeos/dbus/blocking_method_caller.h new file mode 100644 index 0000000..48d21cf --- /dev/null +++ b/chromeos/dbus/blocking_method_caller.h @@ -0,0 +1,46 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLOCKING_METHOD_CALLER_H_ +#define CHROMEOS_DBUS_BLOCKING_METHOD_CALLER_H_ +#pragma once + +#include "base/callback.h" +#include "base/synchronization/waitable_event.h" +#include "chromeos/chromeos_export.h" + +namespace dbus { + +class Bus; +class ObjectProxy; +class MethodCall; +class Response; + +} // namespace dbus + +namespace chromeos { + +// A utility class to call D-Bus methods in a synchronous (blocking) way. +// Note: Blocking the thread until it returns is not a good idea in most cases. +// Avoid using this class as hard as you can. +class CHROMEOS_EXPORT BlockingMethodCaller { + public: + BlockingMethodCaller(dbus::Bus* bus, dbus::ObjectProxy* proxy); + virtual ~BlockingMethodCaller(); + + // Calls the method and blocks until it returns. + // The caller is responsible to delete the returned object. + dbus::Response* CallMethodAndBlock(dbus::MethodCall* method_call); + + private: + dbus::Bus* bus_; + dbus::ObjectProxy* proxy_; + base::WaitableEvent on_blocking_method_call_; + + DISALLOW_COPY_AND_ASSIGN(BlockingMethodCaller); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLOCKING_METHOD_CALLER_H_ diff --git a/chromeos/dbus/blocking_method_caller_unittest.cc b/chromeos/dbus/blocking_method_caller_unittest.cc new file mode 100644 index 0000000..eb2394a --- /dev/null +++ b/chromeos/dbus/blocking_method_caller_unittest.cc @@ -0,0 +1,125 @@ +// 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/blocking_method_caller.h" + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "dbus/message.h" +#include "dbus/mock_bus.h" +#include "dbus/mock_object_proxy.h" +#include "dbus/object_path.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::Invoke; +using ::testing::Return; + +namespace chromeos { + +class BlockingMethodCallerTest : public testing::Test { + public: + BlockingMethodCallerTest() { + } + + virtual void SetUp() { + // Create a mock bus. + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SYSTEM; + mock_bus_ = new dbus::MockBus(options); + + // Create a mock proxy. + mock_proxy_ = new dbus::MockObjectProxy( + mock_bus_.get(), + "org.chromium.TestService", + dbus::ObjectPath("/org/chromium/TestObject")); + + // Set an expectation so mock_proxy's CallMethodAndBlock() will use + // CreateMockProxyResponse() to return responses. + EXPECT_CALL(*mock_proxy_, CallMethodAndBlock(_, _)) + .WillRepeatedly(Invoke( + this, &BlockingMethodCallerTest::CreateMockProxyResponse)); + + // Set an expectation so mock_bus's GetObjectProxy() for the given + // service name and the object path will return mock_proxy_. + EXPECT_CALL(*mock_bus_, GetObjectProxy( + "org.chromium.TestService", + dbus::ObjectPath("/org/chromium/TestObject"))) + .WillOnce(Return(mock_proxy_.get())); + + // Set an expectation so mock_bus's PostTaskToDBusThread() will run the + // given task. + EXPECT_CALL(*mock_bus_, PostTaskToDBusThread(_, _)) + .WillRepeatedly(Invoke( + this, &BlockingMethodCallerTest::RunTask)); + + // ShutdownAndBlock() will be called in TearDown(). + EXPECT_CALL(*mock_bus_, ShutdownAndBlock()).WillOnce(Return()); + } + + virtual void TearDown() { + mock_bus_->ShutdownAndBlock(); + } + + protected: + scoped_refptr<dbus::MockBus> mock_bus_; + scoped_refptr<dbus::MockObjectProxy> mock_proxy_; + + private: + // Returns a response for the given method call. Used to implement + // CallMethodAndBlock() for |mock_proxy_|. + dbus::Response* CreateMockProxyResponse(dbus::MethodCall* method_call, + int timeout_ms) { + if (method_call->GetInterface() == "org.chromium.TestInterface" && + method_call->GetMember() == "Echo") { + dbus::MessageReader reader(method_call); + std::string text_message; + if (reader.PopString(&text_message)) { + dbus::Response* response = dbus::Response::CreateEmpty(); + dbus::MessageWriter writer(response); + writer.AppendString(text_message); + return response; + } + } + + LOG(ERROR) << "Unexpected method call: " << method_call->ToString(); + return NULL; + } + + // Runs the given task. + void RunTask(const tracked_objects::Location& from_here, + const base::Closure& task) { + task.Run(); + } +}; + +TEST_F(BlockingMethodCallerTest, Echo) { + const char kHello[] = "Hello"; + // Get an object proxy from the mock bus. + dbus::ObjectProxy* proxy = mock_bus_->GetObjectProxy( + "org.chromium.TestService", + dbus::ObjectPath("/org/chromium/TestObject")); + + // Create a method call. + dbus::MethodCall method_call("org.chromium.TestInterface", "Echo"); + dbus::MessageWriter writer(&method_call); + writer.AppendString(kHello); + + // Call the method. + BlockingMethodCaller blocking_method_caller(mock_bus_.get(), proxy); + scoped_ptr<dbus::Response> response( + blocking_method_caller.CallMethodAndBlock(&method_call)); + + // Check the response. + ASSERT_TRUE(response.get()); + dbus::MessageReader reader(response.get()); + std::string text_message; + ASSERT_TRUE(reader.PopString(&text_message)); + // The text message should be echo'ed back. + EXPECT_EQ(kHello, text_message); +} + +} // namespace chromeos diff --git a/chromeos/dbus/bluetooth_adapter_client.cc b/chromeos/dbus/bluetooth_adapter_client.cc new file mode 100644 index 0000000..566d470 --- /dev/null +++ b/chromeos/dbus/bluetooth_adapter_client.cc @@ -0,0 +1,809 @@ +// 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_adapter_client.h" + +#include <map> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "chromeos/dbus/bluetooth_device_client.h" +#include "chromeos/dbus/bluetooth_manager_client.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 { + +BluetoothAdapterClient::Properties::Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback) + : BluetoothPropertySet(object_proxy, + bluetooth_adapter::kBluetoothAdapterInterface, + callback) { + RegisterProperty(bluetooth_adapter::kAddressProperty, &address); + RegisterProperty(bluetooth_adapter::kNameProperty, &name); + RegisterProperty(bluetooth_adapter::kClassProperty, &bluetooth_class); + RegisterProperty(bluetooth_adapter::kPoweredProperty, &powered); + RegisterProperty(bluetooth_adapter::kDiscoverableProperty, &discoverable); + RegisterProperty(bluetooth_adapter::kPairableProperty, &pairable); + RegisterProperty(bluetooth_adapter::kPairableTimeoutProperty, + &pairable_timeout); + RegisterProperty(bluetooth_adapter::kDiscoverableTimeoutProperty, + &discoverable_timeout); + RegisterProperty(bluetooth_adapter::kDiscoveringProperty, &discovering); + RegisterProperty(bluetooth_adapter::kDevicesProperty, &devices); + RegisterProperty(bluetooth_adapter::kUUIDsProperty, &uuids); +} + +BluetoothAdapterClient::Properties::~Properties() { +} + + +// The BluetoothAdapterClient implementation used in production. +class BluetoothAdapterClientImpl: public BluetoothAdapterClient, + private BluetoothManagerClient::Observer { + public: + explicit BluetoothAdapterClientImpl(dbus::Bus* bus, + BluetoothManagerClient* manager_client) + : weak_ptr_factory_(this), + bus_(bus) { + DVLOG(1) << "Creating BluetoothAdapterClientImpl"; + + DCHECK(manager_client); + manager_client->AddObserver(this); + } + + virtual ~BluetoothAdapterClientImpl() { + // Clean up Properties structures + for (ObjectMap::iterator iter = object_map_.begin(); + iter != object_map_.end(); ++iter) { + Object object = iter->second; + Properties* properties = object.second; + delete properties; + } + } + + // BluetoothAdapterClient override. + virtual void AddObserver(BluetoothAdapterClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothAdapterClient override. + virtual void RemoveObserver(BluetoothAdapterClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // BluetoothAdapterClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + return GetObject(object_path).second; + } + + // BluetoothAdapterClient override. + virtual void RequestSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kRequestSession); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnRequestSession, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void ReleaseSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kReleaseSession); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnReleaseSession, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void StartDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kStartDiscovery); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnStartDiscovery, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void StopDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kStopDiscovery); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnStopDiscovery, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void FindDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const DeviceCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kFindDevice); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(address); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnFindDevice, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void CreateDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const DeviceCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kCreateDevice); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(address); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnCreateDevice, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void CreatePairedDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const dbus::ObjectPath& agent_path, + const std::string& capability, + const DeviceCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kCreatePairedDevice); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(address); + writer.AppendObjectPath(agent_path); + writer.AppendString(capability); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnCreatePairedDevice, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void CancelDeviceCreation(const dbus::ObjectPath& object_path, + const std::string& address, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kCancelDeviceCreation); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(address); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnCancelDeviceCreation, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void RemoveDevice(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kRemoveDevice); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(device_path); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnRemoveDevice, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void RegisterAgent(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& agent_path, + const std::string& capability, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kRegisterAgent); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(agent_path); + writer.AppendString(capability); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnRegisterAgent, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothAdapterClient override. + virtual void UnregisterAgent(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& agent_path, + const AdapterCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kUnregisterAgent); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(agent_path); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothAdapterClientImpl::OnCreateDevice, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + private: + // We maintain a collection of dbus object proxies and properties structures + // for each adapter. + typedef std::pair<dbus::ObjectProxy*, Properties*> Object; + typedef std::map<const dbus::ObjectPath, Object> ObjectMap; + ObjectMap object_map_; + + // BluetoothManagerClient::Observer override. + virtual void AdapterAdded(const dbus::ObjectPath& object_path) OVERRIDE { + } + + // BluetoothManagerClient::Observer override. + virtual void AdapterRemoved(const dbus::ObjectPath& object_path) OVERRIDE { + RemoveObject(object_path); + } + + // Ensures that we have an object proxy and properties structure for + // an adapter with object path |object_path|, creating it if not and + // storing in our |object_map_| map. + Object GetObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) + return iter->second; + + // Create the object proxy. + DCHECK(bus_); + dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy( + bluetooth_adapter::kBluetoothAdapterServiceName, object_path); + + object_proxy->ConnectToSignal( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kDeviceCreatedSignal, + base::Bind(&BluetoothAdapterClientImpl::DeviceCreatedReceived, + weak_ptr_factory_.GetWeakPtr(), object_path), + base::Bind(&BluetoothAdapterClientImpl::DeviceCreatedConnected, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + object_proxy->ConnectToSignal( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kDeviceRemovedSignal, + base::Bind(&BluetoothAdapterClientImpl::DeviceRemovedReceived, + weak_ptr_factory_.GetWeakPtr(), object_path), + base::Bind(&BluetoothAdapterClientImpl::DeviceRemovedConnected, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + object_proxy->ConnectToSignal( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kDeviceFoundSignal, + base::Bind(&BluetoothAdapterClientImpl::DeviceFoundReceived, + weak_ptr_factory_.GetWeakPtr(), object_path), + base::Bind(&BluetoothAdapterClientImpl::DeviceFoundConnected, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + object_proxy->ConnectToSignal( + bluetooth_adapter::kBluetoothAdapterInterface, + bluetooth_adapter::kDeviceDisappearedSignal, + base::Bind(&BluetoothAdapterClientImpl::DeviceDisappearedReceived, + weak_ptr_factory_.GetWeakPtr(), object_path), + base::Bind(&BluetoothAdapterClientImpl::DeviceDisappearedConnected, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + // Create the properties structure. + Properties* properties = new Properties( + object_proxy, + base::Bind(&BluetoothAdapterClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + properties->ConnectSignals(); + properties->GetAll(); + + Object object = std::make_pair(object_proxy, properties); + object_map_[object_path] = object; + return object; + } + + // Removes the dbus object proxy and properties for the adapter with + // dbus object path |object_path| from our |object_map_| map. + void RemoveObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) { + // Clean up the Properties structure. + Object object = iter->second; + Properties* properties = object.second; + delete properties; + + object_map_.erase(iter); + } + } + + // Returns a pointer to the object proxy for |object_path|, creating + // it if necessary. + dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) { + return GetObject(object_path).first; + } + + // 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 dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + AdapterPropertyChanged(object_path, property_name)); + } + + // Called by dbus:: when a DeviceCreated signal is received. + void DeviceCreatedReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + dbus::MessageReader reader(signal); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << object_path.value() + << ": DeviceCreated signal has incorrect parameters: " + << signal->ToString(); + return; + } + + DVLOG(1) << object_path.value() << ": Device created: " + << device_path.value(); + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + DeviceCreated(object_path, device_path)); + } + + // Called by dbus:: when the DeviceCreated signal is initially connected. + void DeviceCreatedConnected(const dbus::ObjectPath& object_path, + const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << object_path.value() + << ": Failed to connect to DeviceCreated signal."; + } + + // Called by dbus:: when a DeviceRemoved signal is received. + void DeviceRemovedReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + dbus::MessageReader reader(signal); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << object_path.value() + << ": DeviceRemoved signal has incorrect parameters: " + << signal->ToString(); + return; + } + + DVLOG(1) << object_path.value() << ": Device removed: " + << device_path.value(); + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + DeviceRemoved(object_path, device_path)); + } + + // Called by dbus:: when the DeviceRemoved signal is initially connected. + void DeviceRemovedConnected(const dbus::ObjectPath& object_path, + const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << object_path.value() + << ": Failed to connect to DeviceRemoved signal."; + } + + // Called by dbus:: when a DeviceFound signal is received. + void DeviceFoundReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + dbus::MessageReader reader(signal); + std::string address; + if (!reader.PopString(&address)) { + LOG(WARNING) << object_path.value() + << ": DeviceFound signal has incorrect parameters: " + << signal->ToString(); + return; + } + + // Create device properties structure without an attached object_proxy + // and a NULL callback; value() functions will work on this, but not + // Get() or Set() calls. + BluetoothDeviceClient::Properties device_properties( + NULL, BluetoothDeviceClient::Properties::PropertyChangedCallback()); + if (!device_properties.UpdatePropertiesFromReader(&reader)) { + LOG(WARNING) << object_path.value() + << ": DeviceFound signal has incorrect parameters: " + << signal->ToString(); + return; + } + + DVLOG(1) << object_path.value() << ": Device found: " << address; + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + DeviceFound(object_path, address, device_properties)); + } + + // Called by dbus:: when the DeviceFound signal is initially connected. + void DeviceFoundConnected(const dbus::ObjectPath& object_path, + const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << object_path.value() + << ": Failed to connect to DeviceFound signal."; + } + + // Called by dbus:: when a DeviceDisappeared signal is received. + void DeviceDisappearedReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + dbus::MessageReader reader(signal); + std::string address; + if (!reader.PopString(&address)) { + LOG(WARNING) << object_path.value() + << ": DeviceDisappeared signal has incorrect parameters: " + << signal->ToString(); + return; + } + + DVLOG(1) << object_path.value() << ": Device disappeared: " << address; + FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_, + DeviceDisappeared(object_path, address)); + } + + // Called by dbus:: when the DeviceDisappeared signal is initially connected. + void DeviceDisappearedConnected(const dbus::ObjectPath& object_path, + const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) + << object_path.value() + << ": Failed to connect to DeviceDisappeared signal."; + } + + // Called when a response for RequestSession() is received. + void OnRequestSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnRequestSession: failed."; + callback.Run(object_path, response); + } + + // Called when a response for ReleaseSession() is received. + void OnReleaseSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnReleaseSession: failed."; + callback.Run(object_path, response); + } + + // Called when a response for StartDiscovery() is received. + void OnStartDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnStartDiscovery: failed."; + callback.Run(object_path, response); + } + + // Called when a response for StopDiscovery() is received. + void OnStopDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnStopDiscovery: failed."; + callback.Run(object_path, response); + } + + // Called when a response for FindDevice() is received. + void OnFindDevice(const dbus::ObjectPath& object_path, + const DeviceCallback& callback, + dbus::Response* response) { + // Parse response. + bool success = false; + dbus::ObjectPath device_path; + if (response != NULL) { + dbus::MessageReader reader(response); + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "FindDevice response has incorrect parameters: " + << response->ToString(); + } else { + success = true; + } + } else { + LOG(WARNING) << "Failed to find device."; + } + + // Notify client. + callback.Run(device_path, success); + } + + // Called when a response for CreateDevice() is received. + void OnCreateDevice(const dbus::ObjectPath& object_path, + const DeviceCallback& callback, + dbus::Response* response) { + // Parse response. + bool success = false; + dbus::ObjectPath device_path; + if (response != NULL) { + dbus::MessageReader reader(response); + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "CreateDevice response has incorrect parameters: " + << response->ToString(); + } else { + success = true; + } + } else { + LOG(WARNING) << "Failed to create device."; + } + + // Notify client. + callback.Run(device_path, success); + } + + // Called when a response for CreatePairedDevice() is received. + void OnCreatePairedDevice(const dbus::ObjectPath& object_path, + const DeviceCallback& callback, + dbus::Response* response) { + // Parse response. + bool success = false; + dbus::ObjectPath device_path; + if (response != NULL) { + dbus::MessageReader reader(response); + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "CreatePairedDevice response has incorrect parameters: " + << response->ToString(); + } else { + success = true; + } + } else { + LOG(WARNING) << "Failed to create paired device."; + } + + // Notify client. + callback.Run(device_path, success); + } + + // Called when a response for CancelDeviceCreation() is received. + void OnCancelDeviceCreation(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnCancelDeviceCreation: failed."; + callback.Run(object_path, response); + } + + // Called when a response for RemoveDevice() is received. + void OnRemoveDevice(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnRemoveDevice: failed."; + callback.Run(object_path, response); + } + + // Called when a response for RegisterAgent() is received. + void OnRegisterAgent(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnRegisterAgent: failed."; + callback.Run(object_path, response); + } + + // Called when a response for UnregisterAgent() is received. + void OnUnregisterAgent(const dbus::ObjectPath& object_path, + const AdapterCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnUnregisterAgent: failed."; + callback.Run(object_path, response); + } + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + base::WeakPtrFactory<BluetoothAdapterClientImpl> weak_ptr_factory_; + + dbus::Bus* bus_; + + // List of observers interested in event notifications from us. + ObserverList<BluetoothAdapterClient::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClientImpl); +}; + +// The BluetoothAdapterClient implementation used on Linux desktop, which does +// nothing. +class BluetoothAdapterClientStubImpl : public BluetoothAdapterClient { + public: + // BluetoothAdapterClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + } + + // BluetoothAdapterClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + } + + // BluetoothAdapterClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + VLOG(1) << "GetProperties: " << object_path.value(); + return NULL; + } + + // BluetoothAdapterClient override. + virtual void RequestSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "RequestSession: " << object_path.value(); + callback.Run(object_path, false); + } + + // BluetoothAdapterClient override. + virtual void ReleaseSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "ReleaseSession: " << object_path.value(); + callback.Run(object_path, false); + } + + // BluetoothAdapterClient override. + virtual void StartDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "StartDiscovery: " << object_path.value(); + callback.Run(object_path, false); + } + + // BluetoothAdapterClient override. + virtual void StopDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "StopDiscovery: " << object_path.value(); + callback.Run(object_path, false); + } + + // BluetoothAdapterClient override. + virtual void FindDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const DeviceCallback& callback) OVERRIDE { + VLOG(1) << "FindDevice: " << object_path.value() << " " << address; + callback.Run(dbus::ObjectPath(), false); + } + + // BluetoothAdapterClient override. + virtual void CreateDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const DeviceCallback& callback) OVERRIDE { + VLOG(1) << "CreateDevice: " << object_path.value() << " " << address; + callback.Run(dbus::ObjectPath(), false); + } + + // BluetoothAdapterClient override. + virtual void CreatePairedDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const dbus::ObjectPath& agent_path, + const std::string& capability, + const DeviceCallback& callback) OVERRIDE { + VLOG(1) << "CreatePairedDevice: " << object_path.value() << " " << address + << " " << agent_path.value() << " " << capability; + callback.Run(dbus::ObjectPath(), false); + } + + // BluetoothAdapterClient override. + virtual void CancelDeviceCreation(const dbus::ObjectPath& object_path, + const std::string& address, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "CancelDeviceCreation: " << object_path.value() + << " " << address; + callback.Run(object_path, false); + } + + // BluetoothAdapterClient override. + virtual void RemoveDevice(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "RemoveDevice: " << object_path.value() + << " " << device_path.value(); + callback.Run(object_path, false); + } + + // BluetoothAdapterClient override. + virtual void RegisterAgent(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& agent_path, + const std::string& capability, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "RegisterAgent: " << object_path.value() + << " " << agent_path.value(); + callback.Run(object_path, false); + } + + // BluetoothAdapterClient override. + virtual void UnregisterAgent(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& agent_path, + const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "UnregisterAgent: " << object_path.value() + << " " << agent_path.value(); + callback.Run(object_path, false); + } +}; + +BluetoothAdapterClient::BluetoothAdapterClient() { +} + +BluetoothAdapterClient::~BluetoothAdapterClient() { +} + +BluetoothAdapterClient* BluetoothAdapterClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothManagerClient* manager_client) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new BluetoothAdapterClientImpl(bus, manager_client); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new BluetoothAdapterClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/bluetooth_adapter_client.h b/chromeos/dbus/bluetooth_adapter_client.h new file mode 100644 index 0000000..6e59429 --- /dev/null +++ b/chromeos/dbus/bluetooth_adapter_client.h @@ -0,0 +1,244 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_ +#define CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/bluetooth_device_client.h" +#include "chromeos/dbus/bluetooth_property.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "dbus/object_path.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +class BluetoothManagerClient; + +// BluetoothAdapterClient is used to communicate with a bluetooth Adapter +// interface. +class CHROMEOS_EXPORT BluetoothAdapterClient { + public: + // Structure of properties associated with bluetooth adapters. + struct Properties : public BluetoothPropertySet { + // The Bluetooth device address of the adapter. Read-only. + BluetoothProperty<std::string> address; + + // The Bluetooth friendly name of the adapter, unlike remote devices, + // this property can be changed to change the presentation for when + // the adapter is discoverable. + BluetoothProperty<std::string> name; + + // The Bluetooth class of the adapter device. Read-only. + BluetoothProperty<uint32> bluetooth_class; + + // Whether the adapter radio is powered. + BluetoothProperty<bool> powered; + + // Whether the adapter is discoverable by other Bluetooth devices. + // |discovering_timeout| is used to automatically disable after a time + // period. + BluetoothProperty<bool> discoverable; + + // Whether the adapter accepts incoming pairing requests from other + // Bluetooth devices. |pairable_timeout| is used to automatically disable + // after a time period. + BluetoothProperty<bool> pairable; + + // The timeout in seconds to cease accepting incoming pairing requests + // after |pairable| is set to true. Zero means adapter remains pairable + // forever. + BluetoothProperty<uint32> pairable_timeout; + + // The timeout in seconds to cease the adapter being discoverable by + // other Bluetooth devices after |discoverable| is set to true. Zero + // means adapter remains discoverable forever. + BluetoothProperty<uint32> discoverable_timeout; + + // Indicates that the adapter is discovering other Bluetooth Devices. + // Read-only. Use StartDiscovery() to begin discovery. + BluetoothProperty<bool> discovering; + + // List of object paths of known Bluetooth devices, known devices are + // those that have previously been connected or paired or are currently + // connected or paired. Read-only. + BluetoothProperty<std::vector<dbus::ObjectPath> > devices; + + // List of 128-bit UUIDs that represent the available local services. + // Read-only. + BluetoothProperty<std::vector<std::string> > uuids; + + Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback); + virtual ~Properties(); + }; + + // Interface for observing changes from a local bluetooth adapter. + class Observer { + public: + virtual ~Observer() {} + + // Called when the adapter with object path |object_path| has a + // change in value of the property named |property_name|. + virtual void AdapterPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + + // Called when the adapter with object path |object_path| has a + // new known device with object path |object_path|. + virtual void DeviceCreated(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path) {} + + // Called when the adapter with object path |object_path| removes + // the known device with object path |object_path|. + virtual void DeviceRemoved(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path) {} + + // Called when the adapter with object path |object_path| discovers + // a new remote device with address |address| and properties + // |properties|, there is no device object path until connected. + // + // |properties| supports only value() calls, not Get() or Set(), and + // should be copied if needed. + virtual void DeviceFound( + const dbus::ObjectPath& object_path, const std::string& address, + const BluetoothDeviceClient::Properties& properties) {} + + // Called when the adapter with object path |object_path| can no + // longer communicate with the discovered removed device with + // address |address|. + virtual void DeviceDisappeared(const dbus::ObjectPath& object_path, + const std::string& address) {} + }; + + virtual ~BluetoothAdapterClient(); + + // Adds and removes observers for events on all local bluetooth + // adapters. Check the |object_path| parameter of observer methods to + // determine which adapter is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Obtain the properties for the adapter with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // The AdapterCallback is used for adapter methods that only return to + // indicate success. It receives two arguments, the |object_path| of the + // adapter the call was made on and |success| which indicates whether + // or not the request succeeded. + typedef base::Callback<void(const dbus::ObjectPath&, bool)> AdapterCallback; + + // Request a client session for the adapter with object path |object_path|, + // possible mode changes must be confirmed by the user via a registered + // agent. + virtual void RequestSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) = 0; + + // Release a previously requested session, restoring the adapter mode to + // that prior to the original request. + virtual void ReleaseSession(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) = 0; + + // Starts a device discovery on the adapter with object path |object_path|. + virtual void StartDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) = 0; + + // Cancels any previous device discovery on the adapter with object path + // |object_path|. + virtual void StopDiscovery(const dbus::ObjectPath& object_path, + const AdapterCallback& callback) = 0; + + // The DeviceCallback is used for adapter methods that return a dbus + // object path for a remote device, as well as success. It receives two + // arguments, the |object_path| of the device returned by the method and + // |success| which indicates whether or not the request succeeded. + typedef base::Callback<void(const dbus::ObjectPath&, bool)> DeviceCallback; + + // Retrieves the dbus object path from the adapter with object path + // |object_path| for the known device with the address |address|. + virtual void FindDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const DeviceCallback& callback) = 0; + + // Creates a new dbus object from the adapter with object path |object_path| + // to the remote device with address |address|, connecting to it and + // retrieving all SDP records. After a successful call, the device is known + // and appear's in the adapter's |devices| interface. This is a low-security + // connection which may not be accepted by the device. + virtual void CreateDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const DeviceCallback& callback) = 0; + + // Creates a new dbus object from the adapter with object path |object_path| + // to the remote device with address |address|, connecting to it, retrieving + // all SDP records and then initiating a pairing. If CreateDevice() has been + // previously called for this device, this only initiates the pairing. + // + // The dbus object path |agent_path| of an agent within the local process + // must be specified to negotiate the pairing, |capability| specifies the + // input and display capabilities of that agent and should be one of the + // constants declared in the bluetooth_agent:: namespace. + virtual void CreatePairedDevice(const dbus::ObjectPath& object_path, + const std::string& address, + const dbus::ObjectPath& agent_path, + const std::string& capability, + const DeviceCallback& callback) = 0; + + // Cancels the currently in progress call to CreateDevice() or + // CreatePairedDevice() on the adapter with object path |object_path| + // for the remote device with address |address|. + virtual void CancelDeviceCreation(const dbus::ObjectPath& object_path, + const std::string& address, + const AdapterCallback& callback) = 0; + + // Removes from the adapter with object path |object_path| the remote + // device with object path |object_path| from the list of known devices + // and discards any pairing information. + virtual void RemoveDevice(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& device_path, + const AdapterCallback& callback) = 0; + + // Registers an adapter-wide agent for the adapter with object path + // |object_path|. This agent is used for incoming pairing connections + // and confirmation of adapter mode changes. The dbus object path + // |agent_path| of an agent within the local process must be specified, + // |capability| specifies the input and display capabilities of that + // agent and should be one of the constants declared in the + // bluetooth_agent:: namespace. + virtual void RegisterAgent(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& agent_path, + const std::string& capability, + const AdapterCallback& callback) = 0; + + // Unregisters an adapter-wide agent with object path |agent_path| from + // the adapter with object path |object_path|. + virtual void UnregisterAgent(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& agent_path, + const AdapterCallback& callback) = 0; + + // Creates the instance. + static BluetoothAdapterClient* Create(DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothManagerClient* manager_client); + + protected: + BluetoothAdapterClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLUETOOTH_ADAPTER_CLIENT_H_ diff --git a/chromeos/dbus/bluetooth_agent_service_provider.cc b/chromeos/dbus/bluetooth_agent_service_provider.cc new file mode 100644 index 0000000..aea7291 --- /dev/null +++ b/chromeos/dbus/bluetooth_agent_service_provider.cc @@ -0,0 +1,568 @@ +// 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_agent_service_provider.h" + +#include <string> + +#include "base/bind.h" +#include "base/chromeos/chromeos_version.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/threading/platform_thread.h" +#include "dbus/bus.h" +#include "dbus/exported_object.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace { + +// Constants used by BlueZ for the ConfirmModeChange method. +const char kModeOff[] = "off"; +const char kModeConnectable[] = "connectable"; +const char kModeDiscoverable[] = "discoverable"; + +} // namespace + +namespace chromeos { + +// The BluetoothAgentServiceProvider implementation used in production. +class BluetoothAgentServiceProviderImpl : public BluetoothAgentServiceProvider { + public: + BluetoothAgentServiceProviderImpl(dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) + : weak_ptr_factory_(this), + origin_thread_id_(base::PlatformThread::CurrentId()), + bus_(bus), + delegate_(delegate), + object_path_(object_path) { + DVLOG(1) << "Creating BluetoothAdapterClientImpl for " + << object_path.value(); + + exported_object_ = bus_->GetExportedObject(object_path_); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRelease, + base::Bind(&BluetoothAgentServiceProviderImpl::Release, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::ReleaseExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRequestPinCode, + base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCode, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCodeExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRequestPasskey, + base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskey, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskeyExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kDisplayPinCode, + base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCode, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCodeExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kDisplayPasskey, + base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskey, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskeyExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kRequestConfirmation, + base::Bind(&BluetoothAgentServiceProviderImpl::RequestConfirmation, + weak_ptr_factory_.GetWeakPtr()), + base::Bind( + &BluetoothAgentServiceProviderImpl::RequestConfirmationExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kAuthorize, + base::Bind(&BluetoothAgentServiceProviderImpl::Authorize, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::AuthorizeExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kConfirmModeChange, + base::Bind(&BluetoothAgentServiceProviderImpl::ConfirmModeChange, + weak_ptr_factory_.GetWeakPtr()), + base::Bind( + &BluetoothAgentServiceProviderImpl::ConfirmModeChangeExported, + weak_ptr_factory_.GetWeakPtr())); + + exported_object_->ExportMethod( + bluetooth_agent::kBluetoothAgentInterface, + bluetooth_agent::kCancel, + base::Bind(&BluetoothAgentServiceProviderImpl::Cancel, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothAgentServiceProviderImpl::CancelExported, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual ~BluetoothAgentServiceProviderImpl() { + // Unregister the object path so we can reuse with a new agent. + bus_->UnregisterExportedObject(object_path_); + } + + private: + // Returns true if the current thread is on the origin thread. + bool OnOriginThread() { + return base::PlatformThread::CurrentId() == origin_thread_id_; + } + + // Called by dbus:: when the agent is unregistered from the Bluetooth + // daemon, generally at the end of a pairing request. + void Release(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Release(); + + dbus::Response* response = dbus::Response::FromMethodCall(method_call); + response_sender.Run(response); + } + + // Called by dbus:: when the Release method is exported. + void ReleaseExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the Bluetooth daemon requires a PIN Code for + // device authentication. + void RequestPinCode(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "RequestPinCode called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::PinCodeCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnPinCode, + weak_ptr_factory_.GetWeakPtr(), + method_call, + response_sender); + + delegate_->RequestPinCode(device_path, callback); + } + + // Called by dbus:: when the RequestPinCode method is exported. + void RequestPinCodeExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the Bluetooth daemon requires a Passkey for + // device authentication. + void RequestPasskey(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + if (!reader.PopObjectPath(&device_path)) { + LOG(WARNING) << "RequestPasskey called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::PasskeyCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnPasskey, + weak_ptr_factory_.GetWeakPtr(), + method_call, + response_sender); + + delegate_->RequestPasskey(device_path, callback); + } + + // Called by dbus:: when the RequestPasskey method is exported. + void RequestPasskeyExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // enter a PIN Code into the remote device so that it may be + // authenticated. + void DisplayPinCode(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + std::string pincode; + if (!reader.PopObjectPath(&device_path) || + !reader.PopString(&pincode)) { + LOG(WARNING) << "DisplayPinCode called with incorrect paramters: " + << method_call->ToString(); + return; + } + + delegate_->DisplayPinCode(device_path, pincode); + + dbus::Response* response = dbus::Response::FromMethodCall(method_call); + response_sender.Run(response); + } + + // Called by dbus:: when the DisplayPinCode method is exported. + void DisplayPinCodeExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // enter a Passkey into the remote device so that it may be + // authenticated. + void DisplayPasskey(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + uint32 passkey; + if (!reader.PopObjectPath(&device_path) || + !reader.PopUint32(&passkey)) { + LOG(WARNING) << "DisplayPasskey called with incorrect paramters: " + << method_call->ToString(); + return; + } + + delegate_->DisplayPasskey(device_path, passkey); + + dbus::Response* response = dbus::Response::FromMethodCall(method_call); + response_sender.Run(response); + } + + // Called by dbus:: when the DisplayPasskey method is exported. + void DisplayPasskeyExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // confirm that a Passkey is displayed on the screen of the remote + // device so that it may be authenticated. + void RequestConfirmation( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + uint32 passkey; + if (!reader.PopObjectPath(&device_path) || + !reader.PopUint32(&passkey)) { + LOG(WARNING) << "RequestConfirmation called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), + method_call, + response_sender); + + delegate_->RequestConfirmation(device_path, passkey, callback); + } + + // Called by dbus:: when the RequestConfirmation method is exported. + void RequestConfirmationExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // confirm that that a remote device is authorized to connect to a service + // UUID. + void Authorize(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + dbus::ObjectPath device_path; + std::string uuid; + if (!reader.PopObjectPath(&device_path) || + !reader.PopString(&uuid)) { + LOG(WARNING) << "Authorize called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), + method_call, + response_sender); + + delegate_->Authorize(device_path, uuid, callback); + } + + // Called by dbus:: when the Authorize method is exported. + void AuthorizeExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the Bluetooth daemon requires that the user + // confirm that the adapter may change mode. + void ConfirmModeChange(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + dbus::MessageReader reader(method_call); + std::string mode_str; + if (!reader.PopString(&mode_str)) { + LOG(WARNING) << "ConfirmModeChange called with incorrect paramters: " + << method_call->ToString(); + return; + } + + Delegate::Mode mode; + if (mode_str == kModeOff) { + mode = Delegate::OFF; + } else if (mode_str == kModeConnectable) { + mode = Delegate::CONNECTABLE; + } else if (mode_str == kModeDiscoverable) { + mode = Delegate::DISCOVERABLE; + } else { + LOG(WARNING) << "ConfirmModeChange called with unknown mode: " + << mode_str; + return; + } + + Delegate::ConfirmationCallback callback = base::Bind( + &BluetoothAgentServiceProviderImpl::OnConfirmation, + weak_ptr_factory_.GetWeakPtr(), + method_call, + response_sender); + + delegate_->ConfirmModeChange(mode, callback); + } + + // Called by dbus:: when the ConfirmModeChange method is exported. + void ConfirmModeChangeExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by dbus:: when the request failed before a reply was returned + // from the device. + void Cancel(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + DCHECK(OnOriginThread()); + DCHECK(delegate_); + + delegate_->Cancel(); + + dbus::Response* response = dbus::Response::FromMethodCall(method_call); + response_sender.Run(response); + } + + // Called by dbus:: when the Cancel method is exported. + void CancelExported(const std::string& interface_name, + const std::string& method_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to export " + << interface_name << "." << method_name; + } + + // Called by the Delegate to response to a method requesting a PIN code. + void OnPinCode(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + Delegate::Status status, + const std::string& pincode) { + DCHECK(OnOriginThread()); + + switch (status) { + case Delegate::SUCCESS: { + dbus::Response* response = dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response); + writer.AppendString(pincode); + response_sender.Run(response); + break; + } + case Delegate::REJECTED: { + dbus::ErrorResponse* response = dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorRejected, "rejected"); + response_sender.Run(response); + break; + } + case Delegate::CANCELLED: { + dbus::ErrorResponse* response = dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorCanceled, "canceled"); + response_sender.Run(response); + break; + } + default: + NOTREACHED() << "Unexpected status code from delegate: " << status; + } + } + + // Called by the Delegate to response to a method requesting a Passkey. + void OnPasskey(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + Delegate::Status status, + uint32 passkey) { + DCHECK(OnOriginThread()); + + switch (status) { + case Delegate::SUCCESS: { + dbus::Response* response = dbus::Response::FromMethodCall(method_call); + dbus::MessageWriter writer(response); + writer.AppendUint32(passkey); + response_sender.Run(response); + break; + } + case Delegate::REJECTED: { + dbus::ErrorResponse* response = dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorRejected, "rejected"); + response_sender.Run(response); + break; + } + case Delegate::CANCELLED: { + dbus::ErrorResponse* response = dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorCanceled, "canceled"); + response_sender.Run(response); + break; + } + default: + NOTREACHED() << "Unexpected status code from delegate: " << status; + } + } + + // Called by the Delegate in response to a method requiring confirmation. + void OnConfirmation(dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender, + Delegate::Status status) { + DCHECK(OnOriginThread()); + + switch (status) { + case Delegate::SUCCESS: { + dbus::Response* response = dbus::Response::FromMethodCall(method_call); + response_sender.Run(response); + break; + } + case Delegate::REJECTED: { + dbus::ErrorResponse* response = dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorRejected, "rejected"); + response_sender.Run(response); + break; + } + case Delegate::CANCELLED: { + dbus::ErrorResponse* response = dbus::ErrorResponse::FromMethodCall( + method_call, bluetooth_agent::kErrorCanceled, "canceled"); + response_sender.Run(response); + break; + } + default: + NOTREACHED() << "Unexpected status code from delegate: " << status; + } + } + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + base::WeakPtrFactory<BluetoothAgentServiceProviderImpl> weak_ptr_factory_; + + // Origin thread (i.e. the UI thread in production). + base::PlatformThreadId origin_thread_id_; + + // D-Bus bus object is exported on, not owned by this object and must + // outlive it. + dbus::Bus* bus_; + + // All incoming method calls are passed on to the Delegate and a callback + // passed to generate the reply. |delegate_| is generally the object that + // owns this one, and must outlive it. + Delegate* delegate_; + + // D-Bus object path of object we are exporting, kept so we can unregister + // again in our destructor. + dbus::ObjectPath object_path_; + + // D-Bus object we are exporting, owned by this object. + scoped_refptr<dbus::ExportedObject> exported_object_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl); +}; + +// The BluetoothAgentServiceProvider implementation used on Linux desktop, +// which does nothing. +class BluetoothAgentServiceProviderStubImpl + : public BluetoothAgentServiceProvider { + public: + explicit BluetoothAgentServiceProviderStubImpl(Delegate* delegate_) { + } + + virtual ~BluetoothAgentServiceProviderStubImpl() { + } +}; + +BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() { +} + +BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() { +} + +// static +BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create( + dbus::Bus* bus, + const dbus::ObjectPath& object_path, + Delegate* delegate) { + if (base::chromeos::IsRunningOnChromeOS()) { + return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate); + } else { + return new BluetoothAgentServiceProviderStubImpl(delegate); + } +} + +} // namespace chromeos diff --git a/chromeos/dbus/bluetooth_agent_service_provider.h b/chromeos/dbus/bluetooth_agent_service_provider.h new file mode 100644 index 0000000..8e4178c --- /dev/null +++ b/chromeos/dbus/bluetooth_agent_service_provider.h @@ -0,0 +1,179 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ +#define CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "dbus/bus.h" +#include "dbus/object_path.h" + +namespace chromeos { + +// BluetoothAgentServiceProvider is used to provide a D-Bus object that BlueZ +// can communicate with during a remote device pairing request. +// +// Instantiate with a chosen D-Bus object path and delegate object, and pass +// the D-Bus object path as the |agent_path| argument to the +// chromeos::BluetoothAdapterClient::CreatePairedDevice() method. Calls made +// to the agent by the Bluetooth daemon will be passed on to your Delegate +// object for handling, and responses returned using the callbacks supplied +// to those methods. +class CHROMEOS_EXPORT BluetoothAgentServiceProvider { + public: + // Interface for reacting to agent requests. + class Delegate { + public: + virtual ~Delegate() {} + + // Possible status values that may be returned to callbacks. Success + // indicates that a pincode or passkey has been obtained, or permission + // granted; rejected indicates the user rejected the request or denied + // permission; cancelled indicates the user cancelled the request + // without confirming either way. + enum Status { + SUCCESS, + REJECTED, + CANCELLED + }; + + // Possible values for the |mode| parameter of the ConfirmModeChange() + // method. Off indicates that the adapter is to be turned off, connectable + // indicates that the adapter is to be turned on and accept incoming + // connections, and discoverable indicates the adapter is to be turned + // on and discoverable by remote devices. + enum Mode { + OFF, + CONNECTABLE, + DISCOVERABLE + }; + + // The PinCodeCallback is used for the RequestPinCode() method, it should + // be called with two arguments, the |status| of the request (success, + // rejected or cancelled) and the |pincode| requested. + typedef base::Callback<void(Status, const std::string&)> PinCodeCallback; + + // The PasskeyCallback is used for the RequestPasskey() method, it should + // be called with two arguments, the |status| of the request (success, + // rejected or cancelled) and the |passkey| requested, a numeric in the + // range 0-999999, + typedef base::Callback<void(Status, uint32)> PasskeyCallback; + + // The ConfirmationCallback is used for methods which request confirmation + // or authorization, it should be called with one argument, the |status| + // of the request (success, rejected or cancelled). + typedef base::Callback<void(Status)> ConfirmationCallback; + + // This method will be called when the agent is unregistered from the + // Bluetooth daemon, generally at the end of a pairing request. It may be + // used to perform cleanup tasks. + virtual void Release() = 0; + + // This method will be called when the Bluetooth daemon requires a + // PIN Code for authentication of the device with object path |device_path|, + // the agent should obtain the code from the user and call |callback| + // to provide it, or indicate rejection or cancellation of the request. + // + // PIN Codes are generally required for Bluetooth 2.0 and earlier devices + // for which there is no automatic pairing or special handling. + virtual void RequestPinCode(const dbus::ObjectPath& device_path, + const PinCodeCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires a + // Passkey for authentication of the device with object path |device_path|, + // the agent should obtain the passkey from the user (a numeric in the + // range 0-999999) and call |callback| to provide it, or indicate + // rejection or cancellation of the request. + // + // Passkeys are generally required for Bluetooth 2.1 and later devices + // which cannot provide input or display on their own, and don't accept + // passkey-less pairing. + virtual void RequestPasskey(const dbus::ObjectPath& device_path, + const PasskeyCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user enter the PIN code |pincode| into the device with object path + // |device_path| so that it may be authenticated. The Cancel() method + // will be called to dismiss the display once pairing is complete or + // cancelled. + // + // This is used for Bluetooth 2.0 and earlier keyboard devices, the + // |pincode| will always be a six-digit numeric in the range 000000-999999 + // for compatibilty with later specifications. + virtual void DisplayPinCode(const dbus::ObjectPath& device_path, + const std::string& pincode) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user enter the Passkey |passkey| into the device with object path + // |device_path| so that it may be authenticated. The Cancel() method + // will be called to dismiss the display once pairing is complete or + // cancelled. + // + // This is used for Bluetooth 2.1 and later devices that support input + // but not display, such as keyboards. The Passkey is a numeric in the + // range 0-999999 and should be always presented zero-padded to six + // digits. + virtual void DisplayPasskey(const dbus::ObjectPath& device_path, + uint32 passkey) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user confirm that the Passkey |passkey| is displayed on the screen + // of the device with object path |object_path| so that it may be + // authenticated. The agent should display to the user and ask for + // confirmation, then call |callback| to provide their response (success, + // rejected or cancelled). + // + // This is used for Bluetooth 2.1 and later devices that support display, + // such as other computers or phones. The Passkey is a numeric in the + // range 0-999999 and should be always present zero-padded to six + // digits. + virtual void RequestConfirmation(const dbus::ObjectPath& device_path, + uint32 passkey, + const ConfirmationCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user confirm that the device with object path |object_path| is + // authorized to connect to the service with UUID |uuid|. The agent should + // confirm with the user and call |callback| to provide their response + // (success, rejected or cancelled). + virtual void Authorize(const dbus::ObjectPath& device_path, + const std::string& uuid, + const ConfirmationCallback& callback) = 0; + + // This method will be called when the Bluetooth daemon requires that the + // user confirm that the device adapter may switch to mode |mode|. The + // agent should confirm with the user and call |callback| to provide + // their response (success, rejected or cancelled). + virtual void ConfirmModeChange(Mode mode, + const ConfirmationCallback& callback) = 0; + + // This method will be called by the Bluetooth daemon to indicate that + // the request failed before a reply was returned from the device. + virtual void Cancel() = 0; + }; + + virtual ~BluetoothAgentServiceProvider(); + + // Creates the instance where |bus| is the D-Bus bus connection to export + // the object onto, |object_path| is the object path that it should have + // and |delegate| is the object to which all method calls will be passed + // and responses generated from. + static BluetoothAgentServiceProvider* Create( + dbus::Bus* bus, const dbus::ObjectPath& object_path, Delegate* delegate); + + protected: + BluetoothAgentServiceProvider(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProvider); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLUETOOTH_AGENT_SERVICE_PROVIDER_H_ diff --git a/chromeos/dbus/bluetooth_device_client.cc b/chromeos/dbus/bluetooth_device_client.cc new file mode 100644 index 0000000..a4ce54b4 --- /dev/null +++ b/chromeos/dbus/bluetooth_device_client.cc @@ -0,0 +1,539 @@ +// 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_device_client.h" + +#include <map> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "chromeos/dbus/bluetooth_adapter_client.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 { + +BluetoothDeviceClient::Properties::Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback) + : BluetoothPropertySet(object_proxy, + bluetooth_device::kBluetoothDeviceInterface, + callback) { + RegisterProperty(bluetooth_device::kAddressProperty, &address); + RegisterProperty(bluetooth_device::kNameProperty, &name); + RegisterProperty(bluetooth_device::kVendorProperty, &vendor); + RegisterProperty(bluetooth_device::kProductProperty, &product); + RegisterProperty(bluetooth_device::kVersionProperty, &version); + RegisterProperty(bluetooth_device::kIconProperty, &icon); + RegisterProperty(bluetooth_device::kClassProperty, &bluetooth_class); + RegisterProperty(bluetooth_device::kUUIDsProperty, &uuids); + RegisterProperty(bluetooth_device::kServicesProperty, &services); + RegisterProperty(bluetooth_device::kPairedProperty, &paired); + RegisterProperty(bluetooth_device::kConnectedProperty, &connected); + RegisterProperty(bluetooth_device::kTrustedProperty, &trusted); + RegisterProperty(bluetooth_device::kBlockedProperty, &blocked); + RegisterProperty(bluetooth_device::kAliasProperty, &alias); + RegisterProperty(bluetooth_device::kNodesProperty, &nodes); + RegisterProperty(bluetooth_device::kAdapterProperty, &adapter); + RegisterProperty(bluetooth_device::kLegacyPairingProperty, &legacy_pairing); +} + +BluetoothDeviceClient::Properties::~Properties() { +} + + +// The BluetoothDeviceClient implementation used in production. +class BluetoothDeviceClientImpl: public BluetoothDeviceClient, + private BluetoothAdapterClient::Observer { + public: + BluetoothDeviceClientImpl(dbus::Bus* bus, + BluetoothAdapterClient* adapter_client) + : weak_ptr_factory_(this), + bus_(bus) { + DVLOG(1) << "Creating BluetoothDeviceClientImpl"; + + DCHECK(adapter_client); + adapter_client->AddObserver(this); + } + + virtual ~BluetoothDeviceClientImpl() { + // Clean up Properties structures + for (ObjectMap::iterator iter = object_map_.begin(); + iter != object_map_.end(); ++iter) { + Object object = iter->second; + Properties* properties = object.second; + delete properties; + } + } + + // BluetoothDeviceClient override. + virtual void AddObserver(BluetoothDeviceClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothDeviceClient override. + virtual void RemoveObserver(BluetoothDeviceClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // BluetoothDeviceClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + return GetObject(object_path).second; + } + + // BluetoothDeviceClient override. + virtual void DiscoverServices(const dbus::ObjectPath& object_path, + const std::string& pattern, + const ServicesCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kDiscoverServices); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(pattern); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnDiscoverServices, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothDeviceClient override. + virtual void CancelDiscovery(const dbus::ObjectPath& object_path, + const DeviceCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kCancelDiscovery); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnCancelDiscovery, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothDeviceClient override. + virtual void Disconnect(const dbus::ObjectPath& object_path, + const DeviceCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kDisconnect); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnDisconnect, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothDeviceClient override. + virtual void CreateNode(const dbus::ObjectPath& object_path, + const std::string& uuid, + const NodeCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kCreateNode); + + dbus::MessageWriter writer(&method_call); + writer.AppendString(uuid); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnCreateNode, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothDeviceClient override. + virtual void RemoveNode(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& node_path, + const DeviceCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kRemoveNode); + + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(node_path); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothDeviceClientImpl::OnRemoveNode, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + private: + // We maintain a collection of dbus object proxies and properties structures + // for each device. + typedef std::pair<dbus::ObjectProxy*, Properties*> Object; + typedef std::map<const dbus::ObjectPath, Object> ObjectMap; + ObjectMap object_map_; + + // BluetoothAdapterClient::Observer override. + virtual void DeviceCreated(const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& object_path) OVERRIDE { + } + + // BluetoothAdapterClient::Observer override. + virtual void DeviceRemoved(const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& object_path) OVERRIDE { + RemoveObject(object_path); + } + + // Ensures that we have an object proxy and properties structure for + // a device with object path |object_path|, creating it if not and + // storing it in our |object_map_| map. + Object GetObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) + return iter->second; + + // Create the object proxy. + DCHECK(bus_); + dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy( + bluetooth_device::kBluetoothDeviceServiceName, object_path); + + object_proxy->ConnectToSignal( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kDisconnectRequestedSignal, + base::Bind(&BluetoothDeviceClientImpl::DisconnectRequestedReceived, + weak_ptr_factory_.GetWeakPtr(), object_path), + base::Bind(&BluetoothDeviceClientImpl::DisconnectRequestedConnected, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + object_proxy->ConnectToSignal( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kNodeCreatedSignal, + base::Bind(&BluetoothDeviceClientImpl::NodeCreatedReceived, + weak_ptr_factory_.GetWeakPtr(), object_path), + base::Bind(&BluetoothDeviceClientImpl::NodeCreatedConnected, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + object_proxy->ConnectToSignal( + bluetooth_device::kBluetoothDeviceInterface, + bluetooth_device::kNodeRemovedSignal, + base::Bind(&BluetoothDeviceClientImpl::NodeRemovedReceived, + weak_ptr_factory_.GetWeakPtr(), object_path), + base::Bind(&BluetoothDeviceClientImpl::NodeRemovedConnected, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + // Create the properties structure. + Properties* properties = new Properties( + object_proxy, + base::Bind(&BluetoothDeviceClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + properties->ConnectSignals(); + properties->GetAll(); + + Object object = std::make_pair(object_proxy, properties); + object_map_[object_path] = object; + return object; + } + + // Removes the dbus object proxy and properties for the device with + // dbus object path |object_path| from our |object_map_| map. + void RemoveObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) { + // Clean up the Properties structure. + Object object = iter->second; + Properties* properties = object.second; + delete properties; + + object_map_.erase(iter); + } + } + + // Returns a pointer to the object proxy for |object_path|, creating + // it if necessary. + dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) { + return GetObject(object_path).first; + } + + // 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 dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DevicePropertyChanged(object_path, property_name)); + } + + // Called by dbus:: when a DisconnectRequested signal is received. + void DisconnectRequestedReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + + DVLOG(1) << object_path.value() << ": Disconnect requested."; + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + DisconnectRequested(object_path)); + } + + // Called by dbus:: when the DisconnectRequested signal is initially + // connected. + void DisconnectRequestedConnected(const dbus::ObjectPath& object_path, + const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << object_path.value() + << ": Failed to connect to " + "DisconnectRequested signal."; + } + + // Called by dbus:: when a NodeCreated signal is received. + void NodeCreatedReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + dbus::MessageReader reader(signal); + dbus::ObjectPath node_path; + if (!reader.PopObjectPath(&node_path)) { + LOG(WARNING) << object_path.value() + << ": NodeCreated signal has incorrect parameters: " + << signal->ToString(); + return; + } + + DVLOG(1) << object_path.value() << ": Node created: " + << node_path.value(); + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + NodeCreated(object_path, node_path)); + } + + // Called by dbus:: when the NodeCreated signal is initially connected. + void NodeCreatedConnected(const dbus::ObjectPath& object_path, + const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << object_path.value() + << ": Failed to connect to NodeCreated signal."; + } + + // Called by dbus:: when a NodeRemoved signal is received. + void NodeRemovedReceived(const dbus::ObjectPath& object_path, + dbus::Signal* signal) { + DCHECK(signal); + dbus::MessageReader reader(signal); + dbus::ObjectPath node_path; + if (!reader.PopObjectPath(&node_path)) { + LOG(WARNING) << object_path.value() + << ": NodeRemoved signal has incorrect parameters: " + << signal->ToString(); + return; + } + + DVLOG(1) << object_path.value() << ": Node removed: " + << node_path.value(); + FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, + NodeRemoved(object_path, node_path)); + } + + // Called by dbus:: when the NodeRemoved signal is initially connected. + void NodeRemovedConnected(const dbus::ObjectPath& object_path, + const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << object_path.value() + << ": Failed to connect to NodeRemoved signal."; + } + + // Called when a response for DiscoverServices() is received. + void OnDiscoverServices(const dbus::ObjectPath& object_path, + const ServicesCallback& callback, + dbus::Response* response) { + // Parse response. + bool success = false; + ServiceMap services; + if (response != NULL) { + dbus::MessageReader reader(response); + + dbus::MessageReader array_reader(NULL); + if (!reader.PopArray(&array_reader)) { + LOG(WARNING) << "DiscoverServices response has incorrect parameters: " + << response->ToString(); + } else { + while (array_reader.HasMoreData()) { + dbus::MessageReader dict_entry_reader(NULL); + uint32 key = 0; + std::string value; + if (!array_reader.PopDictEntry(&dict_entry_reader) + || !dict_entry_reader.PopUint32(&key) + || !dict_entry_reader.PopString(&value)) { + LOG(WARNING) << "DiscoverServices response has " + "incorrect parameters: " << response->ToString(); + } else { + services[key] = value; + } + } + + success = true; + } + } else { + LOG(WARNING) << "Failed to discover services."; + } + + // Notify client. + callback.Run(object_path, services, success); + } + + // Called when a response for CancelDiscovery() is received. + void OnCancelDiscovery(const dbus::ObjectPath& object_path, + const DeviceCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnCancelDiscovery: failed."; + callback.Run(object_path, response); + } + + // Called when a response for Disconnect() is received. + void OnDisconnect(const dbus::ObjectPath& object_path, + const DeviceCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnDisconnect: failed."; + callback.Run(object_path, response); + } + + // Called when a response for CreateNode() is received. + void OnCreateNode(const dbus::ObjectPath& object_path, + const NodeCallback& callback, + dbus::Response* response) { + // Parse response. + bool success = false; + dbus::ObjectPath node_path; + if (response != NULL) { + dbus::MessageReader reader(response); + if (!reader.PopObjectPath(&node_path)) { + LOG(WARNING) << "CreateNode response has incorrect parameters: " + << response->ToString(); + } else { + success = true; + } + } else { + LOG(WARNING) << "Failed to create node."; + } + + // Notify client. + callback.Run(node_path, success); + } + + // Called when a response for RemoveNode() is received. + void OnRemoveNode(const dbus::ObjectPath& object_path, + const DeviceCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnRemoveNode: failed."; + callback.Run(object_path, response); + } + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + base::WeakPtrFactory<BluetoothDeviceClientImpl> weak_ptr_factory_; + + dbus::Bus* bus_; + + // List of observers interested in event notifications from us. + ObserverList<BluetoothDeviceClient::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClientImpl); +}; + +// The BluetoothDeviceClient implementation used on Linux desktop, which does +// nothing. +class BluetoothDeviceClientStubImpl : public BluetoothDeviceClient { + public: + // BluetoothDeviceClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + } + + // BluetoothDeviceClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + } + + // BluetoothDeviceClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + VLOG(1) << "GetProperties: " << object_path.value(); + return NULL; + } + + // BluetoothDeviceClient override. + virtual void DiscoverServices(const dbus::ObjectPath& object_path, + const std::string& pattern, + const ServicesCallback& callback) OVERRIDE { + VLOG(1) << "DiscoverServices: " << object_path.value() << " " << pattern; + + ServiceMap services; + callback.Run(object_path, services, false); + } + + // BluetoothDeviceClient override. + virtual void CancelDiscovery(const dbus::ObjectPath& object_path, + const DeviceCallback& callback) OVERRIDE { + VLOG(1) << "CancelDiscovery: " << object_path.value(); + callback.Run(object_path, false); + } + + // BluetoothDeviceClient override. + virtual void Disconnect(const dbus::ObjectPath& object_path, + const DeviceCallback& callback) OVERRIDE { + VLOG(1) << "Disconnect: " << object_path.value(); + callback.Run(object_path, false); + } + + // BluetoothDeviceClient override. + virtual void CreateNode(const dbus::ObjectPath& object_path, + const std::string& uuid, + const NodeCallback& callback) OVERRIDE { + VLOG(1) << "CreateNode: " << object_path.value() << " " << uuid; + callback.Run(dbus::ObjectPath(), false); + } + + // BluetoothDeviceClient override. + virtual void RemoveNode(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& node_path, + const DeviceCallback& callback) OVERRIDE { + VLOG(1) << "RemoveNode: " << object_path.value() + << " " << node_path.value(); + callback.Run(object_path, false); + } +}; + +BluetoothDeviceClient::BluetoothDeviceClient() { +} + +BluetoothDeviceClient::~BluetoothDeviceClient() { +} + +BluetoothDeviceClient* BluetoothDeviceClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothAdapterClient* adapter_client) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new BluetoothDeviceClientImpl(bus, adapter_client); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new BluetoothDeviceClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/bluetooth_device_client.h b/chromeos/dbus/bluetooth_device_client.h new file mode 100644 index 0000000..cc82126 --- /dev/null +++ b/chromeos/dbus/bluetooth_device_client.h @@ -0,0 +1,212 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_ +#define CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_ +#pragma once + +#include <map> +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/bluetooth_property.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "dbus/object_path.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +class BluetoothAdapterClient; + +// BluetoothDeviceClient is used to communicate with a bluetooth Device +// interface. +class CHROMEOS_EXPORT BluetoothDeviceClient { + public: + // Structure of properties associated with bluetooth devices. + struct Properties : public BluetoothPropertySet { + // The Bluetooth device address of the device. Read-only. + BluetoothProperty<std::string> address; + + // The Bluetooth friendly name of the device. Read-only, to give a + // different local name, use the |alias| property. + BluetoothProperty<std::string> name; + + // Unique numeric identifier for the vendor of the device. Read-only. + BluetoothProperty<uint16> vendor; + + // Unique vendor-assigned product identifier for the product of the + // device. Read-only. + BluetoothProperty<uint16> product; + + // Unique vendor-assigned version identifier for the device. Read-only. + BluetoothProperty<uint16> version; + + // Proposed icon name for the device according to the freedesktop.org + // icon naming specification. Read-only. + BluetoothProperty<std::string> icon; + + // The Bluetooth class of the device. Read-only. + BluetoothProperty<uint32> bluetooth_class; + + // List of 128-bit UUIDs that represent the available remote services. + // Raed-only. + BluetoothProperty<std::vector<std::string> > uuids; + + // List of characteristics-based available remote services. Read-only. + BluetoothProperty<std::vector<dbus::ObjectPath> > services; + + // Indicates that the device is currently paired. Read-only. + BluetoothProperty<bool> paired; + + // Indicates that the device is currently connected. Read-only. + BluetoothProperty<bool> connected; + + // Whether the device is trusted, and connections should be always + // accepted and attempted when the device is visible. + BluetoothProperty<bool> trusted; + + // Whether the device is blocked, connections will be always rejected + // and the device will not be visible. + BluetoothProperty<bool> blocked; + + // Local alias for the device, if not set, is equal to |name|. + BluetoothProperty<std::string> alias; + + // List of object paths of nodes the device provides. Read-only. + BluetoothProperty<std::vector<dbus::ObjectPath> > nodes; + + // Object path of the adapter the device belongs to. Read-only. + BluetoothProperty<dbus::ObjectPath> adapter; + + // Indicates whether the device is likely to only support pre-2.1 + // PIN Code pairing rather than 2.1 Secure Simple Pairing, this can + // give false positives. Read-only. + BluetoothProperty<bool> legacy_pairing; + + Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback); + virtual ~Properties(); + }; + + // Interface for observing changes from a remote bluetooth device. + class Observer { + public: + virtual ~Observer() {} + + // Called when the device with object path |object_path| has a + // change in value of the property named |property_name|. + virtual void DevicePropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + + // Called when the device with object path |object_path| is about + // to be disconnected, giving a chance for application layers to + // shut down cleanly. + virtual void DisconnectRequested(const dbus::ObjectPath& object_path) {} + + // Called when the device with object path |object_path| has a new + // persistent device node with object path |node_path|. + virtual void NodeCreated(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& node_path) {} + + // Called when the device with object path |object_path| removes + // the persistent device node with object path |node_path|. + virtual void NodeRemoved(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& node_path) {} + }; + + virtual ~BluetoothDeviceClient(); + + // Adds and removes observers for events on all remote bluetooth + // devices. Check the |object_path| parameter of observer methods to + // determine which device is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Obtain the properties for the device with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // The Services map is used to convey the set of services discovered + // on a device. The keys are unique record handles and the values are + // XML-formatted service records. Both can be generated using the + // spdtool(1) binary distributed with bluetoothd. + typedef std::map<const uint32, std::string> ServiceMap; + + // The ServicesCallback is used for the DiscoverServices() method. It + // receives three arguments, the |object_path| of the device, the + // dictionary of the |services| discovered where the keys are unique + // record handles and the values are XML formatted service records, + // and |success| which indicates whether or not the request succeded. + typedef base::Callback<void(const dbus::ObjectPath&, const ServiceMap&, + bool)> ServicesCallback; + + // Starts the service discovery process for the device with object path + // |object_path|, the |pattern| paramter can be used to specify specific + // UUIDs while an empty string will look for the public browse group. + virtual void DiscoverServices(const dbus::ObjectPath& object_path, + const std::string& pattern, + const ServicesCallback& callback) = 0; + + // The DeviceCallback is used for device methods that only return to + // indicate success. It receives two arguments, the |object_path| of the + // device the call was made on and |success| which indicates whether or + // not the request succeeded. + typedef base::Callback<void(const dbus::ObjectPath&, bool)> DeviceCallback; + + // Cancels any previous service discovery processes for the device with + // object path |object_path|. + virtual void CancelDiscovery(const dbus::ObjectPath& object_path, + const DeviceCallback& callback) = 0; + + // Disconnects the device with object path |object_path|, terminating + // the low-level ACL connection and any application connections using it. + // Actual disconnection takes place after two seconds during which a + // DisconnectRequested signal is emitted by the device to allow those + // applications to terminate gracefully. + virtual void Disconnect(const dbus::ObjectPath& object_path, + const DeviceCallback& callback) = 0; + + // The NodeCallback is used for device methods that return a dbus + // object path for a persistent device node binding, as well as success. + // It receives two arguments, the |object_path| of the persistent device + // node binding object returned by the method and |success} which indicates + // whether or not the request succeeded. + typedef base::Callback<void(const dbus::ObjectPath&, bool)> NodeCallback; + + // Creates a persistent device node binding with the device with object path + // |object_path| using the specified service |uuid|. The actual support + // depends on the device driver, at the moment only RFCOMM TTY nodes are + // supported. + virtual void CreateNode(const dbus::ObjectPath& object_path, + const std::string& uuid, + const NodeCallback& callback) = 0; + + // Removes the persistent device node binding with the dbus object path + // |node_path| from the device with object path |object_path|. + virtual void RemoveNode(const dbus::ObjectPath& object_path, + const dbus::ObjectPath& node_path, + const DeviceCallback& callback) = 0; + + // Creates the instance. + static BluetoothDeviceClient* Create(DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothAdapterClient* adapter_client); + + protected: + BluetoothDeviceClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLUETOOTH_DEVICE_CLIENT_H_ diff --git a/chromeos/dbus/bluetooth_input_client.cc b/chromeos/dbus/bluetooth_input_client.cc new file mode 100644 index 0000000..6e9b890 --- /dev/null +++ b/chromeos/dbus/bluetooth_input_client.cc @@ -0,0 +1,264 @@ +// 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_input_client.h" + +#include <map> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "chromeos/dbus/bluetooth_adapter_client.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 { + +BluetoothInputClient::Properties::Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback) + : BluetoothPropertySet(object_proxy, + bluetooth_input::kBluetoothInputInterface, + callback) { + RegisterProperty(bluetooth_input::kConnectedProperty, &connected); +} + +BluetoothInputClient::Properties::~Properties() { +} + + +// The BluetoothInputClient implementation used in production. +class BluetoothInputClientImpl: public BluetoothInputClient, + private BluetoothAdapterClient::Observer { + public: + BluetoothInputClientImpl(dbus::Bus* bus, + BluetoothAdapterClient* adapter_client) + : weak_ptr_factory_(this), + bus_(bus) { + DVLOG(1) << "Creating BluetoothInputClientImpl"; + + DCHECK(adapter_client); + adapter_client->AddObserver(this); + } + + virtual ~BluetoothInputClientImpl() { + // Clean up Properties structures + for (ObjectMap::iterator iter = object_map_.begin(); + iter != object_map_.end(); ++iter) { + Object object = iter->second; + Properties* properties = object.second; + delete properties; + } + } + + // BluetoothInputClient override. + virtual void AddObserver(BluetoothInputClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothInputClient override. + virtual void RemoveObserver(BluetoothInputClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // BluetoothInputClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + return GetObject(object_path).second; + } + + // BluetoothInputClient override. + virtual void Connect(const dbus::ObjectPath& object_path, + const InputCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_input::kBluetoothInputInterface, + bluetooth_input::kConnect); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothInputClientImpl::OnConnect, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + // BluetoothInputClient override. + virtual void Disconnect(const dbus::ObjectPath& object_path, + const InputCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + bluetooth_input::kBluetoothInputInterface, + bluetooth_input::kDisconnect); + + dbus::ObjectProxy* object_proxy = GetObjectProxy(object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&BluetoothInputClientImpl::OnDisconnect, + weak_ptr_factory_.GetWeakPtr(), object_path, callback)); + } + + private: + // We maintain a collection of dbus object proxies and properties structures + // for each input device. + typedef std::pair<dbus::ObjectProxy*, Properties*> Object; + typedef std::map<const dbus::ObjectPath, Object> ObjectMap; + ObjectMap object_map_; + + // BluetoothAdapterClient::Observer override. + virtual void DeviceCreated(const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& object_path) OVERRIDE { + } + + // BluetoothAdapterClient::Observer override. + virtual void DeviceRemoved(const dbus::ObjectPath& adapter_path, + const dbus::ObjectPath& object_path) OVERRIDE { + RemoveObject(object_path); + } + + // Ensures that we have an object proxy and properties structure for + // an input device with object path |object_path|, creating it if not and + // storing it in our |object_map_| map. + Object GetObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) + return iter->second; + + // Create the object proxy. + DCHECK(bus_); + dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy( + bluetooth_input::kBluetoothInputServiceName, object_path); + + // Create the properties structure. + Properties* properties = new Properties( + object_proxy, + base::Bind(&BluetoothInputClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + properties->ConnectSignals(); + properties->GetAll(); + + Object object = std::make_pair(object_proxy, properties); + object_map_[object_path] = object; + return object; + } + + // Removes the dbus object proxy and properties for the input device with + // dbus object path |object_path| from our |object_map_| map. + void RemoveObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) { + // Clean up the Properties structure. + Object object = iter->second; + Properties* properties = object.second; + delete properties; + + object_map_.erase(iter); + } + } + + // Returns a pointer to the object proxy for |object_path|, creating + // it if necessary. + dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) { + return GetObject(object_path).first; + } + + // 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 dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothInputClient::Observer, observers_, + InputPropertyChanged(object_path, property_name)); + } + + // Called when a response for Connect() is received. + void OnConnect(const dbus::ObjectPath& object_path, + const InputCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnConnect: failed."; + callback.Run(object_path, response); + } + + // Called when a response for Disconnect() is received. + void OnDisconnect(const dbus::ObjectPath& object_path, + const InputCallback& callback, + dbus::Response* response) { + LOG_IF(WARNING, !response) << object_path.value() + << ": OnDisconnect: failed."; + callback.Run(object_path, response); + } + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + base::WeakPtrFactory<BluetoothInputClientImpl> weak_ptr_factory_; + + dbus::Bus* bus_; + + // List of observers interested in event notifications from us. + ObserverList<BluetoothInputClient::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothInputClientImpl); +}; + +// The BluetoothInputClient implementation used on Linux desktop, which does +// nothing. +class BluetoothInputClientStubImpl : public BluetoothInputClient { + public: + // BluetoothInputClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + } + + // BluetoothInputClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + } + + // BluetoothInputClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + VLOG(1) << "GetProperties: " << object_path.value(); + return NULL; + } + + // BluetoothInputClient override. + virtual void Connect(const dbus::ObjectPath& object_path, + const InputCallback& callback) OVERRIDE { + VLOG(1) << "Connect: " << object_path.value(); + callback.Run(object_path, false); + } + + // BluetoothInputClient override. + virtual void Disconnect(const dbus::ObjectPath& object_path, + const InputCallback& callback) OVERRIDE { + VLOG(1) << "Disconnect: " << object_path.value(); + callback.Run(object_path, false); + } +}; + +BluetoothInputClient::BluetoothInputClient() { +} + +BluetoothInputClient::~BluetoothInputClient() { +} + +BluetoothInputClient* BluetoothInputClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothAdapterClient* adapter_client) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new BluetoothInputClientImpl(bus, adapter_client); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new BluetoothInputClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/bluetooth_input_client.h b/chromeos/dbus/bluetooth_input_client.h new file mode 100644 index 0000000..2c1e015 --- /dev/null +++ b/chromeos/dbus/bluetooth_input_client.h @@ -0,0 +1,96 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_ +#define CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_ +#pragma once + +#include <string> + +#include "base/callback.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/bluetooth_property.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "dbus/object_path.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +class BluetoothAdapterClient; + +// BluetoothInputClient is used to communicate with the Input interface +// of a bluetooth device, rather than the generic device interface. Input +// devices are those conforming to the Bluetooth SIG HID (Human Interface +// Device) Profile such as keyboards, mice, trackpads and joysticks. +class CHROMEOS_EXPORT BluetoothInputClient { + public: + // Structure of properties associated with bluetooth input devices. + struct Properties : public BluetoothPropertySet { + // Indicates that the device is currently connected. Read-only. + BluetoothProperty<bool> connected; + + Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback); + virtual ~Properties(); + }; + + // Interface for observing changes from a bluetooth input device. + class Observer { + public: + virtual ~Observer() {} + + // Called when the device with object path |object_path| has a + // change in value of the input property named |property_name|. + virtual void InputPropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + virtual ~BluetoothInputClient(); + + // Adds and removes observers for events on all bluetooth input + // devices. Check the |object_path| parameter of observer methods to + // determine which device is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Obtain the input properties for the device with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // The InputCallback is used for input device methods that only return to + // indicate success. It receives two arguments, the |object_path| of the + // input devuce the call was made on and |success| which indicates whether + // or not the request succeeded. + typedef base::Callback<void(const dbus::ObjectPath&, bool)> InputCallback; + + // Connects the input subsystem to the device with object path + // |object_path|, which should already be a known device on the adapter. + virtual void Connect(const dbus::ObjectPath& object_path, + const InputCallback& callback) = 0; + + // Disconnects the input subsystem from the device with object path + // |object_path| without terminating the low-level ACL connection, + virtual void Disconnect(const dbus::ObjectPath& object_path, + const InputCallback& callback) = 0; + + // Creates the instance. + static BluetoothInputClient* Create(DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothAdapterClient* adapter_client); + + protected: + BluetoothInputClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothInputClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLUETOOTH_INPUT_CLIENT_H_ diff --git a/chromeos/dbus/bluetooth_manager_client.cc b/chromeos/dbus/bluetooth_manager_client.cc new file mode 100644 index 0000000..1ff3f62 --- /dev/null +++ b/chromeos/dbus/bluetooth_manager_client.cc @@ -0,0 +1,316 @@ +// 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 "base/bind.h" +#include "base/logging.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, + 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) + : weak_ptr_factory_(this), + object_proxy_(NULL) { + DVLOG(1) << "Creating BluetoothManagerClientImpl"; + + // 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) { + 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; + } + + DVLOG(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; + } + + DVLOG(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; + } + + DVLOG(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); + } + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + base::WeakPtrFactory<BluetoothManagerClientImpl> weak_ptr_factory_; + + // 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<Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothManagerClientImpl); +}; + +// The BluetoothManagerClient implementation used on Linux desktop, which does +// nothing. +class BluetoothManagerClientStubImpl : public BluetoothManagerClient { + public: + // BluetoothManagerClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + } + + // BluetoothManagerClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + } + + // BluetoothManagerClient override. + virtual Properties* GetProperties() OVERRIDE { + VLOG(1) << "GetProperties"; + return NULL; + } + + // BluetoothManagerClient override. + virtual void DefaultAdapter(const AdapterCallback& callback) OVERRIDE { + VLOG(1) << "DefaultAdapter."; + callback.Run(dbus::ObjectPath(), false); + } + + // BluetoothManagerClient override. + virtual void FindAdapter(const std::string& address, + const AdapterCallback& callback) { + VLOG(1) << "FindAdapter: " << address; + callback.Run(dbus::ObjectPath(), false); + } +}; + +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 diff --git a/chromeos/dbus/bluetooth_manager_client.h b/chromeos/dbus/bluetooth_manager_client.h new file mode 100644 index 0000000..13d7599 --- /dev/null +++ b/chromeos/dbus/bluetooth_manager_client.h @@ -0,0 +1,100 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLUETOOTH_MANAGER_CLIENT_H_ +#define CHROMEOS_DBUS_BLUETOOTH_MANAGER_CLIENT_H_ +#pragma once + +#include <string> + +#include "base/callback.h" +#include "base/observer_list.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/bluetooth_property.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "dbus/object_path.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +// BluetoothManagerClient is used to communicate with the bluetooth +// daemon's Manager interface. +class CHROMEOS_EXPORT BluetoothManagerClient { + public: + // Structure of properties associated with the bluetooth manager. + struct Properties : public BluetoothPropertySet { + // List of object paths of local Bluetooth adapters. Read-only. + BluetoothProperty<std::vector<dbus::ObjectPath> > adapters; + + Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback); + virtual ~Properties(); + }; + + // Interface for observing changes from the bluetooth manager. + class Observer { + public: + virtual ~Observer() {} + + // Called when the manager has a change in value of the property + // named |property_name|. + virtual void ManagerPropertyChanged(const std::string& property_name) {} + + // Called when a local bluetooth adapter is added. + // |object_path| is the dbus object path of the adapter. + virtual void AdapterAdded(const dbus::ObjectPath& object_path) {} + + // Called when a local bluetooth adapter is removed. + // |object_path| is the dbus object path of the adapter. + virtual void AdapterRemoved(const dbus::ObjectPath& object_path) {} + + // Called when the default local bluetooth adapter changes. + // |object_path| is the dbus object path of the new default adapter. + // Not called if all adapters are removed. + virtual void DefaultAdapterChanged(const dbus::ObjectPath& object_path) {} + }; + + virtual ~BluetoothManagerClient(); + + // Adds and removes observers. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Obtain the properties for the manager, any values should be copied + // if needed. + virtual Properties* GetProperties() = 0; + + // The AdapterCallback is used for both the DefaultAdapter() and + // FindAdapter() methods. It receives two arguments, the |object_path| + // of the adapter and |success| which indicates whether or not the request + // succeeded. + typedef base::Callback<void(const dbus::ObjectPath&, bool)> AdapterCallback; + + // Retrieves the dbus object path for the default adapter. + // The default adapter is the preferred local bluetooth interface when a + // client does not specify a particular interface. + virtual void DefaultAdapter(const AdapterCallback& callback) = 0; + + // Retrieves the dbus object path for the adapter with the address |address|, + // which may also be an interface name. + virtual void FindAdapter(const std::string& address, + const AdapterCallback& callback) = 0; + + // Creates the instance. + static BluetoothManagerClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + protected: + BluetoothManagerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothManagerClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLUETOOTH_MANAGER_CLIENT_H_ diff --git a/chromeos/dbus/bluetooth_node_client.cc b/chromeos/dbus/bluetooth_node_client.cc new file mode 100644 index 0000000..52959cf --- /dev/null +++ b/chromeos/dbus/bluetooth_node_client.cc @@ -0,0 +1,201 @@ +// 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_node_client.h" + +#include <map> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "chromeos/dbus/bluetooth_device_client.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 { + +BluetoothNodeClient::Properties::Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback) + : BluetoothPropertySet(object_proxy, + bluetooth_node::kBluetoothNodeInterface, + callback) { + RegisterProperty(bluetooth_node::kNameProperty, &name); + RegisterProperty(bluetooth_node::kDeviceProperty, &device); +} + +BluetoothNodeClient::Properties::~Properties() { +} + + +// The BluetoothNodeClient implementation used in production. +class BluetoothNodeClientImpl: public BluetoothNodeClient, + private BluetoothDeviceClient::Observer { + public: + BluetoothNodeClientImpl(dbus::Bus* bus, + BluetoothDeviceClient* device_client) + : weak_ptr_factory_(this), + bus_(bus) { + DVLOG(1) << "Creating BluetoothNodeClientImpl"; + + DCHECK(device_client); + device_client->AddObserver(this); + } + + virtual ~BluetoothNodeClientImpl() { + // Clean up Properties structures + for (ObjectMap::iterator iter = object_map_.begin(); + iter != object_map_.end(); ++iter) { + Object object = iter->second; + Properties* properties = object.second; + delete properties; + } + } + + // BluetoothNodeClient override. + virtual void AddObserver(BluetoothNodeClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.AddObserver(observer); + } + + // BluetoothNodeClient override. + virtual void RemoveObserver(BluetoothNodeClient::Observer* observer) + OVERRIDE { + DCHECK(observer); + observers_.RemoveObserver(observer); + } + + // BluetoothNodeClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + return GetObject(object_path).second; + } + + private: + // We maintain a collection of dbus object proxies and properties structures + // for each node binding. + typedef std::pair<dbus::ObjectProxy*, Properties*> Object; + typedef std::map<const dbus::ObjectPath, Object> ObjectMap; + ObjectMap object_map_; + + // BluetoothDeviceClient::Observer override. + virtual void NodeCreated(const dbus::ObjectPath& device_path, + const dbus::ObjectPath& object_path) OVERRIDE { + } + + // BluetoothDeviceClient::Observer override. + virtual void NodeRemoved(const dbus::ObjectPath& device_path, + const dbus::ObjectPath& object_path) OVERRIDE { + RemoveObject(object_path); + } + + // Ensures that we have an object proxy and properties structure for + // a node binding with object path |object_path|, creating it if not and + // storing it in our |object_map_| map. + Object GetObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) + return iter->second; + + // Create the object proxy. + DCHECK(bus_); + dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy( + bluetooth_node::kBluetoothNodeServiceName, object_path); + + // Create the properties structure. + Properties* properties = new Properties( + object_proxy, + base::Bind(&BluetoothNodeClientImpl::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr(), object_path)); + + properties->ConnectSignals(); + properties->GetAll(); + + Object object = std::make_pair(object_proxy, properties); + object_map_[object_path] = object; + return object; + } + + // Removes the dbus object proxy and properties for the node binding with + // dbus object path |object_path| from our |object_map_| map. + void RemoveObject(const dbus::ObjectPath& object_path) { + ObjectMap::iterator iter = object_map_.find(object_path); + if (iter != object_map_.end()) { + // Clean up the Properties structure. + Object object = iter->second; + Properties* properties = object.second; + delete properties; + + object_map_.erase(iter); + } + } + + // Returns a pointer to the object proxy for |object_path|, creating + // it if necessary. + dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) { + return GetObject(object_path).first; + } + + // 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 dbus::ObjectPath& object_path, + const std::string& property_name) { + FOR_EACH_OBSERVER(BluetoothNodeClient::Observer, observers_, + NodePropertyChanged(object_path, property_name)); + } + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + base::WeakPtrFactory<BluetoothNodeClientImpl> weak_ptr_factory_; + + dbus::Bus* bus_; + + // List of observers interested in event notifications from us. + ObserverList<BluetoothNodeClient::Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothNodeClientImpl); +}; + +// The BluetoothNodeClient implementation used on Linux desktop, which does +// nothing. +class BluetoothNodeClientStubImpl : public BluetoothNodeClient { + public: + // BluetoothNodeClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + } + + // BluetoothNodeClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + } + + // BluetoothNodeClient override. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) + OVERRIDE { + VLOG(1) << "GetProperties: " << object_path.value(); + return NULL; + } +}; + +BluetoothNodeClient::BluetoothNodeClient() { +} + +BluetoothNodeClient::~BluetoothNodeClient() { +} + +BluetoothNodeClient* BluetoothNodeClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothDeviceClient* adapter_client) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new BluetoothNodeClientImpl(bus, adapter_client); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new BluetoothNodeClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/bluetooth_node_client.h b/chromeos/dbus/bluetooth_node_client.h new file mode 100644 index 0000000..f99d17f --- /dev/null +++ b/chromeos/dbus/bluetooth_node_client.h @@ -0,0 +1,82 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLUETOOTH_NODE_CLIENT_H_ +#define CHROMEOS_DBUS_BLUETOOTH_NODE_CLIENT_H_ +#pragma once + +#include <string> + +#include "base/callback.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/bluetooth_property.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "dbus/object_path.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +class BluetoothDeviceClient; + +// BluetoothNodeClient is used to represent persistent device nodes +// bound to bluetooth devices, such as RFCOMM TTY bindings to ttyX devices +// in Linux. +class CHROMEOS_EXPORT BluetoothNodeClient { + public: + // Structure of properties associated with persistent device nodes. + struct Properties : public BluetoothPropertySet { + // The name of the device node under /dev. Read-only. + BluetoothProperty<std::string> name; + + // Object path of the device the node binding belongs to. Read-only. + BluetoothProperty<dbus::ObjectPath> device; + + Properties(dbus::ObjectProxy* object_proxy, + PropertyChangedCallback callback); + virtual ~Properties(); + }; + + // Interface for observing changes from a persistent device node binding. + class Observer { + public: + virtual ~Observer() {} + + // Called when the node binding with object path |object_path| has a + // change in value of the property named |property_name|. + virtual void NodePropertyChanged(const dbus::ObjectPath& object_path, + const std::string& property_name) {} + }; + + virtual ~BluetoothNodeClient(); + + // Adds and removes observers for events on all persistent device node + // bindings. Check the |object_path| parameter of observer methods to + // determine which device node binding is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Obtain the properties for the node binding with object path |object_path|, + // any values should be copied if needed. + virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0; + + // Creates the instance. + static BluetoothNodeClient* Create(DBusClientImplementationType type, + dbus::Bus* bus, + BluetoothDeviceClient* device_client); + + protected: + BluetoothNodeClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(BluetoothNodeClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLUETOOTH_NODE_CLIENT_H_ diff --git a/chromeos/dbus/bluetooth_property.cc b/chromeos/dbus/bluetooth_property.cc new file mode 100644 index 0000000..24a1958 --- /dev/null +++ b/chromeos/dbus/bluetooth_property.cc @@ -0,0 +1,43 @@ +// 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_property.h" + +#include "base/bind.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +void BluetoothPropertySet::ConnectSignals() { + dbus::ObjectProxy* object_proxy = this->object_proxy(); + DCHECK(object_proxy); + object_proxy->ConnectToSignal( + interface(), + bluetooth_common::kPropertyChangedSignal, + base::Bind(&dbus::PropertySet::ChangedReceived, GetWeakPtr()), + base::Bind(&dbus::PropertySet::ChangedConnected, GetWeakPtr())); +} + +void BluetoothPropertySet::ChangedReceived(dbus::Signal* signal) { + DCHECK(signal); + + dbus::MessageReader reader(signal); + UpdatePropertyFromReader(&reader); +} + +void BluetoothPropertySet::GetAll() { + dbus::MethodCall method_call(interface(), + bluetooth_common::kGetProperties); + + dbus::ObjectProxy* object_proxy = this->object_proxy(); + DCHECK(object_proxy); + object_proxy->CallMethod(&method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&dbus::PropertySet::OnGetAll, + GetWeakPtr())); +} + +} diff --git a/chromeos/dbus/bluetooth_property.h b/chromeos/dbus/bluetooth_property.h new file mode 100644 index 0000000..ccfbff1 --- /dev/null +++ b/chromeos/dbus/bluetooth_property.h @@ -0,0 +1,96 @@ +// 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. + +#ifndef CHROMEOS_DBUS_BLUETOOTH_PROPERTY_H_ +#define CHROMEOS_DBUS_BLUETOOTH_PROPERTY_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "dbus/property.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +// BlueZ predates the common D-Bus Properties API (though it inspired it), +// override dbus::PropertySet to generate the correct method call to get +// all properties, conenect to the correct signal and parse it correctly. +// +// BluetoothPropertySet should be used with BluetoothProperty<>. +class BluetoothPropertySet : public dbus::PropertySet { + public: + BluetoothPropertySet(dbus::ObjectProxy* object_proxy, + const std::string& interface, + PropertyChangedCallback callback) + : dbus::PropertySet(object_proxy, interface, callback) {} + + // dbus::PropertySet override. + // + // Call after construction to connect property change notification + // signals. Sub-classes may override to use different D-Bus signals. + virtual void ConnectSignals() OVERRIDE; + + // dbus::PropertySet override. + // + // Queries the remote object for values of all properties and updates + // initial values. + virtual void GetAll() OVERRIDE; + + // dbus::PropertySet override. + // + // Method connected by ConnectSignals() and called by dbus:: when + // a property is changed. + virtual void ChangedReceived(dbus::Signal* signal) OVERRIDE; +}; + +// BlueZ predates the common D-Bus Properties API (though it inspired it), +// override dbus::Property<> to generate the correct method call to set a +// new property value. +template <class T> +class BluetoothProperty : public dbus::Property<T> { + public: + // Import the callbacks into our namespace (this is a template derived from + // a template, the C++ standard gets a bit wibbly and doesn't do it for us). + // + // |success| indicates whether or not the value could be retrived, or new + // value set. For Get, if true the new value can be obtained by calling + // value() on the property; for Set() a Get() call may be necessary. + typedef typename dbus::Property<T>::GetCallback GetCallback; + typedef typename dbus::Property<T>::SetCallback SetCallback; + + // dbus::Property<> override. + // + // Requests an updated value from the remote object incurring a + // round-trip. |callback| will be called when the new value is available. + virtual void Get(GetCallback callback) OVERRIDE { + NOTREACHED() << "BlueZ does not implement Get for properties"; + } + + // dbus::Property<> override. + // + // Requests that the remote object change the property value to |value|, + // |callback| will be called to indicate the success or failure of the + // request, however the new value may not be available depending on the + // remote object. + virtual void Set(const T& value, SetCallback callback) OVERRIDE { + dbus::MethodCall method_call(this->property_set()->interface(), + bluetooth_common::kSetProperty); + dbus::MessageWriter writer(&method_call); + writer.AppendString(this->name()); + this->AppendToWriter(&writer, value); + + dbus::ObjectProxy *object_proxy = this->property_set()->object_proxy(); + DCHECK(object_proxy); + object_proxy->CallMethod(&method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&dbus::Property<T>::OnSet, + this->GetWeakPtr(), + callback)); + } +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_BLUETOOTH_PROPERTY_H_ diff --git a/chromeos/dbus/cashew_client.cc b/chromeos/dbus/cashew_client.cc new file mode 100644 index 0000000..93d1f3d --- /dev/null +++ b/chromeos/dbus/cashew_client.cc @@ -0,0 +1,134 @@ +// 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/cashew_client.h" + +#include "base/bind.h" +#include "base/values.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "dbus/values_util.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +namespace { + +// Does nothing. +// This method is used to handle results of RequestDataPlansUpdate method call. +void DoNothing(dbus::Response* response) { +} + +// The CashewClient implementation. +class CashewClientImpl : public CashewClient { + public: + explicit CashewClientImpl(dbus::Bus* bus) + : proxy_(bus->GetObjectProxy( + cashew::kCashewServiceName, + dbus::ObjectPath(cashew::kCashewServicePath))), + weak_ptr_factory_(this) { + proxy_->ConnectToSignal( + cashew::kCashewServiceInterface, + cashew::kMonitorDataPlanUpdate, + base::Bind(&CashewClientImpl::OnDataPlansUpdate, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&CashewClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + // CashewClient override. + virtual void SetDataPlansUpdateHandler( + DataPlansUpdateHandler handler) OVERRIDE { + data_plans_update_handler_ = handler; + } + + // CashewClient override. + virtual void ResetDataPlansUpdateHandler() OVERRIDE { + data_plans_update_handler_.Reset(); + } + + // CashewClient override. + virtual void RequestDataPlansUpdate() OVERRIDE { + dbus::MethodCall method_call(cashew::kCashewServiceInterface, + cashew::kRequestDataPlanFunction); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&DoNothing)); + } + + private: + // Handles DataPlansUpdate signal. + void OnDataPlansUpdate(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string service; + if (!reader.PopString(&service)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + scoped_ptr<Value> value(dbus::PopDataAsValue(&reader)); + ListValue* data_plans = NULL; + if (!value.get() || !value->GetAsList(&data_plans)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + if (!data_plans_update_handler_.is_null()) + data_plans_update_handler_.Run(service, *data_plans); + } + + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool successed) { + LOG_IF(ERROR, !successed) << "Connect to " << interface << " " << + signal << " failed."; + } + + dbus::ObjectProxy* proxy_; + base::WeakPtrFactory<CashewClientImpl> weak_ptr_factory_; + DataPlansUpdateHandler data_plans_update_handler_; + + DISALLOW_COPY_AND_ASSIGN(CashewClientImpl); +}; + +// A stub implementaion of CashewClient. +class CashewClientStubImpl : public CashewClient { + public: + CashewClientStubImpl() {} + + virtual ~CashewClientStubImpl() {} + + // CashewClient override. + virtual void SetDataPlansUpdateHandler( + DataPlansUpdateHandler handler) OVERRIDE {} + + // CashewClient override. + virtual void ResetDataPlansUpdateHandler() OVERRIDE {} + + // CashewClient override. + virtual void RequestDataPlansUpdate() OVERRIDE {} + + private: + DISALLOW_COPY_AND_ASSIGN(CashewClientStubImpl); +}; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// CashewClient + +CashewClient::CashewClient() {} + +CashewClient::~CashewClient() {} + +// static +CashewClient* CashewClient::Create(DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new CashewClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new CashewClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/cashew_client.h b/chromeos/dbus/cashew_client.h new file mode 100644 index 0000000..2238e1b --- /dev/null +++ b/chromeos/dbus/cashew_client.h @@ -0,0 +1,65 @@ +// 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. + +#ifndef CHROMEOS_DBUS_CASHEW_CLIENT_H_ +#define CHROMEOS_DBUS_CASHEW_CLIENT_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +namespace base { +class ListValue; +} + +namespace dbus { +class Bus; +} + +namespace chromeos { + +// CashewClient is used to communicate with the Cashew service. +// All methods should be called from the origin thread (UI thread) which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT CashewClient { + public: + // A callback to handle "DataPlansUpdate" signal. + // |service| is the D-Bus path of the cellular service. + // (e.g. /service/cellular_0271266ce2ce_310260467781434) + typedef base::Callback<void(const std::string& service, + const base::ListValue& data_plans)> + DataPlansUpdateHandler; + + virtual ~CashewClient(); + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static CashewClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + // Sets DataPlansUpdate signal handler. + virtual void SetDataPlansUpdateHandler(DataPlansUpdateHandler handler) = 0; + + // Resets DataPlansUpdate signal handler. + virtual void ResetDataPlansUpdateHandler() = 0; + + // Calls RequestDataPlansUpdate method. + virtual void RequestDataPlansUpdate() = 0; + + protected: + // Create() should be used instead. + CashewClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(CashewClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_CASHEW_CLIENT_H_ diff --git a/chromeos/dbus/cros_disks_client.cc b/chromeos/dbus/cros_disks_client.cc new file mode 100644 index 0000000..217382c --- /dev/null +++ b/chromeos/dbus/cros_disks_client.cc @@ -0,0 +1,566 @@ +// 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/cros_disks_client.h" + +#include "base/bind.h" +#include "base/stl_util.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 { + +namespace { + +const char* kDefaultMountOptions[] = { + "rw", + "nodev", + "noexec", + "nosuid", +}; + +const char* kDefaultUnmountOptions[] = { + "force", +}; + +// Checks if retrieved media type is in boundaries of DeviceMediaType. +bool IsValidMediaType(uint32 type) { + return type < static_cast<uint32>(cros_disks::DEVICE_MEDIA_NUM_VALUES); +} + + +// Translates enum used in cros-disks to enum used in Chrome. +// Note that we could just do static_cast, but this is less sensitive to +// changes in cros-disks. +DeviceType DeviceMediaTypeToDeviceType(uint32 media_type_uint32) { + if (!IsValidMediaType(media_type_uint32)) + return DEVICE_TYPE_UNKNOWN; + + cros_disks::DeviceMediaType media_type = + cros_disks::DeviceMediaType(media_type_uint32); + + switch (media_type) { + case(cros_disks::DEVICE_MEDIA_UNKNOWN): + return DEVICE_TYPE_UNKNOWN; + case(cros_disks::DEVICE_MEDIA_USB): + return DEVICE_TYPE_USB; + case(cros_disks::DEVICE_MEDIA_SD): + return DEVICE_TYPE_SD; + case(cros_disks::DEVICE_MEDIA_OPTICAL_DISC): + return DEVICE_TYPE_OPTICAL_DISC; + case(cros_disks::DEVICE_MEDIA_MOBILE): + return DEVICE_TYPE_MOBILE; + default: + return DEVICE_TYPE_UNKNOWN; + } +} + +// Pops a bool value when |reader| is not NULL. +// Returns true when a value is popped, false otherwise. +bool MaybePopBool(dbus::MessageReader* reader, bool* value) { + if (!reader) + return false; + return reader->PopBool(value); +} + +// Pops a string value when |reader| is not NULL. +// Returns true when a value is popped, false otherwise. +bool MaybePopString(dbus::MessageReader* reader, std::string* value) { + if (!reader) + return false; + return reader->PopString(value); +} + +// Pops a uint32 value when |reader| is not NULL. +// Returns true when a value is popped, false otherwise. +bool MaybePopUint32(dbus::MessageReader* reader, uint32* value) { + if (!reader) + return false; + + return reader->PopUint32(value); +} + +// Pops a uint64 value when |reader| is not NULL. +// Returns true when a value is popped, false otherwise. +bool MaybePopUint64(dbus::MessageReader* reader, uint64* value) { + if (!reader) + return false; + return reader->PopUint64(value); +} + +// Pops an array of strings when |reader| is not NULL. +// Returns true when an array is popped, false otherwise. +bool MaybePopArrayOfStrings(dbus::MessageReader* reader, + std::vector<std::string>* value) { + if (!reader) + return false; + return reader->PopArrayOfStrings(value); +} + +// The CrosDisksClient implementation. +class CrosDisksClientImpl : public CrosDisksClient { + public: + explicit CrosDisksClientImpl(dbus::Bus* bus) + : proxy_(bus->GetObjectProxy( + cros_disks::kCrosDisksServiceName, + dbus::ObjectPath(cros_disks::kCrosDisksServicePath))), + weak_ptr_factory_(this) { + } + + // CrosDisksClient override. + virtual void Mount(const std::string& source_path, + MountType type, + MountCallback callback, + ErrorCallback error_callback) OVERRIDE { + dbus::MethodCall method_call(cros_disks::kCrosDisksInterface, + cros_disks::kMount); + dbus::MessageWriter writer(&method_call); + writer.AppendString(source_path); + writer.AppendString(""); // auto detect filesystem. + std::vector<std::string> mount_options(kDefaultMountOptions, + kDefaultMountOptions + + arraysize(kDefaultMountOptions)); + writer.AppendArrayOfStrings(mount_options); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CrosDisksClientImpl::OnMount, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // CrosDisksClient override. + virtual void Unmount(const std::string& device_path, + UnmountCallback callback, + ErrorCallback error_callback) OVERRIDE { + dbus::MethodCall method_call(cros_disks::kCrosDisksInterface, + cros_disks::kUnmount); + dbus::MessageWriter writer(&method_call); + writer.AppendString(device_path); + std::vector<std::string> unmount_options(kDefaultUnmountOptions, + kDefaultUnmountOptions + + arraysize(kDefaultUnmountOptions)); + writer.AppendArrayOfStrings(unmount_options); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CrosDisksClientImpl::OnUnmount, + weak_ptr_factory_.GetWeakPtr(), + device_path, + callback, + error_callback)); + } + + // CrosDisksClient override. + virtual void EnumerateAutoMountableDevices( + EnumerateAutoMountableDevicesCallback callback, + ErrorCallback error_callback) OVERRIDE { + dbus::MethodCall method_call(cros_disks::kCrosDisksInterface, + cros_disks::kEnumerateAutoMountableDevices); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices, + weak_ptr_factory_.GetWeakPtr(), + callback, + error_callback)); + } + + // CrosDisksClient override. + virtual void FormatDevice(const std::string& device_path, + const std::string& filesystem, + FormatDeviceCallback callback, + ErrorCallback error_callback) OVERRIDE { + dbus::MethodCall method_call(cros_disks::kCrosDisksInterface, + cros_disks::kFormatDevice); + dbus::MessageWriter writer(&method_call); + writer.AppendString(device_path); + writer.AppendString(filesystem); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CrosDisksClientImpl::OnFormatDevice, + weak_ptr_factory_.GetWeakPtr(), + device_path, + callback, + error_callback)); + } + + // CrosDisksClient override. + virtual void GetDeviceProperties(const std::string& device_path, + GetDevicePropertiesCallback callback, + ErrorCallback error_callback) OVERRIDE { + dbus::MethodCall method_call(cros_disks::kCrosDisksInterface, + cros_disks::kGetDeviceProperties); + dbus::MessageWriter writer(&method_call); + writer.AppendString(device_path); + proxy_->CallMethod(&method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties, + weak_ptr_factory_.GetWeakPtr(), + device_path, + callback, + error_callback)); + } + + // CrosDisksClient override. + virtual void SetUpConnections( + MountEventHandler mount_event_handler, + MountCompletedHandler mount_completed_handler) OVERRIDE { + static const SignalEventTuple kSignalEventTuples[] = { + { cros_disks::kDeviceAdded, DEVICE_ADDED }, + { cros_disks::kDeviceScanned, DEVICE_SCANNED }, + { cros_disks::kDeviceRemoved, DEVICE_REMOVED }, + { cros_disks::kDiskAdded, DISK_ADDED }, + { cros_disks::kDiskChanged, DISK_CHANGED }, + { cros_disks::kDiskRemoved, DISK_REMOVED }, + { cros_disks::kFormattingFinished, FORMATTING_FINISHED }, + }; + const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples); + + for (size_t i = 0; i < kNumSignalEventTuples; ++i) { + proxy_->ConnectToSignal( + cros_disks::kCrosDisksInterface, + kSignalEventTuples[i].signal_name, + base::Bind(&CrosDisksClientImpl::OnMountEvent, + weak_ptr_factory_.GetWeakPtr(), + kSignalEventTuples[i].event_type, + mount_event_handler), + base::Bind(&CrosDisksClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + proxy_->ConnectToSignal( + cros_disks::kCrosDisksInterface, + cros_disks::kMountCompleted, + base::Bind(&CrosDisksClientImpl::OnMountCompleted, + weak_ptr_factory_.GetWeakPtr(), + mount_completed_handler ), + base::Bind(&CrosDisksClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + private: + // A struct to contain a pair of signal name and mount event type. + // Used by SetUpConnections. + struct SignalEventTuple { + const char *signal_name; + MountEventType event_type; + }; + + // Handles the result of Mount and calls |callback| or |error_callback|. + void OnMount(MountCallback callback, + ErrorCallback error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + callback.Run(); + } + + // Handles the result of Unount and calls |callback| or |error_callback|. + void OnUnmount(const std::string& device_path, + UnmountCallback callback, + ErrorCallback error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + callback.Run(device_path); + } + + // Handles the result of EnumerateAutoMountableDevices and calls |callback| or + // |error_callback|. + void OnEnumerateAutoMountableDevices( + EnumerateAutoMountableDevicesCallback callback, + ErrorCallback error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + dbus::MessageReader reader(response); + std::vector<std::string> device_paths; + if (!reader.PopArrayOfStrings(&device_paths)) { + LOG(ERROR) << "Invalid response: " << response->ToString(); + error_callback.Run(); + return; + } + callback.Run(device_paths); + } + + // Handles the result of FormatDevice and calls |callback| or + // |error_callback|. + void OnFormatDevice(const std::string& device_path, + FormatDeviceCallback callback, + ErrorCallback error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + dbus::MessageReader reader(response); + bool success = false; + if (!reader.PopBool(&success)) { + LOG(ERROR) << "Invalid response: " << response->ToString(); + error_callback.Run(); + return; + } + callback.Run(device_path, success); + } + + // Handles the result of GetDeviceProperties and calls |callback| or + // |error_callback|. + void OnGetDeviceProperties(const std::string& device_path, + GetDevicePropertiesCallback callback, + ErrorCallback error_callback, + dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + DiskInfo disk(device_path, response); + callback.Run(disk); + } + + // Handles mount event signals and calls |handler|. + void OnMountEvent(MountEventType event_type, + MountEventHandler handler, + dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string device; + if (!reader.PopString(&device)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + handler.Run(event_type, device); + } + + // Handles MountCompleted signal and calls |handler|. + void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) { + dbus::MessageReader reader(signal); + unsigned int error_code = 0; + std::string source_path; + unsigned int mount_type = 0; + std::string mount_path; + if (!reader.PopUint32(&error_code) || + !reader.PopString(&source_path) || + !reader.PopUint32(&mount_type) || + !reader.PopString(&mount_path)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + handler.Run(static_cast<MountError>(error_code), source_path, + static_cast<MountType>(mount_type), mount_path); + } + + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool successed) { + LOG_IF(ERROR, !successed) << "Connect to " << interface << " " << + signal << " failed."; + } + + dbus::ObjectProxy* proxy_; + base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl); +}; + +// A stub implementaion of CrosDisksClient. +class CrosDisksClientStubImpl : public CrosDisksClient { + public: + CrosDisksClientStubImpl() {} + virtual ~CrosDisksClientStubImpl() {} + + virtual void Mount(const std::string& source_path, + MountType type, + MountCallback callback, + ErrorCallback error_callback) OVERRIDE {} + virtual void Unmount(const std::string& device_path, + UnmountCallback callback, + ErrorCallback error_callback) OVERRIDE {} + virtual void EnumerateAutoMountableDevices( + EnumerateAutoMountableDevicesCallback callback, + ErrorCallback error_callback) OVERRIDE {} + virtual void FormatDevice(const std::string& device_path, + const std::string& filesystem, + FormatDeviceCallback callback, + ErrorCallback error_callback) OVERRIDE {} + virtual void GetDeviceProperties(const std::string& device_path, + GetDevicePropertiesCallback callback, + ErrorCallback error_callback) OVERRIDE {} + virtual void SetUpConnections( + MountEventHandler mount_event_handler, + MountCompletedHandler mount_completed_handler) OVERRIDE {} + + private: + DISALLOW_COPY_AND_ASSIGN(CrosDisksClientStubImpl); +}; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// DiskInfo + +DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response) + : device_path_(device_path), + is_drive_(false), + has_media_(false), + on_boot_device_(false), + device_type_(DEVICE_TYPE_UNKNOWN), + total_size_in_bytes_(0), + is_read_only_(false), + is_hidden_(true) { + InitializeFromResponse(response); +} + +DiskInfo::~DiskInfo() { +} + +// Initialize |this| from |response| given by the cros-disks service. +// Below is an example of |response|'s raw message (long string is ellipsized). +// +// +// message_type: MESSAGE_METHOD_RETURN +// destination: :1.8 +// sender: :1.16 +// signature: a{sv} +// serial: 96 +// reply_serial: 267 +// +// array [ +// dict entry { +// string "DeviceFile" +// variant string "/dev/sdb" +// } +// dict entry { +// string "DeviceIsDrive" +// variant bool true +// } +// dict entry { +// string "DeviceIsMediaAvailable" +// variant bool true +// } +// dict entry { +// string "DeviceIsMounted" +// variant bool false +// } +// dict entry { +// string "DeviceIsOnBootDevice" +// variant bool false +// } +// dict entry { +// string "DeviceIsOpticalDisc" +// variant bool false +// } +// dict entry { +// string "DeviceIsReadOnly" +// variant bool false +// } +// dict entry { +// string "DeviceIsVirtual" +// variant bool false +// } +// dict entry { +// string "DeviceMediaType" +// variant uint32 1 +// } +// dict entry { +// string "DeviceMountPaths" +// variant array [ +// ] +// } +// dict entry { +// string "DevicePresentationHide" +// variant bool true +// } +// dict entry { +// string "DeviceSize" +// variant uint64 7998537728 +// } +// dict entry { +// string "DriveIsRotational" +// variant bool false +// } +// dict entry { +// string "DriveModel" +// variant string "TransMemory" +// } +// dict entry { +// string "IdLabel" +// variant string "" +// } +// dict entry { +// string "IdUuid" +// variant string "" +// } +// dict entry { +// string "NativePath" +// variant string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/... +// } +// ] +void DiskInfo::InitializeFromResponse(dbus::Response* response) { + dbus::MessageReader response_reader(response); + dbus::MessageReader array_reader(response); + if (!response_reader.PopArray(&array_reader)) { + LOG(ERROR) << "Invalid response: " << response->ToString(); + return; + } + // TODO(satorux): Rework this code using Protocol Buffers. crosbug.com/22626 + typedef std::map<std::string, dbus::MessageReader*> PropertiesMap; + PropertiesMap properties; + STLValueDeleter<PropertiesMap> properties_value_deleter(&properties); + while (array_reader.HasMoreData()) { + dbus::MessageReader* value_reader = new dbus::MessageReader(response); + dbus::MessageReader dict_entry_reader(response); + std::string key; + if (!array_reader.PopDictEntry(&dict_entry_reader) || + !dict_entry_reader.PopString(&key) || + !dict_entry_reader.PopVariant(value_reader)) { + LOG(ERROR) << "Invalid response: " << response->ToString(); + return; + } + properties[key] = value_reader; + } + MaybePopBool(properties[cros_disks::kDeviceIsDrive], &is_drive_); + MaybePopBool(properties[cros_disks::kDeviceIsReadOnly], &is_read_only_); + MaybePopBool(properties[cros_disks::kDevicePresentationHide], &is_hidden_); + MaybePopBool(properties[cros_disks::kDeviceIsMediaAvailable], &has_media_); + MaybePopBool(properties[cros_disks::kDeviceIsOnBootDevice], + &on_boot_device_); + MaybePopString(properties[cros_disks::kNativePath], &system_path_); + MaybePopString(properties[cros_disks::kDeviceFile], &file_path_); + MaybePopString(properties[cros_disks::kDriveModel], &drive_model_); + MaybePopString(properties[cros_disks::kIdLabel], &label_); + MaybePopUint64(properties[cros_disks::kDeviceSize], &total_size_in_bytes_); + + uint32 media_type_uint32 = 0; + if (MaybePopUint32(properties[cros_disks::kDeviceMediaType], + &media_type_uint32)) { + device_type_ = DeviceMediaTypeToDeviceType(media_type_uint32); + } + + std::vector<std::string> mount_paths; + if (MaybePopArrayOfStrings(properties[cros_disks::kDeviceMountPaths], + &mount_paths) && !mount_paths.empty()) + mount_path_ = mount_paths[0]; +} + +//////////////////////////////////////////////////////////////////////////////// +// CrosDisksClient + +CrosDisksClient::CrosDisksClient() {} + +CrosDisksClient::~CrosDisksClient() {} + +// static +CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new CrosDisksClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new CrosDisksClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/cros_disks_client.h b/chromeos/dbus/cros_disks_client.h new file mode 100644 index 0000000..df7cf49 --- /dev/null +++ b/chromeos/dbus/cros_disks_client.h @@ -0,0 +1,233 @@ +// 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. + +#ifndef CHROMEOS_DBUS_CROS_DISKS_CLIENT_H_ +#define CHROMEOS_DBUS_CROS_DISKS_CLIENT_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +namespace dbus { +class Bus; +class Response; +} + +namespace chromeos { + +// Enum describing types of mount used by cros-disks. +enum MountType { + MOUNT_TYPE_INVALID, + MOUNT_TYPE_DEVICE, + MOUNT_TYPE_ARCHIVE, + MOUNT_TYPE_GDATA, + MOUNT_TYPE_NETWORK_STORAGE, +}; + +// Type of device. +enum DeviceType { + DEVICE_TYPE_UNKNOWN, + DEVICE_TYPE_USB, // USB stick. + DEVICE_TYPE_SD, // SD card. + DEVICE_TYPE_OPTICAL_DISC, // e.g. DVD. + DEVICE_TYPE_MOBILE // Storage on a mobile device (e.g. Android). +}; + +// Mount error code used by cros-disks. +enum MountError { + MOUNT_ERROR_NONE = 0, + MOUNT_ERROR_UNKNOWN = 1, + MOUNT_ERROR_INTERNAL = 2, + MOUNT_ERROR_UNKNOWN_FILESYSTEM = 101, + MOUNT_ERROR_UNSUPORTED_FILESYSTEM = 102, + MOUNT_ERROR_INVALID_ARCHIVE = 201, + MOUNT_ERROR_LIBRARY_NOT_LOADED = 501, + MOUNT_ERROR_NOT_AUTHENTICATED = 601, + MOUNT_ERROR_NETWORK_ERROR = 602, + MOUNT_ERROR_PATH_UNMOUNTED = 901, + // TODO(tbarzic): Add more error codes as they get added to cros-disks and + // consider doing explicit translation from cros-disks error_types. +}; + +// Event type each corresponding to a signal sent from cros-disks. +enum MountEventType { + DISK_ADDED, + DISK_REMOVED, + DISK_CHANGED, + DEVICE_ADDED, + DEVICE_REMOVED, + DEVICE_SCANNED, + FORMATTING_FINISHED, +}; + +// A class to represent information about a disk sent from cros-disks. +class DiskInfo { + public: + DiskInfo(const std::string& device_path, dbus::Response* response); + ~DiskInfo(); + + // Device path. (e.g. /sys/devices/pci0000:00/.../8:0:0:0/block/sdb/sdb1) + std::string device_path() const { return device_path_; } + + // Disk mount path. (e.g. /media/removable/VOLUME) + std::string mount_path() const { return mount_path_; } + + // Disk system path given by udev. + // (e.g. /sys/devices/pci0000:00/.../8:0:0:0/block/sdb/sdb1) + std::string system_path() const { return system_path_; } + + // Is a drive or not. (i.e. true with /dev/sdb, false with /dev/sdb1) + bool is_drive() const { return is_drive_; } + + // Does the disk have media content. + bool has_media() const { return has_media_; } + + // Is the disk on deveice we booted the machine from. + bool on_boot_device() const { return on_boot_device_; } + + // Disk file path (e.g. /dev/sdb). + std::string file_path() const { return file_path_; } + + // Disk label. + std::string label() const { return label_; } + + // Disk model. (e.g. "TransMemory") + std::string drive_label() const { return drive_model_; } + + // Device type. Not working well, yet. + DeviceType device_type() const { return device_type_; } + + // Total size of the disk in bytes. + uint64 total_size_in_bytes() const { return total_size_in_bytes_; } + + // Is the device read-only. + bool is_read_only() const { return is_read_only_; } + + // Returns true if the device should be hidden from the file browser. + bool is_hidden() const { return is_hidden_; } + + private: + void InitializeFromResponse(dbus::Response* response); + + std::string device_path_; + std::string mount_path_; + std::string system_path_; + bool is_drive_; + bool has_media_; + bool on_boot_device_; + + std::string file_path_; + std::string label_; + std::string drive_model_; + DeviceType device_type_; + uint64 total_size_in_bytes_; + bool is_read_only_; + bool is_hidden_; +}; + +// A class to make the actual DBus calls for cros-disks service. +// This class only makes calls, result/error handling should be done +// by callbacks. +class CHROMEOS_EXPORT CrosDisksClient { + public: + // A callback to be called when DBus method call fails. + typedef base::Callback<void()> ErrorCallback; + + // A callback to handle the result of Mount. + typedef base::Callback<void()> MountCallback; + + // A callback to handle the result of Unmount. + // The argument is the device path. + typedef base::Callback<void(const std::string&)> UnmountCallback; + + // A callback to handle the result of EnumerateAutoMountableDevices. + // The argument is the enumerated device paths. + typedef base::Callback<void(const std::vector<std::string>&) + > EnumerateAutoMountableDevicesCallback; + + // A callback to handle the result of FormatDevice. + // The first argument is the device path. + // The second argument is true when formatting succeeded, false otherwise. + typedef base::Callback<void(const std::string&, bool)> FormatDeviceCallback; + + // A callback to handle the result of GetDeviceProperties. + // The argument is the information about the specified device. + typedef base::Callback<void(const DiskInfo&)> GetDevicePropertiesCallback; + + // A callback to handle MountCompleted signal. + // The first argument is the error code. + // The second argument is the source path. + // The third argument is the mount type. + // The fourth argument is the mount path. + typedef base::Callback<void(MountError, const std::string&, MountType, + const std::string&)> MountCompletedHandler; + + // A callback to handle mount events. + // The first argument is the event type. + // The second argument is the device path. + typedef base::Callback<void(MountEventType, const std::string&) + > MountEventHandler; + + virtual ~CrosDisksClient(); + + // Calls Mount method. |callback| is called after the method call succeeds, + // otherwise, |error_callback| is called. + virtual void Mount(const std::string& source_path, + MountType type, + MountCallback callback, + ErrorCallback error_callback) = 0; + + // Calls Unmount method. |callback| is called after the method call succeeds, + // otherwise, |error_callback| is called. + virtual void Unmount(const std::string& device_path, + UnmountCallback callback, + ErrorCallback error_callback) = 0; + + // Calls EnumerateAutoMountableDevices method. |callback| is called after the + // method call succeeds, otherwise, |error_callback| is called. + virtual void EnumerateAutoMountableDevices( + EnumerateAutoMountableDevicesCallback callback, + ErrorCallback error_callback) = 0; + + // Calls FormatDevice method. |callback| is called after the method call + // succeeds, otherwise, |error_callback| is called. + virtual void FormatDevice(const std::string& device_path, + const std::string& filesystem, + FormatDeviceCallback callback, + ErrorCallback error_callback) = 0; + + // Calls GetDeviceProperties method. |callback| is called after the method + // call succeeds, otherwise, |error_callback| is called. + virtual void GetDeviceProperties(const std::string& device_path, + GetDevicePropertiesCallback callback, + ErrorCallback error_callback) = 0; + + // Registers given callback for events. + // |mount_event_handler| is called when mount event signal is received. + // |mount_completed_handler| is called when MountCompleted signal is received. + virtual void SetUpConnections( + MountEventHandler mount_event_handler, + MountCompletedHandler mount_completed_handler) = 0; + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static CrosDisksClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + protected: + // Create() should be used instead. + CrosDisksClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(CrosDisksClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_CROS_DISKS_CLIENT_H_ diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc new file mode 100644 index 0000000..b4d9e3f --- /dev/null +++ b/chromeos/dbus/cryptohome_client.cc @@ -0,0 +1,638 @@ +// 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/cryptohome_client.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "chromeos/dbus/blocking_method_caller.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 { + +namespace { + +// A convenient macro to initialize a dbus::MethodCall while checking the dbus +// method name matches to the C++ method name. +#define INITIALIZE_METHOD_CALL(method_call_name, method_name) \ + DCHECK_EQ(std::string(method_name), __FUNCTION__); \ + dbus::MethodCall method_call_name(cryptohome::kCryptohomeInterface, \ + method_name); +// The CryptohomeClient implementation. +class CryptohomeClientImpl : public CryptohomeClient { + public: + explicit CryptohomeClientImpl(dbus::Bus* bus) + : proxy_(bus->GetObjectProxy( + cryptohome::kCryptohomeServiceName, + dbus::ObjectPath(cryptohome::kCryptohomeServicePath))), + weak_ptr_factory_(this), + blocking_method_caller_(bus, proxy_) { + proxy_->ConnectToSignal( + cryptohome::kCryptohomeInterface, + cryptohome::kSignalAsyncCallStatus, + base::Bind(&CryptohomeClientImpl::OnAsyncCallStatus, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&CryptohomeClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + // CryptohomeClient override. + virtual void SetAsyncCallStatusHandler(AsyncCallStatusHandler handler) + OVERRIDE { + async_call_status_handler_ = handler; + } + + // CryptohomeClient override. + virtual void ResetAsyncCallStatusHandler() OVERRIDE { + async_call_status_handler_.Reset(); + } + + // CryptohomeClient override. + virtual bool IsMounted(bool* is_mounted) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeIsMounted); + return CallBoolMethodAndBlock(&method_call, is_mounted); + } + + // CryptohomeClient override. + virtual bool Unmount(bool *success) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeUnmount); + return CallBoolMethodAndBlock(&method_call, success); + } + + // CryptohomeClient override. + virtual void AsyncCheckKey(const std::string& username, + const std::string& key, + AsyncMethodCallback callback) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeAsyncCheckKey); + dbus::MessageWriter writer(&method_call); + writer.AppendString(username); + writer.AppendString(key); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + virtual void AsyncMigrateKey(const std::string& username, + const std::string& from_key, + const std::string& to_key, + AsyncMethodCallback callback) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeAsyncMigrateKey); + dbus::MessageWriter writer(&method_call); + writer.AppendString(username); + writer.AppendString(from_key); + writer.AppendString(to_key); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + virtual void AsyncRemove(const std::string& username, + AsyncMethodCallback callback) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeAsyncRemove); + dbus::MessageWriter writer(&method_call); + writer.AppendString(username); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + virtual bool GetSystemSalt(std::vector<uint8>* salt) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeGetSystemSalt); + scoped_ptr<dbus::Response> response( + blocking_method_caller_.CallMethodAndBlock(&method_call)); + if (!response.get()) + return false; + dbus::MessageReader reader(response.get()); + uint8* bytes = NULL; + size_t length = 0; + if (!reader.PopArrayOfBytes(&bytes, &length)) + return false; + salt->assign(bytes, bytes + length); + return true; + } + + // CryptohomeClient override. + virtual void AsyncMount(const std::string& username, + const std::string& key, + const bool create_if_missing, + AsyncMethodCallback callback) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeAsyncMount); + dbus::MessageWriter writer(&method_call); + writer.AppendString(username); + writer.AppendString(key); + writer.AppendBool(create_if_missing); + writer.AppendBool(false); // deprecated_replace_tracked_subdirectories + // deprecated_tracked_subdirectories + writer.AppendArrayOfStrings(std::vector<std::string>()); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + virtual void AsyncMountGuest(AsyncMethodCallback callback) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeAsyncMountGuest); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&CryptohomeClientImpl::OnAsyncMethodCall, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + virtual bool TpmIsReady(bool* ready) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeTpmIsReady); + return CallBoolMethodAndBlock(&method_call, ready); + } + + // CryptohomeClient override. + virtual void TpmIsEnabled(BoolMethodCallback callback) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeTpmIsEnabled); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind( + &CryptohomeClientImpl::OnBoolMethod, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + // TODO(hashimoto): Remove this method. crosbug.com/28500 + virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE { + // We don't use INITIALIZE_METHOD_CALL here because the C++ method name is + // different from the D-Bus method name (TpmIsEnabled). + dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, + cryptohome::kCryptohomeTpmIsEnabled); + return CallBoolMethodAndBlock(&method_call, enabled); + } + + // CryptohomeClient override. + virtual bool TpmGetPassword(std::string* password) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeTpmGetPassword); + scoped_ptr<dbus::Response> response( + blocking_method_caller_.CallMethodAndBlock(&method_call)); + if (!response.get()) + return false; + dbus::MessageReader reader(response.get()); + return reader.PopString(password); + } + + // CryptohomeClient override. + virtual bool TpmIsOwned(bool* owned) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeTpmIsOwned); + return CallBoolMethodAndBlock(&method_call, owned); + } + + // CryptohomeClient override. + virtual bool TpmIsBeingOwned(bool* owning) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, cryptohome::kCryptohomeTpmIsBeingOwned); + return CallBoolMethodAndBlock(&method_call, owning); + } + + // CryptohomeClient override. + virtual bool TpmCanAttemptOwnership() OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomeTpmCanAttemptOwnership); + scoped_ptr<dbus::Response> response( + blocking_method_caller_.CallMethodAndBlock(&method_call)); + return response.get() != NULL; + } + + // CryptohomeClient override. + virtual bool TpmClearStoredPassword() OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomeTpmClearStoredPassword); + scoped_ptr<dbus::Response> response( + blocking_method_caller_.CallMethodAndBlock(&method_call)); + return response.get() != NULL; + } + + // CryptohomeClient override. + virtual void Pkcs11IsTpmTokenReady(BoolMethodCallback callback) + OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomePkcs11IsTpmTokenReady); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind( + &CryptohomeClientImpl::OnBoolMethod, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + virtual void Pkcs11GetTpmTokenInfo(Pkcs11GetTpmTokenInfoCallback callback) + OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomePkcs11GetTpmTokenInfo); + proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind( + &CryptohomeClientImpl::OnPkcs11GetTpmTokenInfo, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // CryptohomeClient override. + virtual bool InstallAttributesGet(const std::string& name, + std::vector<uint8>* value, + bool* successful) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomeInstallAttributesGet); + dbus::MessageWriter writer(&method_call); + writer.AppendString(name); + scoped_ptr<dbus::Response> response( + blocking_method_caller_.CallMethodAndBlock(&method_call)); + if (!response.get()) + return false; + dbus::MessageReader reader(response.get()); + uint8* bytes = NULL; + size_t length = 0; + if (!reader.PopArrayOfBytes(&bytes, &length) || + !reader.PopBool(successful)) + return false; + value->assign(bytes, bytes + length); + return true; + } + + // CryptohomeClient override. + virtual bool InstallAttributesSet(const std::string& name, + const std::vector<uint8>& value, + bool* successful) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomeInstallAttributesSet); + dbus::MessageWriter writer(&method_call); + writer.AppendString(name); + writer.AppendArrayOfBytes(value.data(), value.size()); + return CallBoolMethodAndBlock(&method_call, successful); + } + + // CryptohomeClient override. + virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomeInstallAttributesFinalize); + return CallBoolMethodAndBlock(&method_call, successful); + } + + // CryptohomeClient override. + virtual bool InstallAttributesIsReady(bool* is_ready) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomeInstallAttributesIsReady); + return CallBoolMethodAndBlock(&method_call, is_ready); + } + + // CryptohomeClient override. + virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE { + INITIALIZE_METHOD_CALL(method_call, + cryptohome::kCryptohomeInstallAttributesIsInvalid); + return CallBoolMethodAndBlock(&method_call, is_invalid); + } + + // CryptohomeClient override. + virtual bool InstallAttributesIsFirstInstall(bool* is_first_install) OVERRIDE + { + INITIALIZE_METHOD_CALL( + method_call, cryptohome::kCryptohomeInstallAttributesIsFirstInstall); + return CallBoolMethodAndBlock(&method_call, is_first_install); + } + + private: + // Handles the result of AsyncXXX methods. + void OnAsyncMethodCall(AsyncMethodCallback callback, + dbus::Response* response) { + if (!response) + return; + dbus::MessageReader reader(response); + int async_id = 0; + if (!reader.PopInt32(&async_id)) { + LOG(ERROR) << "Invalid response: " << response->ToString(); + return; + } + callback.Run(async_id); + } + + // Calls a method with a bool value reult and block. + bool CallBoolMethodAndBlock(dbus::MethodCall* method_call, + bool* result) { + scoped_ptr<dbus::Response> response( + blocking_method_caller_.CallMethodAndBlock(method_call)); + if (!response.get()) + return false; + dbus::MessageReader reader(response.get()); + return reader.PopBool(result); + } + + // Handles responses for methods with a bool value result. + void OnBoolMethod(BoolMethodCallback callback, + dbus::Response* response) { + if (!response) { + callback.Run(DBUS_METHOD_CALL_FAILURE, false); + return; + } + dbus::MessageReader reader(response); + bool result = false; + if (!reader.PopBool(&result)) { + callback.Run(DBUS_METHOD_CALL_FAILURE, false); + return; + } + callback.Run(DBUS_METHOD_CALL_SUCCESS, result); + } + + // Handles responses for Pkcs11GetTpmtTokenInfo. + void OnPkcs11GetTpmTokenInfo(Pkcs11GetTpmTokenInfoCallback callback, + dbus::Response* response) { + if (!response) { + callback.Run(DBUS_METHOD_CALL_FAILURE, std::string(), std::string()); + return; + } + dbus::MessageReader reader(response); + std::string label; + std::string user_pin; + if (!reader.PopString(&label) || !reader.PopString(&user_pin)) { + callback.Run(DBUS_METHOD_CALL_FAILURE, std::string(), std::string()); + return; + } + callback.Run(DBUS_METHOD_CALL_SUCCESS, label, user_pin); + } + + // Handles AsyncCallStatus signal. + void OnAsyncCallStatus(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + int async_id = 0; + bool return_status = false; + int return_code = 0; + if (!reader.PopInt32(&async_id) || + !reader.PopBool(&return_status) || + !reader.PopInt32(&return_code)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + if (!async_call_status_handler_.is_null()) + async_call_status_handler_.Run(async_id, return_status, return_code); + } + + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool successed) { + LOG_IF(ERROR, !successed) << "Connect to " << interface << " " << + signal << " failed."; + } + + dbus::ObjectProxy* proxy_; + base::WeakPtrFactory<CryptohomeClientImpl> weak_ptr_factory_; + BlockingMethodCaller blocking_method_caller_; + AsyncCallStatusHandler async_call_status_handler_; + + DISALLOW_COPY_AND_ASSIGN(CryptohomeClientImpl); +}; + +// A stub implementaion of CryptohomeClient. +class CryptohomeClientStubImpl : public CryptohomeClient { + public: + CryptohomeClientStubImpl() + : weak_ptr_factory_(this), + async_call_id_(1), + tpm_is_ready_counter_(0), + locked_(false) { + } + + virtual ~CryptohomeClientStubImpl() {} + + // CryptohomeClient override. + virtual void SetAsyncCallStatusHandler(AsyncCallStatusHandler handler) + OVERRIDE { + async_call_status_handler_ = handler; + } + + // CryptohomeClient override. + virtual void ResetAsyncCallStatusHandler() OVERRIDE { + async_call_status_handler_.Reset(); + } + + // CryptohomeClient override. + virtual bool IsMounted(bool* is_mounted) OVERRIDE { + *is_mounted = true; + return true; + } + + // CryptohomeClient override. + virtual bool Unmount(bool* success) OVERRIDE { + *success = true; + return true; + } + + // CryptohomeClient override. + virtual void AsyncCheckKey(const std::string& username, + const std::string& key, + AsyncMethodCallback callback) OVERRIDE { + ReturnAsyncMethodResult(callback); + } + + // CryptohomeClient override. + virtual void AsyncMigrateKey(const std::string& username, + const std::string& from_key, + const std::string& to_key, + AsyncMethodCallback callback) OVERRIDE { + ReturnAsyncMethodResult(callback); + } + + // CryptohomeClient override. + virtual void AsyncRemove(const std::string& username, + AsyncMethodCallback callback) OVERRIDE { + ReturnAsyncMethodResult(callback); + } + + // CryptohomeClient override. + virtual bool GetSystemSalt(std::vector<uint8>* salt) OVERRIDE { + const char kStubSystemSalt[] = "stub_system_salt"; + salt->assign(kStubSystemSalt, + kStubSystemSalt + arraysize(kStubSystemSalt)); + return true; + } + + // CryptohomeClient override. + virtual void AsyncMount(const std::string& username, + const std::string& key, + const bool create_if_missing, + AsyncMethodCallback callback) OVERRIDE { + ReturnAsyncMethodResult(callback); + } + + // CryptohomeClient override. + virtual void AsyncMountGuest(AsyncMethodCallback callback) OVERRIDE { + ReturnAsyncMethodResult(callback); + } + + // CryptohomeClient override. + virtual bool TpmIsReady(bool* ready) OVERRIDE { + *ready = (tpm_is_ready_counter_++ > 20); + return true; + } + + // CryptohomeClient override. + virtual void TpmIsEnabled(BoolMethodCallback callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); + } + + // CryptohomeClient override. + virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE { + *enabled = true; + return true; + } + + // CryptohomeClient override. + virtual bool TpmGetPassword(std::string* password) OVERRIDE { + const char kStubTpmPassword[] = "Stub-TPM-password"; + *password = kStubTpmPassword; + return true; + } + + // CryptohomeClient override. + virtual bool TpmIsOwned(bool* owned) OVERRIDE { + *owned = true; + return true; + } + + // CryptohomeClient override. + virtual bool TpmIsBeingOwned(bool* owning) OVERRIDE { + *owning = true; + return true; + } + + // CryptohomeClient override. + virtual bool TpmCanAttemptOwnership() OVERRIDE { return true; } + + // CryptohomeClient override. + virtual bool TpmClearStoredPassword() OVERRIDE { return true; } + + // CryptohomeClient override. + virtual void Pkcs11IsTpmTokenReady(BoolMethodCallback callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); + } + + // CryptohomeClient override. + virtual void Pkcs11GetTpmTokenInfo( + Pkcs11GetTpmTokenInfoCallback callback) OVERRIDE { + const char kStubLabel[] = "Stub TPM Token"; + const char kStubUserPin[] = "012345"; + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, kStubLabel, + kStubUserPin)); + } + + // CryptohomeClient override. + virtual bool InstallAttributesGet(const std::string& name, + std::vector<uint8>* value, + bool* successful) OVERRIDE { + if (install_attrs_.find(name) != install_attrs_.end()) { + *value = install_attrs_[name]; + *successful = true; + } else { + value->clear(); + *successful = false; + } + return true; + } + + // CryptohomeClient override. + virtual bool InstallAttributesSet(const std::string& name, + const std::vector<uint8>& value, + bool* successful) OVERRIDE { + install_attrs_[name] = value; + *successful = true; + return true; + } + + // CryptohomeClient override. + virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE { + locked_ = true; + *successful = true; + return true; + } + + // CryptohomeClient override. + virtual bool InstallAttributesIsReady(bool* is_ready) OVERRIDE { + *is_ready = true; + return true; + } + + // CryptohomeClient override. + virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE { + *is_invalid = false; + return true; + } + + // CryptohomeClient override. + virtual bool InstallAttributesIsFirstInstall(bool* is_first_install) OVERRIDE + { + *is_first_install = !locked_; + return true; + } + + private: + // Posts tasks which return fake results to the UI thread. + void ReturnAsyncMethodResult(AsyncMethodCallback callback) { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&CryptohomeClientStubImpl::ReturnAsyncMethodResultInternal, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // This method is used to implement ReturnAsyncMethodResult. + void ReturnAsyncMethodResultInternal(AsyncMethodCallback callback) { + callback.Run(async_call_id_); + if (!async_call_status_handler_.is_null()) { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(async_call_status_handler_, + async_call_id_, + true, + cryptohome::MOUNT_ERROR_NONE)); + } + ++async_call_id_; + } + + base::WeakPtrFactory<CryptohomeClientStubImpl> weak_ptr_factory_; + int async_call_id_; + AsyncCallStatusHandler async_call_status_handler_; + int tpm_is_ready_counter_; + std::map<std::string, std::vector<uint8> > install_attrs_; + bool locked_; + + DISALLOW_COPY_AND_ASSIGN(CryptohomeClientStubImpl); +}; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// CryptohomeClient + +CryptohomeClient::CryptohomeClient() {} + +CryptohomeClient::~CryptohomeClient() {} + +// static +CryptohomeClient* CryptohomeClient::Create(DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new CryptohomeClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new CryptohomeClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/cryptohome_client.h b/chromeos/dbus/cryptohome_client.h new file mode 100644 index 0000000..df93832 --- /dev/null +++ b/chromeos/dbus/cryptohome_client.h @@ -0,0 +1,179 @@ +// 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. + +#ifndef CHROMEOS_DBUS_CRYPTOHOME_CLIENT_H_ +#define CHROMEOS_DBUS_CRYPTOHOME_CLIENT_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "chromeos/dbus/dbus_method_call_status.h" + +namespace dbus { +class Bus; +} + +namespace chromeos { + +// CryptohomeClient is used to communicate with the Cryptohome service. +// All method should be called from the origin thread (UI thread) which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT CryptohomeClient { + public: + // A callback to handle AsyncCallStatus signals. + typedef base::Callback<void(int async_id, bool return_status, int return_code) + > AsyncCallStatusHandler; + // A callback to handle responses of AsyncXXX methods. + typedef base::Callback<void(int async_id)> AsyncMethodCallback; + // A callback to handle responses of methods returning a bool value. + typedef base::Callback<void(DBusMethodCallStatus call_status, + bool result)> BoolMethodCallback; + // A callback to handle responses of Pkcs11GetTpmTokenInfo method. + typedef base::Callback<void( + DBusMethodCallStatus call_status, + const std::string& label, + const std::string& user_pin)> Pkcs11GetTpmTokenInfoCallback; + + virtual ~CryptohomeClient(); + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static CryptohomeClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + // Sets AsyncCallStatus signal handler. + // |handler| is called when results for AsyncXXX methods are returned. + // Cryptohome service will process the calls in a first-in-first-out manner + // when they are made in parallel. + virtual void SetAsyncCallStatusHandler(AsyncCallStatusHandler handler) = 0; + + // Resets AsyncCallStatus signal handler. + virtual void ResetAsyncCallStatusHandler() = 0; + + // Calls IsMounted method and returns true when the call succeeds. + // This method blocks until the call returns. + virtual bool IsMounted(bool* is_mounted) = 0; + + // Calls Unmount method and returns true when the call succeeds. + // This method blocks until the call returns. + virtual bool Unmount(bool* success) = 0; + + // Calls AsyncCheckKey method. |callback| is called after the method call + // succeeds. + virtual void AsyncCheckKey(const std::string& username, + const std::string& key, + AsyncMethodCallback callback) = 0; + + // Calls AsyncMigrateKey method. |callback| is called after the method call + // succeeds. + virtual void AsyncMigrateKey(const std::string& username, + const std::string& from_key, + const std::string& to_key, + AsyncMethodCallback callback) = 0; + + // Calls AsyncRemove method. |callback| is called after the method call + // succeeds. + virtual void AsyncRemove(const std::string& username, + AsyncMethodCallback callback) = 0; + + // Calls GetSystemSalt method. This method blocks until the call returns. + // The original content of |salt| is lost. + virtual bool GetSystemSalt(std::vector<uint8>* salt) = 0; + + // Calls AsyncMount method. |callback| is called after the method call + // succeeds. + virtual void AsyncMount(const std::string& username, + const std::string& key, + const bool create_if_missing, + AsyncMethodCallback callback) = 0; + + // Calls AsyncMountGuest method. |callback| is called after the method call + // succeeds. + virtual void AsyncMountGuest(AsyncMethodCallback callback) = 0; + + // Calls TpmIsReady method and returns true when the call succeeds. + // This method blocks until the call returns. + virtual bool TpmIsReady(bool* ready) = 0; + + // Calls TpmIsEnabled method. + virtual void TpmIsEnabled(BoolMethodCallback callback) = 0; + + // Calls TpmIsEnabled method and returns true when the call succeeds. + // This method blocks until the call returns. + // TODO(hashimoto): Remove this method. crosbug.com/28500 + virtual bool CallTpmIsEnabledAndBlock(bool* enabled) = 0; + + // Calls TpmGetPassword method and returns true when the call succeeds. + // This method blocks until the call returns. + // The original content of |password| is lost. + virtual bool TpmGetPassword(std::string* password) = 0; + + // Calls TpmIsOwned method and returns true when the call succeeds. + // This method blocks until the call returns. + virtual bool TpmIsOwned(bool* owned) = 0; + + // Calls TpmIsBeingOwned method and returns true when the call succeeds. + // This method blocks until the call returns. + virtual bool TpmIsBeingOwned(bool* owning) = 0; + + // Calls TpmCanAttemptOwnership method and returns true when the call + // succeeds. This method blocks until the call returns. + virtual bool TpmCanAttemptOwnership() = 0; + + // Calls TpmClearStoredPassword method and returns true when the call + // succeeds. This method blocks until the call returns. + virtual bool TpmClearStoredPassword() = 0; + + // Calls Pkcs11IsTpmTokenReady method. + virtual void Pkcs11IsTpmTokenReady(BoolMethodCallback callback) = 0; + + // Calls Pkcs11GetTpmTokenInfo method. + virtual void Pkcs11GetTpmTokenInfo( + Pkcs11GetTpmTokenInfoCallback callback) = 0; + + // Calls InstallAttributesGet method and returns true when the call succeeds. + // This method blocks until the call returns. + // The original content of |value| is lost. + virtual bool InstallAttributesGet(const std::string& name, + std::vector<uint8>* value, + bool* successful) = 0; + + // Calls InstallAttributesSet method and returns true when the call succeeds. + // This method blocks until the call returns. + virtual bool InstallAttributesSet(const std::string& name, + const std::vector<uint8>& value, + bool* successful) = 0; + + // Calls InstallAttributesFinalize method and returns true when the call + // succeeds. This method blocks until the call returns. + virtual bool InstallAttributesFinalize(bool* successful) = 0; + + // Calls InstallAttributesIsReady method and returns true when the call + // succeeds. This method blocks until the call returns. + virtual bool InstallAttributesIsReady(bool* is_ready) = 0; + + // Calls InstallAttributesIsInvalid method and returns true when the call + // succeeds. This method blocks until the call returns. + virtual bool InstallAttributesIsInvalid(bool* is_invalid) = 0; + + // Calls InstallAttributesIsFirstInstall method and returns true when the call + // succeeds. This method blocks until the call returns. + virtual bool InstallAttributesIsFirstInstall(bool* is_first_install) = 0; + + protected: + // Create() should be used instead. + CryptohomeClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(CryptohomeClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_CRYPTOHOME_CLIENT_H_ diff --git a/chromeos/dbus/dbus_client_implementation_type.h b/chromeos/dbus/dbus_client_implementation_type.h new file mode 100644 index 0000000..45fb492 --- /dev/null +++ b/chromeos/dbus/dbus_client_implementation_type.h @@ -0,0 +1,18 @@ +// 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. + +#ifndef CHROMEOS_DBUS_DBUS_CLIENT_IMPLEMENTATION_TYPE_H_ +#define CHROMEOS_DBUS_DBUS_CLIENT_IMPLEMENTATION_TYPE_H_ + +namespace chromeos { + +// An enum to describe the desired type of D-Bus client implemenation. +enum DBusClientImplementationType { + REAL_DBUS_CLIENT_IMPLEMENTATION, // The real implementation. + STUB_DBUS_CLIENT_IMPLEMENTATION, // A stub implementation. +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_DBUS_CLIENT_IMPLEMENTATION_TYPE_H_ diff --git a/chromeos/dbus/dbus_method_call_status.h b/chromeos/dbus/dbus_method_call_status.h new file mode 100644 index 0000000..6cfb11e --- /dev/null +++ b/chromeos/dbus/dbus_method_call_status.h @@ -0,0 +1,18 @@ +// 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. + +#ifndef CHROMEOS_DBUS_DBUS_METHOD_CALL_STATUS_H_ +#define CHROMEOS_DBUS_DBUS_METHOD_CALL_STATUS_H_ + +namespace chromeos { + +// An enum to describe whether or not a DBus method call succeeded. +enum DBusMethodCallStatus { + DBUS_METHOD_CALL_FAILURE, + DBUS_METHOD_CALL_SUCCESS, +}; + +} // namespace + +#endif // CHROMEOS_DBUS_DBUS_METHOD_CALL_STATUS_H_ diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc new file mode 100644 index 0000000..79ba37d --- /dev/null +++ b/chromeos/dbus/dbus_thread_manager.cc @@ -0,0 +1,279 @@ +// 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/dbus_thread_manager.h" + +#include "base/chromeos/chromeos_version.h" +#include "base/threading/thread.h" +#include "chromeos/dbus/bluetooth_adapter_client.h" +#include "chromeos/dbus/bluetooth_device_client.h" +#include "chromeos/dbus/bluetooth_input_client.h" +#include "chromeos/dbus/bluetooth_manager_client.h" +#include "chromeos/dbus/bluetooth_node_client.h" +#include "chromeos/dbus/cashew_client.h" +#include "chromeos/dbus/cros_disks_client.h" +#include "chromeos/dbus/cryptohome_client.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/flimflam_ipconfig_client.h" +#include "chromeos/dbus/flimflam_network_client.h" +#include "chromeos/dbus/flimflam_profile_client.h" +#include "chromeos/dbus/image_burner_client.h" +#include "chromeos/dbus/introspectable_client.h" +#include "chromeos/dbus/power_manager_client.h" +#include "chromeos/dbus/session_manager_client.h" +#include "chromeos/dbus/speech_synthesizer_client.h" +#include "chromeos/dbus/update_engine_client.h" +#include "dbus/bus.h" + +namespace chromeos { + +static DBusThreadManager* g_dbus_thread_manager = NULL; + +// The DBusThreadManager implementation used in production. +class DBusThreadManagerImpl : public DBusThreadManager { + public: + DBusThreadManagerImpl() { + // Create the D-Bus thread. + base::Thread::Options thread_options; + thread_options.message_loop_type = MessageLoop::TYPE_IO; + dbus_thread_.reset(new base::Thread("D-Bus thread")); + dbus_thread_->StartWithOptions(thread_options); + + // Create the connection to the system bus. + dbus::Bus::Options system_bus_options; + system_bus_options.bus_type = dbus::Bus::SYSTEM; + system_bus_options.connection_type = dbus::Bus::PRIVATE; + system_bus_options.dbus_thread_message_loop_proxy = + dbus_thread_->message_loop_proxy(); + system_bus_ = new dbus::Bus(system_bus_options); + + // Determine whether we use stub or real client implementations. + const DBusClientImplementationType client_type = + base::chromeos::IsRunningOnChromeOS() ? + REAL_DBUS_CLIENT_IMPLEMENTATION : STUB_DBUS_CLIENT_IMPLEMENTATION; + + // Create the bluetooth clients. + bluetooth_manager_client_.reset(BluetoothManagerClient::Create( + client_type, system_bus_.get())); + bluetooth_adapter_client_.reset(BluetoothAdapterClient::Create( + client_type, system_bus_.get(), bluetooth_manager_client_.get())); + bluetooth_device_client_.reset(BluetoothDeviceClient::Create( + client_type, system_bus_.get(), bluetooth_adapter_client_.get())); + bluetooth_input_client_.reset(BluetoothInputClient::Create( + client_type, system_bus_.get(), bluetooth_adapter_client_.get())); + bluetooth_node_client_.reset(BluetoothNodeClient::Create( + client_type, system_bus_.get(), bluetooth_device_client_.get())); + // Create the Cashew client. + cashew_client_.reset(CashewClient::Create(client_type, system_bus_.get())); + // Create the cros-disks client. + cros_disks_client_.reset( + CrosDisksClient::Create(client_type, system_bus_.get())); + // Create the Cryptohome client. + cryptohome_client_.reset( + CryptohomeClient::Create(client_type, system_bus_.get())); + // Create the debugdaemon client. + debugdaemon_client_.reset( + DebugDaemonClient::Create(client_type, system_bus_.get())); + // Create the Flimflam IPConfig client. + flimflam_ipconfig_client_.reset( + FlimflamIPConfigClient::Create(client_type, system_bus_.get())); + // Create the Flimflam Network client. + flimflam_network_client_.reset( + FlimflamNetworkClient::Create(client_type, system_bus_.get())); + // Create the Flimflam Profile client. + flimflam_profile_client_.reset( + FlimflamProfileClient::Create(client_type, system_bus_.get())); + // Create the image burner client. + image_burner_client_.reset(ImageBurnerClient::Create(client_type, + system_bus_.get())); + // Create the introspectable object client. + introspectable_client_.reset( + IntrospectableClient::Create(client_type, system_bus_.get())); + // Create the power manager client. + power_manager_client_.reset(PowerManagerClient::Create(client_type, + system_bus_.get())); + // Create the session manager client. + session_manager_client_.reset( + SessionManagerClient::Create(client_type, system_bus_.get())); + // Create the speech synthesizer client. + speech_synthesizer_client_.reset( + SpeechSynthesizerClient::Create(client_type, system_bus_.get())); + // Create the update engine client. + update_engine_client_.reset( + UpdateEngineClient::Create(client_type, system_bus_.get())); + } + + virtual ~DBusThreadManagerImpl() { + // Shut down the bus. During the browser shutdown, it's ok to shut down + // the bus synchronously. + system_bus_->ShutdownOnDBusThreadAndBlock(); + + // Stop the D-Bus thread. + dbus_thread_->Stop(); + } + + // DBusThreadManager override. + virtual dbus::Bus* GetSystemBus() OVERRIDE { + return system_bus_.get(); + } + + // DBusThreadManager override. + virtual BluetoothAdapterClient* GetBluetoothAdapterClient() OVERRIDE { + return bluetooth_adapter_client_.get(); + } + + // DBusThreadManager override. + virtual BluetoothDeviceClient* GetBluetoothDeviceClient() OVERRIDE { + return bluetooth_device_client_.get(); + } + + // DBusThreadManager override. + virtual BluetoothInputClient* GetBluetoothInputClient() OVERRIDE { + return bluetooth_input_client_.get(); + } + + // DBusThreadManager override. + virtual BluetoothManagerClient* GetBluetoothManagerClient() OVERRIDE { + return bluetooth_manager_client_.get(); + } + + // DBusThreadManager override. + virtual BluetoothNodeClient* GetBluetoothNodeClient() OVERRIDE { + return bluetooth_node_client_.get(); + } + + // DBusThreadManager override. + virtual CashewClient* GetCashewClient() OVERRIDE { + return cashew_client_.get(); + } + + // DBusThreadManager override. + virtual CrosDisksClient* GetCrosDisksClient() OVERRIDE { + return cros_disks_client_.get(); + } + + // DBusThreadManager override. + virtual CryptohomeClient* GetCryptohomeClient() OVERRIDE { + return cryptohome_client_.get(); + } + + // DBusThreadManager override. + virtual DebugDaemonClient* GetDebugDaemonClient() OVERRIDE { + return debugdaemon_client_.get(); + } + + // DBusThreadManager override. + virtual FlimflamIPConfigClient* GetFlimflamIPConfigClient() OVERRIDE { + return flimflam_ipconfig_client_.get(); + } + + virtual FlimflamNetworkClient* GetFlimflamNetworkClient() OVERRIDE { + return flimflam_network_client_.get(); + } + + // DBusThreadManager override. + virtual FlimflamProfileClient* GetFlimflamProfileClient() OVERRIDE { + return flimflam_profile_client_.get(); + } + + // DBusThreadManager override. + virtual ImageBurnerClient* GetImageBurnerClient() OVERRIDE { + return image_burner_client_.get(); + } + + // DBusThreadManager override. + virtual IntrospectableClient* GetIntrospectableClient() OVERRIDE { + return introspectable_client_.get(); + } + + // DBusThreadManager override. + virtual PowerManagerClient* GetPowerManagerClient() OVERRIDE { + return power_manager_client_.get(); + } + + // DBusThreadManager override. + virtual SessionManagerClient* GetSessionManagerClient() OVERRIDE { + return session_manager_client_.get(); + } + + // DBusThreadManager override. + virtual SpeechSynthesizerClient* GetSpeechSynthesizerClient() OVERRIDE { + return speech_synthesizer_client_.get(); + } + + // DBusThreadManager override. + virtual UpdateEngineClient* GetUpdateEngineClient() OVERRIDE { + return update_engine_client_.get(); + } + + scoped_ptr<base::Thread> dbus_thread_; + scoped_refptr<dbus::Bus> system_bus_; + scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_; + scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_; + scoped_ptr<BluetoothInputClient> bluetooth_input_client_; + scoped_ptr<BluetoothManagerClient> bluetooth_manager_client_; + scoped_ptr<BluetoothNodeClient> bluetooth_node_client_; + scoped_ptr<CashewClient> cashew_client_; + scoped_ptr<CrosDisksClient> cros_disks_client_; + scoped_ptr<CryptohomeClient> cryptohome_client_; + scoped_ptr<DebugDaemonClient> debugdaemon_client_; + scoped_ptr<FlimflamIPConfigClient> flimflam_ipconfig_client_; + scoped_ptr<FlimflamNetworkClient> flimflam_network_client_; + scoped_ptr<FlimflamProfileClient> flimflam_profile_client_; + scoped_ptr<ImageBurnerClient> image_burner_client_; + scoped_ptr<IntrospectableClient> introspectable_client_; + scoped_ptr<PowerManagerClient> power_manager_client_; + scoped_ptr<SessionManagerClient> session_manager_client_; + scoped_ptr<SpeechSynthesizerClient> speech_synthesizer_client_; + scoped_ptr<UpdateEngineClient> update_engine_client_; +}; + +// static +void DBusThreadManager::Initialize() { + if (g_dbus_thread_manager) { + LOG(WARNING) << "DBusThreadManager was already initialized"; + return; + } + g_dbus_thread_manager = new DBusThreadManagerImpl; + VLOG(1) << "DBusThreadManager initialized"; +} + +// static +void DBusThreadManager::InitializeForTesting( + DBusThreadManager* dbus_thread_manager) { + if (g_dbus_thread_manager) { + LOG(WARNING) << "DBusThreadManager was already initialized"; + return; + } + g_dbus_thread_manager = dbus_thread_manager; + VLOG(1) << "DBusThreadManager initialized"; +} + +// static +void DBusThreadManager::Shutdown() { + if (!g_dbus_thread_manager) { + // TODO(satorux): Make it a DCHECK() once it's ready. + LOG(WARNING) << "DBusThreadManager::Shutdown() called with NULL manager"; + return; + } + delete g_dbus_thread_manager; + g_dbus_thread_manager = NULL; + VLOG(1) << "DBusThreadManager Shutdown completed"; +} + +DBusThreadManager::DBusThreadManager() { +} + +DBusThreadManager::~DBusThreadManager() { +} + +// static +DBusThreadManager* DBusThreadManager::Get() { + CHECK(g_dbus_thread_manager) + << "DBusThreadManager::Get() called before Initialize()"; + return g_dbus_thread_manager; +} + +} // namespace chromeos diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h new file mode 100644 index 0000000..2e413540 --- /dev/null +++ b/chromeos/dbus/dbus_thread_manager.h @@ -0,0 +1,181 @@ +// 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. + +#ifndef CHROMEOS_DBUS_DBUS_THREAD_MANAGER_H_ +#define CHROMEOS_DBUS_DBUS_THREAD_MANAGER_H_ +#pragma once + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "chromeos/chromeos_export.h" + +namespace base { +class Thread; +}; + +namespace dbus { +class Bus; +}; + +namespace chromeos { + +// Style Note: Clients are sorted by names. +class BluetoothAdapterClient; +class BluetoothDeviceClient; +class BluetoothInputClient; +class BluetoothManagerClient; +class BluetoothNodeClient; +class CashewClient; +class CrosDisksClient; +class CryptohomeClient; +class DebugDaemonClient; +class FlimflamIPConfigClient; +class FlimflamNetworkClient; +class FlimflamProfileClient; +class ImageBurnerClient; +class IntrospectableClient; +class PowerManagerClient; +class SessionManagerClient; +class SpeechSynthesizerClient; +class UpdateEngineClient; + +// DBusThreadManager manages the D-Bus thread, the thread dedicated to +// handling asynchronous D-Bus operations. +// +// This class also manages D-Bus connections and D-Bus clients, which +// depend on the D-Bus thread to ensure the right order of shutdowns for +// the D-Bus thread, the D-Bus connections, and the D-Bus clients. +// +// CALLBACKS IN D-BUS CLIENTS: +// +// D-Bus clients managed by DBusThreadManager are guaranteed to be deleted +// after the D-Bus thread so the clients don't need to worry if new +// incoming messages arrive from the D-Bus thread during shutdown of the +// clients. The UI message loop is not running during the shutdown hence +// the UI message loop won't post tasks to D-BUS clients during the +// shutdown. However, to be extra cautious, clients should use +// WeakPtrFactory when creating callbacks that run on UI thread. See +// session_manager_client.cc for examples. +// +class CHROMEOS_EXPORT DBusThreadManager { + public: + // Sets the global instance. Must be called before any calls to Get(). + // We explicitly initialize and shut down the global object, rather than + // making it a Singleton, to ensure clean startup and shutdown. + static void Initialize(); + + // Similar to Initialize(), but can inject an alternative + // DBusThreadManager such as MockDBusThreadManager for testing. + // The injected object will be owned by the internal pointer and deleted + // by Shutdown(). + static void InitializeForTesting(DBusThreadManager* dbus_thread_manager); + + // Destroys the global instance. + static void Shutdown(); + + // Gets the global instance. Initialize() must be called first. + static DBusThreadManager* Get(); + + // Returns the D-Bus system bus instance, owned by DBusThreadManager. + virtual dbus::Bus* GetSystemBus() = 0; + + // Returns the bluetooth adapter client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual BluetoothAdapterClient* GetBluetoothAdapterClient() = 0; + + // Returns the bluetooth device client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual BluetoothDeviceClient* GetBluetoothDeviceClient() = 0; + + // Returns the bluetooth input client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual BluetoothInputClient* GetBluetoothInputClient() = 0; + + // Returns the bluetooth manager client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual BluetoothManagerClient* GetBluetoothManagerClient() = 0; + + // Returns the bluetooth node client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual BluetoothNodeClient* GetBluetoothNodeClient() = 0; + + // Returns the Cashew client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual CashewClient* GetCashewClient() = 0; + + // Returns the cros-disks client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual CrosDisksClient* GetCrosDisksClient() = 0; + + // Returns the Cryptohome client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual CryptohomeClient* GetCryptohomeClient() = 0; + + // Returns the DebugDaemon client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual DebugDaemonClient* GetDebugDaemonClient() = 0; + + // Returns the Flimflam IPConfig client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual FlimflamIPConfigClient* GetFlimflamIPConfigClient() = 0; + + // Returns the Flimflam Network client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual FlimflamNetworkClient* GetFlimflamNetworkClient() = 0; + + // Returns the Flimflam Profile client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual FlimflamProfileClient* GetFlimflamProfileClient() = 0; + + // Returns the image burner client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManger is shut + // down. + virtual ImageBurnerClient* GetImageBurnerClient() = 0; + + // Returns the introspectable object client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManger is shut + // down. + virtual IntrospectableClient* GetIntrospectableClient() = 0; + + // Returns the power manager client, owned by DBusThreadManager. + // See also comments at session_manager_client(). + virtual PowerManagerClient* GetPowerManagerClient() = 0; + + // Returns the session manager client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual SessionManagerClient* GetSessionManagerClient() = 0; + + // Returns the speech synthesizer client, owned by DBusThreadManager. + // Do not cache this pointer and use it after DBusThreadManager is shut + // down. + virtual SpeechSynthesizerClient* GetSpeechSynthesizerClient() = 0; + + // Returns the update engine client, owned by DBusThreadManager. Do not + // cache this pointer and use it after DBusThreadManager is shut down. + virtual UpdateEngineClient* GetUpdateEngineClient() = 0; + + virtual ~DBusThreadManager(); + + protected: + DBusThreadManager(); + + DISALLOW_COPY_AND_ASSIGN(DBusThreadManager); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_DBUS_THREAD_MANAGER_H_ diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc new file mode 100644 index 0000000..bc8e06d --- /dev/null +++ b/chromeos/dbus/debug_daemon_client.cc @@ -0,0 +1,277 @@ +// 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 <fcntl.h> +#include <unistd.h> + +#include "chromeos/dbus/debug_daemon_client.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/chromeos/chromeos_version.h" +#include "base/eintr_wrapper.h" +#include "base/memory/ref_counted_memory.h" +#include "base/platform_file.h" +#include "base/string_util.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "net/base/file_stream.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace { + +// Used in DebugDaemonClient::EmptySystemStopTracingCallback(). +void EmptyStopSystemTracingCallbackBody( + const scoped_refptr<base::RefCountedString>& unused_result) { +} + +// Simple class to encapsulate collecting data from a pipe into a +// string. To use, instantiate the class, start i/o, and then delete +// the instance on callback. The data should be retrieved before +// delete and extracted or copied. +// +// TODO(sleffler) move data collection to a sub-class so this +// can be reused to process data as it is received +class PipeReader { + public: + typedef base::Callback<void(void)>IOCompleteCallback; + + explicit PipeReader(IOCompleteCallback callback) + : data_stream_(NULL), + io_buffer_(new net::IOBufferWithSize(4096)), + weak_ptr_factory_(this), + callback_(callback) { + pipe_fd_[0] = pipe_fd_[1] = -1; + } + + virtual ~PipeReader() { + if (pipe_fd_[0] != -1) + if (HANDLE_EINTR(close(pipe_fd_[0])) < 0) + PLOG(ERROR) << "close[0]"; + if (pipe_fd_[1] != -1) + if (HANDLE_EINTR(close(pipe_fd_[1])) < 0) + PLOG(ERROR) << "close[1]"; + } + + // Returns descriptor for the writeable side of the pipe. + int GetWriteFD() { return pipe_fd_[1]; } + + // Closes writeable descriptor; normally used in parent process after fork. + void CloseWriteFD() { + if (pipe_fd_[1] != -1) { + if (HANDLE_EINTR(close(pipe_fd_[1])) < 0) + PLOG(ERROR) << "close"; + pipe_fd_[1] = -1; + } + } + + // Returns collected data. + std::string* data() { return &data_; } + + // Starts data collection. Returns true if stream was setup correctly. + // On success data will automatically be accumulated into a string that + // can be retrieved with PipeReader::data(). To shutdown collection delete + // the instance and/or use PipeReader::OnDataReady(-1). + bool StartIO() { + // Use a pipe to collect data + const int status = HANDLE_EINTR(pipe(pipe_fd_)); + if (status < 0) { + PLOG(ERROR) << "pipe"; + return false; + } + base::PlatformFile data_file_ = pipe_fd_[0]; // read side + data_stream_.reset(new net::FileStream(data_file_, + base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC, + NULL)); + + // Post an initial async read to setup data collection + int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(), + base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr())); + if (rv != net::ERR_IO_PENDING) { + LOG(ERROR) << "Unable to post initial read"; + return false; + } + return true; + } + + // Called when pipe data are available. Can also be used to shutdown + // data collection by passing -1 for |byte_count|. + void OnDataReady(int byte_count) { + DVLOG(1) << "OnDataReady byte_count " << byte_count; + if (byte_count <= 0) { + callback_.Run(); // signal creator to take data and delete us + return; + } + data_.append(io_buffer_->data(), byte_count); + + // Post another read + int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(), + base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr())); + if (rv != net::ERR_IO_PENDING) { + LOG(ERROR) << "Unable to post another read"; + // TODO(sleffler) do something more intelligent? + } + } + + private: + friend class base::RefCounted<PipeReader>; + + int pipe_fd_[2]; + scoped_ptr<net::FileStream> data_stream_; + scoped_refptr<net::IOBufferWithSize> io_buffer_; + base::WeakPtrFactory<PipeReader> weak_ptr_factory_; + std::string data_; + IOCompleteCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(PipeReader); +}; + +} // namespace + +namespace chromeos { + +// The DebugDaemonClient implementation used in production. +class DebugDaemonClientImpl : public DebugDaemonClient { + public: + explicit DebugDaemonClientImpl(dbus::Bus* bus) + : debugdaemon_proxy_(NULL), + weak_ptr_factory_(this), + pipe_reader_(NULL) { + debugdaemon_proxy_ = bus->GetObjectProxy( + debugd::kDebugdServiceName, + dbus::ObjectPath(debugd::kDebugdServicePath)); + } + + virtual ~DebugDaemonClientImpl() {} + + // DebugDaemonClient override. + virtual void StartSystemTracing() OVERRIDE { + dbus::MethodCall method_call( + debugd::kDebugdInterface, + debugd::kSystraceStart); + dbus::MessageWriter writer(&method_call); + writer.AppendString("all"); // TODO(sleffler) parameterize category list + + DVLOG(1) << "Requesting a systrace start"; + debugdaemon_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&DebugDaemonClientImpl::OnStartSystemTracing, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual bool RequestStopSystemTracing(const StopSystemTracingCallback& + callback) OVERRIDE { + if (pipe_reader_ != NULL) { + LOG(ERROR) << "Busy doing StopSystemTracing"; + return false; + } + + pipe_reader_.reset(new PipeReader( + base::Bind(&DebugDaemonClientImpl::OnIOComplete, + weak_ptr_factory_.GetWeakPtr()))); + int write_fd = -1; + if (!pipe_reader_->StartIO()) { + LOG(ERROR) << "Cannot create pipe reader"; + // NB: continue anyway to shutdown tracing; toss trace data + write_fd = HANDLE_EINTR(open("/dev/null", O_WRONLY)); + // TODO(sleffler) if this fails AppendFileDescriptor will abort + } else { + write_fd = pipe_reader_->GetWriteFD(); + } + + DCHECK(callback.is_null()); + callback_ = callback; + + // Issue the dbus request to stop system tracing + dbus::MethodCall method_call( + debugd::kDebugdInterface, + debugd::kSystraceStop); + dbus::MessageWriter writer(&method_call); + dbus::FileDescriptor temp(write_fd); // NB: explicit temp for C++98 + writer.AppendFileDescriptor(temp); + + DVLOG(1) << "Requesting a systrace stop"; + debugdaemon_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&DebugDaemonClientImpl::OnRequestStopSystemTracing, + weak_ptr_factory_.GetWeakPtr())); + + pipe_reader_->CloseWriteFD(); // close our copy of fd after send + + return true; + } + + private: + // Called when a response for StartSystemTracing() is received. + void OnStartSystemTracing(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request systrace start"; + return; + } + } + + // Called when a response for RequestStopSystemTracing() is received. + void OnRequestStopSystemTracing(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request systrace stop"; + pipe_reader_->OnDataReady(-1); // terminate data stream + } + // NB: requester is signaled when i/o completes + } + + // Called when pipe i/o completes; pass data on and delete the instance. + void OnIOComplete() { + callback_.Run(base::RefCountedString::TakeString(pipe_reader_->data())); + pipe_reader_.reset(); + } + + dbus::ObjectProxy* debugdaemon_proxy_; + base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_; + scoped_ptr<PipeReader> pipe_reader_; + StopSystemTracingCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(DebugDaemonClientImpl); +}; + +// The DebugDaemonClient implementation used on Linux desktop, +// which does nothing. +class DebugDaemonClientStubImpl : public DebugDaemonClient { + // DebugDaemonClient overrides. + virtual void StartSystemTracing() OVERRIDE {} + virtual bool RequestStopSystemTracing(const StopSystemTracingCallback& + callback) OVERRIDE { + std::string no_data; + callback.Run(base::RefCountedString::TakeString(&no_data)); + return true; + } +}; + +DebugDaemonClient::DebugDaemonClient() { +} + +DebugDaemonClient::~DebugDaemonClient() { +} + +// static +DebugDaemonClient::StopSystemTracingCallback +DebugDaemonClient::EmptyStopSystemTracingCallback() { + return base::Bind(&EmptyStopSystemTracingCallbackBody); +} + +// static +DebugDaemonClient* DebugDaemonClient::Create(DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new DebugDaemonClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new DebugDaemonClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/debug_daemon_client.h b/chromeos/dbus/debug_daemon_client.h new file mode 100644 index 0000000..38e4015 --- /dev/null +++ b/chromeos/dbus/debug_daemon_client.h @@ -0,0 +1,53 @@ +// 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. + +#ifndef CHROMEOS_DBUS_DEBUG_DAEMON_CLIENT_H_ +#define CHROMEOS_DBUS_DEBUG_DAEMON_CLIENT_H_ + +#include "base/callback.h" +#include "base/memory/ref_counted_memory.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +// DebugDaemonClient is used to communicate with the debug daemon. +class CHROMEOS_EXPORT DebugDaemonClient { + public: + virtual ~DebugDaemonClient(); + + // Requests to start system/kernel tracing. + virtual void StartSystemTracing() = 0; + + // Called once RequestStopSystemTracing() is complete. Takes one parameter: + // - result: the data collected while tracing was active + typedef base::Callback<void(const scoped_refptr<base::RefCountedString>& + result)> StopSystemTracingCallback; + + // Requests to stop system tracing and calls |callback| when completed. + virtual bool RequestStopSystemTracing(const StopSystemTracingCallback& + callback) = 0; + + // Returns an empty SystemTracingCallback that does nothing. + static StopSystemTracingCallback EmptyStopSystemTracingCallback(); + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static DebugDaemonClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + protected: + // Create() should be used instead. + DebugDaemonClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(DebugDaemonClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_DEBUG_DAEMON_CLIENT_H_ diff --git a/chromeos/dbus/flimflam_client_helper.cc b/chromeos/dbus/flimflam_client_helper.cc new file mode 100644 index 0000000..0d5c754 --- /dev/null +++ b/chromeos/dbus/flimflam_client_helper.cc @@ -0,0 +1,111 @@ +// 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/flimflam_client_helper.h" + +#include "base/bind.h" +#include "base/values.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" +#include "dbus/values_util.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +FlimflamClientHelper::FlimflamClientHelper(dbus::ObjectProxy* proxy) + : weak_ptr_factory_(this), + proxy_(proxy) { +} + +FlimflamClientHelper::~FlimflamClientHelper() { +} + +void FlimflamClientHelper::SetPropertyChangedHandler( + const PropertyChangedHandler& handler) { + property_changed_handler_ = handler; +} + +void FlimflamClientHelper::ResetPropertyChangedHandler() { + property_changed_handler_.Reset(); +} + +void FlimflamClientHelper::MonitorPropertyChanged( + const std::string& interface_name) { + // We are not using dbus::PropertySet to monitor PropertyChanged signal + // because the interface is not "org.freedesktop.DBus.Properties". + proxy_->ConnectToSignal(interface_name, + flimflam::kMonitorPropertyChanged, + base::Bind(&FlimflamClientHelper::OnPropertyChanged, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&FlimflamClientHelper::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); +} + +void FlimflamClientHelper::CallVoidMethod(dbus::MethodCall* method_call, + const VoidCallback& callback) { + proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&FlimflamClientHelper::OnVoidMethod, + weak_ptr_factory_.GetWeakPtr(), + callback)); +} + +void FlimflamClientHelper::CallDictionaryValueMethod( + dbus::MethodCall* method_call, + const DictionaryValueCallback& callback) { + proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&FlimflamClientHelper::OnDictionaryValueMethod, + weak_ptr_factory_.GetWeakPtr(), + callback)); +} + +void FlimflamClientHelper::OnSignalConnected(const std::string& interface, + const std::string& signal, + bool success) { + LOG_IF(ERROR, !success) << "Connect to " << interface << " " << signal + << " failed."; +} + +void FlimflamClientHelper::OnPropertyChanged(dbus::Signal* signal) { + if (property_changed_handler_.is_null()) + return; + + dbus::MessageReader reader(signal); + std::string name; + if (!reader.PopString(&name)) + return; + scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); + if (!value.get()) + return; + property_changed_handler_.Run(name, *value); +} + +void FlimflamClientHelper::OnVoidMethod(const VoidCallback& callback, + dbus::Response* response) { + if (!response) { + callback.Run(DBUS_METHOD_CALL_FAILURE); + return; + } + callback.Run(DBUS_METHOD_CALL_SUCCESS); +} + +void FlimflamClientHelper::OnDictionaryValueMethod( + const DictionaryValueCallback& callback, + dbus::Response* response) { + if (!response) { + base::DictionaryValue result; + callback.Run(DBUS_METHOD_CALL_FAILURE, result); + return; + } + dbus::MessageReader reader(response); + scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); + base::DictionaryValue* result = NULL; + if (!value.get() || !value->GetAsDictionary(&result)) { + base::DictionaryValue result; + callback.Run(DBUS_METHOD_CALL_FAILURE, result); + return; + } + callback.Run(DBUS_METHOD_CALL_SUCCESS, *result); +} + +} // namespace chromeos diff --git a/chromeos/dbus/flimflam_client_helper.h b/chromeos/dbus/flimflam_client_helper.h new file mode 100644 index 0000000..bfe4612 --- /dev/null +++ b/chromeos/dbus/flimflam_client_helper.h @@ -0,0 +1,94 @@ +// 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. + +#ifndef CHROMEOS_DBUS_FLIMFLAM_CLIENT_HELPER_H_ +#define CHROMEOS_DBUS_FLIMFLAM_CLIENT_HELPER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "chromeos/dbus/dbus_method_call_status.h" + +namespace base { + +class Value; +class DictionaryValue; + +} // namespace base + +namespace dbus { + +class MethodCall; +class ObjectProxy; +class Response; +class Signal; + +} // namespace dbus + +namespace chromeos { + +// A class to help implement Flimflam clients. +class FlimflamClientHelper { + public: + explicit FlimflamClientHelper(dbus::ObjectProxy* proxy); + + virtual ~FlimflamClientHelper(); + + // A callback to handle PropertyChanged signals. + typedef base::Callback<void(const std::string& name, + const base::Value& value)> PropertyChangedHandler; + + // A callback to handle responses for methods without results. + typedef base::Callback<void(DBusMethodCallStatus call_status)> VoidCallback; + + // A callback to handle responses for methods with DictionaryValue results. + typedef base::Callback<void( + DBusMethodCallStatus call_status, + const base::DictionaryValue& result)> DictionaryValueCallback; + + // Sets PropertyChanged signal handler. + void SetPropertyChangedHandler(const PropertyChangedHandler& handler); + + // Resets PropertyChanged signal handler. + void ResetPropertyChangedHandler(); + + // Starts monitoring PropertyChanged signal. + void MonitorPropertyChanged(const std::string& interface_name); + + // Calls a method without results. + void CallVoidMethod(dbus::MethodCall* method_call, + const VoidCallback& callback); + + // Calls a method with a dictionary value result. + void CallDictionaryValueMethod(dbus::MethodCall* method_call, + const DictionaryValueCallback& callback); + + private: + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool success); + + // Handles PropertyChanged signal. + void OnPropertyChanged(dbus::Signal* signal); + + // Handles responses for methods without results. + void OnVoidMethod(const VoidCallback& callback, dbus::Response* response); + + // Handles responses for methods with DictionaryValue results. + void OnDictionaryValueMethod(const DictionaryValueCallback& callback, + dbus::Response* response); + + base::WeakPtrFactory<FlimflamClientHelper> weak_ptr_factory_; + dbus::ObjectProxy* proxy_; + PropertyChangedHandler property_changed_handler_; + + DISALLOW_COPY_AND_ASSIGN(FlimflamClientHelper); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FLIMFLAM_CLIENT_HELPER_H_ diff --git a/chromeos/dbus/flimflam_client_unittest_base.cc b/chromeos/dbus/flimflam_client_unittest_base.cc new file mode 100644 index 0000000..d9591f8 --- /dev/null +++ b/chromeos/dbus/flimflam_client_unittest_base.cc @@ -0,0 +1,173 @@ +// 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/flimflam_client_unittest_base.h" + +#include "base/bind.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/values_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +using ::testing::_; +using ::testing::Invoke; +using ::testing::Return; + +namespace chromeos { + +FlimflamClientUnittestBase::FlimflamClientUnittestBase( + const std::string& interface_name) : interface_name_(interface_name) { +} + +FlimflamClientUnittestBase::~FlimflamClientUnittestBase() { +} + +void FlimflamClientUnittestBase::SetUp() { + // Create a mock bus. + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SYSTEM; + mock_bus_ = new dbus::MockBus(options); + + // Create a mock proxy. + mock_proxy_ = new dbus::MockObjectProxy( + mock_bus_.get(), + flimflam::kFlimflamServiceName, + dbus::ObjectPath(flimflam::kFlimflamServicePath)); + + // Set an expectation so mock_proxy's CallMethod() will use OnCallMethod() + // to return responses. + EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _)) + .WillRepeatedly(Invoke(this, &FlimflamClientUnittestBase::OnCallMethod)); + + // Set an expectation so mock_proxy's ConnectToSignal() will use + // OnConnectToSignal() to run the callback. + EXPECT_CALL(*mock_proxy_, ConnectToSignal( + interface_name_, + flimflam::kMonitorPropertyChanged, _, _)) + .WillRepeatedly(Invoke(this, + &FlimflamClientUnittestBase::OnConnectToSignal)); + + // Set an expectation so mock_bus's GetObjectProxy() for the given + // service name and the object path will return mock_proxy_. + EXPECT_CALL(*mock_bus_, GetObjectProxy( + flimflam::kFlimflamServiceName, + dbus::ObjectPath(flimflam::kFlimflamServicePath))) + .WillOnce(Return(mock_proxy_.get())); + + // ShutdownAndBlock() will be called in TearDown(). + EXPECT_CALL(*mock_bus_, ShutdownAndBlock()).WillOnce(Return()); +} + +void FlimflamClientUnittestBase::TearDown() { + mock_bus_->ShutdownAndBlock(); +} + +void FlimflamClientUnittestBase::PrepareForMethodCall( + const std::string& method_name, + ArgumentCheckCallback argument_checker, + dbus::Response* response) { + expected_method_name_ = method_name; + argument_checker_ = argument_checker; + response_ = response; +} + +void FlimflamClientUnittestBase::SendPropertyChangedSignal( + dbus::Signal* signal) { + ASSERT_FALSE(property_changed_handler_.is_null()); + property_changed_handler_.Run(signal); +} + +// static +void FlimflamClientUnittestBase::ExpectPropertyChanged( + const std::string& expected_name, + const base::Value* expected_value, + const std::string& name, + const base::Value& value) { + EXPECT_EQ(expected_name, name); + EXPECT_TRUE(expected_value->Equals(&value)); +} + +// static +void FlimflamClientUnittestBase::ExpectNoArgument(dbus::MessageReader* reader) { + EXPECT_FALSE(reader->HasMoreData()); +} + +// static +void FlimflamClientUnittestBase::ExpectStringArgument( + const std::string& expected_string, + dbus::MessageReader* reader) { + std::string str; + ASSERT_TRUE(reader->PopString(&str)); + EXPECT_EQ(expected_string, str); + EXPECT_FALSE(reader->HasMoreData()); +} + +// static +void FlimflamClientUnittestBase::ExpectValueArgument( + const base::Value* expected_value, + dbus::MessageReader* reader) { + scoped_ptr<base::Value> value(dbus::PopDataAsValue(reader)); + ASSERT_TRUE(value.get()); + EXPECT_TRUE(value->Equals(expected_value)); + EXPECT_FALSE(reader->HasMoreData()); +} + +// static +void FlimflamClientUnittestBase::ExpectStringAndValueArguments( + const std::string& expected_string, + const base::Value* expected_value, + dbus::MessageReader* reader) { + std::string str; + ASSERT_TRUE(reader->PopString(&str)); + EXPECT_EQ(expected_string, str); + scoped_ptr<base::Value> value(dbus::PopDataAsValue(reader)); + ASSERT_TRUE(value.get()); + EXPECT_TRUE(value->Equals(expected_value)); + EXPECT_FALSE(reader->HasMoreData()); +} + +// static +void FlimflamClientUnittestBase::ExpectNoResultValue( + DBusMethodCallStatus call_status) { + EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status); +} + +// static +void FlimflamClientUnittestBase::ExpectDictionaryValueResult( + const base::DictionaryValue* expected_result, + DBusMethodCallStatus call_status, + const base::DictionaryValue& result) { + EXPECT_EQ(DBUS_METHOD_CALL_SUCCESS, call_status); + EXPECT_TRUE(expected_result->Equals(&result)); +} + +void FlimflamClientUnittestBase::OnConnectToSignal( + const std::string& interface_name, + const std::string& signal_name, + dbus::ObjectProxy::SignalCallback signal_callback, + dbus::ObjectProxy::OnConnectedCallback on_connected_callback) { + property_changed_handler_ = signal_callback; + const bool success = true; + message_loop_.PostTask(FROM_HERE, + base::Bind(on_connected_callback, + interface_name, + signal_name, + success)); +} + +void FlimflamClientUnittestBase::OnCallMethod( + dbus::MethodCall* method_call, + int timeout_ms, + dbus::ObjectProxy::ResponseCallback response_callback) { + EXPECT_EQ(interface_name_, method_call->GetInterface()); + EXPECT_EQ(expected_method_name_, method_call->GetMember()); + dbus::MessageReader reader(method_call); + argument_checker_.Run(&reader); + message_loop_.PostTask(FROM_HERE, + base::Bind(response_callback, response_)); +} + +} // namespace chromeos diff --git a/chromeos/dbus/flimflam_client_unittest_base.h b/chromeos/dbus/flimflam_client_unittest_base.h new file mode 100644 index 0000000..9781fda --- /dev/null +++ b/chromeos/dbus/flimflam_client_unittest_base.h @@ -0,0 +1,123 @@ +// 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. + +#ifndef CHROMEOS_DBUS_FLIMFLAM_CLIENT_UNITTEST_BASE_H_ +#define CHROMEOS_DBUS_FLIMFLAM_CLIENT_UNITTEST_BASE_H_ + +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "chromeos/dbus/dbus_method_call_status.h" +#include "dbus/mock_bus.h" +#include "dbus/mock_object_proxy.h" +#include "dbus/object_proxy.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { + +class Value; +class DictionaryValue; + +} // namespace base + +namespace dbus { + +class MessageReader; + +} // namespace dbus + +namespace chromeos { + +// A class to provide functionalities needed for testing Flimflam D-Bus clients. +class FlimflamClientUnittestBase : public testing::Test { + public: + explicit FlimflamClientUnittestBase(const std::string& interface_name); + virtual ~FlimflamClientUnittestBase(); + + virtual void SetUp() OVERRIDE; + virtual void TearDown() OVERRIDE; + + protected: + // A callback to intercept and check the method call arguments. + typedef base::Callback<void( + dbus::MessageReader* reader)> ArgumentCheckCallback; + + // Sets expectations for called method name and arguments, and sets response. + void PrepareForMethodCall(const std::string& method_name, + ArgumentCheckCallback argument_checker, + dbus::Response* response); + + // Sends property changed signal to the tested client. + void SendPropertyChangedSignal(dbus::Signal* signal); + + // Checks the name and the value which are sent by PropertyChanged signal. + static void ExpectPropertyChanged(const std::string& expected_name, + const base::Value* expected_value, + const std::string& name, + const base::Value& value); + + // Expects the reader to be empty. + static void ExpectNoArgument(dbus::MessageReader* reader); + + // Expects the reader to have a string. + static void ExpectStringArgument(const std::string& expected_string, + dbus::MessageReader* reader); + + // Expects the reader to have a Value. + static void ExpectValueArgument(const base::Value* expected_value, + dbus::MessageReader* reader); + + // Expects the reader to have a string and a Value. + static void ExpectStringAndValueArguments(const std::string& expected_string, + const base::Value* expected_value, + dbus::MessageReader* reader); + + // Expects the call status to be SUCCESS. + static void ExpectNoResultValue(DBusMethodCallStatus call_status); + + // Checks the result and expects the call status to be SUCCESS. + static void ExpectDictionaryValueResult( + const base::DictionaryValue* expected_result, + DBusMethodCallStatus call_status, + const base::DictionaryValue& result); + + // A message loop to emulate asynchronous behavior. + MessageLoop message_loop_; + // The mock bus. + scoped_refptr<dbus::MockBus> mock_bus_; + + private: + // Checks the requested interface name and signal name. + // Used to implement the mock proxy. + void OnConnectToSignal( + const std::string& interface_name, + const std::string& signal_name, + dbus::ObjectProxy::SignalCallback signal_callback, + dbus::ObjectProxy::OnConnectedCallback on_connected_callback); + + // Checks the content of the method call and returns the response. + // Used to implement the mock proxy. + void OnCallMethod(dbus::MethodCall* method_call, + int timeout_ms, + dbus::ObjectProxy::ResponseCallback response_callback); + + // The interface name. + const std::string interface_name_; + // The mock object proxy. + scoped_refptr<dbus::MockObjectProxy> mock_proxy_; + // The PropertyChanged signal handler given by the tested client. + dbus::ObjectProxy::SignalCallback property_changed_handler_; + // The name of the method which is expected to be called. + std::string expected_method_name_; + // The response which the mock object proxy returns. + dbus::Response* response_; + // A callback to intercept and check the method call arguments. + ArgumentCheckCallback argument_checker_; +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FLIMFLAM_CLIENT_UNITTEST_BASE_H_ diff --git a/chromeos/dbus/flimflam_ipconfig_client.cc b/chromeos/dbus/flimflam_ipconfig_client.cc new file mode 100644 index 0000000..2ad5b2a --- /dev/null +++ b/chromeos/dbus/flimflam_ipconfig_client.cc @@ -0,0 +1,204 @@ +// 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/flimflam_ipconfig_client.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "dbus/values_util.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +namespace { + +// The FlimflamIPConfigClient implementation. +class FlimflamIPConfigClientImpl : public FlimflamIPConfigClient { + public: + explicit FlimflamIPConfigClientImpl(dbus::Bus* bus); + + // FlimflamIPConfigClient override. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) OVERRIDE; + + // FlimflamIPConfigClient override. + virtual void ResetPropertyChangedHandler() OVERRIDE; + // FlimflamIPConfigClient override. + virtual void GetProperties(const DictionaryValueCallback& callback) OVERRIDE; + // FlimflamIPConfigClient override. + virtual void SetProperty(const std::string& name, + const base::Value& value, + const VoidCallback& callback) OVERRIDE; + // FlimflamIPConfigClient override. + virtual void ClearProperty(const std::string& name, + const VoidCallback& callback) OVERRIDE; + // FlimflamIPConfigClient override. + virtual void Remove(const VoidCallback& callback) OVERRIDE; + + private: + dbus::ObjectProxy* proxy_; + FlimflamClientHelper helper_; + + DISALLOW_COPY_AND_ASSIGN(FlimflamIPConfigClientImpl); +}; + +FlimflamIPConfigClientImpl::FlimflamIPConfigClientImpl(dbus::Bus* bus) + : proxy_(bus->GetObjectProxy( + flimflam::kFlimflamServiceName, + dbus::ObjectPath(flimflam::kFlimflamServicePath))), + helper_(proxy_) { + helper_.MonitorPropertyChanged(flimflam::kFlimflamIPConfigInterface); +} + +void FlimflamIPConfigClientImpl::SetPropertyChangedHandler( + const PropertyChangedHandler& handler) { + helper_.SetPropertyChangedHandler(handler); +} + +void FlimflamIPConfigClientImpl::ResetPropertyChangedHandler() { + helper_.ResetPropertyChangedHandler(); +} + +// FlimflamIPConfigClient override. +void FlimflamIPConfigClientImpl::GetProperties( + const DictionaryValueCallback& callback) { + dbus::MethodCall method_call(flimflam::kFlimflamIPConfigInterface, + flimflam::kGetPropertiesFunction); + helper_.CallDictionaryValueMethod(&method_call, callback); +} + +// FlimflamIPConfigClient override. +void FlimflamIPConfigClientImpl::SetProperty(const std::string& name, + const base::Value& value, + const VoidCallback& callback) { + dbus::MethodCall method_call(flimflam::kFlimflamIPConfigInterface, + flimflam::kSetPropertyFunction); + dbus::MessageWriter writer(&method_call); + writer.AppendString(name); + // IPConfig supports writing basic type and string array properties. + switch (value.GetType()) { + case base::Value::TYPE_LIST: { + const base::ListValue* list_value = NULL; + value.GetAsList(&list_value); + dbus::MessageWriter variant_writer(NULL); + writer.OpenVariant("as", &variant_writer); + dbus::MessageWriter array_writer(NULL); + variant_writer.OpenArray("s", &array_writer); + for (base::ListValue::const_iterator it = list_value->begin(); + it != list_value->end(); + ++it) { + DLOG_IF(ERROR, (*it)->GetType() != base::Value::TYPE_STRING) + << "Unexpected type " << (*it)->GetType(); + std::string str; + (*it)->GetAsString(&str); + array_writer.AppendString(str); + } + variant_writer.CloseContainer(&array_writer); + writer.CloseContainer(&variant_writer); + } + case base::Value::TYPE_BOOLEAN: + case base::Value::TYPE_INTEGER: + case base::Value::TYPE_DOUBLE: + case base::Value::TYPE_STRING: + dbus::AppendBasicTypeValueDataAsVariant(&writer, value); + break; + default: + DLOG(ERROR) << "Unexpected type " << value.GetType(); + } + helper_.CallVoidMethod(&method_call, callback); +} + +// FlimflamIPConfigClient override. +void FlimflamIPConfigClientImpl::ClearProperty(const std::string& name, + const VoidCallback& callback) { + dbus::MethodCall method_call(flimflam::kFlimflamIPConfigInterface, + flimflam::kClearPropertyFunction); + dbus::MessageWriter writer(&method_call); + writer.AppendString(name); + helper_.CallVoidMethod(&method_call, callback); +} + +// FlimflamIPConfigClient override. +void FlimflamIPConfigClientImpl::Remove(const VoidCallback& callback) { + dbus::MethodCall method_call(flimflam::kFlimflamIPConfigInterface, + flimflam::kRemoveConfigFunction); + helper_.CallVoidMethod(&method_call, callback); +} + +// A stub implementation of FlimflamIPConfigClient. +class FlimflamIPConfigClientStubImpl : public FlimflamIPConfigClient { + public: + FlimflamIPConfigClientStubImpl() : weak_ptr_factory_(this) {} + + virtual ~FlimflamIPConfigClientStubImpl() {} + + // FlimflamIPConfigClient override. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) OVERRIDE {} + + // FlimflamIPConfigClient override. + virtual void ResetPropertyChangedHandler() OVERRIDE {} + + // FlimflamIPConfigClient override. + virtual void GetProperties(const DictionaryValueCallback& callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&FlimflamIPConfigClientStubImpl::PassProperties, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // FlimflamIPConfigClient override. + virtual void SetProperty(const std::string& name, + const base::Value& value, + const VoidCallback& callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS)); + } + + // FlimflamIPConfigClient override. + virtual void ClearProperty(const std::string& name, + const VoidCallback& callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS)); + } + + // FlimflamIPConfigClient override. + virtual void Remove(const VoidCallback& callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS)); + } + + private: + // Runs callback with |properties_|. + void PassProperties(const DictionaryValueCallback& callback) const { + callback.Run(DBUS_METHOD_CALL_SUCCESS, properties_); + } + + base::WeakPtrFactory<FlimflamIPConfigClientStubImpl> weak_ptr_factory_; + base::DictionaryValue properties_; + + DISALLOW_COPY_AND_ASSIGN(FlimflamIPConfigClientStubImpl); +}; + +} // namespace + +FlimflamIPConfigClient::FlimflamIPConfigClient() {} + +FlimflamIPConfigClient::~FlimflamIPConfigClient() {} + +// static +FlimflamIPConfigClient* FlimflamIPConfigClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new FlimflamIPConfigClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new FlimflamIPConfigClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/flimflam_ipconfig_client.h b/chromeos/dbus/flimflam_ipconfig_client.h new file mode 100644 index 0000000..80a2074 --- /dev/null +++ b/chromeos/dbus/flimflam_ipconfig_client.h @@ -0,0 +1,83 @@ +// 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. + +#ifndef CHROMEOS_DBUS_FLIMFLAM_IPCONFIG_CLIENT_H_ +#define CHROMEOS_DBUS_FLIMFLAM_IPCONFIG_CLIENT_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "chromeos/dbus/flimflam_client_helper.h" + +namespace base { + +class Value; +class DictionaryValue; + +} // namespace base + +namespace dbus { + +class Bus; +class ObjectPath; + +} // namespace dbus + +namespace chromeos { + +// FlimflamIPConfigClient is used to communicate with the Flimflam IPConfig +// service. All methods should be called from the origin thread which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT FlimflamIPConfigClient { + public: + typedef FlimflamClientHelper::PropertyChangedHandler PropertyChangedHandler; + typedef FlimflamClientHelper::VoidCallback VoidCallback; + typedef FlimflamClientHelper::DictionaryValueCallback DictionaryValueCallback; + virtual ~FlimflamIPConfigClient(); + + // Factory function, creates a new instance which is owned by the caller. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static FlimflamIPConfigClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + // Sets PropertyChanged signal handler. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) = 0; + + // Resets PropertyChanged signal handler. + virtual void ResetPropertyChangedHandler() = 0; + + // Calls GetProperties method. + // |callback| is called after the method call succeeds. + virtual void GetProperties(const DictionaryValueCallback& callback) = 0; + + // Calls SetProperty method. + // |callback| is called after the method call succeeds. + virtual void SetProperty(const std::string& name, + const base::Value& value, + const VoidCallback& callback) = 0; + + // Calls ClearProperty method. + // |callback| is called after the method call succeeds. + virtual void ClearProperty(const std::string& name, + const VoidCallback& callback) = 0; + + // Calls Remove method. + // |callback| is called after the method call succeeds. + virtual void Remove(const VoidCallback& callback) = 0; + + protected: + // Create() should be used instead. + FlimflamIPConfigClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(FlimflamIPConfigClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FLIMFLAM_IPCONFIG_CLIENT_H_ diff --git a/chromeos/dbus/flimflam_network_client.cc b/chromeos/dbus/flimflam_network_client.cc new file mode 100644 index 0000000..9fbd01f --- /dev/null +++ b/chromeos/dbus/flimflam_network_client.cc @@ -0,0 +1,93 @@ +// 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/flimflam_network_client.h" + +#include "base/bind.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "dbus/values_util.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +namespace { + +// The FlimflamNetworkClient implementation. +class FlimflamNetworkClientImpl : public FlimflamNetworkClient { + public: + explicit FlimflamNetworkClientImpl(dbus::Bus* bus) + : proxy_(bus->GetObjectProxy( + flimflam::kFlimflamServiceName, + dbus::ObjectPath(flimflam::kFlimflamServicePath))), + helper_(proxy_) { + helper_.MonitorPropertyChanged(flimflam::kFlimflamNetworkInterface); + } + + // FlimflamNetworkClient override. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) OVERRIDE { + helper_.SetPropertyChangedHandler(handler); + } + + // FlimflamNetworkClient override. + virtual void ResetPropertyChangedHandler() OVERRIDE { + helper_.ResetPropertyChangedHandler(); + } + + // FlimflamNetworkClient override. + virtual void GetProperties(const DictionaryValueCallback& callback) OVERRIDE { + dbus::MethodCall method_call(flimflam::kFlimflamNetworkInterface, + flimflam::kGetPropertiesFunction); + helper_.CallDictionaryValueMethod(&method_call, callback); + } + + private: + dbus::ObjectProxy* proxy_; + FlimflamClientHelper helper_; + + DISALLOW_COPY_AND_ASSIGN(FlimflamNetworkClientImpl); +}; + +// A stub implementation of FlimflamNetworkClient. +class FlimflamNetworkClientStubImpl : public FlimflamNetworkClient { + public: + FlimflamNetworkClientStubImpl() {} + + virtual ~FlimflamNetworkClientStubImpl() {} + + // FlimflamNetworkClient override. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) OVERRIDE {} + + // FlimflamNetworkClient override. + virtual void ResetPropertyChangedHandler() OVERRIDE {} + + // FlimflamNetworkClient override. + virtual void GetProperties(const DictionaryValueCallback& callback) OVERRIDE { + } + + private: + DISALLOW_COPY_AND_ASSIGN(FlimflamNetworkClientStubImpl); +}; + +} // namespace + +FlimflamNetworkClient::FlimflamNetworkClient() {} + +FlimflamNetworkClient::~FlimflamNetworkClient() {} + +// static +FlimflamNetworkClient* FlimflamNetworkClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new FlimflamNetworkClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new FlimflamNetworkClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/flimflam_network_client.h b/chromeos/dbus/flimflam_network_client.h new file mode 100644 index 0000000..902cbe2 --- /dev/null +++ b/chromeos/dbus/flimflam_network_client.h @@ -0,0 +1,67 @@ +// 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. + +#ifndef CHROMEOS_DBUS_FLIMFLAM_NETWORK_CLIENT_H_ +#define CHROMEOS_DBUS_FLIMFLAM_NETWORK_CLIENT_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "chromeos/dbus/flimflam_client_helper.h" + +namespace base { + +class Value; +class DictionaryValue; + +} // namespace base + +namespace dbus { + +class Bus; + +} // namespace dbus + +namespace chromeos { + +// FlimflamNetworkClient is used to communicate with the Flimflam Network +// service. All methods should be called from the origin thread which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT FlimflamNetworkClient { + public: + typedef FlimflamClientHelper::PropertyChangedHandler PropertyChangedHandler; + typedef FlimflamClientHelper::DictionaryValueCallback DictionaryValueCallback; + + virtual ~FlimflamNetworkClient(); + + // Factory function, creates a new instance which is owned by the caller. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static FlimflamNetworkClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + // Sets PropertyChanged signal handler. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) = 0; + + // Resets PropertyChanged signal handler. + virtual void ResetPropertyChangedHandler() = 0; + + // Calls GetProperties method. + // |callback| is called after the method call succeeds. + virtual void GetProperties(const DictionaryValueCallback& callback) = 0; + + protected: + // Create() should be used instead. + FlimflamNetworkClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(FlimflamNetworkClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FLIMFLAM_NETWORK_CLIENT_H_ diff --git a/chromeos/dbus/flimflam_network_client_unittest.cc b/chromeos/dbus/flimflam_network_client_unittest.cc new file mode 100644 index 0000000..f17bdbf --- /dev/null +++ b/chromeos/dbus/flimflam_network_client_unittest.cc @@ -0,0 +1,124 @@ +// 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 "base/bind.h" +#include "chromeos/dbus/flimflam_client_unittest_base.h" +#include "chromeos/dbus/flimflam_network_client.h" +#include "dbus/message.h" +#include "dbus/values_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +class FlimflamNetworkClientTest : public FlimflamClientUnittestBase { + public: + FlimflamNetworkClientTest() + : FlimflamClientUnittestBase(flimflam::kFlimflamNetworkInterface) { + } + + virtual void SetUp() { + FlimflamClientUnittestBase::SetUp(); + // Create a client with the mock bus. + client_.reset(FlimflamNetworkClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION, + mock_bus_)); + // Run the message loop to run the signal connection result callback. + message_loop_.RunAllPending(); + } + + virtual void TearDown() { + FlimflamClientUnittestBase::TearDown(); + } + + protected: + scoped_ptr<FlimflamNetworkClient> client_; +}; + +TEST_F(FlimflamNetworkClientTest, PropertyChanged) { + // Create a signal. + const base::FundamentalValue kConnected(true); + dbus::Signal signal(flimflam::kFlimflamNetworkInterface, + flimflam::kMonitorPropertyChanged); + dbus::MessageWriter writer(&signal); + writer.AppendString(flimflam::kConnectedProperty); + dbus::AppendBasicTypeValueDataAsVariant(&writer, kConnected); + + // Set expectations. + client_->SetPropertyChangedHandler(base::Bind(&ExpectPropertyChanged, + flimflam::kConnectedProperty, + &kConnected)); + // Run the signal callback. + SendPropertyChangedSignal(&signal); + + // Reset the handler. + client_->ResetPropertyChangedHandler(); +} + +TEST_F(FlimflamNetworkClientTest, GetProperties) { + const char kAddress[] = "address"; + const char kName[] = "name"; + const uint8 kSignalStrength = 1; + const uint32 kWifiChannel = 1; + const bool kConnected = true; + + // Create response. + scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty()); + dbus::MessageWriter writer(response.get()); + dbus::MessageWriter array_writer(NULL); + writer.OpenArray("{sv}", &array_writer); + dbus::MessageWriter entry_writer(NULL); + // Append address. + array_writer.OpenDictEntry(&entry_writer); + entry_writer.AppendString(flimflam::kAddressProperty); + entry_writer.AppendVariantOfString(kAddress); + array_writer.CloseContainer(&entry_writer); + // Append name. + array_writer.OpenDictEntry(&entry_writer); + entry_writer.AppendString(flimflam::kNameProperty); + entry_writer.AppendVariantOfString(kName); + array_writer.CloseContainer(&entry_writer); + // Append signal strength. + array_writer.OpenDictEntry(&entry_writer); + entry_writer.AppendString(flimflam::kSignalStrengthProperty); + entry_writer.AppendVariantOfByte(kSignalStrength); + array_writer.CloseContainer(&entry_writer); + // Append Wifi channel. + array_writer.OpenDictEntry(&entry_writer); + entry_writer.AppendString(flimflam::kWifiChannelProperty); + entry_writer.AppendVariantOfUint32(kWifiChannel); + array_writer.CloseContainer(&entry_writer); + // Append connected. + array_writer.OpenDictEntry(&entry_writer); + entry_writer.AppendString(flimflam::kConnectedProperty); + entry_writer.AppendVariantOfBool(kConnected); + array_writer.CloseContainer(&entry_writer); + writer.CloseContainer(&array_writer); + + // Create the expected value. + base::DictionaryValue value; + value.SetWithoutPathExpansion(flimflam::kAddressProperty, + base::Value::CreateStringValue(kAddress)); + value.SetWithoutPathExpansion(flimflam::kNameProperty, + base::Value::CreateStringValue(kName)); + value.SetWithoutPathExpansion( + flimflam::kSignalStrengthProperty, + base::Value::CreateIntegerValue(kSignalStrength)); + // WiFi.Channel is set as a double because uint32 is larger than int32. + value.SetWithoutPathExpansion(flimflam::kWifiChannelProperty, + base::Value::CreateDoubleValue(kWifiChannel)); + value.SetWithoutPathExpansion(flimflam::kConnectedProperty, + base::Value::CreateBooleanValue(kConnected)); + + // Set expectations. + PrepareForMethodCall(flimflam::kGetPropertiesFunction, + base::Bind(&ExpectNoArgument), + response.get()); + // Call method. + client_->GetProperties(base::Bind(&ExpectDictionaryValueResult, + &value)); + // Run the message loop. + message_loop_.RunAllPending(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/flimflam_profile_client.cc b/chromeos/dbus/flimflam_profile_client.cc new file mode 100644 index 0000000..81aedb6b --- /dev/null +++ b/chromeos/dbus/flimflam_profile_client.cc @@ -0,0 +1,165 @@ +// 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/flimflam_profile_client.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "dbus/values_util.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +namespace { + +// The FlimflamProfileClient implementation. +class FlimflamProfileClientImpl : public FlimflamProfileClient { + public: + explicit FlimflamProfileClientImpl(dbus::Bus* bus); + + // FlimflamProfileClient overrides: + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) OVERRIDE; + virtual void ResetPropertyChangedHandler() OVERRIDE; + virtual void GetProperties(const DictionaryValueCallback& callback) OVERRIDE; + virtual void GetEntry(const dbus::ObjectPath& path, + const DictionaryValueCallback& callback) OVERRIDE; + virtual void DeleteEntry(const dbus::ObjectPath& path, + const VoidCallback& callback) OVERRIDE; + + private: + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool success); + // Handles PropertyChanged signal. + void OnPropertyChanged(dbus::Signal* signal); + // Handles responses for methods without results. + void OnVoidMethod(const VoidCallback& callback, dbus::Response* response); + // Handles responses for methods with DictionaryValue results. + void OnDictionaryValueMethod(const DictionaryValueCallback& callback, + dbus::Response* response); + + dbus::ObjectProxy* proxy_; + FlimflamClientHelper helper_; + + DISALLOW_COPY_AND_ASSIGN(FlimflamProfileClientImpl); +}; + +FlimflamProfileClientImpl::FlimflamProfileClientImpl(dbus::Bus* bus) + : proxy_(bus->GetObjectProxy( + flimflam::kFlimflamServiceName, + dbus::ObjectPath(flimflam::kFlimflamServicePath))), + helper_(proxy_) { + helper_.MonitorPropertyChanged(flimflam::kFlimflamProfileInterface); +} + +void FlimflamProfileClientImpl::SetPropertyChangedHandler( + const PropertyChangedHandler& handler) { + helper_.SetPropertyChangedHandler(handler); +} + +void FlimflamProfileClientImpl::ResetPropertyChangedHandler() { + helper_.ResetPropertyChangedHandler(); +} + +void FlimflamProfileClientImpl::GetProperties( + const DictionaryValueCallback& callback) { + dbus::MethodCall method_call(flimflam::kFlimflamProfileInterface, + flimflam::kGetPropertiesFunction); + helper_.CallDictionaryValueMethod(&method_call, callback); +} + +void FlimflamProfileClientImpl::GetEntry( + const dbus::ObjectPath& path, + const DictionaryValueCallback& callback) { + dbus::MethodCall method_call(flimflam::kFlimflamProfileInterface, + flimflam::kGetEntryFunction); + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(path); + helper_.CallDictionaryValueMethod(&method_call, callback); +} + +void FlimflamProfileClientImpl::DeleteEntry(const dbus::ObjectPath& path, + const VoidCallback& callback) { + dbus::MethodCall method_call(flimflam::kFlimflamProfileInterface, + flimflam::kDeleteEntryFunction); + dbus::MessageWriter writer(&method_call); + writer.AppendObjectPath(path); + helper_.CallVoidMethod(&method_call, callback); +} + +// A stub implementation of FlimflamProfileClient. +class FlimflamProfileClientStubImpl : public FlimflamProfileClient { + public: + FlimflamProfileClientStubImpl() : weak_ptr_factory_(this) {} + + virtual ~FlimflamProfileClientStubImpl() {} + + // FlimflamProfileClient override. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) OVERRIDE {} + + // FlimflamProfileClient override. + virtual void ResetPropertyChangedHandler() OVERRIDE {} + + // FlimflamProfileClient override. + virtual void GetProperties(const DictionaryValueCallback& callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&FlimflamProfileClientStubImpl::PassEmptyDictionaryValue, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // FlimflamProfileClient override. + virtual void GetEntry(const dbus::ObjectPath& path, + const DictionaryValueCallback& callback) OVERRIDE { + MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&FlimflamProfileClientStubImpl::PassEmptyDictionaryValue, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // FlimflamProfileClient override. + virtual void DeleteEntry(const dbus::ObjectPath& path, + const VoidCallback& callback) OVERRIDE { + MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, + DBUS_METHOD_CALL_SUCCESS)); + } + + private: + void PassEmptyDictionaryValue(const DictionaryValueCallback& callback) const { + base::DictionaryValue dictionary; + callback.Run(DBUS_METHOD_CALL_SUCCESS, dictionary); + } + + base::WeakPtrFactory<FlimflamProfileClientStubImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FlimflamProfileClientStubImpl); +}; + +} // namespace + +FlimflamProfileClient::FlimflamProfileClient() {} + +FlimflamProfileClient::~FlimflamProfileClient() {} + +// static +FlimflamProfileClient* FlimflamProfileClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new FlimflamProfileClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new FlimflamProfileClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/flimflam_profile_client.h b/chromeos/dbus/flimflam_profile_client.h new file mode 100644 index 0000000..4cc9f70 --- /dev/null +++ b/chromeos/dbus/flimflam_profile_client.h @@ -0,0 +1,79 @@ +// 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. + +#ifndef CHROMEOS_DBUS_FLIMFLAM_PROFILE_CLIENT_H_ +#define CHROMEOS_DBUS_FLIMFLAM_PROFILE_CLIENT_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "chromeos/dbus/flimflam_client_helper.h" + +namespace base { + +class Value; +class DictionaryValue; + +} // namespace base + +namespace dbus { + +class Bus; +class ObjectPath; + +} // namespace dbus + +namespace chromeos { + +// FlimflamProfileClient is used to communicate with the Flimflam Profile +// service. All methods should be called from the origin thread which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT FlimflamProfileClient { + public: + typedef FlimflamClientHelper::PropertyChangedHandler PropertyChangedHandler; + typedef FlimflamClientHelper::VoidCallback VoidCallback; + typedef FlimflamClientHelper::DictionaryValueCallback DictionaryValueCallback; + + virtual ~FlimflamProfileClient(); + + // Factory function, creates a new instance which is owned by the caller. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static FlimflamProfileClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + // Sets PropertyChanged signal handler. + virtual void SetPropertyChangedHandler( + const PropertyChangedHandler& handler) = 0; + + // Resets PropertyChanged signal handler. + virtual void ResetPropertyChangedHandler() = 0; + + // Calls GetProperties method. + // |callback| is called after the method call succeeds. + virtual void GetProperties(const DictionaryValueCallback& callback) = 0; + + // Calls GetEntry method. + // |callback| is called after the method call succeeds. + virtual void GetEntry(const dbus::ObjectPath& path, + const DictionaryValueCallback& callback) = 0; + + // Calls DeleteEntry method. + // |callback| is called after the method call succeeds. + virtual void DeleteEntry(const dbus::ObjectPath& path, + const VoidCallback& callback) = 0; + + protected: + // Create() should be used instead. + FlimflamProfileClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(FlimflamProfileClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FLIMFLAM_PROFILE_CLIENT_H_ diff --git a/chromeos/dbus/image_burner_client.cc b/chromeos/dbus/image_burner_client.cc new file mode 100644 index 0000000..343c02d --- /dev/null +++ b/chromeos/dbus/image_burner_client.cc @@ -0,0 +1,166 @@ +// 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/image_burner_client.h" + +#include "base/bind.h" +#include "base/compiler_specific.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 { + +namespace { + +// The ImageBurnerClient implementation. +class ImageBurnerClientImpl : public ImageBurnerClient { + public: + explicit ImageBurnerClientImpl(dbus::Bus* bus) + : proxy_(NULL), + weak_ptr_factory_(this) { + proxy_ = bus->GetObjectProxy( + imageburn::kImageBurnServiceName, + dbus::ObjectPath(imageburn::kImageBurnServicePath)); + proxy_->ConnectToSignal( + imageburn::kImageBurnServiceInterface, + imageburn::kSignalBurnFinishedName, + base::Bind(&ImageBurnerClientImpl::OnBurnFinished, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ImageBurnerClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + proxy_->ConnectToSignal( + imageburn::kImageBurnServiceInterface, + imageburn::kSignalBurnUpdateName, + base::Bind(&ImageBurnerClientImpl::OnBurnProgressUpdate, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ImageBurnerClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + virtual ~ImageBurnerClientImpl() {} + + // ImageBurnerClient override. + virtual void BurnImage(const std::string& from_path, + const std::string& to_path, + ErrorCallback error_callback) OVERRIDE { + dbus::MethodCall method_call(imageburn::kImageBurnServiceInterface, + imageburn::kBurnImage); + dbus::MessageWriter writer(&method_call); + writer.AppendString(from_path); + writer.AppendString(to_path); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&ImageBurnerClientImpl::OnBurnImage, + weak_ptr_factory_.GetWeakPtr(), + error_callback)); + } + + // ImageBurnerClient override. + virtual void SetEventHandlers( + BurnFinishedHandler burn_finished_handler, + BurnProgressUpdateHandler burn_progress_update_handler) OVERRIDE { + burn_finished_handler_ = burn_finished_handler; + burn_progress_update_handler_ = burn_progress_update_handler; + } + + // ImageBurnerClient override. + virtual void ResetEventHandlers() OVERRIDE { + burn_finished_handler_.Reset(); + burn_progress_update_handler_.Reset(); + } + + private: + // Called when a response for BurnImage is received + void OnBurnImage(ErrorCallback error_callback, dbus::Response* response) { + if (!response) { + error_callback.Run(); + return; + } + } + + // Handles burn_finished signal and calls |handler|. + void OnBurnFinished(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string target_path; + bool success; + std::string error; + if (!reader.PopString(&target_path) || + !reader.PopBool(&success) || + !reader.PopString(&error)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + if (!burn_finished_handler_.is_null()) + burn_finished_handler_.Run(target_path, success, error); + } + + // Handles burn_progress_udpate signal and calls |handler|. + void OnBurnProgressUpdate(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string target_path; + int64 num_bytes_burnt; + int64 total_size; + if (!reader.PopString(&target_path) || + !reader.PopInt64(&num_bytes_burnt) || + !reader.PopInt64(&total_size)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + if (!burn_progress_update_handler_.is_null()) + burn_progress_update_handler_.Run(target_path, num_bytes_burnt, + total_size); + } + + // Handles the result of signal connection setup. + void OnSignalConnected(const std::string& interface, + const std::string& signal, + bool successed) { + LOG_IF(ERROR, !successed) << "Connect to " << interface << " " << + signal << " failed."; + } + + dbus::ObjectProxy* proxy_; + base::WeakPtrFactory<ImageBurnerClientImpl> weak_ptr_factory_; + BurnFinishedHandler burn_finished_handler_; + BurnProgressUpdateHandler burn_progress_update_handler_; + + DISALLOW_COPY_AND_ASSIGN(ImageBurnerClientImpl); +}; + +// A stub implementaion of ImageBurnerClient. +class ImageBurnerClientStubImpl : public ImageBurnerClient { + public: + ImageBurnerClientStubImpl() {} + virtual ~ImageBurnerClientStubImpl() {} + virtual void BurnImage(const std::string& from_path, + const std::string& to_path, + ErrorCallback error_callback) OVERRIDE {} + virtual void SetEventHandlers( + BurnFinishedHandler burn_finished_handler, + BurnProgressUpdateHandler burn_progress_update_handler) OVERRIDE {} + virtual void ResetEventHandlers() OVERRIDE {} + + private: + DISALLOW_COPY_AND_ASSIGN(ImageBurnerClientStubImpl); +}; + +} // namespace + +ImageBurnerClient::ImageBurnerClient() { +} + +ImageBurnerClient::~ImageBurnerClient() { +} + +// static +ImageBurnerClient* ImageBurnerClient::Create(DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new ImageBurnerClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new ImageBurnerClientStubImpl(); +} + +} // chromeos diff --git a/chromeos/dbus/image_burner_client.h b/chromeos/dbus/image_burner_client.h new file mode 100644 index 0000000..513496d --- /dev/null +++ b/chromeos/dbus/image_burner_client.h @@ -0,0 +1,74 @@ +// 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. + +#ifndef CHROMEOS_DBUS_IMAGE_BURNER_CLIENT_H_ +#define CHROMEOS_DBUS_IMAGE_BURNER_CLIENT_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +namespace dbus { +class Bus; +} + +namespace chromeos { + +// ImageBurnerClient is used to communicate with the image burner. +// All method should be called from the origin thread (UI thread) which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT ImageBurnerClient { + public: + virtual ~ImageBurnerClient(); + + // A callback to be called when DBus method call fails. + typedef base::Callback<void()> ErrorCallback; + + // A callback to handle burn_finished signal. + typedef base::Callback<void(const std::string& target_path, + bool success, + const std::string& error)> BurnFinishedHandler; + + // A callback to handle burn_progress_update signal. + typedef base::Callback<void(const std::string& target_path, + int64 num_bytes_burnt, + int64 total_size)> BurnProgressUpdateHandler; + + // Burns the image |from_path| to the disk |to_path|. + virtual void BurnImage(const std::string& from_path, + const std::string& to_path, + ErrorCallback error_callback) = 0; + + // Sets callbacks as event handlers. + // |burn_finished_handler| is called when burn_finished signal is received. + // |burn_progress_update_handler| is called when burn_progress_update signal + // is received. + virtual void SetEventHandlers( + BurnFinishedHandler burn_finished_handler, + BurnProgressUpdateHandler burn_progress_update_handler) = 0; + + // Resets event handlers. After calling this method, nothing is done when + // signals are received. + virtual void ResetEventHandlers() = 0; + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static ImageBurnerClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + protected: + // Create() should be used instead. + ImageBurnerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(ImageBurnerClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_IMAGE_BURNER_CLIENT_H_ diff --git a/chromeos/dbus/introspectable_client.cc b/chromeos/dbus/introspectable_client.cc new file mode 100644 index 0000000..d29563f --- /dev/null +++ b/chromeos/dbus/introspectable_client.cc @@ -0,0 +1,117 @@ +// 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/introspectable_client.h" + +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/logging.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" + +namespace { + +// D-Bus specification constants. +const char kIntrospectableInterface[] = "org.freedesktop.DBus.Introspectable"; +const char kIntrospect[] = "Introspect"; + +} // namespace + +namespace chromeos { + +// The IntrospectableClient implementation used in production. +class IntrospectableClientImpl : public IntrospectableClient { + public: + explicit IntrospectableClientImpl(dbus::Bus* bus) + : weak_ptr_factory_(this), + bus_(bus) { + DVLOG(1) << "Creating IntrospectableClientImpl"; + } + + virtual ~IntrospectableClientImpl() { + } + + // IntrospectableClient override. + virtual void Introspect(const std::string& service_name, + const dbus::ObjectPath& object_path, + const IntrospectCallback& callback) OVERRIDE { + dbus::MethodCall method_call(kIntrospectableInterface, kIntrospect); + + dbus::ObjectProxy* object_proxy = bus_->GetObjectProxy(service_name, + object_path); + + object_proxy->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&IntrospectableClientImpl::OnIntrospect, + weak_ptr_factory_.GetWeakPtr(), + service_name, object_path, callback)); + } + + private: + // Called by dbus:: when a response for Introspect() is recieved. + void OnIntrospect(const std::string& service_name, + const dbus::ObjectPath& object_path, + const IntrospectCallback& callback, + dbus::Response* response) { + // Parse response. + bool success = false; + std::string xml_data; + if (response != NULL) { + dbus::MessageReader reader(response); + if (!reader.PopString(&xml_data)) { + LOG(WARNING) << "Introspect response has incorrect paramters: " + << response->ToString(); + } else { + success = true; + } + } + + // Notify client. + callback.Run(service_name, object_path, xml_data, success); + } + + // Weak pointer factory for generating 'this' pointers that might live longer + // than we do. + base::WeakPtrFactory<IntrospectableClientImpl> weak_ptr_factory_; + + dbus::Bus* bus_; + + DISALLOW_COPY_AND_ASSIGN(IntrospectableClientImpl); +}; + +// The IntrospectableClient implementation used on Linux desktop, which does +// nothing. +class IntrospectableClientStubImpl : public IntrospectableClient { + public: + // IntrospectableClient override. + virtual void Introspect(const std::string& service_name, + const dbus::ObjectPath& object_path, + const IntrospectCallback& callback) OVERRIDE { + VLOG(1) << "Introspect: " << service_name << " " << object_path.value(); + callback.Run(service_name, object_path, "", false); + } +}; + +IntrospectableClient::IntrospectableClient() { +} + +IntrospectableClient::~IntrospectableClient() { +} + +// static +IntrospectableClient* IntrospectableClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new IntrospectableClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new IntrospectableClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/introspectable_client.h b/chromeos/dbus/introspectable_client.h new file mode 100644 index 0000000..c21eb94 --- /dev/null +++ b/chromeos/dbus/introspectable_client.h @@ -0,0 +1,58 @@ +// 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. + +#ifndef CHROMEOS_DBUS_INTROSPECTABLE_CLIENT_H_ +#define CHROMEOS_DBUS_INTROSPECTABLE_CLIENT_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" +#include "dbus/object_path.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { + +// IntrospectableClient is used to retrieve the D-Bus introspection data +// from a remote object. +class CHROMEOS_EXPORT IntrospectableClient { + public: + virtual ~IntrospectableClient(); + + // The IntrospectCallback is used for the Introspect() method. It receives + // four arguments, the first two are the |service_name| and |object_path| + // of the remote object being introspected, the third is the |xml_data| of + // the object as described in + // http://dbus.freedesktop.org/doc/dbus-specification.html, the fourth + // |success| indicates whether the request succeeded. + typedef base::Callback<void(const std::string&, const dbus::ObjectPath&, + const std::string&, bool)> IntrospectCallback; + + // Retrieves introspection data from the remote object on service name + // |service_name| with object path |object_path|, calling |callback| with + // the XML-formatted data received. + virtual void Introspect(const std::string& service_name, + const dbus::ObjectPath& object_path, + const IntrospectCallback& callback) = 0; + + // Creates the instance + static IntrospectableClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + protected: + IntrospectableClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(IntrospectableClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_INTROSPECTABLE_CLIENT_H_ diff --git a/chromeos/dbus/mock_bluetooth_adapter_client.cc b/chromeos/dbus/mock_bluetooth_adapter_client.cc new file mode 100644 index 0000000..bef773c --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_adapter_client.cc @@ -0,0 +1,13 @@ +// 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/mock_bluetooth_adapter_client.h" + +namespace chromeos { + +MockBluetoothAdapterClient::MockBluetoothAdapterClient() {} + +MockBluetoothAdapterClient::~MockBluetoothAdapterClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_bluetooth_adapter_client.h b/chromeos/dbus/mock_bluetooth_adapter_client.h new file mode 100644 index 0000000..4c7e389 --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_adapter_client.h @@ -0,0 +1,59 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_BLUETOOTH_ADAPTER_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_BLUETOOTH_ADAPTER_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/bluetooth_adapter_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockBluetoothAdapterClient : public BluetoothAdapterClient { + public: + MockBluetoothAdapterClient(); + virtual ~MockBluetoothAdapterClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD1(GetProperties, Properties*(const dbus::ObjectPath&)); + MOCK_METHOD2(RequestSession, void(const dbus::ObjectPath&, + const AdapterCallback&)); + MOCK_METHOD2(ReleaseSession, void(const dbus::ObjectPath&, + const AdapterCallback&)); + MOCK_METHOD2(StartDiscovery, void(const dbus::ObjectPath&, + const AdapterCallback&)); + MOCK_METHOD2(StopDiscovery, void(const dbus::ObjectPath&, + const AdapterCallback&)); + MOCK_METHOD3(FindDevice, void(const dbus::ObjectPath&, + const std::string&, + const DeviceCallback&)); + MOCK_METHOD3(CreateDevice, void(const dbus::ObjectPath&, + const std::string&, + const DeviceCallback&)); + MOCK_METHOD5(CreatePairedDevice, void(const dbus::ObjectPath&, + const std::string&, + const dbus::ObjectPath&, + const std::string&, + const DeviceCallback&)); + MOCK_METHOD3(CancelDeviceCreation, void(const dbus::ObjectPath&, + const std::string&, + const AdapterCallback&)); + MOCK_METHOD3(RemoveDevice, void(const dbus::ObjectPath&, + const dbus::ObjectPath&, + const AdapterCallback&)); + MOCK_METHOD4(RegisterAgent, void(const dbus::ObjectPath&, + const dbus::ObjectPath&, + const std::string&, + const AdapterCallback&)); + MOCK_METHOD3(UnregisterAgent, void(const dbus::ObjectPath&, + const dbus::ObjectPath&, + const AdapterCallback&)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_BLUETOOTH_ADAPTER_CLIENT_H_ diff --git a/chromeos/dbus/mock_bluetooth_device_client.cc b/chromeos/dbus/mock_bluetooth_device_client.cc new file mode 100644 index 0000000..75b5c44 --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_device_client.cc @@ -0,0 +1,13 @@ +// 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/mock_bluetooth_device_client.h" + +namespace chromeos { + +MockBluetoothDeviceClient::MockBluetoothDeviceClient() {} + +MockBluetoothDeviceClient::~MockBluetoothDeviceClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_bluetooth_device_client.h b/chromeos/dbus/mock_bluetooth_device_client.h new file mode 100644 index 0000000..35050e2 --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_device_client.h @@ -0,0 +1,40 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_BLUETOOTH_DEVICE_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_BLUETOOTH_DEVICE_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/bluetooth_device_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockBluetoothDeviceClient : public BluetoothDeviceClient { + public: + MockBluetoothDeviceClient(); + virtual ~MockBluetoothDeviceClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD1(GetProperties, Properties*(const dbus::ObjectPath&)); + MOCK_METHOD3(DiscoverServices, void(const dbus::ObjectPath&, + const std::string&, + const ServicesCallback&)); + MOCK_METHOD2(CancelDiscovery, void(const dbus::ObjectPath&, + const DeviceCallback&)); + MOCK_METHOD2(Disconnect, void(const dbus::ObjectPath&, + const DeviceCallback&)); + MOCK_METHOD3(CreateNode, void(const dbus::ObjectPath&, + const std::string&, + const NodeCallback&)); + MOCK_METHOD3(RemoveNode, void(const dbus::ObjectPath&, + const dbus::ObjectPath&, + const NodeCallback&)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_BLUETOOTH_DEVICE_CLIENT_H_ diff --git a/chromeos/dbus/mock_bluetooth_input_client.cc b/chromeos/dbus/mock_bluetooth_input_client.cc new file mode 100644 index 0000000..b73ef1e --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_input_client.cc @@ -0,0 +1,13 @@ +// 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/mock_bluetooth_input_client.h" + +namespace chromeos { + +MockBluetoothInputClient::MockBluetoothInputClient() {} + +MockBluetoothInputClient::~MockBluetoothInputClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_bluetooth_input_client.h b/chromeos/dbus/mock_bluetooth_input_client.h new file mode 100644 index 0000000..35fe0cb --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_input_client.h @@ -0,0 +1,31 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_BLUETOOTH_INPUT_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_BLUETOOTH_INPUT_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/bluetooth_input_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockBluetoothInputClient : public BluetoothInputClient { + public: + MockBluetoothInputClient(); + virtual ~MockBluetoothInputClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD1(GetProperties, Properties*(const dbus::ObjectPath&)); + MOCK_METHOD2(Connect, void(const dbus::ObjectPath&, + const InputCallback&)); + MOCK_METHOD2(Disconnect, void(const dbus::ObjectPath&, + const InputCallback&)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_BLUETOOTH_INPUT_CLIENT_H_ diff --git a/chromeos/dbus/mock_bluetooth_manager_client.cc b/chromeos/dbus/mock_bluetooth_manager_client.cc new file mode 100644 index 0000000..9fd6f93 --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_manager_client.cc @@ -0,0 +1,13 @@ +// 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/mock_bluetooth_manager_client.h" + +namespace chromeos { + +MockBluetoothManagerClient::MockBluetoothManagerClient() {} + +MockBluetoothManagerClient::~MockBluetoothManagerClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_bluetooth_manager_client.h b/chromeos/dbus/mock_bluetooth_manager_client.h new file mode 100644 index 0000000..9485e24 --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_manager_client.h @@ -0,0 +1,30 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_BLUETOOTH_MANAGER_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_BLUETOOTH_MANAGER_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/bluetooth_manager_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockBluetoothManagerClient : public BluetoothManagerClient { + public: + MockBluetoothManagerClient(); + virtual ~MockBluetoothManagerClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD0(GetProperties, Properties*()); + MOCK_METHOD1(DefaultAdapter, void(const AdapterCallback& callback)); + MOCK_METHOD2(FindAdapter, void(const std::string&, + const AdapterCallback& callback)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_BLUETOOTH_MANAGER_CLIENT_H_ diff --git a/chromeos/dbus/mock_bluetooth_node_client.cc b/chromeos/dbus/mock_bluetooth_node_client.cc new file mode 100644 index 0000000..fddd878 --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_node_client.cc @@ -0,0 +1,13 @@ +// 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/mock_bluetooth_node_client.h" + +namespace chromeos { + +MockBluetoothNodeClient::MockBluetoothNodeClient() {} + +MockBluetoothNodeClient::~MockBluetoothNodeClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_bluetooth_node_client.h b/chromeos/dbus/mock_bluetooth_node_client.h new file mode 100644 index 0000000..78b1497 --- /dev/null +++ b/chromeos/dbus/mock_bluetooth_node_client.h @@ -0,0 +1,27 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_BLUETOOTH_NODE_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_BLUETOOTH_NODE_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/bluetooth_node_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockBluetoothNodeClient : public BluetoothNodeClient { + public: + MockBluetoothNodeClient(); + virtual ~MockBluetoothNodeClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD1(GetProperties, Properties*(const dbus::ObjectPath&)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_BLUETOOTH_NODE_CLIENT_H_ diff --git a/chromeos/dbus/mock_cashew_client.cc b/chromeos/dbus/mock_cashew_client.cc new file mode 100644 index 0000000..1742ab2 --- /dev/null +++ b/chromeos/dbus/mock_cashew_client.cc @@ -0,0 +1,13 @@ +// 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/mock_cashew_client.h" + +namespace chromeos { + +MockCashewClient::MockCashewClient() {} + +MockCashewClient::~MockCashewClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_cashew_client.h b/chromeos/dbus/mock_cashew_client.h new file mode 100644 index 0000000..c4167dc --- /dev/null +++ b/chromeos/dbus/mock_cashew_client.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_CASHEW_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_CASHEW_CLIENT_H_ +#pragma once + +#include "chromeos/dbus/cashew_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockCashewClient : public CashewClient { + public: + MockCashewClient(); + virtual ~MockCashewClient(); + + MOCK_METHOD1(SetDataPlansUpdateHandler, void(DataPlansUpdateHandler handler)); + MOCK_METHOD0(ResetDataPlansUpdateHandler, void()); + MOCK_METHOD0(RequestDataPlansUpdate, void()); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_CASHEW_CLIENT_H_ diff --git a/chromeos/dbus/mock_cros_disks_client.cc b/chromeos/dbus/mock_cros_disks_client.cc new file mode 100644 index 0000000..998c550 --- /dev/null +++ b/chromeos/dbus/mock_cros_disks_client.cc @@ -0,0 +1,13 @@ +// 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/mock_cros_disks_client.h" + +namespace chromeos { + +MockCrosDisksClient::MockCrosDisksClient() {} + +MockCrosDisksClient::~MockCrosDisksClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_cros_disks_client.h b/chromeos/dbus/mock_cros_disks_client.h new file mode 100644 index 0000000..0b242f98 --- /dev/null +++ b/chromeos/dbus/mock_cros_disks_client.h @@ -0,0 +1,37 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_CROS_DISKS_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_CROS_DISKS_CLIENT_H_ +#pragma once + +#include <string> + +#include "chromeos/dbus/cros_disks_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockCrosDisksClient : public CrosDisksClient { + public: + MockCrosDisksClient(); + virtual ~MockCrosDisksClient(); + + MOCK_METHOD4(Mount, void(const std::string&, MountType, MountCallback, + ErrorCallback)); + MOCK_METHOD3(Unmount, void(const std::string&, UnmountCallback, + ErrorCallback)); + MOCK_METHOD2(EnumerateAutoMountableDevices, void( + EnumerateAutoMountableDevicesCallback, ErrorCallback)); + MOCK_METHOD4(FormatDevice, void(const std::string&, const std::string&, + FormatDeviceCallback, ErrorCallback)); + MOCK_METHOD3(GetDeviceProperties, void( + const std::string&, GetDevicePropertiesCallback, ErrorCallback)); + MOCK_METHOD2(SetUpConnections, void(MountEventHandler, + MountCompletedHandler)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_CROS_DISKS_CLIENT_H_ diff --git a/chromeos/dbus/mock_cryptohome_client.cc b/chromeos/dbus/mock_cryptohome_client.cc new file mode 100644 index 0000000..6ef380d --- /dev/null +++ b/chromeos/dbus/mock_cryptohome_client.cc @@ -0,0 +1,13 @@ +// 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/mock_cryptohome_client.h" + +namespace chromeos { + +MockCryptohomeClient::MockCryptohomeClient() {} + +MockCryptohomeClient::~MockCryptohomeClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_cryptohome_client.h b/chromeos/dbus/mock_cryptohome_client.h new file mode 100644 index 0000000..ad6c327 --- /dev/null +++ b/chromeos/dbus/mock_cryptohome_client.h @@ -0,0 +1,70 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_CRYPTOHOME_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_CRYPTOHOME_CLIENT_H_ +#pragma once + +#include <string> + +#include "chromeos/dbus/cryptohome_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockCryptohomeClient : public CryptohomeClient { + public: + MockCryptohomeClient(); + virtual ~MockCryptohomeClient(); + + MOCK_METHOD1(SetAsyncCallStatusHandler, void(AsyncCallStatusHandler handler)); + MOCK_METHOD0(ResetAsyncCallStatusHandler, void()); + MOCK_METHOD1(IsMounted, bool(bool* is_mounted)); + MOCK_METHOD1(Unmount, bool(bool* success)); + MOCK_METHOD3(AsyncCheckKey, + void(const std::string& username, + const std::string& key, + base::Callback<void(int async_id)> callback)); + MOCK_METHOD4(AsyncMigrateKey, + void(const std::string& username, + const std::string& from_key, + const std::string& to_key, + base::Callback<void(int async_id)> callback)); + MOCK_METHOD2(AsyncRemove, void(const std::string& username, + base::Callback<void(int async_id)> callback)); + MOCK_METHOD1(GetSystemSalt, bool(std::vector<uint8>* salt)); + MOCK_METHOD4(AsyncMount, void(const std::string& username, + const std::string& key, + const bool create_if_missing, + base::Callback<void(int async_id)> callback)); + MOCK_METHOD1(AsyncMountGuest, + void(base::Callback<void(int async_id)> callback)); + MOCK_METHOD1(TpmIsReady, bool(bool* ready)); + MOCK_METHOD1(TpmIsEnabled, void(BoolMethodCallback callback)); + MOCK_METHOD1(CallTpmIsEnabledAndBlock, bool(bool* enabled)); + MOCK_METHOD1(TpmGetPassword, bool(std::string* password)); + MOCK_METHOD1(TpmIsOwned, bool(bool* owned)); + MOCK_METHOD1(TpmIsBeingOwned, bool(bool* owning)); + MOCK_METHOD0(TpmCanAttemptOwnership, bool()); + MOCK_METHOD0(TpmClearStoredPassword, bool()); + MOCK_METHOD1(Pkcs11IsTpmTokenReady, void(BoolMethodCallback callback)); + MOCK_METHOD1(Pkcs11GetTpmTokenInfo, + void(Pkcs11GetTpmTokenInfoCallback callback)); + MOCK_METHOD3(InstallAttributesGet, + bool(const std::string& name, + std::vector<uint8>* value, + bool* successful)); + MOCK_METHOD3(InstallAttributesSet, + bool(const std::string& name, + const std::vector<uint8>& value, + bool* successful)); + MOCK_METHOD1(InstallAttributesFinalize, bool(bool* successful)); + MOCK_METHOD1(InstallAttributesIsReady, bool(bool* is_ready)); + MOCK_METHOD1(InstallAttributesIsInvalid, bool(bool* is_invalid)); + MOCK_METHOD1(InstallAttributesIsFirstInstall, bool(bool* is_first_install)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_CRYPTOHOME_CLIENT_H_ diff --git a/chromeos/dbus/mock_dbus_thread_manager.cc b/chromeos/dbus/mock_dbus_thread_manager.cc new file mode 100644 index 0000000..7687c10 --- /dev/null +++ b/chromeos/dbus/mock_dbus_thread_manager.cc @@ -0,0 +1,113 @@ +// 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/mock_dbus_thread_manager.h" + +#include "chromeos/dbus/mock_bluetooth_adapter_client.h" +#include "chromeos/dbus/mock_bluetooth_device_client.h" +#include "chromeos/dbus/mock_bluetooth_input_client.h" +#include "chromeos/dbus/mock_bluetooth_manager_client.h" +#include "chromeos/dbus/mock_bluetooth_node_client.h" +#include "chromeos/dbus/mock_cashew_client.h" +#include "chromeos/dbus/mock_cros_disks_client.h" +#include "chromeos/dbus/mock_cryptohome_client.h" +#include "chromeos/dbus/mock_debug_daemon_client.h" +#include "chromeos/dbus/mock_flimflam_ipconfig_client.h" +#include "chromeos/dbus/mock_flimflam_network_client.h" +#include "chromeos/dbus/mock_flimflam_profile_client.h" +#include "chromeos/dbus/mock_image_burner_client.h" +#include "chromeos/dbus/mock_introspectable_client.h" +#include "chromeos/dbus/mock_power_manager_client.h" +#include "chromeos/dbus/mock_session_manager_client.h" +#include "chromeos/dbus/mock_speech_synthesizer_client.h" +#include "chromeos/dbus/mock_update_engine_client.h" + +using ::testing::AnyNumber; +using ::testing::Return; +using ::testing::_; + +namespace chromeos { + +MockDBusThreadManager::MockDBusThreadManager() + : mock_bluetooth_adapter_client_(new MockBluetoothAdapterClient), + mock_bluetooth_device_client_(new MockBluetoothDeviceClient), + mock_bluetooth_input_client_(new MockBluetoothInputClient), + mock_bluetooth_manager_client_(new MockBluetoothManagerClient), + mock_bluetooth_node_client_(new MockBluetoothNodeClient), + mock_cashew_client_(new MockCashewClient), + mock_cros_disks_client_(new MockCrosDisksClient), + mock_cryptohome_client_(new MockCryptohomeClient), + mock_debugdaemon_client_(new MockDebugDaemonClient), + mock_flimflam_ipconfig_client_(new MockFlimflamIPConfigClient), + mock_flimflam_network_client_(new MockFlimflamNetworkClient), + mock_flimflam_profile_client_(new MockFlimflamProfileClient), + mock_image_burner_client_(new MockImageBurnerClient), + mock_introspectable_client_(new MockIntrospectableClient), + mock_power_manager_client_(new MockPowerManagerClient), + mock_session_manager_client_(new MockSessionManagerClient), + mock_speech_synthesizer_client_(new MockSpeechSynthesizerClient), + mock_update_engine_client_(new MockUpdateEngineClient) { + EXPECT_CALL(*this, GetBluetoothAdapterClient()) + .WillRepeatedly(Return(mock_bluetooth_adapter_client_.get())); + EXPECT_CALL(*this, GetBluetoothDeviceClient()) + .WillRepeatedly(Return(mock_bluetooth_device_client_.get())); + EXPECT_CALL(*this, GetBluetoothInputClient()) + .WillRepeatedly(Return(mock_bluetooth_input_client_.get())); + EXPECT_CALL(*this, GetBluetoothManagerClient()) + .WillRepeatedly(Return(mock_bluetooth_manager_client())); + EXPECT_CALL(*this, GetBluetoothNodeClient()) + .WillRepeatedly(Return(mock_bluetooth_node_client_.get())); + EXPECT_CALL(*this, GetCashewClient()) + .WillRepeatedly(Return(mock_cashew_client())); + EXPECT_CALL(*this, GetCrosDisksClient()) + .WillRepeatedly(Return(mock_cros_disks_client())); + EXPECT_CALL(*this, GetCryptohomeClient()) + .WillRepeatedly(Return(mock_cryptohome_client())); + EXPECT_CALL(*this, GetDebugDaemonClient()) + .WillRepeatedly(Return(mock_debugdaemon_client())); + EXPECT_CALL(*this, GetFlimflamIPConfigClient()) + .WillRepeatedly(Return(mock_flimflam_ipconfig_client())); + EXPECT_CALL(*this, GetFlimflamNetworkClient()) + .WillRepeatedly(Return(mock_flimflam_network_client())); + EXPECT_CALL(*this, GetFlimflamProfileClient()) + .WillRepeatedly(Return(mock_flimflam_profile_client())); + EXPECT_CALL(*this, GetImageBurnerClient()) + .WillRepeatedly(Return(mock_image_burner_client())); + EXPECT_CALL(*this, GetIntrospectableClient()) + .WillRepeatedly(Return(mock_introspectable_client())); + EXPECT_CALL(*this, GetPowerManagerClient()) + .WillRepeatedly(Return(mock_power_manager_client_.get())); + EXPECT_CALL(*this, GetSessionManagerClient()) + .WillRepeatedly(Return(mock_session_manager_client_.get())); + EXPECT_CALL(*this, GetSpeechSynthesizerClient()) + .WillRepeatedly(Return(mock_speech_synthesizer_client_.get())); + EXPECT_CALL(*this, GetUpdateEngineClient()) + .WillRepeatedly(Return(mock_update_engine_client_.get())); + + // These observers calls are used in ChromeBrowserMainPartsChromeos. + EXPECT_CALL(*mock_power_manager_client_.get(), AddObserver(_)) + .Times(AnyNumber()); + EXPECT_CALL(*mock_power_manager_client_.get(), RemoveObserver(_)) + .Times(AnyNumber()); + EXPECT_CALL(*mock_session_manager_client_.get(), AddObserver(_)) + .Times(AnyNumber()); + EXPECT_CALL(*mock_session_manager_client_.get(), RemoveObserver(_)) + .Times(AnyNumber()); + EXPECT_CALL(*mock_update_engine_client_.get(), AddObserver(_)) + .Times(AnyNumber()); + EXPECT_CALL(*mock_update_engine_client_.get(), RemoveObserver(_)) + .Times(AnyNumber()); + + // Called from PowerMenuButton ctor. + EXPECT_CALL(*mock_power_manager_client_.get(), RequestStatusUpdate(_)) + .Times(AnyNumber()); + + // Called from DiskMountManager::Initialize(), ChromeBrowserMainPartsChromeos. + EXPECT_CALL(*mock_cros_disks_client_.get(), SetUpConnections(_, _)) + .Times(AnyNumber()); +} + +MockDBusThreadManager::~MockDBusThreadManager() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_dbus_thread_manager.h b/chromeos/dbus/mock_dbus_thread_manager.h new file mode 100644 index 0000000..2088eeb --- /dev/null +++ b/chromeos/dbus/mock_dbus_thread_manager.h @@ -0,0 +1,148 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_DBUS_THREAD_MANAGER_H_ +#define CHROMEOS_DBUS_MOCK_DBUS_THREAD_MANAGER_H_ + +#include <string> + +#include "chromeos/dbus/dbus_thread_manager.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace dbus { + +class Bus; + +} // namespace dbus + +namespace chromeos { + +class MockBluetoothAdapterClient; +class MockBluetoothDeviceClient; +class MockBluetoothInputClient; +class MockBluetoothManagerClient; +class MockBluetoothNodeClient; +class MockCashewClient; +class MockCrosDisksClient; +class MockCryptohomeClient; +class MockDebugDaemonClient; +class MockFlimflamIPConfigClient; +class MockFlimflamNetworkClient; +class MockFlimflamProfileClient; +class MockImageBurnerClient; +class MockIntrospectableClient; +class MockPowerManagerClient; +class MockSessionManagerClient; +class MockSpeechSynthesizerClient; +class MockUpdateEngineClient; + +// This class provides a mock DBusThreadManager with mock clients +// installed. You can customize the behaviors of mock clients with +// mock_foo_client() functions. +class MockDBusThreadManager : public DBusThreadManager { + public: + MockDBusThreadManager(); + virtual ~MockDBusThreadManager(); + + MOCK_METHOD0(GetSystemBus, dbus::Bus*(void)); + MOCK_METHOD0(GetBluetoothAdapterClient, BluetoothAdapterClient*(void)); + MOCK_METHOD0(GetBluetoothDeviceClient, BluetoothDeviceClient*(void)); + MOCK_METHOD0(GetBluetoothInputClient, BluetoothInputClient*(void)); + MOCK_METHOD0(GetBluetoothManagerClient, BluetoothManagerClient*(void)); + MOCK_METHOD0(GetBluetoothNodeClient, BluetoothNodeClient*(void)); + MOCK_METHOD0(GetCashewClient, CashewClient*(void)); + MOCK_METHOD0(GetCrosDisksClient, CrosDisksClient*(void)); + MOCK_METHOD0(GetCryptohomeClient, CryptohomeClient*(void)); + MOCK_METHOD0(GetDebugDaemonClient, DebugDaemonClient*(void)); + MOCK_METHOD0(GetFlimflamIPConfigClient, FlimflamIPConfigClient*(void)); + MOCK_METHOD0(GetFlimflamNetworkClient, FlimflamNetworkClient*(void)); + MOCK_METHOD0(GetFlimflamProfileClient, FlimflamProfileClient*(void)); + MOCK_METHOD0(GetImageBurnerClient, ImageBurnerClient*(void)); + MOCK_METHOD0(GetIntrospectableClient, IntrospectableClient*(void)); + MOCK_METHOD0(GetPowerManagerClient, PowerManagerClient*(void)); + MOCK_METHOD0(GetSessionManagerClient, SessionManagerClient*(void)); + MOCK_METHOD0(GetSpeechSynthesizerClient, SpeechSynthesizerClient*(void)); + MOCK_METHOD0(GetUpdateEngineClient, UpdateEngineClient*(void)); + + MockBluetoothAdapterClient* mock_bluetooth_adapter_client() { + return mock_bluetooth_adapter_client_.get(); + } + MockBluetoothDeviceClient* mock_bluetooth_device_client() { + return mock_bluetooth_device_client_.get(); + } + MockBluetoothInputClient* mock_bluetooth_input_client() { + return mock_bluetooth_input_client_.get(); + } + MockBluetoothManagerClient* mock_bluetooth_manager_client() { + return mock_bluetooth_manager_client_.get(); + } + MockBluetoothNodeClient* mock_bluetooth_node_client() { + return mock_bluetooth_node_client_.get(); + } + MockCashewClient* mock_cashew_client() { + return mock_cashew_client_.get(); + } + MockCrosDisksClient* mock_cros_disks_client() { + return mock_cros_disks_client_.get(); + } + MockCryptohomeClient* mock_cryptohome_client() { + return mock_cryptohome_client_.get(); + } + MockDebugDaemonClient* mock_debugdaemon_client() { + return mock_debugdaemon_client_.get(); + } + MockFlimflamIPConfigClient* mock_flimflam_ipconfig_client() { + return mock_flimflam_ipconfig_client_.get(); + } + MockFlimflamNetworkClient* mock_flimflam_network_client() { + return mock_flimflam_network_client_.get(); + } + MockFlimflamProfileClient* mock_flimflam_profile_client() { + return mock_flimflam_profile_client_.get(); + } + MockImageBurnerClient* mock_image_burner_client() { + return mock_image_burner_client_.get(); + } + MockIntrospectableClient* mock_introspectable_client() { + return mock_introspectable_client_.get(); + } + MockPowerManagerClient* mock_power_manager_client() { + return mock_power_manager_client_.get(); + } + MockSessionManagerClient* mock_session_manager_client() { + return mock_session_manager_client_.get(); + } + MockSpeechSynthesizerClient* mock_speech_synthesizer_client() { + return mock_speech_synthesizer_client_.get(); + } + MockUpdateEngineClient* mock_update_engine_client() { + return mock_update_engine_client_.get(); + } + + private: + scoped_ptr<MockBluetoothAdapterClient> mock_bluetooth_adapter_client_; + scoped_ptr<MockBluetoothDeviceClient> mock_bluetooth_device_client_; + scoped_ptr<MockBluetoothInputClient> mock_bluetooth_input_client_; + scoped_ptr<MockBluetoothManagerClient> mock_bluetooth_manager_client_; + scoped_ptr<MockBluetoothNodeClient> mock_bluetooth_node_client_; + scoped_ptr<MockCashewClient> mock_cashew_client_; + scoped_ptr<MockCrosDisksClient> mock_cros_disks_client_; + scoped_ptr<MockCryptohomeClient> mock_cryptohome_client_; + scoped_ptr<MockDebugDaemonClient> mock_debugdaemon_client_; + scoped_ptr<MockFlimflamIPConfigClient> mock_flimflam_ipconfig_client_; + scoped_ptr<MockFlimflamNetworkClient> mock_flimflam_network_client_; + scoped_ptr<MockFlimflamProfileClient> mock_flimflam_profile_client_; + scoped_ptr<MockImageBurnerClient> mock_image_burner_client_; + scoped_ptr<MockIntrospectableClient> mock_introspectable_client_; + scoped_ptr<MockPowerManagerClient> mock_power_manager_client_; + scoped_ptr<MockSessionManagerClient> mock_session_manager_client_; + scoped_ptr<MockSpeechSynthesizerClient> mock_speech_synthesizer_client_; + scoped_ptr<MockUpdateEngineClient> mock_update_engine_client_; + + DISALLOW_COPY_AND_ASSIGN(MockDBusThreadManager); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_DBUS_THREAD_MANAGER_H_ diff --git a/chromeos/dbus/mock_debug_daemon_client.cc b/chromeos/dbus/mock_debug_daemon_client.cc new file mode 100644 index 0000000..4e9430a --- /dev/null +++ b/chromeos/dbus/mock_debug_daemon_client.cc @@ -0,0 +1,13 @@ +// 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/mock_debug_daemon_client.h" + +namespace chromeos { + +MockDebugDaemonClient::MockDebugDaemonClient() {} + +MockDebugDaemonClient::~MockDebugDaemonClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_debug_daemon_client.h b/chromeos/dbus/mock_debug_daemon_client.h new file mode 100644 index 0000000..05f553f --- /dev/null +++ b/chromeos/dbus/mock_debug_daemon_client.h @@ -0,0 +1,25 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_DEBUG_DAEMON_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_DEBUG_DAEMON_CLIENT_H_ + +#include "chromeos/dbus/debug_daemon_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockDebugDaemonClient : public DebugDaemonClient { + public: + MockDebugDaemonClient(); + virtual ~MockDebugDaemonClient(); + + MOCK_METHOD1(RequestStopSystemTracing, + bool(const StopSystemTracingCallback&)); + MOCK_METHOD0(StartSystemTracing, void()); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_DEBUG_DAEMON_CLIENT_H_ diff --git a/chromeos/dbus/mock_flimflam_ipconfig_client.cc b/chromeos/dbus/mock_flimflam_ipconfig_client.cc new file mode 100644 index 0000000..62ca0cf --- /dev/null +++ b/chromeos/dbus/mock_flimflam_ipconfig_client.cc @@ -0,0 +1,13 @@ +// 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/mock_flimflam_ipconfig_client.h" + +namespace chromeos { + +MockFlimflamIPConfigClient::MockFlimflamIPConfigClient() {} + +MockFlimflamIPConfigClient::~MockFlimflamIPConfigClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_flimflam_ipconfig_client.h b/chromeos/dbus/mock_flimflam_ipconfig_client.h new file mode 100644 index 0000000..7e98da0 --- /dev/null +++ b/chromeos/dbus/mock_flimflam_ipconfig_client.h @@ -0,0 +1,33 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_FLIMFLAM_IPCONFIG_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_FLIMFLAM_IPCONFIG_CLIENT_H_ + +#include "base/values.h" +#include "chromeos/dbus/flimflam_ipconfig_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockFlimflamIPConfigClient : public FlimflamIPConfigClient { + public: + MockFlimflamIPConfigClient(); + virtual ~MockFlimflamIPConfigClient(); + + MOCK_METHOD1(SetPropertyChangedHandler, + void(const PropertyChangedHandler& handler)); + MOCK_METHOD0(ResetPropertyChangedHandler, void()); + MOCK_METHOD1(GetProperties, void(const DictionaryValueCallback& callback)); + MOCK_METHOD3(SetProperty, void(const std::string& name, + const base::Value& value, + const VoidCallback& callback)); + MOCK_METHOD2(ClearProperty, void(const std::string& name, + const VoidCallback& callback)); + MOCK_METHOD1(Remove, void(const VoidCallback& callback)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_FLIMFLAM_IPCONFIG_CLIENT_H_ diff --git a/chromeos/dbus/mock_flimflam_network_client.cc b/chromeos/dbus/mock_flimflam_network_client.cc new file mode 100644 index 0000000..e190375 --- /dev/null +++ b/chromeos/dbus/mock_flimflam_network_client.cc @@ -0,0 +1,13 @@ +// 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/mock_flimflam_network_client.h" + +namespace chromeos { + +MockFlimflamNetworkClient::MockFlimflamNetworkClient() {} + +MockFlimflamNetworkClient::~MockFlimflamNetworkClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_flimflam_network_client.h b/chromeos/dbus/mock_flimflam_network_client.h new file mode 100644 index 0000000..df0d31b --- /dev/null +++ b/chromeos/dbus/mock_flimflam_network_client.h @@ -0,0 +1,26 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_FLIMFLAM_NETWORK_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_FLIMFLAM_NETWORK_CLIENT_H_ + +#include "chromeos/dbus/flimflam_network_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockFlimflamNetworkClient : public FlimflamNetworkClient { + public: + MockFlimflamNetworkClient(); + virtual ~MockFlimflamNetworkClient(); + + MOCK_METHOD1(SetPropertyChangedHandler, + void(const PropertyChangedHandler& handler)); + MOCK_METHOD0(ResetPropertyChangedHandler, void()); + MOCK_METHOD1(GetProperties, void(const DictionaryValueCallback& callback)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_FLIMFLAM_NETWORK_CLIENT_H_ diff --git a/chromeos/dbus/mock_flimflam_profile_client.cc b/chromeos/dbus/mock_flimflam_profile_client.cc new file mode 100644 index 0000000..a9dc01e --- /dev/null +++ b/chromeos/dbus/mock_flimflam_profile_client.cc @@ -0,0 +1,13 @@ +// 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/mock_flimflam_profile_client.h" + +namespace chromeos { + +MockFlimflamProfileClient::MockFlimflamProfileClient() {} + +MockFlimflamProfileClient::~MockFlimflamProfileClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_flimflam_profile_client.h b/chromeos/dbus/mock_flimflam_profile_client.h new file mode 100644 index 0000000..61afc1b --- /dev/null +++ b/chromeos/dbus/mock_flimflam_profile_client.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_FLIMFLAM_PROFILE_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_FLIMFLAM_PROFILE_CLIENT_H_ + +#include "base/values.h" +#include "chromeos/dbus/flimflam_profile_client.h" +#include "dbus/object_path.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockFlimflamProfileClient : public FlimflamProfileClient { + public: + MockFlimflamProfileClient(); + virtual ~MockFlimflamProfileClient(); + + MOCK_METHOD1(SetPropertyChangedHandler, + void(const PropertyChangedHandler& handler)); + MOCK_METHOD0(ResetPropertyChangedHandler, void()); + MOCK_METHOD1(GetProperties, void(const DictionaryValueCallback& callback)); + MOCK_METHOD2(GetEntry, void(const dbus::ObjectPath& path, + const DictionaryValueCallback& callback)); + MOCK_METHOD2(DeleteEntry, void(const dbus::ObjectPath& path, + const VoidCallback& callback)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_FLIMFLAM_PROFILE_CLIENT_H_ diff --git a/chromeos/dbus/mock_image_burner_client.cc b/chromeos/dbus/mock_image_burner_client.cc new file mode 100644 index 0000000..fb95831 --- /dev/null +++ b/chromeos/dbus/mock_image_burner_client.cc @@ -0,0 +1,13 @@ +// 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/mock_image_burner_client.h" + +namespace chromeos { + +MockImageBurnerClient::MockImageBurnerClient() {} + +MockImageBurnerClient::~MockImageBurnerClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_image_burner_client.h b/chromeos/dbus/mock_image_burner_client.h new file mode 100644 index 0000000..8db0a44 --- /dev/null +++ b/chromeos/dbus/mock_image_burner_client.h @@ -0,0 +1,31 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_IMAGE_BURNER_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_IMAGE_BURNER_CLIENT_H_ +#pragma once + +#include <string> + +#include "chromeos/dbus/image_burner_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockImageBurnerClient : public ImageBurnerClient { + public: + MockImageBurnerClient(); + virtual ~MockImageBurnerClient(); + + MOCK_METHOD3(BurnImage, + void(const std::string&, const std::string&, ErrorCallback)); + MOCK_METHOD2(SetEventHandlers, + void(BurnFinishedHandler, BurnProgressUpdateHandler)); + MOCK_METHOD0(ResetEventHandlers, void()); + +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_IMAGE_BURNER_CLIENT_H_ diff --git a/chromeos/dbus/mock_introspectable_client.cc b/chromeos/dbus/mock_introspectable_client.cc new file mode 100644 index 0000000..27ece38 --- /dev/null +++ b/chromeos/dbus/mock_introspectable_client.cc @@ -0,0 +1,13 @@ +// 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/mock_introspectable_client.h" + +namespace chromeos { + +MockIntrospectableClient::MockIntrospectableClient() {} + +MockIntrospectableClient::~MockIntrospectableClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_introspectable_client.h b/chromeos/dbus/mock_introspectable_client.h new file mode 100644 index 0000000..6a10de6 --- /dev/null +++ b/chromeos/dbus/mock_introspectable_client.h @@ -0,0 +1,25 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_INTROSPECTABLE_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_INTROSPECTABLE_CLIENT_H_ + +#include "chromeos/dbus/introspectable_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockIntrospectableClient : public IntrospectableClient { + public: + MockIntrospectableClient(); + virtual ~MockIntrospectableClient(); + + MOCK_METHOD3(Introspect, void(const std::string&, + const dbus::ObjectPath&, + const IntrospectCallback&)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_INTROSPECTABLE_CLIENT_H_ diff --git a/chromeos/dbus/mock_power_manager_client.cc b/chromeos/dbus/mock_power_manager_client.cc new file mode 100644 index 0000000..34c5170 --- /dev/null +++ b/chromeos/dbus/mock_power_manager_client.cc @@ -0,0 +1,13 @@ +// 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/mock_power_manager_client.h" + +namespace chromeos { + +MockPowerManagerClient::MockPowerManagerClient() {} + +MockPowerManagerClient::~MockPowerManagerClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_power_manager_client.h b/chromeos/dbus/mock_power_manager_client.h new file mode 100644 index 0000000..e4eb030 --- /dev/null +++ b/chromeos/dbus/mock_power_manager_client.h @@ -0,0 +1,46 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_POWER_MANAGER_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_POWER_MANAGER_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/power_manager_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockPowerManagerClient : public PowerManagerClient { + public: + MockPowerManagerClient(); + virtual ~MockPowerManagerClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD1(HasObserver, bool(Observer*)); + MOCK_METHOD1(DecreaseScreenBrightness, void(bool)); + MOCK_METHOD0(IncreaseScreenBrightness, void(void)); + MOCK_METHOD2(SetScreenBrightnessPercent, void(double, bool)); + MOCK_METHOD1(GetScreenBrightnessPercent, + void(const GetScreenBrightnessPercentCallback&)); + MOCK_METHOD1(RequestStatusUpdate, void(UpdateRequestType)); + MOCK_METHOD0(RequestRestart, void(void)); + MOCK_METHOD0(RequestShutdown, void(void)); + MOCK_METHOD1(CalculateIdleTime, void(const CalculateIdleTimeCallback&)); + MOCK_METHOD1(RequestIdleNotification, void(int64)); + MOCK_METHOD0(RequestActiveNotification, void(void)); + MOCK_METHOD4(RequestPowerStateOverrides, void(uint32, + uint32, + int, + PowerStateRequestIdCallback)); + MOCK_METHOD0(NotifyScreenLockRequested, void(void)); + MOCK_METHOD0(NotifyScreenLockCompleted, void(void)); + MOCK_METHOD0(NotifyScreenUnlockRequested, void(void)); + MOCK_METHOD0(NotifyScreenUnlockCompleted, void(void)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_POWER_MANAGER_CLIENT_H_ diff --git a/chromeos/dbus/mock_session_manager_client.cc b/chromeos/dbus/mock_session_manager_client.cc new file mode 100644 index 0000000..a4b260a --- /dev/null +++ b/chromeos/dbus/mock_session_manager_client.cc @@ -0,0 +1,14 @@ +// 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/mock_session_manager_client.h" + +namespace chromeos { + +MockSessionManagerClient::MockSessionManagerClient() {} + +MockSessionManagerClient::~MockSessionManagerClient() {} + +} // namespace chromeos + diff --git a/chromeos/dbus/mock_session_manager_client.h b/chromeos/dbus/mock_session_manager_client.h new file mode 100644 index 0000000..6ed73bb --- /dev/null +++ b/chromeos/dbus/mock_session_manager_client.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_SESSION_MANAGER_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_SESSION_MANAGER_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/session_manager_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockSessionManagerClient : public SessionManagerClient { + public: + MockSessionManagerClient(); + virtual ~MockSessionManagerClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD0(EmitLoginPromptReady, void(void)); + MOCK_METHOD0(EmitLoginPromptVisible, void(void)); + MOCK_METHOD0(RestartEntd, void(void)); + MOCK_METHOD2(RestartJob, void(int, const std::string&)); + MOCK_METHOD1(StartSession, void(const std::string&)); + MOCK_METHOD0(StopSession, void(void)); + MOCK_METHOD1(RetrieveDevicePolicy, void(RetrievePolicyCallback)); + MOCK_METHOD1(RetrieveUserPolicy, void(RetrievePolicyCallback)); + MOCK_METHOD2(StoreDevicePolicy, void(const std::string&, + StorePolicyCallback)); + MOCK_METHOD2(StoreUserPolicy, void(const std::string&, + StorePolicyCallback)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_SESSION_MANAGER_CLIENT_H_ diff --git a/chromeos/dbus/mock_speech_synthesizer_client.cc b/chromeos/dbus/mock_speech_synthesizer_client.cc new file mode 100644 index 0000000..1bd847e --- /dev/null +++ b/chromeos/dbus/mock_speech_synthesizer_client.cc @@ -0,0 +1,13 @@ +// 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/mock_speech_synthesizer_client.h" + +namespace chromeos { + +MockSpeechSynthesizerClient::MockSpeechSynthesizerClient() {} + +MockSpeechSynthesizerClient::~MockSpeechSynthesizerClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_speech_synthesizer_client.h b/chromeos/dbus/mock_speech_synthesizer_client.h new file mode 100644 index 0000000..f687df4 --- /dev/null +++ b/chromeos/dbus/mock_speech_synthesizer_client.h @@ -0,0 +1,27 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_SPEECH_SYNTHESIZER_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_SPEECH_SYNTHESIZER_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/speech_synthesizer_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockSpeechSynthesizerClient : public SpeechSynthesizerClient { + public: + MockSpeechSynthesizerClient(); + virtual ~MockSpeechSynthesizerClient(); + + MOCK_METHOD2(Speak, void(const std::string&, const std::string&)); + MOCK_METHOD0(StopSpeaking, void()); + MOCK_METHOD1(IsSpeaking, void(const IsSpeakingCallback&)); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_SPEECH_SYNTHESIZER_CLIENT_H_ diff --git a/chromeos/dbus/mock_update_engine_client.cc b/chromeos/dbus/mock_update_engine_client.cc new file mode 100644 index 0000000..32ba344 --- /dev/null +++ b/chromeos/dbus/mock_update_engine_client.cc @@ -0,0 +1,13 @@ +// 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/mock_update_engine_client.h" + +namespace chromeos { + +MockUpdateEngineClient::MockUpdateEngineClient() {} + +MockUpdateEngineClient::~MockUpdateEngineClient() {} + +} // namespace chromeos diff --git a/chromeos/dbus/mock_update_engine_client.h b/chromeos/dbus/mock_update_engine_client.h new file mode 100644 index 0000000..385a0c5 --- /dev/null +++ b/chromeos/dbus/mock_update_engine_client.h @@ -0,0 +1,32 @@ +// 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. + +#ifndef CHROMEOS_DBUS_MOCK_UPDATE_ENGINE_CLIENT_H_ +#define CHROMEOS_DBUS_MOCK_UPDATE_ENGINE_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/update_engine_client.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace chromeos { + +class MockUpdateEngineClient : public UpdateEngineClient { + public: + MockUpdateEngineClient(); + virtual ~MockUpdateEngineClient(); + + MOCK_METHOD1(AddObserver, void(Observer*)); + MOCK_METHOD1(RemoveObserver, void(Observer*)); + MOCK_METHOD1(HasObserver, bool(Observer*)); + MOCK_METHOD1(RequestUpdateCheck, void(UpdateCheckCallback)); + MOCK_METHOD0(RebootAfterUpdate, void()); + MOCK_METHOD1(SetReleaseTrack, void(const std::string&)); + MOCK_METHOD1(GetReleaseTrack, void(GetReleaseTrackCallback)); + MOCK_METHOD0(GetLastStatus, Status()); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_MOCK_UPDATE_ENGINE_CLIENT_H_ diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc new file mode 100644 index 0000000..d74feab --- /dev/null +++ b/chromeos/dbus/power_manager_client.cc @@ -0,0 +1,616 @@ +// 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/power_manager_client.h" + +#include <algorithm> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/format_macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" +#include "base/stringprintf.h" +#include "base/time.h" +#include "base/timer.h" +#include "chromeos/dbus/power_state_control.pb.h" +#include "chromeos/dbus/power_supply_properties.pb.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 { + +// The PowerManagerClient implementation used in production. +class PowerManagerClientImpl : public PowerManagerClient { + public: + explicit PowerManagerClientImpl(dbus::Bus* bus) + : power_manager_proxy_(NULL), + weak_ptr_factory_(this) { + power_manager_proxy_ = bus->GetObjectProxy( + power_manager::kPowerManagerServiceName, + dbus::ObjectPath(power_manager::kPowerManagerServicePath)); + + session_manager_proxy_ = bus->GetObjectProxy( + login_manager::kSessionManagerServiceName, + dbus::ObjectPath(login_manager::kSessionManagerServicePath)); + + // Monitor the D-Bus signal for brightness changes. Only the power + // manager knows the actual brightness level. We don't cache the + // brightness level in Chrome as it'll make things less reliable. + power_manager_proxy_->ConnectToSignal( + power_manager::kPowerManagerInterface, + power_manager::kBrightnessChangedSignal, + base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + power_manager_proxy_->ConnectToSignal( + power_manager::kPowerManagerInterface, + power_manager::kPowerSupplyPollSignal, + base::Bind(&PowerManagerClientImpl::PowerSupplyPollReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + power_manager_proxy_->ConnectToSignal( + power_manager::kPowerManagerInterface, + power_manager::kPowerStateChangedSignal, + base::Bind(&PowerManagerClientImpl::PowerStateChangedSignalReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + power_manager_proxy_->ConnectToSignal( + power_manager::kPowerManagerInterface, + power_manager::kButtonEventSignal, + base::Bind(&PowerManagerClientImpl::ButtonEventSignalReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + session_manager_proxy_->ConnectToSignal( + chromium::kChromiumInterface, + chromium::kLockScreenSignal, + base::Bind(&PowerManagerClientImpl::ScreenLockSignalReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + session_manager_proxy_->ConnectToSignal( + chromium::kChromiumInterface, + chromium::kUnlockScreenSignal, + base::Bind(&PowerManagerClientImpl::ScreenUnlockSignalReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + session_manager_proxy_->ConnectToSignal( + chromium::kChromiumInterface, + chromium::kUnlockScreenFailedSignal, + base::Bind(&PowerManagerClientImpl::ScreenUnlockFailedSignalReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + power_manager_proxy_->ConnectToSignal( + power_manager::kPowerManagerInterface, + power_manager::kIdleNotifySignal, + base::Bind(&PowerManagerClientImpl::IdleNotifySignalReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + power_manager_proxy_->ConnectToSignal( + power_manager::kPowerManagerInterface, + power_manager::kActiveNotifySignal, + base::Bind(&PowerManagerClientImpl::ActiveNotifySignalReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&PowerManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual ~PowerManagerClientImpl() { + } + + // PowerManagerClient overrides: + + virtual void AddObserver(Observer* observer) OVERRIDE { + CHECK(observer); // http://crbug.com/119976 + observers_.AddObserver(observer); + } + + virtual void RemoveObserver(Observer* observer) OVERRIDE { + observers_.RemoveObserver(observer); + } + + virtual bool HasObserver(Observer* observer) OVERRIDE { + return observers_.HasObserver(observer); + } + + virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE { + dbus::MethodCall method_call( + power_manager::kPowerManagerInterface, + power_manager::kDecreaseScreenBrightness); + dbus::MessageWriter writer(&method_call); + writer.AppendBool(allow_off); + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + dbus::ObjectProxy::EmptyResponseCallback()); + } + + virtual void IncreaseScreenBrightness() OVERRIDE { + SimpleMethodCallToPowerManager(power_manager::kIncreaseScreenBrightness); + } + + virtual void SetScreenBrightnessPercent(double percent, bool gradual) { + dbus::MethodCall method_call( + power_manager::kPowerManagerInterface, + power_manager::kSetScreenBrightnessPercent); + dbus::MessageWriter writer(&method_call); + writer.AppendDouble(percent); + writer.AppendInt32( + gradual ? + power_manager::kBrightnessTransitionGradual : + power_manager::kBrightnessTransitionInstant); + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + dbus::ObjectProxy::EmptyResponseCallback()); + } + + virtual void GetScreenBrightnessPercent( + const GetScreenBrightnessPercentCallback& callback) OVERRIDE { + dbus::MethodCall method_call(power_manager::kPowerManagerInterface, + power_manager::kGetScreenBrightnessPercent); + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&PowerManagerClientImpl::OnGetScreenBrightnessPercent, + weak_ptr_factory_.GetWeakPtr(), callback)); + } + + virtual void RequestStatusUpdate(UpdateRequestType update_type) OVERRIDE { + dbus::MethodCall method_call( + power_manager::kPowerManagerInterface, + power_manager::kGetPowerSupplyPropertiesMethod); + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&PowerManagerClientImpl::OnGetPowerSupplyPropertiesMethod, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual void RequestRestart() OVERRIDE { + SimpleMethodCallToPowerManager(power_manager::kRequestRestartMethod); + }; + + virtual void RequestShutdown() OVERRIDE { + SimpleMethodCallToPowerManager(power_manager::kRequestShutdownMethod); + } + + virtual void CalculateIdleTime(const CalculateIdleTimeCallback& callback) + OVERRIDE { + dbus::MethodCall method_call(power_manager::kPowerManagerInterface, + power_manager::kGetIdleTime); + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&PowerManagerClientImpl::OnGetIdleTime, + weak_ptr_factory_.GetWeakPtr(), callback)); + } + + virtual void RequestIdleNotification(int64 threshold) OVERRIDE { + dbus::MethodCall method_call(power_manager::kPowerManagerInterface, + power_manager::kRequestIdleNotification); + dbus::MessageWriter writer(&method_call); + writer.AppendInt64(threshold); + + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + dbus::ObjectProxy::EmptyResponseCallback()); + } + + virtual void RequestActiveNotification() OVERRIDE { + RequestIdleNotification(0); + } + + virtual void RequestPowerStateOverrides( + uint32 request_id, + uint32 duration, + int overrides, + PowerStateRequestIdCallback callback) OVERRIDE { + dbus::MethodCall method_call(power_manager::kPowerManagerInterface, + power_manager::kStateOverrideRequest); + dbus::MessageWriter writer(&method_call); + + PowerStateControl protobuf; + protobuf.set_request_id(request_id); + protobuf.set_duration(duration); + protobuf.set_disable_idle_dim(overrides & DISABLE_IDLE_DIM); + protobuf.set_disable_idle_blank(overrides & DISABLE_IDLE_BLANK); + protobuf.set_disable_idle_suspend(overrides & DISABLE_IDLE_SUSPEND); + protobuf.set_disable_lid_suspend(overrides & DISABLE_IDLE_LID_SUSPEND); + + writer.AppendProtoAsArrayOfBytes(protobuf); + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&PowerManagerClientImpl::OnPowerStateOverride, + weak_ptr_factory_.GetWeakPtr(), callback)); + } + + virtual void NotifyScreenLockRequested() OVERRIDE { + SimpleMethodCallToPowerManager(power_manager::kRequestLockScreenMethod); + } + + virtual void NotifyScreenLockCompleted() OVERRIDE { + SimpleMethodCallToPowerManager(power_manager::kScreenIsLockedMethod); + } + + virtual void NotifyScreenUnlockRequested() OVERRIDE { + SimpleMethodCallToPowerManager(power_manager::kRequestUnlockScreenMethod); + } + + virtual void NotifyScreenUnlockCompleted() OVERRIDE { + SimpleMethodCallToPowerManager(power_manager::kScreenIsUnlockedMethod); + } + + private: + // Called when a dbus signal is initially connected. + void SignalConnected(const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) << "Failed to connect to signal " + << signal_name << "."; + } + + // Make a method call to power manager with no arguments and no response. + void SimpleMethodCallToPowerManager(const std::string& method_name) { + dbus::MethodCall method_call(power_manager::kPowerManagerInterface, + method_name); + power_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + dbus::ObjectProxy::EmptyResponseCallback()); + } + + void BrightnessChangedReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + int32 brightness_level = 0; + bool user_initiated = 0; + if (!(reader.PopInt32(&brightness_level) && + reader.PopBool(&user_initiated))) { + LOG(ERROR) << "Brightness changed signal had incorrect parameters: " + << signal->ToString(); + return; + } + VLOG(1) << "Brightness changed to " << brightness_level + << ": user initiated " << user_initiated; + FOR_EACH_OBSERVER(Observer, observers_, + BrightnessChanged(brightness_level, user_initiated)); + } + + void PowerStateChangedSignalReceived(dbus::Signal* signal) { + VLOG(1) << "Received power state changed signal."; + dbus::MessageReader reader(signal); + std::string power_state_string; + if (!reader.PopString(&power_state_string)) { + LOG(ERROR) << "Error reading signal args: " << signal->ToString(); + return; + } + if (power_state_string != "on") + return; + FOR_EACH_OBSERVER(Observer, observers_, SystemResumed()); + } + + void ButtonEventSignalReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string button_name; + bool down = false; + int64 timestamp_internal = 0; + if (!reader.PopString(&button_name) || + !reader.PopBool(&down) || + !reader.PopInt64(×tamp_internal)) { + LOG(ERROR) << "Button signal had incorrect parameters: " + << signal->ToString(); + return; + } + base::TimeTicks timestamp = + base::TimeTicks::FromInternalValue(timestamp_internal); + + if (button_name == power_manager::kPowerButtonName) { + FOR_EACH_OBSERVER( + Observer, observers_, PowerButtonStateChanged(down, timestamp)); + } else if (button_name == power_manager::kLockButtonName) { + FOR_EACH_OBSERVER( + Observer, observers_, LockButtonStateChanged(down, timestamp)); + } + } + + void PowerSupplyPollReceived(dbus::Signal* unused_signal) { + VLOG(1) << "Received power supply poll signal."; + RequestStatusUpdate(UPDATE_POLL); + } + + void OnGetPowerSupplyPropertiesMethod(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Error calling " + << power_manager::kGetPowerSupplyPropertiesMethod; + return; + } + + dbus::MessageReader reader(response); + PowerSupplyProperties protobuf; + reader.PopArrayOfBytesAsProto(&protobuf); + + PowerSupplyStatus status; + status.line_power_on = protobuf.line_power_on(); + status.battery_seconds_to_empty = protobuf.battery_time_to_empty(); + status.battery_seconds_to_full = protobuf.battery_time_to_full(); + status.battery_percentage = protobuf.battery_percentage(); + status.battery_is_present = protobuf.battery_is_present(); + status.battery_is_full = protobuf.battery_is_charged(); + + VLOG(1) << "Power status: " << status.ToString(); + FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(status)); + } + + void OnGetIdleTime(const CalculateIdleTimeCallback& callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Error calling " << power_manager::kGetIdleTime; + return; + } + dbus::MessageReader reader(response); + int64 idle_time_ms = 0; + if (!reader.PopInt64(&idle_time_ms)) { + LOG(ERROR) << "Error reading response from powerd: " + << response->ToString(); + callback.Run(-1); + return; + } + if (idle_time_ms < 0) { + LOG(ERROR) << "Power manager failed to calculate idle time."; + callback.Run(-1); + return; + } + callback.Run(idle_time_ms/1000); + } + + void OnPowerStateOverride(const PowerStateRequestIdCallback& callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Error calling " << power_manager::kStateOverrideRequest; + return; + } + + dbus::MessageReader reader(response); + uint32 request_id = 0; + if (!reader.PopUint32(&request_id)) { + LOG(ERROR) << "Error reading response from powerd: " + << response->ToString(); + callback.Run(0); + return; + } + + callback.Run(request_id); + } + + void OnGetScreenBrightnessPercent( + const GetScreenBrightnessPercentCallback& callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Error calling " + << power_manager::kGetScreenBrightnessPercent; + return; + } + dbus::MessageReader reader(response); + double percent = 0.0; + if (!reader.PopDouble(&percent)) + LOG(ERROR) << "Error reading response from powerd: " + << response->ToString(); + callback.Run(percent); + } + + void ScreenLockSignalReceived(dbus::Signal* signal) { + FOR_EACH_OBSERVER(Observer, observers_, LockScreen()); + } + + void ScreenUnlockSignalReceived(dbus::Signal* signal) { + FOR_EACH_OBSERVER(Observer, observers_, UnlockScreen()); + } + + void ScreenUnlockFailedSignalReceived(dbus::Signal* signal) { + FOR_EACH_OBSERVER(Observer, observers_, UnlockScreenFailed()); + } + + + void IdleNotifySignalReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + int64 threshold = 0; + if (!reader.PopInt64(&threshold)) { + LOG(ERROR) << "Idle Notify signal had incorrect parameters: " + << signal->ToString(); + return; + } + DCHECK_GT(threshold, 0); + + VLOG(1) << "Idle Notify: " << threshold; + FOR_EACH_OBSERVER(Observer, observers_, IdleNotify(threshold)); + } + + void ActiveNotifySignalReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + int64 threshold = 0; + if (!reader.PopInt64(&threshold)) { + LOG(ERROR) << "Active Notify signal had incorrect parameters: " + << signal->ToString(); + return; + } + DCHECK_EQ(threshold, 0); + + VLOG(1) << "Active Notify."; + FOR_EACH_OBSERVER(Observer, observers_, ActiveNotify()); + } + + + dbus::ObjectProxy* power_manager_proxy_; + dbus::ObjectProxy* session_manager_proxy_; + ObserverList<Observer> observers_; + base::WeakPtrFactory<PowerManagerClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(PowerManagerClientImpl); +}; + +// The PowerManagerClient implementation used on Linux desktop, +// which does nothing. +class PowerManagerClientStubImpl : public PowerManagerClient { + public: + PowerManagerClientStubImpl() + : discharging_(true), + battery_percentage_(81), + pause_count_(0) { + } + + virtual ~PowerManagerClientStubImpl() {} + + // PowerManagerClient overrides: + + virtual void AddObserver(Observer* observer) OVERRIDE { + observers_.AddObserver(observer); + } + + virtual void RemoveObserver(Observer* observer) OVERRIDE { + observers_.RemoveObserver(observer); + } + + virtual bool HasObserver(Observer* observer) OVERRIDE { + return observers_.HasObserver(observer); + } + + virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE { + VLOG(1) << "Requested to descrease screen brightness"; + } + + virtual void IncreaseScreenBrightness() OVERRIDE { + VLOG(1) << "Requested to increase screen brightness"; + } + + virtual void SetScreenBrightnessPercent(double percent, + bool gradual) OVERRIDE { + VLOG(1) << "Requested to set screen brightness to " << percent << "% " + << (gradual ? "gradually" : "instantaneously"); + } + + virtual void GetScreenBrightnessPercent( + const GetScreenBrightnessPercentCallback& callback) OVERRIDE { + callback.Run(100.0); + } + + virtual void RequestStatusUpdate(UpdateRequestType update_type) OVERRIDE { + if (update_type == UPDATE_INITIAL) { + Update(); + return; + } + if (!timer_.IsRunning() && update_type == UPDATE_USER) { + timer_.Start( + FROM_HERE, + base::TimeDelta::FromMilliseconds(1000), + this, + &PowerManagerClientStubImpl::Update); + } else { + timer_.Stop(); + } + } + + virtual void RequestRestart() OVERRIDE {} + virtual void RequestShutdown() OVERRIDE {} + + virtual void CalculateIdleTime(const CalculateIdleTimeCallback& callback) + OVERRIDE { + callback.Run(0); + } + + virtual void RequestIdleNotification(int64 threshold) OVERRIDE {} + virtual void RequestActiveNotification() OVERRIDE {} + virtual void RequestPowerStateOverrides( + uint32 request_id, + uint32 duration, + int overrides, + PowerStateRequestIdCallback callback) OVERRIDE {} + + virtual void NotifyScreenLockRequested() OVERRIDE { + FOR_EACH_OBSERVER(Observer, observers_, LockScreen()); + } + virtual void NotifyScreenLockCompleted() OVERRIDE {} + virtual void NotifyScreenUnlockRequested() OVERRIDE { + FOR_EACH_OBSERVER(Observer, observers_, UnlockScreen()); + } + + virtual void NotifyScreenUnlockCompleted() OVERRIDE {} + + private: + void Update() { + // We pause at 0 and 100% so that it's easier to check those conditions. + if (pause_count_ > 1) { + pause_count_--; + return; + } + + if (battery_percentage_ == 0 || battery_percentage_ == 100) { + if (pause_count_) { + pause_count_ = 0; + discharging_ = !discharging_; + } else { + // Pause twice (i.e. skip updating the menu), including the current + // call to this function. + pause_count_ = 2; + return; + } + } + battery_percentage_ += (discharging_ ? -1 : 1); + + const int kSecondsToEmptyFullBattery(3 * 60 * 60); // 3 hours. + + PowerSupplyStatus status; + status.line_power_on = !discharging_; + status.battery_is_present = true; + status.battery_percentage = battery_percentage_; + status.battery_seconds_to_empty = + std::max(1, battery_percentage_ * kSecondsToEmptyFullBattery / 100); + status.battery_seconds_to_full = + std::max(static_cast<int64>(1), + kSecondsToEmptyFullBattery - status.battery_seconds_to_empty); + + FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(status)); + } + + bool discharging_; + int battery_percentage_; + int pause_count_; + ObserverList<Observer> observers_; + base::RepeatingTimer<PowerManagerClientStubImpl> timer_; +}; + +PowerManagerClient::PowerManagerClient() { +} + +PowerManagerClient::~PowerManagerClient() { +} + +PowerManagerClient* PowerManagerClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new PowerManagerClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new PowerManagerClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/power_manager_client.h b/chromeos/dbus/power_manager_client.h new file mode 100644 index 0000000..3100de8 --- /dev/null +++ b/chromeos/dbus/power_manager_client.h @@ -0,0 +1,183 @@ +// 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. + +#ifndef CHROMEOS_DBUS_POWER_MANAGER_CLIENT_H_ +#define CHROMEOS_DBUS_POWER_MANAGER_CLIENT_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +#include "chromeos/dbus/power_supply_status.h" + +namespace base { +class TimeTicks; +} +namespace dbus { +class Bus; +} + +namespace chromeos { + +// Callback used for processing the idle time. The int64 param is the number of +// seconds the user has been idle. +typedef base::Callback<void(int64)> CalculateIdleTimeCallback; +typedef base::Callback<void(void)> IdleNotificationCallback; +typedef base::Callback<void(uint32)> PowerStateRequestIdCallback; + +// Callback used for getting the current screen brightness. The param is in the +// range [0.0, 100.0]. +typedef base::Callback<void(double)> GetScreenBrightnessPercentCallback; + +// PowerManagerClient is used to communicate with the power manager. +class CHROMEOS_EXPORT PowerManagerClient { + public: + // Interface for observing changes from the power manager. + class Observer { + public: + virtual ~Observer() {} + + // Called when the brightness is changed. + // |level| is of the range [0, 100]. + // |user_initiated| is true if the action is initiated by the user. + virtual void BrightnessChanged(int level, bool user_initiated) {} + + // Called when power supply polling takes place. |status| is a data + // structure that contains the current state of the power supply. + virtual void PowerChanged(const PowerSupplyStatus& status) {} + + // Called when the system resumes from suspend. + virtual void SystemResumed() {} + + // Called when the power button is pressed or released. + virtual void PowerButtonStateChanged(bool down, + const base::TimeTicks& timestamp) {} + + // Called when the lock button is pressed or released. + virtual void LockButtonStateChanged(bool down, + const base::TimeTicks& timestamp) {} + + // Called when the screen is locked. + virtual void LockScreen() {} + + // Called when the screen is unlocked. + virtual void UnlockScreen() {} + + // Called when the screen fails to unlock. + virtual void UnlockScreenFailed() {} + + // Called when we go idle for threshold time. + virtual void IdleNotify(int64 threshold_secs) {} + + // Called when we go from idle to active. + virtual void ActiveNotify() {} + }; + + enum UpdateRequestType { + UPDATE_INITIAL, // Initial update request. + UPDATE_USER, // User initialted update request. + UPDATE_POLL // Update requested by poll signal. + }; + + enum PowerStateOverrideType { + DISABLE_IDLE_DIM = 1, // Disable screen dimming on idle. + DISABLE_IDLE_BLANK = 2, // Disable screen blanking on idle. + DISABLE_IDLE_SUSPEND = 3, // Disable suspend on idle. + DISABLE_IDLE_LID_SUSPEND = 4, // Disable suspend on lid closed. + }; + + // Adds and removes the observer. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + virtual bool HasObserver(Observer* observer) = 0; + + // Decreases the screen brightness. |allow_off| controls whether or not + // it's allowed to turn off the back light. + virtual void DecreaseScreenBrightness(bool allow_off) = 0; + + // Increases the screen brightness. + virtual void IncreaseScreenBrightness() = 0; + + // Set the screen brightness to |percent|, in the range [0.0, 100.0]. + // If |gradual| is true, the transition will be animated. + virtual void SetScreenBrightnessPercent(double percent, bool gradual) = 0; + + // Asynchronously gets the current screen brightness, in the range + // [0.0, 100.0]. + virtual void GetScreenBrightnessPercent( + const GetScreenBrightnessPercentCallback& callback) = 0; + + // Request for power supply status update. + virtual void RequestStatusUpdate(UpdateRequestType update_type) = 0; + + // Requests restart of the system. + virtual void RequestRestart() = 0; + + // Requests shutdown of the system. + virtual void RequestShutdown() = 0; + + // Notifies PowerManager that a user requested to lock the screen. + virtual void NotifyScreenLockRequested() = 0; + + // Notifies PowerManager that screen lock has been completed. + virtual void NotifyScreenLockCompleted() = 0; + + // Notifies PowerManager that a user unlocked the screen. + virtual void NotifyScreenUnlockRequested() = 0; + + // Notifies PowerManager that screen is unlocked. + virtual void NotifyScreenUnlockCompleted() = 0; + + // Idle management functions: + + // Calculates idle time asynchronously, after the idle time request has + // replied. It passes the idle time in seconds to |callback|. If it + // encounters some error, it passes -1 to |callback|. + virtual void CalculateIdleTime(const CalculateIdleTimeCallback& callback) = 0; + + // Requests notification for Idle at a certain threshold. + // NOTE: This notification is one shot, once the machine has been idle for + // threshold time, a notification will be sent and then that request will be + // removed from the notification queue. If you wish notifications the next + // time the machine goes idle for that much time, request again. + virtual void RequestIdleNotification(int64 threshold_secs) = 0; + + // Requests that the observers be notified in case of an Idle->Active event. + // NOTE: Like the previous request, this will also get triggered exactly once. + virtual void RequestActiveNotification() = 0; + + // Override the current power state on the machine. The overrides will be + // applied to the request ID specified. To specify a new request; use 0 as + // the request id and the method will call the provided callback with the + // new request ID for use with further calls. + // The overrides parameter will & out the PowerStateOverrideType types to + // allow specific selection of overrides. For example, to override just dim + // and suspending but leaving blanking in, set overrides to, + // DISABLE_IDLE_DIM | DISABLE_IDLE_SUSPEND. + virtual void RequestPowerStateOverrides( + uint32 request_id, + uint32 duration, + int overrides, + PowerStateRequestIdCallback callback) = 0; + + // Creates the instance. + static PowerManagerClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + virtual ~PowerManagerClient(); + + protected: + // Create() should be used instead. + PowerManagerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(PowerManagerClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_POWER_MANAGER_CLIENT_H_ diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc new file mode 100644 index 0000000..b96d2ad --- /dev/null +++ b/chromeos/dbus/session_manager_client.cc @@ -0,0 +1,358 @@ +// 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/session_manager_client.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/string_util.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 { + +// The SessionManagerClient implementation used in production. +class SessionManagerClientImpl : public SessionManagerClient { + public: + explicit SessionManagerClientImpl(dbus::Bus* bus) + : session_manager_proxy_(NULL), + weak_ptr_factory_(this) { + session_manager_proxy_ = bus->GetObjectProxy( + login_manager::kSessionManagerServiceName, + dbus::ObjectPath(login_manager::kSessionManagerServicePath)); + + // Monitor the D-Bus signal for owner key changes. + session_manager_proxy_->ConnectToSignal( + chromium::kChromiumInterface, + chromium::kOwnerKeySetSignal, + base::Bind(&SessionManagerClientImpl::OwnerKeySetReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&SessionManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + + // Monitor the D-Bus signal for property changes. + session_manager_proxy_->ConnectToSignal( + chromium::kChromiumInterface, + chromium::kPropertyChangeCompleteSignal, + base::Bind(&SessionManagerClientImpl::PropertyChangeCompleteReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&SessionManagerClientImpl::SignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual ~SessionManagerClientImpl() { + } + + // SessionManagerClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + observers_.AddObserver(observer); + } + + // SessionManagerClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + observers_.RemoveObserver(observer); + } + + // SessionManagerClient override. + virtual void EmitLoginPromptReady() OVERRIDE { + dbus::MethodCall method_call( + login_manager::kSessionManagerInterface, + login_manager::kSessionManagerEmitLoginPromptReady); + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnEmitLoginPromptReady, + weak_ptr_factory_.GetWeakPtr())); + } + + // SessionManagerClient override. + virtual void EmitLoginPromptVisible() OVERRIDE { + dbus::MethodCall method_call( + login_manager::kSessionManagerInterface, + login_manager::kSessionManagerEmitLoginPromptVisible); + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnEmitLoginPromptVisible, + weak_ptr_factory_.GetWeakPtr())); + } + + // SessionManagerClient override. + virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE { + dbus::MethodCall method_call(login_manager::kSessionManagerInterface, + login_manager::kSessionManagerRestartJob); + dbus::MessageWriter writer(&method_call); + writer.AppendInt32(pid); + writer.AppendString(command_line); + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnRestartJob, + weak_ptr_factory_.GetWeakPtr())); + } + + // SessionManagerClient override. + virtual void RestartEntd() OVERRIDE { + dbus::MethodCall method_call(login_manager::kSessionManagerInterface, + login_manager::kSessionManagerRestartEntd); + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnRestartEntd, + weak_ptr_factory_.GetWeakPtr())); + } + + // SessionManagerClient override. + virtual void StartSession(const std::string& user_email) OVERRIDE { + dbus::MethodCall method_call(login_manager::kSessionManagerInterface, + login_manager::kSessionManagerStartSession); + dbus::MessageWriter writer(&method_call); + writer.AppendString(user_email); + writer.AppendString(""); // Unique ID is deprecated + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnStartSession, + weak_ptr_factory_.GetWeakPtr())); + } + + // SessionManagerClient override. + virtual void StopSession() OVERRIDE { + dbus::MethodCall method_call(login_manager::kSessionManagerInterface, + login_manager::kSessionManagerStopSession); + dbus::MessageWriter writer(&method_call); + writer.AppendString(""); // Unique ID is deprecated + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnStopSession, + weak_ptr_factory_.GetWeakPtr())); + } + + // SessionManagerClient override. + virtual void RetrieveDevicePolicy(RetrievePolicyCallback callback) OVERRIDE { + CallRetrievePolicy(login_manager::kSessionManagerRetrievePolicy, + callback); + } + + // SessionManagerClient override. + virtual void RetrieveUserPolicy(RetrievePolicyCallback callback) OVERRIDE { + CallRetrievePolicy(login_manager::kSessionManagerRetrieveUserPolicy, + callback); + } + + // SessionManagerClient override. + virtual void StoreDevicePolicy(const std::string& policy_blob, + StorePolicyCallback callback) OVERRIDE { + CallStorePolicy(login_manager::kSessionManagerStorePolicy, + policy_blob, callback); + } + + // SessionManagerClient override. + virtual void StoreUserPolicy(const std::string& policy_blob, + StorePolicyCallback callback) OVERRIDE { + CallStorePolicy(login_manager::kSessionManagerStoreUserPolicy, + policy_blob, callback); + } + + private: + // Helper for Retrieve{User,Device}Policy. + virtual void CallRetrievePolicy(const std::string& method_name, + RetrievePolicyCallback callback) { + dbus::MethodCall method_call(login_manager::kSessionManagerInterface, + method_name); + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnRetrievePolicy, + weak_ptr_factory_.GetWeakPtr(), + method_name, + callback)); + } + + // Helper for Store{User,Device}Policy. + virtual void CallStorePolicy(const std::string& method_name, + const std::string& policy_blob, + StorePolicyCallback callback) { + dbus::MethodCall method_call(login_manager::kSessionManagerInterface, + method_name); + dbus::MessageWriter writer(&method_call); + // static_cast does not work due to signedness. + writer.AppendArrayOfBytes( + reinterpret_cast<const uint8*>(policy_blob.data()), policy_blob.size()); + session_manager_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SessionManagerClientImpl::OnStorePolicy, + weak_ptr_factory_.GetWeakPtr(), + method_name, + callback)); + } + + // Called when kSessionManagerEmitLoginPromptReady method is complete. + void OnEmitLoginPromptReady(dbus::Response* response) { + LOG_IF(ERROR, !response) + << "Failed to call " + << login_manager::kSessionManagerEmitLoginPromptReady; + } + + // Called when kSessionManagerEmitLoginPromptVisible method is complete. + void OnEmitLoginPromptVisible(dbus::Response* response) { + LOG_IF(ERROR, !response) + << "Failed to call " + << login_manager::kSessionManagerEmitLoginPromptVisible; + } + + // Called when kSessionManagerRestartJob method is complete. + void OnRestartJob(dbus::Response* response) { + LOG_IF(ERROR, !response) + << "Failed to call " + << login_manager::kSessionManagerRestartJob; + } + + // Called when kSessionManagerRestartEntd method is complete. + void OnRestartEntd(dbus::Response* response) { + LOG_IF(ERROR, !response) + << "Failed to call " + << login_manager::kSessionManagerRestartEntd; + } + + // Called when kSessionManagerStartSession method is complete. + void OnStartSession(dbus::Response* response) { + LOG_IF(ERROR, !response) + << "Failed to call " + << login_manager::kSessionManagerStartSession; + } + + // Called when kSessionManagerStopSession method is complete. + void OnStopSession(dbus::Response* response) { + LOG_IF(ERROR, !response) + << "Failed to call " + << login_manager::kSessionManagerStopSession; + } + + // Called when kSessionManagerRetrievePolicy or + // kSessionManagerRetrieveUserPolicy method is complete. + void OnRetrievePolicy(const std::string& method_name, + RetrievePolicyCallback callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to call " << method_name; + callback.Run(""); + return; + } + dbus::MessageReader reader(response); + uint8* values = NULL; + size_t length = 0; + if (!reader.PopArrayOfBytes(&values, &length)) { + LOG(ERROR) << "Invalid response: " << response->ToString(); + callback.Run(""); + return; + } + // static_cast does not work due to signedness. + std::string serialized_proto(reinterpret_cast<char*>(values), length); + callback.Run(serialized_proto); + } + + // Called when kSessionManagerStorePolicy or kSessionManagerStoreUserPolicy + // method is complete. + void OnStorePolicy(const std::string& method_name, + StorePolicyCallback callback, + dbus::Response* response) { + bool success = false; + if (!response) { + LOG(ERROR) << "Failed to call " << method_name; + } else { + dbus::MessageReader reader(response); + if (!reader.PopBool(&success)) + LOG(ERROR) << "Invalid response: " << response->ToString(); + } + callback.Run(success); + } + + // Called when the owner key set signal is received. + void OwnerKeySetReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string result_string; + if (!reader.PopString(&result_string)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + const bool success = StartsWithASCII(result_string, "success", false); + FOR_EACH_OBSERVER(Observer, observers_, OwnerKeySet(success)); + } + + // Called when the property change complete signal is received. + void PropertyChangeCompleteReceived(dbus::Signal* signal) { + dbus::MessageReader reader(signal); + std::string result_string; + if (!reader.PopString(&result_string)) { + LOG(ERROR) << "Invalid signal: " << signal->ToString(); + return; + } + const bool success = StartsWithASCII(result_string, "success", false); + FOR_EACH_OBSERVER(Observer, observers_, PropertyChangeComplete(success)); + } + + // Called when the object is connected to the signal. + void SignalConnected(const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(ERROR, !success) << "Failed to connect to " << signal_name; + } + + dbus::ObjectProxy* session_manager_proxy_; + ObserverList<Observer> observers_; + base::WeakPtrFactory<SessionManagerClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(SessionManagerClientImpl); +}; + +// The SessionManagerClient implementation used on Linux desktop, +// which does nothing. +class SessionManagerClientStubImpl : public SessionManagerClient { + // SessionManagerClient overrides. + virtual void AddObserver(Observer* observer) OVERRIDE {} + virtual void RemoveObserver(Observer* observer) OVERRIDE {} + virtual void EmitLoginPromptReady() OVERRIDE {} + virtual void EmitLoginPromptVisible() OVERRIDE {} + virtual void RestartJob(int pid, const std::string& command_line) OVERRIDE {} + virtual void RestartEntd() OVERRIDE {} + virtual void StartSession(const std::string& user_email) OVERRIDE {} + virtual void StopSession() OVERRIDE {} + virtual void RetrieveDevicePolicy(RetrievePolicyCallback callback) OVERRIDE { + callback.Run(""); + } + virtual void RetrieveUserPolicy(RetrievePolicyCallback callback) OVERRIDE { + callback.Run(""); + } + virtual void StoreDevicePolicy(const std::string& policy_blob, + StorePolicyCallback callback) OVERRIDE { + callback.Run(true); + } + virtual void StoreUserPolicy(const std::string& policy_blob, + StorePolicyCallback callback) OVERRIDE { + callback.Run(true); + } +}; + +SessionManagerClient::SessionManagerClient() { +} + +SessionManagerClient::~SessionManagerClient() { +} + +SessionManagerClient* SessionManagerClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new SessionManagerClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new SessionManagerClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/session_manager_client.h b/chromeos/dbus/session_manager_client.h new file mode 100644 index 0000000..c6903f9 --- /dev/null +++ b/chromeos/dbus/session_manager_client.h @@ -0,0 +1,101 @@ +// 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. + +#ifndef CHROMEOS_DBUS_SESSION_MANAGER_CLIENT_H_ +#define CHROMEOS_DBUS_SESSION_MANAGER_CLIENT_H_ + +#include "base/callback.h" +#include "base/observer_list.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +#include <string> + +namespace dbus { +class Bus; +} // namespace + +namespace chromeos { + +// SessionManagerClient is used to communicate with the session manager. +class CHROMEOS_EXPORT SessionManagerClient { + public: + // Interface for observing changes from the session manager. + class Observer { + public: + // Called when the owner key is set. + virtual void OwnerKeySet(bool success) {} + // Called when the property change is complete. + virtual void PropertyChangeComplete(bool success) {} + }; + + // Adds and removes the observer. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + + // Kicks off an attempt to emit the "login-prompt-ready" upstart signal. + virtual void EmitLoginPromptReady() = 0; + + // Kicks off an attempt to emit the "login-prompt-visible" upstart signal. + virtual void EmitLoginPromptVisible() = 0; + + // Restarts a job referenced by |pid| with the provided command line. + virtual void RestartJob(int pid, const std::string& command_line) = 0; + + // Restarts entd (the enterprise daemon). + // DEPRECATED: will be deleted soon. + virtual void RestartEntd() = 0; + + // Starts the session for the user. + virtual void StartSession(const std::string& user_email) = 0; + + // Stops the current session. + virtual void StopSession() = 0; + + // Used for RetrieveDevicePolicy and RetrieveUserPolicy. Takes a serialized + // protocol buffer as string. Upon success, we will pass a protobuf to the + // callback. On failure, we will pass "". + typedef base::Callback<void(const std::string&)> RetrievePolicyCallback; + + // Fetches the device policy blob stored by the session manager. Upon + // completion of the retrieve attempt, we will call the provided callback. + virtual void RetrieveDevicePolicy(RetrievePolicyCallback callback) = 0; + + // Fetches the user policy blob stored by the session manager for the + // currently signed-in user. Upon completion of the retrieve attempt, we will + // call the provided callback. + virtual void RetrieveUserPolicy(RetrievePolicyCallback callback) = 0; + + // Used for StoreDevicePolicy and StoreUserPolicy. Takes a boolean indicating + // whether the operation was successful or not. + typedef base::Callback<void(bool)> StorePolicyCallback; + + // Attempts to asynchronously store |policy_blob| as device policy. Upon + // completion of the store attempt, we will call callback. + virtual void StoreDevicePolicy(const std::string& policy_blob, + StorePolicyCallback callback) = 0; + + // Attempts to asynchronously store |policy_blob| as user policy for the + // currently signed-in user. Upon completion of the store attempt, we will + // call callback. + virtual void StoreUserPolicy(const std::string& policy_blob, + StorePolicyCallback callback) = 0; + + // Creates the instance. + static SessionManagerClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + virtual ~SessionManagerClient(); + + protected: + // Create() should be used instead. + SessionManagerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(SessionManagerClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_SESSION_MANAGER_CLIENT_H_ diff --git a/chromeos/dbus/speech_synthesizer_client.cc b/chromeos/dbus/speech_synthesizer_client.cc new file mode 100644 index 0000000..a6a850a --- /dev/null +++ b/chromeos/dbus/speech_synthesizer_client.cc @@ -0,0 +1,137 @@ +// 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/speech_synthesizer_client.h" + +#include "base/bind.h" +#include "base/compiler_specific.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 { + +// TODO(chaitanyag): rename to "locale" after making equivalent change in +// Chrome OS code. +const char SpeechSynthesizerClient::kSpeechPropertyLocale[] = "name"; + +const char SpeechSynthesizerClient::kSpeechPropertyGender[] = "gender"; +const char SpeechSynthesizerClient::kSpeechPropertyRate[] = "rate"; +const char SpeechSynthesizerClient::kSpeechPropertyPitch[] = "pitch"; +const char SpeechSynthesizerClient::kSpeechPropertyVolume[] = "volume"; +const char SpeechSynthesizerClient::kSpeechPropertyEquals[] = "="; +const char SpeechSynthesizerClient::kSpeechPropertyDelimiter[] = ";"; + +class SpeechSynthesizerClientImpl : public SpeechSynthesizerClient { + public: + explicit SpeechSynthesizerClientImpl(dbus::Bus* bus) + : proxy_(NULL), + weak_ptr_factory_(this) { + proxy_ = bus->GetObjectProxy( + speech_synthesis::kSpeechSynthesizerServiceName, + dbus::ObjectPath(speech_synthesis::kSpeechSynthesizerServicePath)); + } + virtual ~SpeechSynthesizerClientImpl() {} + + virtual void Speak(const std::string& text, + const std::string& properties) OVERRIDE { + dbus::MethodCall method_call(speech_synthesis::kSpeechSynthesizerInterface, + speech_synthesis::kSpeak); + dbus::MessageWriter writer(&method_call); + writer.AppendString(text); + writer.AppendString(properties); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SpeechSynthesizerClientImpl::OnSpeak, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual void StopSpeaking() OVERRIDE { + dbus::MethodCall method_call(speech_synthesis::kSpeechSynthesizerInterface, + speech_synthesis::kStop); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SpeechSynthesizerClientImpl::OnStopSpeaking, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual void IsSpeaking(const IsSpeakingCallback& callback) OVERRIDE { + dbus::MethodCall method_call(speech_synthesis::kSpeechSynthesizerInterface, + speech_synthesis::kIsSpeaking); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&SpeechSynthesizerClientImpl::OnIsSpeaking, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + private: + // Called when a response for Speak() is received + void OnSpeak(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to speak."; + return; + } + VLOG(1) << "Spoke: " << response->ToString(); + } + + // Called when a response for StopSpeaking() is received + void OnStopSpeaking(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to stop speaking."; + return; + } + VLOG(1) << "Stopped speaking: " << response->ToString(); + } + + // Called when a response for IsSpeaking() is received + void OnIsSpeaking(const IsSpeakingCallback& callback, + dbus::Response* response) { + bool value = false; + if (response) { + dbus::MessageReader reader(response); + reader.PopBool(&value); + } else { + LOG(ERROR) << "Failed to ask if it is speaking"; + } + callback.Run(value); + } + + dbus::ObjectProxy* proxy_; + base::WeakPtrFactory<SpeechSynthesizerClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(SpeechSynthesizerClientImpl); +}; + +class SpeechSynthesizerClientStubImpl : public SpeechSynthesizerClient { + public: + SpeechSynthesizerClientStubImpl() {} + virtual ~SpeechSynthesizerClientStubImpl() {} + virtual void Speak(const std::string& text, + const std::string& properties) OVERRIDE {} + virtual void StopSpeaking() OVERRIDE {} + virtual void IsSpeaking(const IsSpeakingCallback& callback) OVERRIDE { + callback.Run(false); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SpeechSynthesizerClientStubImpl); +}; + +SpeechSynthesizerClient::SpeechSynthesizerClient() { +} + +SpeechSynthesizerClient::~SpeechSynthesizerClient() { +} + +// static +SpeechSynthesizerClient* SpeechSynthesizerClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new SpeechSynthesizerClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new SpeechSynthesizerClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/speech_synthesizer_client.h b/chromeos/dbus/speech_synthesizer_client.h new file mode 100644 index 0000000..0ca93dce5 --- /dev/null +++ b/chromeos/dbus/speech_synthesizer_client.h @@ -0,0 +1,69 @@ +// 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. + +#ifndef CHROMEOS_DBUS_SPEECH_SYNTHESIZER_CLIENT_H_ +#define CHROMEOS_DBUS_SPEECH_SYNTHESIZER_CLIENT_H_ +#pragma once + +#include <string> + +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +namespace dbus { +class Bus; +} + +namespace chromeos { + +// SpeechSynthesizerClient is used to communicate with the speech synthesizer. +// All method should be called from the origin thread (UI thread) which +// initializes the DBusThreadManager instance. +class CHROMEOS_EXPORT SpeechSynthesizerClient { + public: + // A callback function called when the result of IsSpeaking is ready. + // The argument indicates if the speech synthesizer is speaking or not. + typedef base::Callback<void(bool)> IsSpeakingCallback; + + virtual ~SpeechSynthesizerClient(); + + // Speaks the specified text with properties. + // Use the constants below for properties. + // An example of |properties|: "rate=1.0 pitch=1.0" + virtual void Speak(const std::string& text, + const std::string& properties) = 0; + + // Stops speaking the current utterance. + virtual void StopSpeaking() = 0; + + // Checks if the engine is currently speaking. + // |callback| will be called on the origin thread later with the result. + virtual void IsSpeaking(const IsSpeakingCallback& callback) = 0; + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static SpeechSynthesizerClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + // Constants to be used with the properties argument to Speak. + static const char kSpeechPropertyLocale[]; + static const char kSpeechPropertyGender[]; + static const char kSpeechPropertyRate[]; + static const char kSpeechPropertyPitch[]; + static const char kSpeechPropertyVolume[]; + static const char kSpeechPropertyEquals[]; + static const char kSpeechPropertyDelimiter[]; + + protected: + // Create() should be used instead. + SpeechSynthesizerClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(SpeechSynthesizerClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_SPEECH_SYNTHESIZER_CLIENT_H_ diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc new file mode 100644 index 0000000..55f5c68 --- /dev/null +++ b/chromeos/dbus/update_engine_client.cc @@ -0,0 +1,290 @@ +// 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/update_engine_client.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/string_util.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 { +namespace { + +// Returns UPDATE_STATUS_ERROR on error. +UpdateEngineClient::UpdateStatusOperation UpdateStatusFromString( + const std::string& str) { + if (str == "UPDATE_STATUS_IDLE") + return UpdateEngineClient::UPDATE_STATUS_IDLE; + if (str == "UPDATE_STATUS_CHECKING_FOR_UPDATE") + return UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE; + if (str == "UPDATE_STATUS_UPDATE_AVAILABLE") + return UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE; + if (str == "UPDATE_STATUS_DOWNLOADING") + return UpdateEngineClient::UPDATE_STATUS_DOWNLOADING; + if (str == "UPDATE_STATUS_VERIFYING") + return UpdateEngineClient::UPDATE_STATUS_VERIFYING; + if (str == "UPDATE_STATUS_FINALIZING") + return UpdateEngineClient::UPDATE_STATUS_FINALIZING; + if (str == "UPDATE_STATUS_UPDATED_NEED_REBOOT") + return UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT; + if (str == "UPDATE_STATUS_REPORTING_ERROR_EVENT") + return UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT; + return UpdateEngineClient::UPDATE_STATUS_ERROR; +} + +// Used in UpdateEngineClient::EmptyUpdateCheckCallback(). +void EmptyUpdateCheckCallbackBody( + UpdateEngineClient::UpdateCheckResult unused_result) { +} + +} // namespace + +// The UpdateEngineClient implementation used in production. +class UpdateEngineClientImpl : public UpdateEngineClient { + public: + explicit UpdateEngineClientImpl(dbus::Bus* bus) + : update_engine_proxy_(NULL), + weak_ptr_factory_(this), + last_status_() { + update_engine_proxy_ = bus->GetObjectProxy( + update_engine::kUpdateEngineServiceName, + dbus::ObjectPath(update_engine::kUpdateEngineServicePath)); + + // Monitor the D-Bus signal for brightness changes. Only the power + // manager knows the actual brightness level. We don't cache the + // brightness level in Chrome as it will make things less reliable. + update_engine_proxy_->ConnectToSignal( + update_engine::kUpdateEngineInterface, + update_engine::kStatusUpdate, + base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&UpdateEngineClientImpl::StatusUpdateConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual ~UpdateEngineClientImpl() { + } + + // UpdateEngineClient override. + virtual void AddObserver(Observer* observer) OVERRIDE { + observers_.AddObserver(observer); + } + + // UpdateEngineClient override. + virtual void RemoveObserver(Observer* observer) OVERRIDE { + observers_.RemoveObserver(observer); + } + + // UpdateEngineClient override. + virtual bool HasObserver(Observer* observer) OVERRIDE { + return observers_.HasObserver(observer); + } + + // UpdateEngineClient override. + virtual void RequestUpdateCheck(UpdateCheckCallback callback) OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kAttemptUpdate); + dbus::MessageWriter writer(&method_call); + writer.AppendString(""); // Unused. + writer.AppendString(""); // Unused. + + VLOG(1) << "Requesting an update check"; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnRequestUpdateCheck, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // UpdateEngineClient override. + virtual void RebootAfterUpdate() OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kRebootIfNeeded); + + VLOG(1) << "Requesting a reboot"; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnRebootAfterUpdate, + weak_ptr_factory_.GetWeakPtr())); + } + + // UpdateEngineClient override. + virtual void SetReleaseTrack(const std::string& track) OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kSetTrack); + dbus::MessageWriter writer(&method_call); + writer.AppendString(track); + + VLOG(1) << "Requesting to set the release track to " << track; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnSetReleaseTrack, + weak_ptr_factory_.GetWeakPtr())); + } + + // UpdateEngineClient override. + virtual void GetReleaseTrack(GetReleaseTrackCallback callback) OVERRIDE { + dbus::MethodCall method_call( + update_engine::kUpdateEngineInterface, + update_engine::kGetTrack); + + VLOG(1) << "Requesting to get the current release track"; + update_engine_proxy_->CallMethod( + &method_call, + dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&UpdateEngineClientImpl::OnGetReleaseTrack, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // UpdateEngineClient override. + virtual Status GetLastStatus() OVERRIDE { + return last_status_; + } + + private: + // Called when a response for RequestUpdateCheck() is received. + void OnRequestUpdateCheck(UpdateCheckCallback callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request update check"; + callback.Run(UPDATE_RESULT_FAILED); + return; + } + callback.Run(UPDATE_RESULT_SUCCESS); + } + + // Called when a response for RebootAfterUpdate() is received. + void OnRebootAfterUpdate(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request rebooting after update"; + return; + } + } + + // Called when a response for SetReleaseTrack() is received. + void OnSetReleaseTrack(dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request setting release track"; + return; + } + } + + // Called when a response for GetReleaseTrack() is received. + void OnGetReleaseTrack(GetReleaseTrackCallback callback, + dbus::Response* response) { + if (!response) { + LOG(ERROR) << "Failed to request getting release track"; + callback.Run(""); + return; + } + dbus::MessageReader reader(response); + std::string release_track; + if (!reader.PopString(&release_track)) { + LOG(ERROR) << "Incorrect response: " << response->ToString(); + callback.Run(""); + return; + } + VLOG(1) << "The current release track received: " << release_track; + callback.Run(release_track); + } + + // Called when a status update signal is received. + void StatusUpdateReceived(dbus::Signal* signal) { + VLOG(1) << "Status update signal received: " << signal->ToString(); + dbus::MessageReader reader(signal); + int64 last_checked_time = 0; + double progress = 0.0; + std::string current_operation; + std::string new_version; + int64_t new_size = 0; + if (!(reader.PopInt64(&last_checked_time) && + reader.PopDouble(&progress) && + reader.PopString(¤t_operation) && + reader.PopString(&new_version) && + reader.PopInt64(&new_size))) { + LOG(ERROR) << "Status changed signal had incorrect parameters: " + << signal->ToString(); + return; + } + Status status; + status.last_checked_time = last_checked_time; + status.download_progress = progress; + status.status = UpdateStatusFromString(current_operation); + status.new_version = new_version; + status.new_size = new_size; + + last_status_ = status; + FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status)); + } + + // Called when the status update signal is initially connected. + void StatusUpdateConnected(const std::string& interface_name, + const std::string& signal_name, + bool success) { + LOG_IF(WARNING, !success) + << "Failed to connect to status updated signal."; + } + + dbus::ObjectProxy* update_engine_proxy_; + ObserverList<Observer> observers_; + base::WeakPtrFactory<UpdateEngineClientImpl> weak_ptr_factory_; + Status last_status_; + + DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientImpl); +}; + +// The UpdateEngineClient implementation used on Linux desktop, +// which does nothing. +class UpdateEngineClientStubImpl : public UpdateEngineClient { + // UpdateEngineClient overrides. + virtual void AddObserver(Observer* observer) OVERRIDE {} + virtual void RemoveObserver(Observer* observer) OVERRIDE {} + virtual bool HasObserver(Observer* observer) OVERRIDE { return false; } + + virtual void RequestUpdateCheck(UpdateCheckCallback callback) OVERRIDE { + callback.Run(UPDATE_RESULT_NOTIMPLEMENTED); + } + virtual void RebootAfterUpdate() OVERRIDE {} + virtual void SetReleaseTrack(const std::string& track) OVERRIDE {} + virtual void GetReleaseTrack(GetReleaseTrackCallback callback) OVERRIDE { + callback.Run("beta-channel"); + } + virtual Status GetLastStatus() OVERRIDE { return Status(); } +}; + +UpdateEngineClient::UpdateEngineClient() { +} + +UpdateEngineClient::~UpdateEngineClient() { +} + +// static +UpdateEngineClient::UpdateCheckCallback +UpdateEngineClient::EmptyUpdateCheckCallback() { + return base::Bind(&EmptyUpdateCheckCallbackBody); +} + +// static +UpdateEngineClient* UpdateEngineClient::Create( + DBusClientImplementationType type, + dbus::Bus* bus) { + if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) + return new UpdateEngineClientImpl(bus); + DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); + return new UpdateEngineClientStubImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/update_engine_client.h b/chromeos/dbus/update_engine_client.h new file mode 100644 index 0000000..7d1692d --- /dev/null +++ b/chromeos/dbus/update_engine_client.h @@ -0,0 +1,126 @@ +// 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. + +#ifndef CHROMEOS_DBUS_UPDATE_ENGINE_CLIENT_H_ +#define CHROMEOS_DBUS_UPDATE_ENGINE_CLIENT_H_ + +#include "base/callback.h" +#include "base/observer_list.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client_implementation_type.h" + +#include <string> + +namespace dbus { +class Bus; +} // namespace + +namespace chromeos { + +// UpdateEngineClient is used to communicate with the update engine. +class CHROMEOS_EXPORT UpdateEngineClient { + public: + // Edges for state machine + // IDLE->CHECKING_FOR_UPDATE + // CHECKING_FOR_UPDATE->IDLE + // CHECKING_FOR_UPDATE->UPDATE_AVAILABLE + // ... + // FINALIZING->UPDATE_NEED_REBOOT + // Any state can transition to REPORTING_ERROR_EVENT and then on to IDLE. + enum UpdateStatusOperation { + UPDATE_STATUS_ERROR = -1, + UPDATE_STATUS_IDLE = 0, + UPDATE_STATUS_CHECKING_FOR_UPDATE, + UPDATE_STATUS_UPDATE_AVAILABLE, + UPDATE_STATUS_DOWNLOADING, + UPDATE_STATUS_VERIFYING, + UPDATE_STATUS_FINALIZING, + UPDATE_STATUS_UPDATED_NEED_REBOOT, + UPDATE_STATUS_REPORTING_ERROR_EVENT + }; + + // The status of the ongoing update attempt. + struct Status { + Status() : status(UPDATE_STATUS_IDLE), + download_progress(0.0), + last_checked_time(0), + new_size(0) { + } + + UpdateStatusOperation status; + double download_progress; // 0.0 - 1.0 + int64_t last_checked_time; // As reported by std::time(). + std::string new_version; + int64_t new_size; // Valid during DOWNLOADING, in bytes. + }; + + // The result code used for RequestUpdateCheck(). + enum UpdateCheckResult { + UPDATE_RESULT_SUCCESS, + UPDATE_RESULT_FAILED, + UPDATE_RESULT_NOTIMPLEMENTED, + }; + + // Interface for observing changes from the update engine. + class Observer { + public: + // Called when the status is updated. + virtual void UpdateStatusChanged(const Status& status) {} + }; + + virtual ~UpdateEngineClient(); + + // Adds and removes the observer. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + // Returns true if this object has the given observer. + virtual bool HasObserver(Observer* observer) = 0; + + // Called once RequestUpdateCheck() is complete. Takes one parameter: + // - UpdateCheckResult: the result of the update check. + typedef base::Callback<void(UpdateCheckResult)> UpdateCheckCallback; + + // Requests an update check and calls |callback| when completed. + virtual void RequestUpdateCheck(UpdateCheckCallback callback) = 0; + + // Reboots if update has been performed. + virtual void RebootAfterUpdate() = 0; + + // Requests to set the release track (channel). |track| should look like + // "beta-channel" or "dev-channel". + virtual void SetReleaseTrack(const std::string& track) = 0; + + // Called once GetReleaseTrack() is complete. Takes one parameter; + // - string: the release track name like "beta-channel". + typedef base::Callback<void(const std::string&)> GetReleaseTrackCallback; + + // Requests to get the release track and calls |callback| with the + // release track (channel). On error, calls |callback| with an empty + // string. + virtual void GetReleaseTrack(GetReleaseTrackCallback callback) = 0; + + // Returns the last status the object received from the update engine. + // + // Ideally, the D-Bus client should be state-less, but there are clients + // that need this information. + virtual Status GetLastStatus() = 0; + + // Returns an empty UpdateCheckCallback that does nothing. + static UpdateCheckCallback EmptyUpdateCheckCallback(); + + // Creates the instance. + static UpdateEngineClient* Create(DBusClientImplementationType type, + dbus::Bus* bus); + + protected: + // Create() should be used instead. + UpdateEngineClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(UpdateEngineClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_UPDATE_ENGINE_CLIENT_H_ |