aw: Move SharedRendererState out of AwContents
[chromium-blink-merge.git] / chromeos / network / network_configuration_handler.cc
blobc0f653e2bca5dee2882adb76ebbd9a862e15d0e3
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.
5 #include "chromeos/network/network_configuration_handler.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/format_macros.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/stl_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/values.h"
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/shill_manager_client.h"
21 #include "chromeos/dbus/shill_profile_client.h"
22 #include "chromeos/dbus/shill_service_client.h"
23 #include "chromeos/network/network_event_log.h"
24 #include "chromeos/network/network_state.h"
25 #include "chromeos/network/network_state_handler.h"
26 #include "chromeos/network/shill_property_util.h"
27 #include "dbus/object_path.h"
28 #include "third_party/cros_system_api/dbus/service_constants.h"
30 namespace chromeos {
32 namespace {
34 // Strip surrounding "" from keys (if present).
35 std::string StripQuotations(const std::string& in_str) {
36 size_t len = in_str.length();
37 if (len >= 2 && in_str[0] == '"' && in_str[len-1] == '"')
38 return in_str.substr(1, len-2);
39 return in_str;
42 void InvokeErrorCallback(const std::string& service_path,
43 const network_handler::ErrorCallback& error_callback,
44 const std::string& error_name) {
45 std::string error_msg = "Config Error: " + error_name;
46 NET_LOG_ERROR(error_msg, service_path);
47 network_handler::RunErrorCallback(
48 error_callback, service_path, error_name, error_msg);
51 void GetPropertiesCallback(
52 const network_handler::DictionaryResultCallback& callback,
53 const network_handler::ErrorCallback& error_callback,
54 const std::string& service_path,
55 DBusMethodCallStatus call_status,
56 const base::DictionaryValue& properties) {
57 if (call_status != DBUS_METHOD_CALL_SUCCESS) {
58 // Because network services are added and removed frequently, we will see
59 // failures regularly, so don't log these.
60 network_handler::RunErrorCallback(error_callback,
61 service_path,
62 network_handler::kDBusFailedError,
63 network_handler::kDBusFailedErrorMessage);
64 return;
66 if (callback.is_null())
67 return;
69 // Get the correct name from WifiHex if necessary.
70 scoped_ptr<base::DictionaryValue> properties_copy(properties.DeepCopy());
71 std::string name =
72 shill_property_util::GetNameFromProperties(service_path, properties);
73 if (!name.empty())
74 properties_copy->SetStringWithoutPathExpansion(shill::kNameProperty, name);
75 callback.Run(service_path, *properties_copy.get());
78 void SetNetworkProfileErrorCallback(
79 const std::string& service_path,
80 const std::string& profile_path,
81 const network_handler::ErrorCallback& error_callback,
82 const std::string& dbus_error_name,
83 const std::string& dbus_error_message) {
84 network_handler::ShillErrorCallbackFunction(
85 "Config.SetNetworkProfile Failed: " + profile_path,
86 service_path, error_callback,
87 dbus_error_name, dbus_error_message);
90 void LogConfigProperties(const std::string& desc,
91 const std::string& path,
92 const base::DictionaryValue& properties) {
93 for (base::DictionaryValue::Iterator iter(properties);
94 !iter.IsAtEnd(); iter.Advance()) {
95 std::string v = "******";
96 if (!shill_property_util::IsPassphraseKey(iter.key()))
97 base::JSONWriter::Write(&iter.value(), &v);
98 NET_LOG_DEBUG(desc, path + "." + iter.key() + "=" + v);
102 } // namespace
104 // Helper class to request from Shill the profile entries associated with a
105 // Service and delete the service from each profile. Triggers either
106 // |callback| on success or |error_callback| on failure, and calls
107 // |handler|->ProfileEntryDeleterCompleted() on completion to delete itself.
108 class NetworkConfigurationHandler::ProfileEntryDeleter
109 : public base::SupportsWeakPtr<ProfileEntryDeleter> {
110 public:
111 ProfileEntryDeleter(NetworkConfigurationHandler* handler,
112 const std::string& service_path,
113 const base::Closure& callback,
114 const network_handler::ErrorCallback& error_callback)
115 : owner_(handler),
116 service_path_(service_path),
117 callback_(callback),
118 error_callback_(error_callback) {
121 void Run() {
122 DBusThreadManager::Get()->GetShillServiceClient()->
123 GetLoadableProfileEntries(
124 dbus::ObjectPath(service_path_),
125 base::Bind(&ProfileEntryDeleter::GetProfileEntriesToDeleteCallback,
126 AsWeakPtr()));
129 private:
130 void GetProfileEntriesToDeleteCallback(
131 DBusMethodCallStatus call_status,
132 const base::DictionaryValue& profile_entries) {
133 if (call_status != DBUS_METHOD_CALL_SUCCESS) {
134 InvokeErrorCallback(
135 service_path_, error_callback_, "GetLoadableProfileEntriesFailed");
136 owner_->ProfileEntryDeleterCompleted(service_path_); // Deletes this.
137 return;
140 for (base::DictionaryValue::Iterator iter(profile_entries);
141 !iter.IsAtEnd(); iter.Advance()) {
142 std::string profile_path = StripQuotations(iter.key());
143 std::string entry_path;
144 iter.value().GetAsString(&entry_path);
145 if (profile_path.empty() || entry_path.empty()) {
146 NET_LOG_ERROR("Failed to parse Profile Entry", base::StringPrintf(
147 "%s: %s", profile_path.c_str(), entry_path.c_str()));
148 continue;
150 if (profile_delete_entries_.count(profile_path) != 0) {
151 NET_LOG_ERROR("Multiple Profile Entries", base::StringPrintf(
152 "%s: %s", profile_path.c_str(), entry_path.c_str()));
153 continue;
155 NET_LOG_DEBUG("Delete Profile Entry", base::StringPrintf(
156 "%s: %s", profile_path.c_str(), entry_path.c_str()));
157 profile_delete_entries_[profile_path] = entry_path;
158 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry(
159 dbus::ObjectPath(profile_path),
160 entry_path,
161 base::Bind(&ProfileEntryDeleter::ProfileEntryDeletedCallback,
162 AsWeakPtr(), profile_path, entry_path),
163 base::Bind(&ProfileEntryDeleter::ShillErrorCallback,
164 AsWeakPtr(), profile_path, entry_path));
168 void ProfileEntryDeletedCallback(const std::string& profile_path,
169 const std::string& entry) {
170 NET_LOG_DEBUG("Profile Entry Deleted", base::StringPrintf(
171 "%s: %s", profile_path.c_str(), entry.c_str()));
172 profile_delete_entries_.erase(profile_path);
173 if (!profile_delete_entries_.empty())
174 return;
175 // Run the callback if this is the last pending deletion.
176 if (!callback_.is_null())
177 callback_.Run();
178 owner_->ProfileEntryDeleterCompleted(service_path_); // Deletes this.
181 void ShillErrorCallback(const std::string& profile_path,
182 const std::string& entry,
183 const std::string& dbus_error_name,
184 const std::string& dbus_error_message) {
185 // Any Shill Error triggers a failure / error.
186 network_handler::ShillErrorCallbackFunction(
187 "GetLoadableProfileEntries Failed", profile_path, error_callback_,
188 dbus_error_name, dbus_error_message);
189 // Delete this even if there are pending deletions; any callbacks will
190 // safely become no-ops (by invalidating the WeakPtrs).
191 owner_->ProfileEntryDeleterCompleted(service_path_); // Deletes this.
194 NetworkConfigurationHandler* owner_; // Unowned
195 std::string service_path_;
196 base::Closure callback_;
197 network_handler::ErrorCallback error_callback_;
199 // Map of pending profile entry deletions, indexed by profile path.
200 std::map<std::string, std::string> profile_delete_entries_;
202 DISALLOW_COPY_AND_ASSIGN(ProfileEntryDeleter);
205 // NetworkConfigurationHandler
207 void NetworkConfigurationHandler::GetProperties(
208 const std::string& service_path,
209 const network_handler::DictionaryResultCallback& callback,
210 const network_handler::ErrorCallback& error_callback) const {
211 NET_LOG_USER("GetProperties", service_path);
212 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
213 dbus::ObjectPath(service_path),
214 base::Bind(&GetPropertiesCallback,
215 callback, error_callback, service_path));
218 void NetworkConfigurationHandler::SetProperties(
219 const std::string& service_path,
220 const base::DictionaryValue& properties,
221 const base::Closure& callback,
222 const network_handler::ErrorCallback& error_callback) {
223 if (properties.empty()) {
224 if (!callback.is_null())
225 callback.Run();
226 return;
228 NET_LOG_USER("SetProperties", service_path);
229 LogConfigProperties("SetProperty", service_path, properties);
231 DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
232 dbus::ObjectPath(service_path),
233 properties,
234 base::Bind(&NetworkConfigurationHandler::SetPropertiesSuccessCallback,
235 AsWeakPtr(), service_path, callback),
236 base::Bind(&NetworkConfigurationHandler::SetPropertiesErrorCallback,
237 AsWeakPtr(), service_path, error_callback));
240 void NetworkConfigurationHandler::ClearProperties(
241 const std::string& service_path,
242 const std::vector<std::string>& names,
243 const base::Closure& callback,
244 const network_handler::ErrorCallback& error_callback) {
245 if (names.empty()) {
246 if (!callback.is_null())
247 callback.Run();
248 return;
250 NET_LOG_USER("ClearProperties", service_path);
251 for (std::vector<std::string>::const_iterator iter = names.begin();
252 iter != names.end(); ++iter) {
253 NET_LOG_DEBUG("ClearProperty", service_path + "." + *iter);
255 DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties(
256 dbus::ObjectPath(service_path),
257 names,
258 base::Bind(&NetworkConfigurationHandler::ClearPropertiesSuccessCallback,
259 AsWeakPtr(), service_path, names, callback),
260 base::Bind(&NetworkConfigurationHandler::ClearPropertiesErrorCallback,
261 AsWeakPtr(), service_path, error_callback));
264 void NetworkConfigurationHandler::CreateConfiguration(
265 const base::DictionaryValue& properties,
266 const network_handler::StringResultCallback& callback,
267 const network_handler::ErrorCallback& error_callback) {
268 ShillManagerClient* manager =
269 DBusThreadManager::Get()->GetShillManagerClient();
270 std::string type;
271 properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
272 DCHECK(!type.empty());
273 if (NetworkTypePattern::Ethernet().MatchesType(type)) {
274 InvokeErrorCallback(
275 shill_property_util::GetNetworkIdFromProperties(properties),
276 error_callback,
277 "ConfigureServiceForProfile: Invalid type: " + type);
278 return;
281 NET_LOG_USER("CreateConfiguration: " + type,
282 shill_property_util::GetNetworkIdFromProperties(properties));
283 LogConfigProperties("Configure", type, properties);
285 std::string profile;
286 properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
287 &profile);
288 DCHECK(!profile.empty());
289 manager->ConfigureServiceForProfile(
290 dbus::ObjectPath(profile),
291 properties,
292 base::Bind(&NetworkConfigurationHandler::RunCreateNetworkCallback,
293 AsWeakPtr(),
294 callback),
295 base::Bind(&network_handler::ShillErrorCallbackFunction,
296 "Config.CreateConfiguration Failed",
298 error_callback));
301 void NetworkConfigurationHandler::RemoveConfiguration(
302 const std::string& service_path,
303 const base::Closure& callback,
304 const network_handler::ErrorCallback& error_callback) {
305 // Service.Remove is not reliable. Instead, request the profile entries
306 // for the service and remove each entry.
307 if (ContainsKey(profile_entry_deleters_, service_path)) {
308 InvokeErrorCallback(
309 service_path, error_callback, "RemoveConfigurationInProgress");
310 return;
313 NET_LOG_USER("Remove Configuration", service_path);
314 ProfileEntryDeleter* deleter =
315 new ProfileEntryDeleter(this, service_path, callback, error_callback);
316 profile_entry_deleters_[service_path] = deleter;
317 deleter->Run();
320 void NetworkConfigurationHandler::SetNetworkProfile(
321 const std::string& service_path,
322 const std::string& profile_path,
323 const base::Closure& callback,
324 const network_handler::ErrorCallback& error_callback) {
325 NET_LOG_USER("SetNetworkProfile", service_path + ": " + profile_path);
326 base::StringValue profile_path_value(profile_path);
327 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
328 dbus::ObjectPath(service_path),
329 shill::kProfileProperty,
330 profile_path_value,
331 callback,
332 base::Bind(&SetNetworkProfileErrorCallback,
333 service_path, profile_path, error_callback));
336 // NetworkConfigurationHandler Private methods
338 NetworkConfigurationHandler::NetworkConfigurationHandler()
339 : network_state_handler_(NULL) {
342 NetworkConfigurationHandler::~NetworkConfigurationHandler() {
343 STLDeleteContainerPairSecondPointers(
344 profile_entry_deleters_.begin(), profile_entry_deleters_.end());
347 void NetworkConfigurationHandler::Init(
348 NetworkStateHandler* network_state_handler) {
349 network_state_handler_ = network_state_handler;
352 void NetworkConfigurationHandler::RunCreateNetworkCallback(
353 const network_handler::StringResultCallback& callback,
354 const dbus::ObjectPath& service_path) {
355 if (!callback.is_null())
356 callback.Run(service_path.value());
357 // This may also get called when CreateConfiguration is used to update an
358 // existing configuration, so request a service update just in case.
359 // TODO(pneubeck): Separate 'Create' and 'Update' calls and only trigger
360 // this on an update.
361 network_state_handler_->RequestUpdateForNetwork(service_path.value());
364 void NetworkConfigurationHandler::ProfileEntryDeleterCompleted(
365 const std::string& service_path) {
366 std::map<std::string, ProfileEntryDeleter*>::iterator iter =
367 profile_entry_deleters_.find(service_path);
368 DCHECK(iter != profile_entry_deleters_.end());
369 delete iter->second;
370 profile_entry_deleters_.erase(iter);
373 void NetworkConfigurationHandler::SetPropertiesSuccessCallback(
374 const std::string& service_path,
375 const base::Closure& callback) {
376 if (!callback.is_null())
377 callback.Run();
378 network_state_handler_->RequestUpdateForNetwork(service_path);
381 void NetworkConfigurationHandler::SetPropertiesErrorCallback(
382 const std::string& service_path,
383 const network_handler::ErrorCallback& error_callback,
384 const std::string& dbus_error_name,
385 const std::string& dbus_error_message) {
386 network_handler::ShillErrorCallbackFunction(
387 "Config.SetProperties Failed",
388 service_path, error_callback,
389 dbus_error_name, dbus_error_message);
390 // Some properties may have changed so request an update regardless.
391 network_state_handler_->RequestUpdateForNetwork(service_path);
394 void NetworkConfigurationHandler::ClearPropertiesSuccessCallback(
395 const std::string& service_path,
396 const std::vector<std::string>& names,
397 const base::Closure& callback,
398 const base::ListValue& result) {
399 const std::string kClearPropertiesFailedError("Error.ClearPropertiesFailed");
400 DCHECK(names.size() == result.GetSize())
401 << "Incorrect result size from ClearProperties.";
403 for (size_t i = 0; i < result.GetSize(); ++i) {
404 bool success = false;
405 result.GetBoolean(i, &success);
406 if (!success) {
407 // If a property was cleared that has never been set, the clear will fail.
408 // We do not track which properties have been set, so just log the error.
409 NET_LOG_ERROR("ClearProperties Failed: " + names[i], service_path);
413 if (!callback.is_null())
414 callback.Run();
415 network_state_handler_->RequestUpdateForNetwork(service_path);
418 void NetworkConfigurationHandler::ClearPropertiesErrorCallback(
419 const std::string& service_path,
420 const network_handler::ErrorCallback& error_callback,
421 const std::string& dbus_error_name,
422 const std::string& dbus_error_message) {
423 network_handler::ShillErrorCallbackFunction(
424 "Config.ClearProperties Failed",
425 service_path, error_callback,
426 dbus_error_name, dbus_error_message);
427 // Some properties may have changed so request an update regardless.
428 network_state_handler_->RequestUpdateForNetwork(service_path);
431 // static
432 NetworkConfigurationHandler* NetworkConfigurationHandler::InitializeForTest(
433 NetworkStateHandler* network_state_handler) {
434 NetworkConfigurationHandler* handler = new NetworkConfigurationHandler();
435 handler->Init(network_state_handler);
436 return handler;
439 } // namespace chromeos