1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// found in the LICENSE file.
4e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chromeos/dbus/bluetooth_gatt_manager_client.h"
6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/bind.h"
8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/memory/weak_ptr.h"
9e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "dbus/bus.h"
10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "dbus/message.h"
11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "dbus/object_proxy.h"
12e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "third_party/cros_system_api/dbus/service_constants.h"
13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace chromeos {
15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst char BluetoothGattManagerClient::kNoResponseError[] =
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    "org.chromium.Error.NoResponse";
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// The BluetoothGattManagerClient implementation used in production.
20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass BluetoothGattManagerClientImpl : public BluetoothGattManagerClient {
21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch public:
22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  BluetoothGattManagerClientImpl()
23e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      : object_proxy_(NULL),
24e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        weak_ptr_factory_(this) {
25e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual ~BluetoothGattManagerClientImpl() {
28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // BluetoothGattManagerClient override.
31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual void RegisterService(const dbus::ObjectPath& service_path,
32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                               const Options& options,
33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                               const base::Closure& callback,
34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                               const ErrorCallback& error_callback) OVERRIDE {
35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MethodCall method_call(
36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_manager::kBluetoothGattManagerInterface,
37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_manager::kRegisterService);
38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter writer(&method_call);
40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.AppendObjectPath(service_path);
41e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // TODO(armansito): The parameters of the Options dictionary are undefined
43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // but the method signature still requires a value dictionary. Pass an
44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // empty dictionary and fill in the contents later once this is defined.
45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter array_writer(NULL);
46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.OpenArray("{sv}", &array_writer);
47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.CloseContainer(&array_writer);
48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(object_proxy_);
50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    object_proxy_->CallMethodWithErrorCallback(
51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        &method_call,
52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattManagerClientImpl::OnSuccess,
54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(), callback),
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattManagerClientImpl::OnError,
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(), error_callback));
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // BluetoothGattManagerClient override.
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual void UnregisterService(const dbus::ObjectPath& service_path,
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 const base::Closure& callback,
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                 const ErrorCallback& error_callback) OVERRIDE {
63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MethodCall method_call(
64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_manager::kBluetoothGattManagerInterface,
65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_manager::kUnregisterService);
66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    dbus::MessageWriter writer(&method_call);
68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    writer.AppendObjectPath(service_path);
69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(object_proxy_);
71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    object_proxy_->CallMethodWithErrorCallback(
72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        &method_call,
73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattManagerClientImpl::OnSuccess,
75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(), callback),
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::Bind(&BluetoothGattManagerClientImpl::OnError,
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   weak_ptr_factory_.GetWeakPtr(), error_callback));
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch protected:
81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // chromeos::DBusClient override.
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  virtual void Init(dbus::Bus* bus) OVERRIDE {
83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(bus);
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    object_proxy_ = bus->GetObjectProxy(
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        bluetooth_gatt_manager::kBluetoothGattManagerServiceName,
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        dbus::ObjectPath(
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            bluetooth_gatt_manager::kBluetoothGattManagerInterface));
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch private:
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called when a response for a successful method call is received.
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void OnSuccess(const base::Closure& callback, dbus::Response* response) {
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DCHECK(response);
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    callback.Run();
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Called when a response for a failed method call is received.
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void OnError(const ErrorCallback& error_callback,
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch               dbus::ErrorResponse* response) {
100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // Error response has optional error message argument.
101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string error_name;
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string error_message;
103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (response) {
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      dbus::MessageReader reader(response);
105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      error_name = response->GetErrorName();
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      reader.PopString(&error_message);
107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    } else {
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      error_name = kNoResponseError;
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    error_callback.Run(error_name, error_message);
111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // The proxy to the remote GATT manager object.
114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  dbus::ObjectProxy* object_proxy_;
115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Weak pointer factory for generating 'this' pointers that might live longer
117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // than we do.
118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Note: This should remain the last member so it'll be destroyed and
119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // invalidate its weak pointers before any other members are destroyed.
120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::WeakPtrFactory<BluetoothGattManagerClientImpl> weak_ptr_factory_;
121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DISALLOW_COPY_AND_ASSIGN(BluetoothGattManagerClientImpl);
123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch};
124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattManagerClient::BluetoothGattManagerClient() {
126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
128e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattManagerClient::~BluetoothGattManagerClient() {
129e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
131e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// static
132e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochBluetoothGattManagerClient* BluetoothGattManagerClient::Create() {
133e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return new BluetoothGattManagerClientImpl();
134e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
135e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
136e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace chromeos
137