Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / bluetooth_gatt_service_service_provider.cc
1 // Copyright 2014 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
5 #include "chromeos/dbus/bluetooth_gatt_service_service_provider.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/threading/platform_thread.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/fake_bluetooth_gatt_service_service_provider.h"
14 #include "dbus/exported_object.h"
15 #include "dbus/message.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17
18 namespace chromeos {
19 namespace {
20 const char kErrorInvalidArgs[] =
21     "org.freedesktop.DBus.Error.InvalidArgs";
22 const char kErrorPropertyReadOnly[] =
23     "org.freedesktop.DBus.Error.PropertyReadOnly";
24 }  // namespace
25
26 // The BluetoothGattServiceServiceProvider implementation used in production.
27 class BluetoothGattServiceServiceProviderImpl
28     : public BluetoothGattServiceServiceProvider {
29  public:
30   BluetoothGattServiceServiceProviderImpl(
31       dbus::Bus* bus,
32       const dbus::ObjectPath& object_path,
33       const std::string& uuid,
34       const std::vector<dbus::ObjectPath>& includes)
35       : origin_thread_id_(base::PlatformThread::CurrentId()),
36         uuid_(uuid),
37         includes_(includes),
38         bus_(bus),
39         object_path_(object_path),
40         weak_ptr_factory_(this) {
41     VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value()
42             << " UUID: " << uuid;
43     DCHECK(!uuid_.empty());
44     DCHECK(object_path_.IsValid());
45     DCHECK(bus_);
46
47     exported_object_ = bus_->GetExportedObject(object_path_);
48
49     exported_object_->ExportMethod(
50         dbus::kDBusPropertiesInterface,
51         dbus::kDBusPropertiesGet,
52         base::Bind(&BluetoothGattServiceServiceProviderImpl::Get,
53                    weak_ptr_factory_.GetWeakPtr()),
54         base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
55                    weak_ptr_factory_.GetWeakPtr()));
56
57     exported_object_->ExportMethod(
58         dbus::kDBusPropertiesInterface,
59         dbus::kDBusPropertiesSet,
60         base::Bind(&BluetoothGattServiceServiceProviderImpl::Set,
61                    weak_ptr_factory_.GetWeakPtr()),
62         base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
63                    weak_ptr_factory_.GetWeakPtr()));
64
65     exported_object_->ExportMethod(
66         dbus::kDBusPropertiesInterface,
67         dbus::kDBusPropertiesGetAll,
68         base::Bind(&BluetoothGattServiceServiceProviderImpl::GetAll,
69                    weak_ptr_factory_.GetWeakPtr()),
70         base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
71                    weak_ptr_factory_.GetWeakPtr()));
72   }
73
74   virtual ~BluetoothGattServiceServiceProviderImpl() {
75     VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value();
76     bus_->UnregisterExportedObject(object_path_);
77   }
78
79  private:
80   // Returns true if the current thread is on the origin thread.
81   bool OnOriginThread() {
82     return base::PlatformThread::CurrentId() == origin_thread_id_;
83   }
84
85   // Called by dbus:: when the Bluetooth daemon fetches a single property of
86   // the service.
87   void Get(dbus::MethodCall* method_call,
88            dbus::ExportedObject::ResponseSender response_sender) {
89     VLOG(2) << "BluetoothGattServiceServiceProvider::Get: "
90             << object_path_.value();
91     DCHECK(OnOriginThread());
92
93     dbus::MessageReader reader(method_call);
94
95     std::string interface_name;
96     std::string property_name;
97     if (!reader.PopString(&interface_name) ||
98         !reader.PopString(&property_name) ||
99         reader.HasMoreData()) {
100       scoped_ptr<dbus::ErrorResponse> error_response =
101           dbus::ErrorResponse::FromMethodCall(
102               method_call, kErrorInvalidArgs, "Expected 'ss'.");
103       response_sender.Run(error_response.Pass());
104       return;
105     }
106
107     // Only the GATT service interface is allowed.
108     if (interface_name !=
109         bluetooth_gatt_service::kBluetoothGattServiceInterface) {
110       scoped_ptr<dbus::ErrorResponse> error_response =
111           dbus::ErrorResponse::FromMethodCall(
112               method_call, kErrorInvalidArgs,
113               "No such interface: '" + interface_name + "'.");
114       response_sender.Run(error_response.Pass());
115       return;
116     }
117
118     // Return error if |property_name| is unknown.
119     if (property_name != bluetooth_gatt_service::kUUIDProperty &&
120         property_name != bluetooth_gatt_service::kIncludesProperty) {
121       scoped_ptr<dbus::ErrorResponse> error_response =
122           dbus::ErrorResponse::FromMethodCall(
123               method_call, kErrorInvalidArgs,
124               "No such property: '" + property_name + "'.");
125       response_sender.Run(error_response.Pass());
126       return;
127     }
128
129     scoped_ptr<dbus::Response> response =
130         dbus::Response::FromMethodCall(method_call);
131     dbus::MessageWriter writer(response.get());
132     dbus::MessageWriter variant_writer(NULL);
133
134     if (property_name == bluetooth_gatt_service::kUUIDProperty) {
135       writer.OpenVariant("s", &variant_writer);
136       variant_writer.AppendString(uuid_);
137       writer.CloseContainer(&variant_writer);
138     } else {
139       writer.OpenVariant("ao", &variant_writer);
140       variant_writer.AppendArrayOfObjectPaths(includes_);
141       writer.CloseContainer(&variant_writer);
142     }
143
144     response_sender.Run(response.Pass());
145   }
146
147   // Called by dbus:: when the Bluetooth daemon sets a single property of the
148   // service.
149   void Set(dbus::MethodCall* method_call,
150            dbus::ExportedObject::ResponseSender response_sender) {
151     VLOG(2) << "BluetoothGattServiceServiceProvider::Set: "
152             << object_path_.value();
153     DCHECK(OnOriginThread());
154
155     // All of the properties on this interface are read-only, so just return
156     // error.
157     scoped_ptr<dbus::ErrorResponse> error_response =
158         dbus::ErrorResponse::FromMethodCall(
159             method_call, kErrorPropertyReadOnly,
160             "All properties are read-only.");
161     response_sender.Run(error_response.Pass());
162   }
163
164   // Called by dbus:: when the Bluetooth daemon fetches all properties of the
165   // service.
166   void GetAll(dbus::MethodCall* method_call,
167               dbus::ExportedObject::ResponseSender response_sender) {
168     VLOG(2) << "BluetoothGattServiceServiceProvider::GetAll: "
169             << object_path_.value();
170     DCHECK(OnOriginThread());
171
172     dbus::MessageReader reader(method_call);
173
174     std::string interface_name;
175     if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
176       scoped_ptr<dbus::ErrorResponse> error_response =
177           dbus::ErrorResponse::FromMethodCall(
178               method_call, kErrorInvalidArgs, "Expected 's'.");
179       response_sender.Run(error_response.Pass());
180       return;
181     }
182
183     // Only the GATT service interface is allowed.
184     if (interface_name !=
185         bluetooth_gatt_service::kBluetoothGattServiceInterface) {
186       scoped_ptr<dbus::ErrorResponse> error_response =
187           dbus::ErrorResponse::FromMethodCall(
188               method_call, kErrorInvalidArgs,
189               "No such interface: '" + interface_name + "'.");
190       response_sender.Run(error_response.Pass());
191       return;
192     }
193
194     scoped_ptr<dbus::Response> response =
195         dbus::Response::FromMethodCall(method_call);
196     dbus::MessageWriter writer(response.get());
197     dbus::MessageWriter array_writer(NULL);
198     dbus::MessageWriter dict_entry_writer(NULL);
199     dbus::MessageWriter variant_writer(NULL);
200
201     writer.OpenArray("{sv}", &array_writer);
202
203     array_writer.OpenDictEntry(&dict_entry_writer);
204     dict_entry_writer.AppendString(bluetooth_gatt_service::kUUIDProperty);
205     dict_entry_writer.AppendVariantOfString(uuid_);
206     array_writer.CloseContainer(&dict_entry_writer);
207
208     array_writer.OpenDictEntry(&dict_entry_writer);
209     dict_entry_writer.AppendString(bluetooth_gatt_service::kIncludesProperty);
210     dict_entry_writer.OpenVariant("ao", &variant_writer);
211     variant_writer.AppendArrayOfObjectPaths(includes_);
212     dict_entry_writer.CloseContainer(&variant_writer);
213     array_writer.CloseContainer(&dict_entry_writer);
214
215     writer.CloseContainer(&array_writer);
216
217     response_sender.Run(response.Pass());
218   }
219
220   // Called by dbus:: when a method is exported.
221   void OnExported(const std::string& interface_name,
222                   const std::string& method_name,
223                   bool success) {
224     LOG_IF(WARNING, !success) << "Failed to export "
225                               << interface_name << "." << method_name;
226   }
227
228   // Origin thread (i.e. the UI thread in production).
229   base::PlatformThreadId origin_thread_id_;
230
231   // 128-bit service UUID of this object.
232   std::string uuid_;
233
234   // List of object paths that represent other exported GATT services that are
235   // included from this service.
236   std::vector<dbus::ObjectPath> includes_;
237
238   // D-Bus bus object is exported on, not owned by this object and must
239   // outlive it.
240   dbus::Bus* bus_;
241
242   // D-Bus object path of object we are exporting, kept so we can unregister
243   // again in our destructor.
244   dbus::ObjectPath object_path_;
245
246   // D-Bus object we are exporting, owned by this object.
247   scoped_refptr<dbus::ExportedObject> exported_object_;
248
249   // Weak pointer factory for generating 'this' pointers that might live longer
250   // than we do.
251   // Note: This should remain the last member so it'll be destroyed and
252   // invalidate its weak pointers before any other members are destroyed.
253   base::WeakPtrFactory<BluetoothGattServiceServiceProviderImpl>
254       weak_ptr_factory_;
255
256   DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProviderImpl);
257 };
258
259 BluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() {
260 }
261
262 BluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() {
263 }
264
265 // static
266 BluetoothGattServiceServiceProvider*
267 BluetoothGattServiceServiceProvider::Create(
268     dbus::Bus* bus,
269     const dbus::ObjectPath& object_path,
270     const std::string& uuid,
271     const std::vector<dbus::ObjectPath>& includes) {
272   if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
273     return new BluetoothGattServiceServiceProviderImpl(
274         bus, object_path, uuid, includes);
275   }
276   return new FakeBluetoothGattServiceServiceProvider(
277       object_path, uuid, includes);
278 }
279
280 }  // namespace chromeos