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