shill_service_client.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright (c) 2012 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/shill_service_client.h"
6
7#include "base/bind.h"
8#include "base/message_loop.h"
9#include "base/stl_util.h"
10#include "base/values.h"
11#include "chromeos/dbus/shill_property_changed_observer.h"
12#include "chromeos/dbus/shill_service_client_stub.h"
13#include "dbus/bus.h"
14#include "dbus/message.h"
15#include "dbus/object_proxy.h"
16#include "third_party/cros_system_api/dbus/service_constants.h"
17
18namespace chromeos {
19
20namespace {
21
22#ifndef DBUS_ERROR_UNKNOWN_OBJECT
23// The linux_chromeos ASAN builder has an older version of dbus-protocol.h
24// so make sure this is defined.
25#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
26#endif
27
28// Error callback for GetProperties.
29void OnGetDictionaryError(
30    const std::string& method_name,
31    const dbus::ObjectPath& service_path,
32    const ShillServiceClient::DictionaryValueCallback& callback,
33    const std::string& error_name,
34    const std::string& error_message) {
35  const std::string log_string =
36      "Failed to call org.chromium.shill.Service." + method_name +
37      " for: " + service_path.value() + ": " +
38      error_name + ": " + error_message;
39
40  // Suppress ERROR messages for UnknownMethod/Object" since this can
41  // happen under normal conditions. See crbug.com/130660 and crbug.com/222210.
42  if (error_name == DBUS_ERROR_UNKNOWN_METHOD ||
43      error_name == DBUS_ERROR_UNKNOWN_OBJECT)
44    VLOG(1) << log_string;
45  else
46    LOG(ERROR) << log_string;
47
48  base::DictionaryValue empty_dictionary;
49  callback.Run(DBUS_METHOD_CALL_FAILURE, empty_dictionary);
50}
51
52// The ShillServiceClient implementation.
53class ShillServiceClientImpl : public ShillServiceClient {
54 public:
55  explicit ShillServiceClientImpl(dbus::Bus* bus)
56      : bus_(bus),
57        helpers_deleter_(&helpers_) {
58  }
59
60  /////////////////////////////////////
61  // ShillServiceClient overrides.
62  virtual void AddPropertyChangedObserver(
63      const dbus::ObjectPath& service_path,
64      ShillPropertyChangedObserver* observer) OVERRIDE {
65    GetHelper(service_path)->AddPropertyChangedObserver(observer);
66  }
67
68  virtual void RemovePropertyChangedObserver(
69      const dbus::ObjectPath& service_path,
70      ShillPropertyChangedObserver* observer) OVERRIDE {
71    GetHelper(service_path)->RemovePropertyChangedObserver(observer);
72  }
73
74  virtual void GetProperties(const dbus::ObjectPath& service_path,
75                             const DictionaryValueCallback& callback) OVERRIDE {
76    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
77                                 flimflam::kGetPropertiesFunction);
78    GetHelper(service_path)->CallDictionaryValueMethodWithErrorCallback(
79        &method_call,
80        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS),
81        base::Bind(&OnGetDictionaryError, "GetProperties",
82                   service_path, callback));
83  }
84
85  virtual void SetProperty(const dbus::ObjectPath& service_path,
86                           const std::string& name,
87                           const base::Value& value,
88                           const base::Closure& callback,
89                           const ErrorCallback& error_callback) OVERRIDE {
90    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
91                                 flimflam::kSetPropertyFunction);
92    dbus::MessageWriter writer(&method_call);
93    writer.AppendString(name);
94    ShillClientHelper::AppendValueDataAsVariant(&writer, value);
95    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
96                                                             callback,
97                                                             error_callback);
98  }
99
100  virtual void SetProperties(const dbus::ObjectPath& service_path,
101                             const base::DictionaryValue& properties,
102                             const base::Closure& callback,
103                             const ErrorCallback& error_callback) OVERRIDE {
104    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
105                                 shill::kSetPropertiesFunction);
106    dbus::MessageWriter writer(&method_call);
107    ShillClientHelper::AppendServicePropertiesDictionary(&writer, properties);
108    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
109                                                             callback,
110                                                             error_callback);
111  }
112
113  virtual void ClearProperty(const dbus::ObjectPath& service_path,
114                             const std::string& name,
115                             const base::Closure& callback,
116                             const ErrorCallback& error_callback) OVERRIDE {
117    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
118                                 flimflam::kClearPropertyFunction);
119    dbus::MessageWriter writer(&method_call);
120    writer.AppendString(name);
121    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
122                                                             callback,
123                                                             error_callback);
124  }
125
126
127  virtual void ClearProperties(const dbus::ObjectPath& service_path,
128                               const std::vector<std::string>& names,
129                               const ListValueCallback& callback,
130                               const ErrorCallback& error_callback) OVERRIDE {
131    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
132                                 shill::kClearPropertiesFunction);
133    dbus::MessageWriter writer(&method_call);
134    writer.AppendArrayOfStrings(names);
135    GetHelper(service_path)->CallListValueMethodWithErrorCallback(
136        &method_call,
137        callback,
138        error_callback);
139  }
140
141  virtual void Connect(const dbus::ObjectPath& service_path,
142                       const base::Closure& callback,
143                       const ErrorCallback& error_callback) OVERRIDE {
144    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
145                                 flimflam::kConnectFunction);
146    GetHelper(service_path)->CallVoidMethodWithErrorCallback(
147        &method_call, callback, error_callback);
148  }
149
150  virtual void Disconnect(const dbus::ObjectPath& service_path,
151                          const base::Closure& callback,
152                          const ErrorCallback& error_callback) OVERRIDE {
153    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
154                                 flimflam::kDisconnectFunction);
155    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
156                                                             callback,
157                                                             error_callback);
158  }
159
160  virtual void Remove(const dbus::ObjectPath& service_path,
161                      const base::Closure& callback,
162                      const ErrorCallback& error_callback) OVERRIDE {
163    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
164                                 flimflam::kRemoveServiceFunction);
165    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
166                                                             callback,
167                                                             error_callback);
168  }
169
170  virtual void ActivateCellularModem(
171      const dbus::ObjectPath& service_path,
172      const std::string& carrier,
173      const base::Closure& callback,
174      const ErrorCallback& error_callback) OVERRIDE {
175    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
176                                 flimflam::kActivateCellularModemFunction);
177    dbus::MessageWriter writer(&method_call);
178    writer.AppendString(carrier);
179    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
180                                                             callback,
181                                                             error_callback);
182  }
183
184  virtual void CompleteCellularActivation(
185      const dbus::ObjectPath& service_path,
186      const base::Closure& callback,
187      const ErrorCallback& error_callback) OVERRIDE {
188    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
189                                 shill::kCompleteCellularActivationFunction);
190    dbus::MessageWriter writer(&method_call);
191    GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call,
192                                                             callback,
193                                                             error_callback);
194  }
195
196  virtual bool CallActivateCellularModemAndBlock(
197      const dbus::ObjectPath& service_path,
198      const std::string& carrier) OVERRIDE {
199    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
200                                 flimflam::kActivateCellularModemFunction);
201    dbus::MessageWriter writer(&method_call);
202    writer.AppendString(carrier);
203    return GetHelper(service_path)->CallVoidMethodAndBlock(&method_call);
204  }
205
206  virtual void GetLoadableProfileEntries(
207      const dbus::ObjectPath& service_path,
208      const DictionaryValueCallback& callback) OVERRIDE {
209    dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface,
210                                 shill::kGetLoadableProfileEntriesFunction);
211    GetHelper(service_path)->CallDictionaryValueMethodWithErrorCallback(
212        &method_call,
213        base::Bind(callback, DBUS_METHOD_CALL_SUCCESS),
214        base::Bind(&OnGetDictionaryError, "GetLoadableProfileEntries",
215                   service_path, callback));
216  }
217
218  virtual ShillServiceClient::TestInterface* GetTestInterface() OVERRIDE {
219    return NULL;
220  }
221
222 private:
223  typedef std::map<std::string, ShillClientHelper*> HelperMap;
224
225  // Returns the corresponding ShillClientHelper for the profile.
226  ShillClientHelper* GetHelper(const dbus::ObjectPath& service_path) {
227    HelperMap::iterator it = helpers_.find(service_path.value());
228    if (it != helpers_.end())
229      return it->second;
230
231    // There is no helper for the profile, create it.
232    dbus::ObjectProxy* object_proxy =
233        bus_->GetObjectProxy(flimflam::kFlimflamServiceName, service_path);
234    ShillClientHelper* helper = new ShillClientHelper(bus_, object_proxy);
235    helper->MonitorPropertyChanged(flimflam::kFlimflamServiceInterface);
236    helpers_.insert(HelperMap::value_type(service_path.value(), helper));
237    return helper;
238  }
239
240  dbus::Bus* bus_;
241  HelperMap helpers_;
242  STLValueDeleter<HelperMap> helpers_deleter_;
243
244  DISALLOW_COPY_AND_ASSIGN(ShillServiceClientImpl);
245};
246
247}  // namespace
248
249ShillServiceClient::ShillServiceClient() {}
250
251ShillServiceClient::~ShillServiceClient() {}
252
253// static
254ShillServiceClient* ShillServiceClient::Create(
255    DBusClientImplementationType type,
256    dbus::Bus* bus) {
257  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
258    return new ShillServiceClientImpl(bus);
259  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
260  return new ShillServiceClientStub();
261}
262
263}  // namespace chromeos
264