gesture_properties_service_provider.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/dbus/gesture_properties_service_provider.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/logging.h"
  9. #include "dbus/message.h"
  10. #include "third_party/cros_system_api/dbus/service_constants.h"
  11. #include "ui/ozone/public/input_controller.h"
  12. #include "ui/ozone/public/ozone_platform.h"
  13. namespace ash {
  14. GesturePropertiesServiceProvider::GesturePropertiesServiceProvider()
  15. : weak_ptr_factory_(this) {}
  16. GesturePropertiesServiceProvider::~GesturePropertiesServiceProvider() = default;
  17. void GesturePropertiesServiceProvider::Start(
  18. scoped_refptr<dbus::ExportedObject> exported_object) {
  19. auto on_exported =
  20. base::BindRepeating(&GesturePropertiesServiceProvider::OnExported,
  21. weak_ptr_factory_.GetWeakPtr());
  22. exported_object->ExportMethod(
  23. chromeos::kGesturePropertiesServiceInterface,
  24. chromeos::kGesturePropertiesServiceListDevicesMethod,
  25. base::BindRepeating(&GesturePropertiesServiceProvider::ListDevices,
  26. weak_ptr_factory_.GetWeakPtr()),
  27. on_exported);
  28. exported_object->ExportMethod(
  29. chromeos::kGesturePropertiesServiceInterface,
  30. chromeos::kGesturePropertiesServiceListPropertiesMethod,
  31. base::BindRepeating(&GesturePropertiesServiceProvider::ListProperties,
  32. weak_ptr_factory_.GetWeakPtr()),
  33. on_exported);
  34. exported_object->ExportMethod(
  35. chromeos::kGesturePropertiesServiceInterface,
  36. chromeos::kGesturePropertiesServiceGetPropertyMethod,
  37. base::BindRepeating(&GesturePropertiesServiceProvider::GetProperty,
  38. weak_ptr_factory_.GetWeakPtr()),
  39. on_exported);
  40. exported_object->ExportMethod(
  41. chromeos::kGesturePropertiesServiceInterface,
  42. chromeos::kGesturePropertiesServiceSetPropertyMethod,
  43. base::BindRepeating(&GesturePropertiesServiceProvider::SetProperty,
  44. weak_ptr_factory_.GetWeakPtr()),
  45. on_exported);
  46. }
  47. void GesturePropertiesServiceProvider::OnExported(
  48. const std::string& interface_name,
  49. const std::string& method_name,
  50. bool success) {
  51. if (!success)
  52. LOG(ERROR) << "Failed to export " << interface_name << "." << method_name;
  53. }
  54. namespace {
  55. void GetPropertyCallback(dbus::MethodCall* method_call,
  56. std::unique_ptr<dbus::Response> response,
  57. dbus::ExportedObject::ResponseSender response_sender,
  58. bool is_read_only,
  59. ui::ozone::mojom::GesturePropValuePtr values) {
  60. if (values.is_null()) {
  61. std::move(response_sender)
  62. .Run(dbus::ErrorResponse::FromMethodCall(
  63. method_call, DBUS_ERROR_INVALID_ARGS,
  64. "The device ID or property name specified was not found."));
  65. return;
  66. }
  67. dbus::MessageWriter writer(response.get());
  68. dbus::MessageWriter variant_writer(nullptr);
  69. dbus::MessageWriter array_writer(nullptr);
  70. writer.AppendBool(is_read_only);
  71. switch (values->which()) {
  72. case ui::ozone::mojom::GesturePropValue::Tag::kInts: {
  73. writer.AppendUint32(values->get_ints().size());
  74. writer.OpenVariant("ai", &variant_writer);
  75. variant_writer.AppendArrayOfInt32s(values->get_ints().data(),
  76. values->get_ints().size());
  77. writer.CloseContainer(&variant_writer);
  78. break;
  79. }
  80. case ui::ozone::mojom::GesturePropValue::Tag::kShorts: {
  81. writer.AppendUint32(values->get_shorts().size());
  82. writer.OpenVariant("an", &variant_writer);
  83. variant_writer.OpenArray("n", &array_writer);
  84. for (int16_t value : values->get_shorts()) {
  85. array_writer.AppendInt16(value);
  86. }
  87. variant_writer.CloseContainer(&array_writer);
  88. writer.CloseContainer(&variant_writer);
  89. break;
  90. }
  91. case ui::ozone::mojom::GesturePropValue::Tag::kBools: {
  92. writer.AppendUint32(values->get_bools().size());
  93. writer.OpenVariant("ab", &variant_writer);
  94. variant_writer.OpenArray("b", &array_writer);
  95. for (bool value : values->get_bools()) {
  96. array_writer.AppendBool(value);
  97. }
  98. variant_writer.CloseContainer(&array_writer);
  99. writer.CloseContainer(&variant_writer);
  100. break;
  101. }
  102. case ui::ozone::mojom::GesturePropValue::Tag::kStr: {
  103. writer.AppendUint32(1);
  104. writer.AppendVariantOfString(values->get_str());
  105. break;
  106. }
  107. case ui::ozone::mojom::GesturePropValue::Tag::kReals: {
  108. writer.AppendUint32(values->get_reals().size());
  109. writer.OpenVariant("ad", &variant_writer);
  110. variant_writer.AppendArrayOfDoubles(values->get_reals().data(),
  111. values->get_reals().size());
  112. writer.CloseContainer(&variant_writer);
  113. break;
  114. }
  115. default: {
  116. // This should never happen.
  117. LOG(WARNING) << "No value set on GesturePropValue union; not returning "
  118. "values to GetProperty call.";
  119. writer.AppendUint32(0);
  120. break;
  121. }
  122. }
  123. std::move(response_sender).Run(std::move(response));
  124. }
  125. void SetPropertyCallback(dbus::MethodCall* method_call,
  126. dbus::ExportedObject::ResponseSender response_sender,
  127. ui::ozone::mojom::SetGesturePropErrorCode error) {
  128. std::string error_message;
  129. switch (error) {
  130. case ui::ozone::mojom::SetGesturePropErrorCode::SUCCESS:
  131. std::move(response_sender)
  132. .Run(dbus::Response::FromMethodCall(method_call));
  133. return;
  134. case ui::ozone::mojom::SetGesturePropErrorCode::NOT_FOUND:
  135. error_message = "The device ID or property name specified was not found.";
  136. break;
  137. case ui::ozone::mojom::SetGesturePropErrorCode::READ_ONLY:
  138. error_message = "That property is read-only.";
  139. break;
  140. case ui::ozone::mojom::SetGesturePropErrorCode::TYPE_MISMATCH:
  141. error_message =
  142. "The property is of a different type than the value(s) "
  143. "provided.";
  144. break;
  145. case ui::ozone::mojom::SetGesturePropErrorCode::SIZE_MISMATCH:
  146. error_message =
  147. "The property has a different number of values to that "
  148. "provided.";
  149. break;
  150. case ui::ozone::mojom::SetGesturePropErrorCode::UNKNOWN_ERROR:
  151. default:
  152. error_message = "An unknown error occurred.";
  153. break;
  154. }
  155. LOG(ERROR) << "SetProperty error: " << error_message;
  156. std::move(response_sender)
  157. .Run(dbus::ErrorResponse::FromMethodCall(
  158. method_call, DBUS_ERROR_INVALID_ARGS, error_message));
  159. }
  160. void ListDevicesCallback(std::unique_ptr<dbus::Response> response,
  161. dbus::ExportedObject::ResponseSender response_sender,
  162. const base::flat_map<int, std::string>& result) {
  163. dbus::MessageWriter writer(response.get());
  164. writer.AppendUint32(result.size());
  165. dbus::MessageWriter dict_writer(nullptr);
  166. writer.OpenArray("{is}", &dict_writer);
  167. for (const auto& pair : result) {
  168. dbus::MessageWriter dict_entry_writer(nullptr);
  169. dict_writer.OpenDictEntry(&dict_entry_writer);
  170. dict_entry_writer.AppendInt32(pair.first);
  171. dict_entry_writer.AppendString(pair.second);
  172. dict_writer.CloseContainer(&dict_entry_writer);
  173. }
  174. writer.CloseContainer(&dict_writer);
  175. std::move(response_sender).Run(std::move(response));
  176. }
  177. void ListPropertiesCallback(
  178. std::unique_ptr<dbus::Response> response,
  179. dbus::ExportedObject::ResponseSender response_sender,
  180. const std::vector<std::string>& result) {
  181. dbus::MessageWriter writer(response.get());
  182. writer.AppendUint32(result.size());
  183. writer.AppendArrayOfStrings(result);
  184. std::move(response_sender).Run(std::move(response));
  185. }
  186. } // namespace
  187. void GesturePropertiesServiceProvider::ListDevices(
  188. dbus::MethodCall* method_call,
  189. dbus::ExportedObject::ResponseSender response_sender) {
  190. std::unique_ptr<dbus::Response> response =
  191. dbus::Response::FromMethodCall(method_call);
  192. GetService()->ListDevices(base::BindOnce(
  193. &ListDevicesCallback, std::move(response), std::move(response_sender)));
  194. }
  195. void GesturePropertiesServiceProvider::ListProperties(
  196. dbus::MethodCall* method_call,
  197. dbus::ExportedObject::ResponseSender response_sender) {
  198. dbus::MessageReader reader(method_call);
  199. int32_t device_id;
  200. if (!reader.PopInt32(&device_id)) {
  201. std::move(response_sender)
  202. .Run(dbus::ErrorResponse::FromMethodCall(
  203. method_call, DBUS_ERROR_INVALID_ARGS,
  204. "The device ID (int32) is missing."));
  205. return;
  206. }
  207. std::unique_ptr<dbus::Response> response =
  208. dbus::Response::FromMethodCall(method_call);
  209. GetService()->ListProperties(
  210. device_id, base::BindOnce(&ListPropertiesCallback, std::move(response),
  211. std::move(response_sender)));
  212. }
  213. void GesturePropertiesServiceProvider::GetProperty(
  214. dbus::MethodCall* method_call,
  215. dbus::ExportedObject::ResponseSender response_sender) {
  216. dbus::MessageReader reader(method_call);
  217. int32_t device_id;
  218. std::string property_name;
  219. if (!reader.PopInt32(&device_id) || !reader.PopString(&property_name)) {
  220. std::move(response_sender)
  221. .Run(dbus::ErrorResponse::FromMethodCall(
  222. method_call, DBUS_ERROR_INVALID_ARGS,
  223. "The device ID (int32) and/or property name (string) is missing."));
  224. return;
  225. }
  226. std::unique_ptr<dbus::Response> response =
  227. dbus::Response::FromMethodCall(method_call);
  228. GetService()->GetProperty(
  229. device_id, property_name,
  230. base::BindOnce(&GetPropertyCallback, method_call, std::move(response),
  231. std::move(response_sender)));
  232. }
  233. static ui::ozone::mojom::GesturePropValuePtr GesturePropValueFromVariant(
  234. dbus::MessageReader* variant_reader,
  235. std::string* error_message) {
  236. std::string string_value;
  237. if (variant_reader->PopString(&string_value)) {
  238. return ui::ozone::mojom::GesturePropValue::NewStr(string_value);
  239. }
  240. dbus::MessageReader array_reader(nullptr);
  241. if (!variant_reader->PopArray(&array_reader)) {
  242. *error_message =
  243. "Value(s) should be specified either as a string or an "
  244. "array of the appropriate type.";
  245. return nullptr;
  246. }
  247. switch (array_reader.GetDataType()) {
  248. case dbus::Message::DataType::INT32: {
  249. std::vector<int32_t> values = {};
  250. int32_t value;
  251. while (array_reader.PopInt32(&value)) {
  252. values.push_back(value);
  253. }
  254. return ui::ozone::mojom::GesturePropValue::NewInts(values);
  255. }
  256. case dbus::Message::DataType::INT16: {
  257. std::vector<int16_t> values = {};
  258. int16_t value;
  259. while (array_reader.PopInt16(&value)) {
  260. values.push_back(value);
  261. }
  262. return ui::ozone::mojom::GesturePropValue::NewShorts(values);
  263. }
  264. case dbus::Message::DataType::BOOL: {
  265. std::vector<bool> values = {};
  266. bool value;
  267. while (array_reader.PopBool(&value)) {
  268. values.push_back(value);
  269. }
  270. return ui::ozone::mojom::GesturePropValue::NewBools(values);
  271. }
  272. case dbus::Message::DataType::DOUBLE: {
  273. std::vector<double> values = {};
  274. double value;
  275. while (array_reader.PopDouble(&value)) {
  276. values.push_back(value);
  277. }
  278. return ui::ozone::mojom::GesturePropValue::NewReals(values);
  279. }
  280. case dbus::Message::DataType::STRING: {
  281. *error_message =
  282. "String properties can only have one value, and so "
  283. "should not be specified as arrays.";
  284. return nullptr;
  285. }
  286. default: {
  287. *error_message =
  288. "Unsupported D-Bus value type; supported types are "
  289. "int32, int16, bool, double, and string.";
  290. return nullptr;
  291. }
  292. }
  293. }
  294. void GesturePropertiesServiceProvider::SetProperty(
  295. dbus::MethodCall* method_call,
  296. dbus::ExportedObject::ResponseSender response_sender) {
  297. dbus::MessageReader reader(method_call);
  298. int32_t device_id;
  299. std::string property_name;
  300. if (!reader.PopInt32(&device_id) || !reader.PopString(&property_name)) {
  301. std::move(response_sender)
  302. .Run(dbus::ErrorResponse::FromMethodCall(
  303. method_call, DBUS_ERROR_INVALID_ARGS,
  304. "The device ID (int32) and/or property name (string) is missing."));
  305. return;
  306. }
  307. if (!reader.HasMoreData()) {
  308. std::move(response_sender)
  309. .Run(dbus::ErrorResponse::FromMethodCall(
  310. method_call, DBUS_ERROR_INVALID_ARGS, "No value(s) specified."));
  311. return;
  312. }
  313. std::string error_message;
  314. ui::ozone::mojom::GesturePropValuePtr values =
  315. GesturePropValueFromVariant(&reader, &error_message);
  316. if (values.is_null()) {
  317. std::move(response_sender)
  318. .Run(dbus::ErrorResponse::FromMethodCall(
  319. method_call, DBUS_ERROR_INVALID_ARGS, error_message));
  320. return;
  321. }
  322. GetService()->SetProperty(device_id, property_name, std::move(values),
  323. base::BindOnce(&SetPropertyCallback, method_call,
  324. std::move(response_sender)));
  325. }
  326. ui::ozone::mojom::GesturePropertiesService*
  327. GesturePropertiesServiceProvider::GetService() {
  328. if (service_for_test_ != nullptr)
  329. return service_for_test_;
  330. if (!service_.is_bound()) {
  331. ui::OzonePlatform::GetInstance()
  332. ->GetInputController()
  333. ->GetGesturePropertiesService(service_.BindNewPipeAndPassReceiver());
  334. }
  335. return service_.get();
  336. }
  337. } // namespace ash