1// Copyright 2013 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_profile_manager_client.h"
6
7#include "base/bind.h"
8#include "base/logging.h"
9#include "dbus/bus.h"
10#include "dbus/message.h"
11#include "dbus/object_path.h"
12#include "dbus/object_proxy.h"
13#include "third_party/cros_system_api/dbus/service_constants.h"
14
15namespace chromeos {
16
17const char BluetoothProfileManagerClient::kNoResponseError[] =
18    "org.chromium.Error.NoResponse";
19
20
21BluetoothProfileManagerClient::Options::Options() {
22}
23
24BluetoothProfileManagerClient::Options::~Options() {
25}
26
27// The BluetoothProfileManagerClient implementation used in production.
28class BluetoothProfileManagerClientImpl
29    : public BluetoothProfileManagerClient {
30 public:
31  BluetoothProfileManagerClientImpl() : weak_ptr_factory_(this) {}
32
33  virtual ~BluetoothProfileManagerClientImpl() {
34  }
35
36  // BluetoothProfileManagerClient override.
37  virtual void RegisterProfile(const dbus::ObjectPath& profile_path,
38                               const std::string& uuid,
39                               const Options& options,
40                               const base::Closure& callback,
41                               const ErrorCallback& error_callback) OVERRIDE {
42    dbus::MethodCall method_call(
43    bluetooth_profile_manager::kBluetoothProfileManagerInterface,
44    bluetooth_profile_manager::kRegisterProfile);
45
46    dbus::MessageWriter writer(&method_call);
47    writer.AppendObjectPath(profile_path);
48    writer.AppendString(uuid);
49
50    dbus::MessageWriter array_writer(NULL);
51    writer.OpenArray("{sv}", &array_writer);
52
53    dbus::MessageWriter dict_writer(NULL);
54
55    // Send Name if provided.
56    if (options.name.get() != NULL) {
57      array_writer.OpenDictEntry(&dict_writer);
58      dict_writer.AppendString(bluetooth_profile_manager::kNameOption);
59      dict_writer.AppendVariantOfString(*(options.name));
60      array_writer.CloseContainer(&dict_writer);
61    }
62
63    // Send Service if provided.
64    if (options.service.get() != NULL) {
65      dbus::MessageWriter dict_writer(NULL);
66      array_writer.OpenDictEntry(&dict_writer);
67      dict_writer.AppendString(bluetooth_profile_manager::kServiceOption);
68      dict_writer.AppendVariantOfString(*(options.service));
69      array_writer.CloseContainer(&dict_writer);
70    }
71
72    // Send Role if not the default value.
73    if (options.role != SYMMETRIC) {
74      dbus::MessageWriter dict_writer(NULL);
75      array_writer.OpenDictEntry(&dict_writer);
76      dict_writer.AppendString(bluetooth_profile_manager::kRoleOption);
77      if (options.role == CLIENT)
78        dict_writer.AppendVariantOfString(
79            bluetooth_profile_manager::kClientRoleOption);
80      else if (options.role == SERVER)
81        dict_writer.AppendVariantOfString(
82            bluetooth_profile_manager::kServerRoleOption);
83      else
84        dict_writer.AppendVariantOfString("");
85      array_writer.CloseContainer(&dict_writer);
86    }
87
88    // Send Channel if provided.
89    if (options.channel.get() != NULL) {
90      dbus::MessageWriter dict_writer(NULL);
91      array_writer.OpenDictEntry(&dict_writer);
92      dict_writer.AppendString(bluetooth_profile_manager::kChannelOption);
93      dict_writer.AppendVariantOfUint16(*(options.channel));
94      array_writer.CloseContainer(&dict_writer);
95    }
96
97    // Send PSM if provided.
98    if (options.psm.get() != NULL) {
99      dbus::MessageWriter dict_writer(NULL);
100      array_writer.OpenDictEntry(&dict_writer);
101      dict_writer.AppendString(bluetooth_profile_manager::kPSMOption);
102      dict_writer.AppendVariantOfUint16(*(options.psm));
103      array_writer.CloseContainer(&dict_writer);
104    }
105
106    // Send RequireAuthentication if provided.
107    if (options.require_authentication.get() != NULL) {
108      array_writer.OpenDictEntry(&dict_writer);
109      dict_writer.AppendString(
110          bluetooth_profile_manager::kRequireAuthenticationOption);
111      dict_writer.AppendVariantOfBool(*(options.require_authentication));
112      array_writer.CloseContainer(&dict_writer);
113    }
114
115    // Send RequireAuthorization if provided.
116    if (options.require_authorization.get() != NULL) {
117      array_writer.OpenDictEntry(&dict_writer);
118      dict_writer.AppendString(
119          bluetooth_profile_manager::kRequireAuthorizationOption);
120      dict_writer.AppendVariantOfBool(*(options.require_authorization));
121      array_writer.CloseContainer(&dict_writer);
122    }
123
124    // Send AutoConnect if provided.
125    if (options.auto_connect.get() != NULL) {
126      array_writer.OpenDictEntry(&dict_writer);
127      dict_writer.AppendString(
128          bluetooth_profile_manager::kAutoConnectOption);
129      dict_writer.AppendVariantOfBool(*(options.auto_connect));
130      array_writer.CloseContainer(&dict_writer);
131    }
132
133    // Send ServiceRecord if provided.
134    if (options.service_record.get() != NULL) {
135      dbus::MessageWriter dict_writer(NULL);
136      array_writer.OpenDictEntry(&dict_writer);
137      dict_writer.AppendString(bluetooth_profile_manager::kServiceRecordOption);
138      dict_writer.AppendVariantOfString(*(options.service_record));
139      array_writer.CloseContainer(&dict_writer);
140    }
141
142    // Send Version if provided.
143    if (options.version.get() != NULL) {
144      dbus::MessageWriter dict_writer(NULL);
145      array_writer.OpenDictEntry(&dict_writer);
146      dict_writer.AppendString(bluetooth_profile_manager::kVersionOption);
147      dict_writer.AppendVariantOfUint16(*(options.version));
148      array_writer.CloseContainer(&dict_writer);
149    }
150
151    // Send Features if provided.
152    if (options.features.get() != NULL) {
153      dbus::MessageWriter dict_writer(NULL);
154      array_writer.OpenDictEntry(&dict_writer);
155      dict_writer.AppendString(bluetooth_profile_manager::kFeaturesOption);
156      dict_writer.AppendVariantOfUint16(*(options.features));
157      array_writer.CloseContainer(&dict_writer);
158    }
159
160    writer.CloseContainer(&array_writer);
161
162    object_proxy_->CallMethodWithErrorCallback(
163        &method_call,
164        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
165        base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess,
166                   weak_ptr_factory_.GetWeakPtr(), callback),
167        base::Bind(&BluetoothProfileManagerClientImpl::OnError,
168                   weak_ptr_factory_.GetWeakPtr(), error_callback));
169  }
170
171  // BluetoothProfileManagerClient override.
172  virtual void UnregisterProfile(const dbus::ObjectPath& profile_path,
173                                 const base::Closure& callback,
174                                 const ErrorCallback& error_callback) OVERRIDE {
175    dbus::MethodCall method_call(
176      bluetooth_profile_manager::kBluetoothProfileManagerInterface,
177      bluetooth_profile_manager::kUnregisterProfile);
178
179    dbus::MessageWriter writer(&method_call);
180    writer.AppendObjectPath(profile_path);
181
182    object_proxy_->CallMethodWithErrorCallback(
183        &method_call,
184        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
185        base::Bind(&BluetoothProfileManagerClientImpl::OnSuccess,
186                   weak_ptr_factory_.GetWeakPtr(), callback),
187        base::Bind(&BluetoothProfileManagerClientImpl::OnError,
188                   weak_ptr_factory_.GetWeakPtr(), error_callback));
189  }
190
191 protected:
192  virtual void Init(dbus::Bus* bus) OVERRIDE {
193    DCHECK(bus);
194    object_proxy_ = bus->GetObjectProxy(
195        bluetooth_profile_manager::kBluetoothProfileManagerServiceName,
196        dbus::ObjectPath(
197            bluetooth_profile_manager::kBluetoothProfileManagerServicePath));
198  }
199
200 private:
201  // Called when a response for successful method call is received.
202  void OnSuccess(const base::Closure& callback,
203                 dbus::Response* response) {
204    DCHECK(response);
205    callback.Run();
206  }
207
208  // Called when a response for a failed method call is received.
209  void OnError(const ErrorCallback& error_callback,
210               dbus::ErrorResponse* response) {
211    // Error response has optional error message argument.
212    std::string error_name;
213    std::string error_message;
214    if (response) {
215      dbus::MessageReader reader(response);
216      error_name = response->GetErrorName();
217      reader.PopString(&error_message);
218    } else {
219      error_name = kNoResponseError;
220      error_message = "";
221    }
222    error_callback.Run(error_name, error_message);
223  }
224
225  dbus::ObjectProxy* object_proxy_;
226
227  // Weak pointer factory for generating 'this' pointers that might live longer
228  // than we do.
229  // Note: This should remain the last member so it'll be destroyed and
230  // invalidate its weak pointers before any other members are destroyed.
231  base::WeakPtrFactory<BluetoothProfileManagerClientImpl> weak_ptr_factory_;
232
233  DISALLOW_COPY_AND_ASSIGN(BluetoothProfileManagerClientImpl);
234};
235
236BluetoothProfileManagerClient::BluetoothProfileManagerClient() {
237}
238
239BluetoothProfileManagerClient::~BluetoothProfileManagerClient() {
240}
241
242BluetoothProfileManagerClient* BluetoothProfileManagerClient::Create() {
243  return new BluetoothProfileManagerClientImpl();
244}
245
246}  // namespace chromeos
247