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_ipconfig_client.h"
6
7#include "base/bind.h"
8#include "base/message_loop/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 "dbus/bus.h"
13#include "dbus/message.h"
14#include "dbus/object_path.h"
15#include "dbus/object_proxy.h"
16#include "dbus/values_util.h"
17#include "third_party/cros_system_api/dbus/service_constants.h"
18
19namespace chromeos {
20
21namespace {
22
23// The ShillIPConfigClient implementation.
24class ShillIPConfigClientImpl : public ShillIPConfigClient {
25 public:
26  ShillIPConfigClientImpl();
27
28  ////////////////////////////////////
29  // ShillIPConfigClient overrides.
30  virtual void AddPropertyChangedObserver(
31      const dbus::ObjectPath& ipconfig_path,
32      ShillPropertyChangedObserver* observer) OVERRIDE {
33    GetHelper(ipconfig_path)->AddPropertyChangedObserver(observer);
34  }
35
36  virtual void RemovePropertyChangedObserver(
37      const dbus::ObjectPath& ipconfig_path,
38      ShillPropertyChangedObserver* observer) OVERRIDE {
39    GetHelper(ipconfig_path)->RemovePropertyChangedObserver(observer);
40  }
41  virtual void Refresh(const dbus::ObjectPath& ipconfig_path,
42                       const VoidDBusMethodCallback& callback) OVERRIDE;
43  virtual void GetProperties(const dbus::ObjectPath& ipconfig_path,
44                             const DictionaryValueCallback& callback) OVERRIDE;
45  virtual void SetProperty(const dbus::ObjectPath& ipconfig_path,
46                           const std::string& name,
47                           const base::Value& value,
48                           const VoidDBusMethodCallback& callback) OVERRIDE;
49  virtual void ClearProperty(const dbus::ObjectPath& ipconfig_path,
50                             const std::string& name,
51                             const VoidDBusMethodCallback& callback) OVERRIDE;
52  virtual void Remove(const dbus::ObjectPath& ipconfig_path,
53                      const VoidDBusMethodCallback& callback) OVERRIDE;
54  virtual ShillIPConfigClient::TestInterface* GetTestInterface() OVERRIDE;
55
56 protected:
57  virtual void Init(dbus::Bus* bus) OVERRIDE {
58    bus_ = bus;
59  }
60
61 private:
62  typedef std::map<std::string, ShillClientHelper*> HelperMap;
63
64  // Returns the corresponding ShillClientHelper for the profile.
65  ShillClientHelper* GetHelper(const dbus::ObjectPath& ipconfig_path) {
66    HelperMap::iterator it = helpers_.find(ipconfig_path.value());
67    if (it != helpers_.end())
68      return it->second;
69
70    // There is no helper for the profile, create it.
71    dbus::ObjectProxy* object_proxy =
72        bus_->GetObjectProxy(shill::kFlimflamServiceName, ipconfig_path);
73    ShillClientHelper* helper = new ShillClientHelper(object_proxy);
74    helper->MonitorPropertyChanged(shill::kFlimflamIPConfigInterface);
75    helpers_.insert(HelperMap::value_type(ipconfig_path.value(), helper));
76    return helper;
77  }
78
79  dbus::Bus* bus_;
80  HelperMap helpers_;
81  STLValueDeleter<HelperMap> helpers_deleter_;
82
83  DISALLOW_COPY_AND_ASSIGN(ShillIPConfigClientImpl);
84};
85
86ShillIPConfigClientImpl::ShillIPConfigClientImpl()
87    : bus_(NULL),
88      helpers_deleter_(&helpers_) {
89}
90
91void ShillIPConfigClientImpl::GetProperties(
92    const dbus::ObjectPath& ipconfig_path,
93    const DictionaryValueCallback& callback) {
94  dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
95                               shill::kGetPropertiesFunction);
96  GetHelper(ipconfig_path)->CallDictionaryValueMethod(&method_call, callback);
97}
98
99void ShillIPConfigClientImpl::Refresh(
100    const dbus::ObjectPath& ipconfig_path,
101    const VoidDBusMethodCallback& callback) {
102  dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
103                               shill::kRefreshFunction);
104  GetHelper(ipconfig_path)->CallVoidMethod(&method_call, callback);
105}
106
107void ShillIPConfigClientImpl::SetProperty(
108    const dbus::ObjectPath& ipconfig_path,
109    const std::string& name,
110    const base::Value& value,
111    const VoidDBusMethodCallback& callback) {
112  dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
113                               shill::kSetPropertyFunction);
114  dbus::MessageWriter writer(&method_call);
115  writer.AppendString(name);
116  // IPConfig supports writing basic type and string array properties.
117  switch (value.GetType()) {
118    case base::Value::TYPE_LIST: {
119      const base::ListValue* list_value = NULL;
120      value.GetAsList(&list_value);
121      dbus::MessageWriter variant_writer(NULL);
122      writer.OpenVariant("as", &variant_writer);
123      dbus::MessageWriter array_writer(NULL);
124      variant_writer.OpenArray("s", &array_writer);
125      for (base::ListValue::const_iterator it = list_value->begin();
126           it != list_value->end();
127           ++it) {
128        DLOG_IF(ERROR, (*it)->GetType() != base::Value::TYPE_STRING)
129            << "Unexpected type " << (*it)->GetType();
130        std::string str;
131        (*it)->GetAsString(&str);
132        array_writer.AppendString(str);
133      }
134      variant_writer.CloseContainer(&array_writer);
135      writer.CloseContainer(&variant_writer);
136    }
137    case base::Value::TYPE_BOOLEAN:
138    case base::Value::TYPE_INTEGER:
139    case base::Value::TYPE_DOUBLE:
140    case base::Value::TYPE_STRING:
141      dbus::AppendBasicTypeValueDataAsVariant(&writer, value);
142      break;
143    default:
144      DLOG(ERROR) << "Unexpected type " << value.GetType();
145  }
146  GetHelper(ipconfig_path)->CallVoidMethod(&method_call, callback);
147}
148
149void ShillIPConfigClientImpl::ClearProperty(
150    const dbus::ObjectPath& ipconfig_path,
151    const std::string& name,
152    const VoidDBusMethodCallback& callback) {
153  dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
154                               shill::kClearPropertyFunction);
155  dbus::MessageWriter writer(&method_call);
156  writer.AppendString(name);
157  GetHelper(ipconfig_path)->CallVoidMethod(&method_call, callback);
158}
159
160void ShillIPConfigClientImpl::Remove(
161    const dbus::ObjectPath& ipconfig_path,
162    const VoidDBusMethodCallback& callback) {
163  dbus::MethodCall method_call(shill::kFlimflamIPConfigInterface,
164                               shill::kRemoveConfigFunction);
165  GetHelper(ipconfig_path)->CallVoidMethod(&method_call, callback);
166}
167
168ShillIPConfigClient::TestInterface*
169ShillIPConfigClientImpl::GetTestInterface() {
170  return NULL;
171}
172
173}  // namespace
174
175ShillIPConfigClient::ShillIPConfigClient() {}
176
177ShillIPConfigClient::~ShillIPConfigClient() {}
178
179// static
180ShillIPConfigClient* ShillIPConfigClient::Create() {
181  return new ShillIPConfigClientImpl();
182}
183
184}  // namespace chromeos
185