network_configuration_handler.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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/network/network_configuration_handler.h"
6
7#include <string>
8#include <vector>
9
10#include "base/bind.h"
11#include "base/logging.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/values.h"
15#include "chromeos/dbus/dbus_method_call_status.h"
16#include "chromeos/dbus/dbus_thread_manager.h"
17#include "chromeos/dbus/shill_manager_client.h"
18#include "chromeos/dbus/shill_service_client.h"
19#include "dbus/object_path.h"
20#include "third_party/cros_system_api/dbus/service_constants.h"
21
22namespace chromeos {
23
24namespace {
25
26const char kLogModule[] = "NetworkConfigurationHandler";
27
28NetworkConfigurationHandler* g_configuration_handler_instance = NULL;
29
30// None of these error messages are user-facing: they should only appear in
31// logs.
32const char kErrorsListTag[] = "errors";
33const char kClearPropertiesFailedError[] = "Error.ClearPropertiesFailed";
34const char kClearPropertiesFailedErrorMessage[] = "Clear properties failed";
35const char kDBusFailedError[] = "Error.DBusFailed";
36const char kDBusFailedErrorMessage[] = "DBus call failed.";
37
38void ClearPropertiesCallback(
39    const std::vector<std::string>& names,
40    const std::string& service_path,
41    const base::Closure& callback,
42    const network_handler::ErrorCallback& error_callback,
43    const base::ListValue& result) {
44  bool some_failed = false;
45  for (size_t i = 0; i < result.GetSize(); ++i) {
46    bool success;
47    if (result.GetBoolean(i, &success)) {
48      if (!success) {
49        some_failed = true;
50        break;
51      }
52    } else {
53      NOTREACHED() << "Result garbled from ClearProperties";
54    }
55  }
56
57  if (some_failed) {
58    DCHECK(names.size() == result.GetSize())
59        << "Result wrong size from ClearProperties.";
60    scoped_ptr<base::DictionaryValue> error_data(
61        network_handler::CreateErrorData(service_path,
62                                         kClearPropertiesFailedError,
63                                         kClearPropertiesFailedErrorMessage));
64    LOG(ERROR) << "ClearPropertiesCallback failed for service path: "
65               << service_path;
66    error_data->Set("errors", result.DeepCopy());
67    scoped_ptr<base::ListValue> name_list(new base::ListValue);
68    name_list->AppendStrings(names);
69    error_data->Set("names", name_list.release());
70    error_callback.Run(kClearPropertiesFailedError, error_data.Pass());
71  } else {
72    callback.Run();
73  }
74}
75
76// Used to translate the dbus dictionary callback into one that calls
77// the error callback if we have a failure.
78void RunCallbackWithDictionaryValue(
79    const network_handler::DictionaryResultCallback& callback,
80    const network_handler::ErrorCallback& error_callback,
81    const std::string& service_path,
82    DBusMethodCallStatus call_status,
83    const base::DictionaryValue& value) {
84  if (call_status != DBUS_METHOD_CALL_SUCCESS) {
85    scoped_ptr<base::DictionaryValue> error_data(
86        network_handler::CreateErrorData(service_path,
87                                         kDBusFailedError,
88                                         kDBusFailedErrorMessage));
89    LOG(ERROR) << "CallbackWithDictionaryValue failed for service path: "
90               << service_path;
91    error_callback.Run(kDBusFailedError, error_data.Pass());
92  } else {
93    callback.Run(service_path, value);
94  }
95}
96
97void RunCreateNetworkCallback(
98    const network_handler::StringResultCallback& callback,
99    const dbus::ObjectPath& service_path) {
100  callback.Run(service_path.value());
101}
102
103void IgnoreObjectPathCallback(const base::Closure& callback,
104                              const dbus::ObjectPath& object_path) {
105  callback.Run();
106}
107
108}  // namespace
109
110// static
111void NetworkConfigurationHandler::Initialize() {
112  CHECK(!g_configuration_handler_instance);
113  g_configuration_handler_instance = new NetworkConfigurationHandler;
114}
115
116// static
117void NetworkConfigurationHandler::Shutdown() {
118  CHECK(g_configuration_handler_instance);
119  delete g_configuration_handler_instance;
120  g_configuration_handler_instance = NULL;
121}
122
123// static
124NetworkConfigurationHandler* NetworkConfigurationHandler::Get() {
125  CHECK(g_configuration_handler_instance)
126      << "NetworkConfigurationHandler::Get() called before Initialize()";
127  return g_configuration_handler_instance;
128}
129
130void NetworkConfigurationHandler::GetProperties(
131    const std::string& service_path,
132    const network_handler::DictionaryResultCallback& callback,
133    const network_handler::ErrorCallback& error_callback) const {
134  DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
135      dbus::ObjectPath(service_path),
136      base::Bind(&RunCallbackWithDictionaryValue,
137                 callback,
138                 error_callback,
139                 service_path));
140}
141
142void NetworkConfigurationHandler::SetProperties(
143    const std::string& service_path,
144    const base::DictionaryValue& properties,
145    const base::Closure& callback,
146    const network_handler::ErrorCallback& error_callback) const {
147  DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService(
148      properties,
149      base::Bind(&IgnoreObjectPathCallback, callback),
150      base::Bind(&network_handler::ShillErrorCallbackFunction,
151                 kLogModule, service_path, error_callback));
152}
153
154void NetworkConfigurationHandler::ClearProperties(
155    const std::string& service_path,
156    const std::vector<std::string>& names,
157    const base::Closure& callback,
158    const network_handler::ErrorCallback& error_callback) {
159  DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties(
160      dbus::ObjectPath(service_path),
161      names,
162      base::Bind(&ClearPropertiesCallback,
163                 names,
164                 service_path,
165                 callback,
166                 error_callback),
167      base::Bind(&network_handler::ShillErrorCallbackFunction,
168                 kLogModule, service_path, error_callback));
169}
170
171void NetworkConfigurationHandler::CreateConfiguration(
172    const base::DictionaryValue& properties,
173    const network_handler::StringResultCallback& callback,
174    const network_handler::ErrorCallback& error_callback) const {
175  ShillManagerClient* manager =
176      DBusThreadManager::Get()->GetShillManagerClient();
177
178  std::string type;
179  properties.GetStringWithoutPathExpansion(flimflam::kTypeProperty, &type);
180  // Shill supports ConfigureServiceForProfile only for network type WiFi. In
181  // all other cases, we have to rely on GetService for now. This is
182  // unproblematic for VPN (user profile only), but will lead to inconsistencies
183  // with WiMax, for example.
184  if (type == flimflam::kTypeWifi) {
185    std::string profile;
186    properties.GetStringWithoutPathExpansion(flimflam::kProfileProperty,
187                                             &profile);
188    manager->ConfigureServiceForProfile(
189        dbus::ObjectPath(profile),
190        properties,
191        base::Bind(&RunCreateNetworkCallback, callback),
192        base::Bind(&network_handler::ShillErrorCallbackFunction,
193                   kLogModule, "", error_callback));
194  } else {
195    manager->GetService(
196        properties,
197        base::Bind(&RunCreateNetworkCallback, callback),
198        base::Bind(&network_handler::ShillErrorCallbackFunction,
199                   kLogModule, "", error_callback));
200  }
201}
202
203void NetworkConfigurationHandler::RemoveConfiguration(
204    const std::string& service_path,
205    const base::Closure& callback,
206    const network_handler::ErrorCallback& error_callback) const {
207  DBusThreadManager::Get()->GetShillServiceClient()->Remove(
208      dbus::ObjectPath(service_path),
209      callback,
210      base::Bind(&network_handler::ShillErrorCallbackFunction,
211                 kLogModule, service_path, error_callback));
212}
213
214NetworkConfigurationHandler::NetworkConfigurationHandler() {
215}
216
217NetworkConfigurationHandler::~NetworkConfigurationHandler() {
218}
219
220}  // namespace chromeos
221