summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-06 01:54:36 +0000
committerhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-06 01:54:36 +0000
commit64e199254481d6132c3a7ccdf9b3a743bff86a88 (patch)
treec10cdf03cbde8439d1d8a7070a6c7f9fdf10f517 /chromeos
parent81a476c9ce1088345db02cf1647399d0e673d487 (diff)
downloadchromium_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')
-rw-r--r--chromeos/chromeos.gyp159
-rw-r--r--chromeos/dbus/DEPS3
-rw-r--r--chromeos/dbus/blocking_method_caller.cc67
-rw-r--r--chromeos/dbus/blocking_method_caller.h46
-rw-r--r--chromeos/dbus/blocking_method_caller_unittest.cc125
-rw-r--r--chromeos/dbus/bluetooth_adapter_client.cc809
-rw-r--r--chromeos/dbus/bluetooth_adapter_client.h244
-rw-r--r--chromeos/dbus/bluetooth_agent_service_provider.cc568
-rw-r--r--chromeos/dbus/bluetooth_agent_service_provider.h179
-rw-r--r--chromeos/dbus/bluetooth_device_client.cc539
-rw-r--r--chromeos/dbus/bluetooth_device_client.h212
-rw-r--r--chromeos/dbus/bluetooth_input_client.cc264
-rw-r--r--chromeos/dbus/bluetooth_input_client.h96
-rw-r--r--chromeos/dbus/bluetooth_manager_client.cc316
-rw-r--r--chromeos/dbus/bluetooth_manager_client.h100
-rw-r--r--chromeos/dbus/bluetooth_node_client.cc201
-rw-r--r--chromeos/dbus/bluetooth_node_client.h82
-rw-r--r--chromeos/dbus/bluetooth_property.cc43
-rw-r--r--chromeos/dbus/bluetooth_property.h96
-rw-r--r--chromeos/dbus/cashew_client.cc134
-rw-r--r--chromeos/dbus/cashew_client.h65
-rw-r--r--chromeos/dbus/cros_disks_client.cc566
-rw-r--r--chromeos/dbus/cros_disks_client.h233
-rw-r--r--chromeos/dbus/cryptohome_client.cc638
-rw-r--r--chromeos/dbus/cryptohome_client.h179
-rw-r--r--chromeos/dbus/dbus_client_implementation_type.h18
-rw-r--r--chromeos/dbus/dbus_method_call_status.h18
-rw-r--r--chromeos/dbus/dbus_thread_manager.cc279
-rw-r--r--chromeos/dbus/dbus_thread_manager.h181
-rw-r--r--chromeos/dbus/debug_daemon_client.cc277
-rw-r--r--chromeos/dbus/debug_daemon_client.h53
-rw-r--r--chromeos/dbus/flimflam_client_helper.cc111
-rw-r--r--chromeos/dbus/flimflam_client_helper.h94
-rw-r--r--chromeos/dbus/flimflam_client_unittest_base.cc173
-rw-r--r--chromeos/dbus/flimflam_client_unittest_base.h123
-rw-r--r--chromeos/dbus/flimflam_ipconfig_client.cc204
-rw-r--r--chromeos/dbus/flimflam_ipconfig_client.h83
-rw-r--r--chromeos/dbus/flimflam_network_client.cc93
-rw-r--r--chromeos/dbus/flimflam_network_client.h67
-rw-r--r--chromeos/dbus/flimflam_network_client_unittest.cc124
-rw-r--r--chromeos/dbus/flimflam_profile_client.cc165
-rw-r--r--chromeos/dbus/flimflam_profile_client.h79
-rw-r--r--chromeos/dbus/image_burner_client.cc166
-rw-r--r--chromeos/dbus/image_burner_client.h74
-rw-r--r--chromeos/dbus/introspectable_client.cc117
-rw-r--r--chromeos/dbus/introspectable_client.h58
-rw-r--r--chromeos/dbus/mock_bluetooth_adapter_client.cc13
-rw-r--r--chromeos/dbus/mock_bluetooth_adapter_client.h59
-rw-r--r--chromeos/dbus/mock_bluetooth_device_client.cc13
-rw-r--r--chromeos/dbus/mock_bluetooth_device_client.h40
-rw-r--r--chromeos/dbus/mock_bluetooth_input_client.cc13
-rw-r--r--chromeos/dbus/mock_bluetooth_input_client.h31
-rw-r--r--chromeos/dbus/mock_bluetooth_manager_client.cc13
-rw-r--r--chromeos/dbus/mock_bluetooth_manager_client.h30
-rw-r--r--chromeos/dbus/mock_bluetooth_node_client.cc13
-rw-r--r--chromeos/dbus/mock_bluetooth_node_client.h27
-rw-r--r--chromeos/dbus/mock_cashew_client.cc13
-rw-r--r--chromeos/dbus/mock_cashew_client.h26
-rw-r--r--chromeos/dbus/mock_cros_disks_client.cc13
-rw-r--r--chromeos/dbus/mock_cros_disks_client.h37
-rw-r--r--chromeos/dbus/mock_cryptohome_client.cc13
-rw-r--r--chromeos/dbus/mock_cryptohome_client.h70
-rw-r--r--chromeos/dbus/mock_dbus_thread_manager.cc113
-rw-r--r--chromeos/dbus/mock_dbus_thread_manager.h148
-rw-r--r--chromeos/dbus/mock_debug_daemon_client.cc13
-rw-r--r--chromeos/dbus/mock_debug_daemon_client.h25
-rw-r--r--chromeos/dbus/mock_flimflam_ipconfig_client.cc13
-rw-r--r--chromeos/dbus/mock_flimflam_ipconfig_client.h33
-rw-r--r--chromeos/dbus/mock_flimflam_network_client.cc13
-rw-r--r--chromeos/dbus/mock_flimflam_network_client.h26
-rw-r--r--chromeos/dbus/mock_flimflam_profile_client.cc13
-rw-r--r--chromeos/dbus/mock_flimflam_profile_client.h32
-rw-r--r--chromeos/dbus/mock_image_burner_client.cc13
-rw-r--r--chromeos/dbus/mock_image_burner_client.h31
-rw-r--r--chromeos/dbus/mock_introspectable_client.cc13
-rw-r--r--chromeos/dbus/mock_introspectable_client.h25
-rw-r--r--chromeos/dbus/mock_power_manager_client.cc13
-rw-r--r--chromeos/dbus/mock_power_manager_client.h46
-rw-r--r--chromeos/dbus/mock_session_manager_client.cc14
-rw-r--r--chromeos/dbus/mock_session_manager_client.h38
-rw-r--r--chromeos/dbus/mock_speech_synthesizer_client.cc13
-rw-r--r--chromeos/dbus/mock_speech_synthesizer_client.h27
-rw-r--r--chromeos/dbus/mock_update_engine_client.cc13
-rw-r--r--chromeos/dbus/mock_update_engine_client.h32
-rw-r--r--chromeos/dbus/power_manager_client.cc616
-rw-r--r--chromeos/dbus/power_manager_client.h183
-rw-r--r--chromeos/dbus/session_manager_client.cc358
-rw-r--r--chromeos/dbus/session_manager_client.h101
-rw-r--r--chromeos/dbus/speech_synthesizer_client.cc137
-rw-r--r--chromeos/dbus/speech_synthesizer_client.h69
-rw-r--r--chromeos/dbus/update_engine_client.cc290
-rw-r--r--chromeos/dbus/update_engine_client.h126
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(&timestamp_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(&current_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_