Commit 09afcec7 authored by Harry Cutts's avatar Harry Cutts Committed by Commit Bot

Add `GetProperty` to gesture props D-Bus service

See go/cros-gesture-properties-dbus-design (Google internal only, sorry)
for more details about the full design.

Bug: 952054
Test: call the `GetProperty` method with this command (substituting a
valid device ID):
    dbus-send --print-reply --system \
	--dest=org.chromium.GesturePropertiesService \
	/org/chromium/GesturePropertiesService \
	org.chromium.GesturePropertiesServiceInterface.GetProperty \
	int32:"$DEVICE_ID" string:"Log Path"

Change-Id: I4b663486cf22a50f9e46611e50d35da287099fcd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1589449
Commit-Queue: Harry Cutts <hcutts@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#678448}
parent c856ab97
...@@ -39,6 +39,12 @@ void GesturePropertiesServiceProvider::Start( ...@@ -39,6 +39,12 @@ void GesturePropertiesServiceProvider::Start(
base::BindRepeating(&GesturePropertiesServiceProvider::ListProperties, base::BindRepeating(&GesturePropertiesServiceProvider::ListProperties,
weak_ptr_factory_.GetWeakPtr()), weak_ptr_factory_.GetWeakPtr()),
on_exported); on_exported);
exported_object->ExportMethod(
chromeos::kGesturePropertiesServiceInterface,
chromeos::kGesturePropertiesServiceGetPropertyMethod,
base::BindRepeating(&GesturePropertiesServiceProvider::GetProperty,
weak_ptr_factory_.GetWeakPtr()),
on_exported);
} }
void GesturePropertiesServiceProvider::OnExported( void GesturePropertiesServiceProvider::OnExported(
...@@ -51,6 +57,78 @@ void GesturePropertiesServiceProvider::OnExported( ...@@ -51,6 +57,78 @@ void GesturePropertiesServiceProvider::OnExported(
namespace { namespace {
void GetPropertyCallback(
dbus::MethodCall* method_call,
std::unique_ptr<dbus::Response> response,
const dbus::ExportedObject::ResponseSender& response_sender,
bool is_read_only,
ui::ozone::mojom::GesturePropValuePtr values) {
if (values.is_null()) {
response_sender.Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_INVALID_ARGS,
"The device ID or property name specified was not found."));
return;
}
dbus::MessageWriter writer(response.get());
dbus::MessageWriter variant_writer(nullptr);
dbus::MessageWriter array_writer(nullptr);
writer.AppendBool(is_read_only);
switch (values->which()) {
case ui::ozone::mojom::GesturePropValue::Tag::INTS: {
writer.AppendUint32(values->get_ints().size());
writer.OpenVariant("ai", &variant_writer);
variant_writer.AppendArrayOfInt32s(values->get_ints().data(),
values->get_ints().size());
writer.CloseContainer(&variant_writer);
break;
}
case ui::ozone::mojom::GesturePropValue::Tag::SHORTS: {
writer.AppendUint32(values->get_shorts().size());
writer.OpenVariant("an", &variant_writer);
variant_writer.OpenArray("n", &array_writer);
for (int16_t value : values->get_shorts()) {
array_writer.AppendInt16(value);
}
variant_writer.CloseContainer(&array_writer);
writer.CloseContainer(&variant_writer);
break;
}
case ui::ozone::mojom::GesturePropValue::Tag::BOOLS: {
writer.AppendUint32(values->get_bools().size());
writer.OpenVariant("ab", &variant_writer);
variant_writer.OpenArray("b", &array_writer);
for (bool value : values->get_bools()) {
array_writer.AppendBool(value);
}
variant_writer.CloseContainer(&array_writer);
writer.CloseContainer(&variant_writer);
break;
}
case ui::ozone::mojom::GesturePropValue::Tag::STR: {
writer.AppendUint32(1);
writer.AppendVariantOfString(values->get_str());
break;
}
case ui::ozone::mojom::GesturePropValue::Tag::REALS: {
writer.AppendUint32(values->get_reals().size());
writer.OpenVariant("ad", &variant_writer);
variant_writer.AppendArrayOfDoubles(values->get_reals().data(),
values->get_reals().size());
writer.CloseContainer(&variant_writer);
break;
}
default: {
// This should never happen.
LOG(WARNING) << "No value set on GesturePropValue union; not returning "
"values to GetProperty call.";
writer.AppendUint32(0);
break;
}
}
response_sender.Run(std::move(response));
}
void ListDevicesCallback( void ListDevicesCallback(
std::unique_ptr<dbus::Response> response, std::unique_ptr<dbus::Response> response,
const dbus::ExportedObject::ResponseSender& response_sender, const dbus::ExportedObject::ResponseSender& response_sender,
...@@ -112,6 +190,30 @@ void GesturePropertiesServiceProvider::ListProperties( ...@@ -112,6 +190,30 @@ void GesturePropertiesServiceProvider::ListProperties(
response_sender)); response_sender));
} }
void GesturePropertiesServiceProvider::GetProperty(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
dbus::MessageReader reader(method_call);
int32_t device_id;
std::string property_name;
if (!reader.PopInt32(&device_id) || !reader.PopString(&property_name)) {
response_sender.Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_INVALID_ARGS,
"The device ID (int32) and/or property name (string) is missing."));
return;
}
std::unique_ptr<dbus::Response> response =
dbus::Response::FromMethodCall(method_call);
GetService()->GetProperty(
device_id, property_name,
base::BindOnce(&GetPropertyCallback, method_call, std::move(response),
response_sender));
}
ui::ozone::mojom::GesturePropertiesService* ui::ozone::mojom::GesturePropertiesService*
GesturePropertiesServiceProvider::GetService() { GesturePropertiesServiceProvider::GetService() {
if (service_for_test_ != nullptr) if (service_for_test_ != nullptr)
......
...@@ -55,6 +55,10 @@ class ASH_EXPORT GesturePropertiesServiceProvider ...@@ -55,6 +55,10 @@ class ASH_EXPORT GesturePropertiesServiceProvider
void ListProperties(dbus::MethodCall* method_call, void ListProperties(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender); dbus::ExportedObject::ResponseSender response_sender);
// Called on UI thread in response to a D-Bus request.
void GetProperty(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
ui::ozone::mojom::GesturePropertiesService* GetService(); ui::ozone::mojom::GesturePropertiesService* GetService();
ui::ozone::mojom::GesturePropertiesServicePtr service_; ui::ozone::mojom::GesturePropertiesServicePtr service_;
......
...@@ -21,6 +21,18 @@ namespace ash { ...@@ -21,6 +21,18 @@ namespace ash {
namespace { namespace {
bool expect_bool(dbus::MessageReader* reader) {
bool result;
EXPECT_TRUE(reader->PopBool(&result));
return result;
}
int16_t expect_int16(dbus::MessageReader* reader) {
int16_t result;
EXPECT_TRUE(reader->PopInt16(&result));
return result;
}
uint32_t expect_uint32(dbus::MessageReader* reader) { uint32_t expect_uint32(dbus::MessageReader* reader) {
uint32_t result; uint32_t result;
EXPECT_TRUE(reader->PopUint32(&result)); EXPECT_TRUE(reader->PopUint32(&result));
...@@ -39,6 +51,12 @@ std::string expect_string(dbus::MessageReader* reader) { ...@@ -39,6 +51,12 @@ std::string expect_string(dbus::MessageReader* reader) {
return result; return result;
} }
double expect_double(dbus::MessageReader* reader) {
double result;
EXPECT_TRUE(reader->PopDouble(&result));
return result;
}
} // namespace } // namespace
class GesturePropertiesServiceProviderTest : public testing::Test { class GesturePropertiesServiceProviderTest : public testing::Test {
...@@ -52,7 +70,9 @@ class GesturePropertiesServiceProviderTest : public testing::Test { ...@@ -52,7 +70,9 @@ class GesturePropertiesServiceProviderTest : public testing::Test {
ON_CALL(*mock_service_, ListProperties(_, _)) ON_CALL(*mock_service_, ListProperties(_, _))
.WillByDefault(Invoke( .WillByDefault(Invoke(
this, &GesturePropertiesServiceProviderTest::FakeListProperties)); this, &GesturePropertiesServiceProviderTest::FakeListProperties));
ON_CALL(*mock_service_, GetProperty(_, _, _))
.WillByDefault(Invoke(
this, &GesturePropertiesServiceProviderTest::FakeGetProperty));
service_provider_ = std::make_unique<GesturePropertiesServiceProvider>(); service_provider_ = std::make_unique<GesturePropertiesServiceProvider>();
service_provider_->set_service_for_test(mock_service_.get()); service_provider_->set_service_for_test(mock_service_.get());
} }
...@@ -72,6 +92,15 @@ class GesturePropertiesServiceProviderTest : public testing::Test { ...@@ -72,6 +92,15 @@ class GesturePropertiesServiceProviderTest : public testing::Test {
std::move(callback).Run(list_properties_response_); std::move(callback).Run(list_properties_response_);
} }
void FakeGetProperty(
Unused,
Unused,
ui::ozone::mojom::GesturePropertiesService::GetPropertyCallback
callback) {
std::move(callback).Run(get_property_read_only_,
std::move(get_property_response_));
}
protected: protected:
void CallDBusMethod(std::string name, void CallDBusMethod(std::string name,
dbus::MethodCall* method_call, dbus::MethodCall* method_call,
...@@ -92,6 +121,19 @@ class GesturePropertiesServiceProviderTest : public testing::Test { ...@@ -92,6 +121,19 @@ class GesturePropertiesServiceProviderTest : public testing::Test {
CallDBusMethod(name, std::move(method_call), response); CallDBusMethod(name, std::move(method_call), response);
} }
void CallGetProperty(int32_t device_id,
std::string name,
std::unique_ptr<dbus::Response>& response) {
dbus::MethodCall* method_call = new dbus::MethodCall(
chromeos::kGesturePropertiesServiceInterface,
chromeos::kGesturePropertiesServiceGetPropertyMethod);
dbus::MessageWriter writer(method_call);
writer.AppendInt32(device_id);
writer.AppendString(name);
CallDBusMethod(chromeos::kGesturePropertiesServiceGetPropertyMethod,
std::move(method_call), response);
}
void CheckMethodErrorsWithNoParameters(std::string name) { void CheckMethodErrorsWithNoParameters(std::string name) {
std::unique_ptr<dbus::Response> response = nullptr; std::unique_ptr<dbus::Response> response = nullptr;
CallWithoutParameters(name, response); CallWithoutParameters(name, response);
...@@ -100,6 +142,8 @@ class GesturePropertiesServiceProviderTest : public testing::Test { ...@@ -100,6 +142,8 @@ class GesturePropertiesServiceProviderTest : public testing::Test {
base::flat_map<int, std::string> list_devices_response_ = {}; base::flat_map<int, std::string> list_devices_response_ = {};
std::vector<std::string> list_properties_response_ = {}; std::vector<std::string> list_properties_response_ = {};
bool get_property_read_only_ = true;
ui::ozone::mojom::GesturePropValuePtr get_property_response_ = nullptr;
std::unique_ptr<MockGesturePropertiesService> mock_service_; std::unique_ptr<MockGesturePropertiesService> mock_service_;
...@@ -203,4 +247,126 @@ TEST_F(GesturePropertiesServiceProviderTest, ListPropertiesMissingParameter) { ...@@ -203,4 +247,126 @@ TEST_F(GesturePropertiesServiceProviderTest, ListPropertiesMissingParameter) {
chromeos::kGesturePropertiesServiceListPropertiesMethod); chromeos::kGesturePropertiesServiceListPropertiesMethod);
} }
TEST_F(GesturePropertiesServiceProviderTest, GetPropertySuccessInts) {
get_property_read_only_ = false;
get_property_response_ =
ui::ozone::mojom::GesturePropValue::NewInts({1, 2, 4});
EXPECT_CALL(*mock_service_, GetProperty(4, "prop 1", _));
std::unique_ptr<dbus::Response> response = nullptr;
CallGetProperty(4, "prop 1", response);
dbus::MessageReader reader(response.get());
EXPECT_EQ(false, expect_bool(&reader));
EXPECT_EQ(3u, expect_uint32(&reader));
dbus::MessageReader variant_reader(nullptr);
ASSERT_TRUE(reader.PopVariant(&variant_reader));
dbus::MessageReader array_reader(nullptr);
ASSERT_TRUE(variant_reader.PopArray(&array_reader));
EXPECT_EQ(1, expect_int32(&array_reader));
EXPECT_EQ(2, expect_int32(&array_reader));
EXPECT_EQ(4, expect_int32(&array_reader));
EXPECT_FALSE(array_reader.HasMoreData());
EXPECT_FALSE(reader.HasMoreData());
}
TEST_F(GesturePropertiesServiceProviderTest, GetPropertySuccessShorts) {
get_property_read_only_ = false;
get_property_response_ =
ui::ozone::mojom::GesturePropValue::NewShorts({1, 2, 4});
EXPECT_CALL(*mock_service_, GetProperty(4, "prop 1", _));
std::unique_ptr<dbus::Response> response = nullptr;
CallGetProperty(4, "prop 1", response);
dbus::MessageReader reader(response.get());
EXPECT_EQ(false, expect_bool(&reader));
EXPECT_EQ(3u, expect_uint32(&reader));
dbus::MessageReader variant_reader(nullptr);
ASSERT_TRUE(reader.PopVariant(&variant_reader));
dbus::MessageReader array_reader(nullptr);
ASSERT_TRUE(variant_reader.PopArray(&array_reader));
EXPECT_EQ(1, expect_int16(&array_reader));
EXPECT_EQ(2, expect_int16(&array_reader));
EXPECT_EQ(4, expect_int16(&array_reader));
EXPECT_FALSE(array_reader.HasMoreData());
EXPECT_FALSE(reader.HasMoreData());
}
TEST_F(GesturePropertiesServiceProviderTest, GetPropertySuccessBools) {
get_property_read_only_ = false;
get_property_response_ =
ui::ozone::mojom::GesturePropValue::NewBools({true, false});
EXPECT_CALL(*mock_service_, GetProperty(4, "prop 1", _));
std::unique_ptr<dbus::Response> response = nullptr;
CallGetProperty(4, "prop 1", response);
dbus::MessageReader reader(response.get());
EXPECT_EQ(false, expect_bool(&reader));
EXPECT_EQ(2u, expect_uint32(&reader));
dbus::MessageReader variant_reader(nullptr);
ASSERT_TRUE(reader.PopVariant(&variant_reader));
dbus::MessageReader array_reader(nullptr);
ASSERT_TRUE(variant_reader.PopArray(&array_reader));
EXPECT_EQ(true, expect_bool(&array_reader));
EXPECT_EQ(false, expect_bool(&array_reader));
EXPECT_FALSE(array_reader.HasMoreData());
EXPECT_FALSE(reader.HasMoreData());
}
TEST_F(GesturePropertiesServiceProviderTest, GetPropertySuccessStr) {
get_property_read_only_ = false;
get_property_response_ = ui::ozone::mojom::GesturePropValue::NewStr("llama");
EXPECT_CALL(*mock_service_, GetProperty(4, "prop 1", _));
std::unique_ptr<dbus::Response> response = nullptr;
CallGetProperty(4, "prop 1", response);
dbus::MessageReader reader(response.get());
EXPECT_EQ(false, expect_bool(&reader));
EXPECT_EQ(1u, expect_uint32(&reader));
dbus::MessageReader variant_reader(nullptr);
ASSERT_TRUE(reader.PopVariant(&variant_reader));
EXPECT_EQ("llama", expect_string(&variant_reader));
EXPECT_FALSE(reader.HasMoreData());
}
TEST_F(GesturePropertiesServiceProviderTest, GetPropertySuccessReals) {
get_property_read_only_ = false;
get_property_response_ =
ui::ozone::mojom::GesturePropValue::NewReals({3.14, 6.28});
EXPECT_CALL(*mock_service_, GetProperty(4, "prop 1", _));
std::unique_ptr<dbus::Response> response = nullptr;
CallGetProperty(4, "prop 1", response);
dbus::MessageReader reader(response.get());
EXPECT_EQ(false, expect_bool(&reader));
EXPECT_EQ(2u, expect_uint32(&reader));
dbus::MessageReader variant_reader(nullptr);
ASSERT_TRUE(reader.PopVariant(&variant_reader));
dbus::MessageReader array_reader(nullptr);
ASSERT_TRUE(variant_reader.PopArray(&array_reader));
EXPECT_EQ(3.14, expect_double(&array_reader));
EXPECT_EQ(6.28, expect_double(&array_reader));
EXPECT_FALSE(array_reader.HasMoreData());
EXPECT_FALSE(reader.HasMoreData());
}
TEST_F(GesturePropertiesServiceProviderTest, GetPropertyPropertyDoesntExist) {
get_property_read_only_ = true;
get_property_response_ = nullptr;
EXPECT_CALL(*mock_service_, GetProperty(4, "prop 1", _));
std::unique_ptr<dbus::Response> response = nullptr;
CallGetProperty(4, "prop 1", response);
EXPECT_EQ(dbus::Message::MESSAGE_ERROR, response->GetMessageType());
}
TEST_F(GesturePropertiesServiceProviderTest, GetPropertyMissingParameters) {
CheckMethodErrorsWithNoParameters(
chromeos::kGesturePropertiesServiceGetPropertyMethod);
}
} // namespace ash } // namespace ash
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment