shill_service_client.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/memory/weak_ptr.h" 9#include "base/message_loop/message_loop.h" 10#include "base/stl_util.h" 11#include "base/values.h" 12#include "chromeos/dbus/shill_property_changed_observer.h" 13#include "chromeos/network/network_event_log.h" 14#include "dbus/bus.h" 15#include "dbus/message.h" 16#include "dbus/object_proxy.h" 17#include "third_party/cros_system_api/dbus/service_constants.h" 18 19namespace chromeos { 20 21namespace { 22 23#ifndef DBUS_ERROR_UNKNOWN_OBJECT 24// The linux_chromeos ASAN builder has an older version of dbus-protocol.h 25// so make sure this is defined. 26#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject" 27#endif 28 29// Error callback for GetProperties. 30void OnGetDictionaryError( 31 const std::string& method_name, 32 const dbus::ObjectPath& service_path, 33 const ShillServiceClient::DictionaryValueCallback& callback, 34 const std::string& error_name, 35 const std::string& error_message) { 36 const std::string log_string = 37 "Failed to call org.chromium.shill.Service." + method_name + 38 " for: " + service_path.value() + ": " + 39 error_name + ": " + error_message; 40 41 // Suppress ERROR messages for UnknownMethod/Object" since this can 42 // happen under normal conditions. See crbug.com/130660 and crbug.com/222210. 43 if (error_name == DBUS_ERROR_UNKNOWN_METHOD || 44 error_name == DBUS_ERROR_UNKNOWN_OBJECT) 45 VLOG(1) << log_string; 46 else 47 LOG(ERROR) << log_string; 48 49 base::DictionaryValue empty_dictionary; 50 callback.Run(DBUS_METHOD_CALL_FAILURE, empty_dictionary); 51} 52 53// The ShillServiceClient implementation. 54class ShillServiceClientImpl : public ShillServiceClient { 55 public: 56 explicit ShillServiceClientImpl() 57 : bus_(NULL), 58 weak_ptr_factory_(this) { 59 } 60 61 virtual ~ShillServiceClientImpl() { 62 for (HelperMap::iterator iter = helpers_.begin(); 63 iter != helpers_.end(); ++iter) { 64 ShillClientHelper* helper = iter->second; 65 bus_->RemoveObjectProxy(shill::kFlimflamServiceName, 66 helper->object_proxy()->object_path(), 67 base::Bind(&base::DoNothing)); 68 delete helper; 69 } 70 } 71 72 virtual void AddPropertyChangedObserver( 73 const dbus::ObjectPath& service_path, 74 ShillPropertyChangedObserver* observer) OVERRIDE { 75 GetHelper(service_path)->AddPropertyChangedObserver(observer); 76 } 77 78 virtual void RemovePropertyChangedObserver( 79 const dbus::ObjectPath& service_path, 80 ShillPropertyChangedObserver* observer) OVERRIDE { 81 GetHelper(service_path)->RemovePropertyChangedObserver(observer); 82 } 83 84 virtual void GetProperties(const dbus::ObjectPath& service_path, 85 const DictionaryValueCallback& callback) OVERRIDE { 86 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 87 shill::kGetPropertiesFunction); 88 GetHelper(service_path)->CallDictionaryValueMethodWithErrorCallback( 89 &method_call, 90 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS), 91 base::Bind(&OnGetDictionaryError, "GetProperties", 92 service_path, callback)); 93 } 94 95 virtual void SetProperty(const dbus::ObjectPath& service_path, 96 const std::string& name, 97 const base::Value& value, 98 const base::Closure& callback, 99 const ErrorCallback& error_callback) OVERRIDE { 100 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 101 shill::kSetPropertyFunction); 102 dbus::MessageWriter writer(&method_call); 103 writer.AppendString(name); 104 ShillClientHelper::AppendValueDataAsVariant(&writer, value); 105 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 106 callback, 107 error_callback); 108 } 109 110 virtual void SetProperties(const dbus::ObjectPath& service_path, 111 const base::DictionaryValue& properties, 112 const base::Closure& callback, 113 const ErrorCallback& error_callback) OVERRIDE { 114 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 115 shill::kSetPropertiesFunction); 116 dbus::MessageWriter writer(&method_call); 117 ShillClientHelper::AppendServicePropertiesDictionary(&writer, properties); 118 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 119 callback, 120 error_callback); 121 } 122 123 virtual void ClearProperty(const dbus::ObjectPath& service_path, 124 const std::string& name, 125 const base::Closure& callback, 126 const ErrorCallback& error_callback) OVERRIDE { 127 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 128 shill::kClearPropertyFunction); 129 dbus::MessageWriter writer(&method_call); 130 writer.AppendString(name); 131 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 132 callback, 133 error_callback); 134 } 135 136 137 virtual void ClearProperties(const dbus::ObjectPath& service_path, 138 const std::vector<std::string>& names, 139 const ListValueCallback& callback, 140 const ErrorCallback& error_callback) OVERRIDE { 141 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 142 shill::kClearPropertiesFunction); 143 dbus::MessageWriter writer(&method_call); 144 writer.AppendArrayOfStrings(names); 145 GetHelper(service_path)->CallListValueMethodWithErrorCallback( 146 &method_call, 147 callback, 148 error_callback); 149 } 150 151 virtual void Connect(const dbus::ObjectPath& service_path, 152 const base::Closure& callback, 153 const ErrorCallback& error_callback) OVERRIDE { 154 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 155 shill::kConnectFunction); 156 GetHelper(service_path)->CallVoidMethodWithErrorCallback( 157 &method_call, callback, error_callback); 158 } 159 160 virtual void Disconnect(const dbus::ObjectPath& service_path, 161 const base::Closure& callback, 162 const ErrorCallback& error_callback) OVERRIDE { 163 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 164 shill::kDisconnectFunction); 165 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 166 callback, 167 error_callback); 168 } 169 170 virtual void Remove(const dbus::ObjectPath& service_path, 171 const base::Closure& callback, 172 const ErrorCallback& error_callback) OVERRIDE { 173 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 174 shill::kRemoveServiceFunction); 175 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 176 callback, 177 error_callback); 178 } 179 180 virtual void ActivateCellularModem( 181 const dbus::ObjectPath& service_path, 182 const std::string& carrier, 183 const base::Closure& callback, 184 const ErrorCallback& error_callback) OVERRIDE { 185 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 186 shill::kActivateCellularModemFunction); 187 dbus::MessageWriter writer(&method_call); 188 writer.AppendString(carrier); 189 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 190 callback, 191 error_callback); 192 } 193 194 virtual void CompleteCellularActivation( 195 const dbus::ObjectPath& service_path, 196 const base::Closure& callback, 197 const ErrorCallback& error_callback) OVERRIDE { 198 dbus::MethodCall method_call(shill::kFlimflamServiceInterface, 199 shill::kCompleteCellularActivationFunction); 200 dbus::MessageWriter writer(&method_call); 201 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 202 callback, 203 error_callback); 204 } 205 206 virtual void GetLoadableProfileEntries( 207 const dbus::ObjectPath& service_path, 208 const DictionaryValueCallback& callback) OVERRIDE { 209 dbus::MethodCall method_call(shill::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 protected: 223 virtual void Init(dbus::Bus* bus) OVERRIDE { 224 bus_ = bus; 225 } 226 227 private: 228 typedef std::map<std::string, ShillClientHelper*> HelperMap; 229 230 // Returns the corresponding ShillClientHelper for the profile. 231 ShillClientHelper* GetHelper(const dbus::ObjectPath& service_path) { 232 HelperMap::iterator it = helpers_.find(service_path.value()); 233 if (it != helpers_.end()) 234 return it->second; 235 236 // There is no helper for the profile, create it. 237 NET_LOG_DEBUG("AddShillClientHelper", service_path.value()); 238 dbus::ObjectProxy* object_proxy = 239 bus_->GetObjectProxy(shill::kFlimflamServiceName, service_path); 240 ShillClientHelper* helper = new ShillClientHelper(object_proxy); 241 helper->SetReleasedCallback( 242 base::Bind(&ShillServiceClientImpl::NotifyReleased, 243 weak_ptr_factory_.GetWeakPtr())); 244 helper->MonitorPropertyChanged(shill::kFlimflamServiceInterface); 245 helpers_.insert(HelperMap::value_type(service_path.value(), helper)); 246 return helper; 247 } 248 249 void NotifyReleased(ShillClientHelper* helper) { 250 // New Shill Service DBus objects are created relatively frequently, so 251 // remove them when they become inactive (no observers and no active method 252 // calls). 253 dbus::ObjectPath object_path = helper->object_proxy()->object_path(); 254 // Make sure we don't release the proxy used by ShillManagerClient ("/"). 255 // This shouldn't ever happen, but might if a bug in the code requests 256 // a service with path "/", or a bug in Shill passes "/" as a service path. 257 // Either way this would cause an invalid memory access in 258 // ShillManagerClient, see crbug.com/324849. 259 if (object_path == dbus::ObjectPath(shill::kFlimflamServicePath)) { 260 NET_LOG_ERROR("ShillServiceClient service has invalid path", 261 shill::kFlimflamServicePath); 262 return; 263 } 264 NET_LOG_DEBUG("RemoveShillClientHelper", object_path.value()); 265 bus_->RemoveObjectProxy(shill::kFlimflamServiceName, 266 object_path, base::Bind(&base::DoNothing)); 267 helpers_.erase(object_path.value()); 268 delete helper; 269 } 270 271 dbus::Bus* bus_; 272 HelperMap helpers_; 273 base::WeakPtrFactory<ShillServiceClientImpl> weak_ptr_factory_; 274 275 DISALLOW_COPY_AND_ASSIGN(ShillServiceClientImpl); 276}; 277 278} // namespace 279 280ShillServiceClient::ShillServiceClient() {} 281 282ShillServiceClient::~ShillServiceClient() {} 283 284// static 285ShillServiceClient* ShillServiceClient::Create() { 286 return new ShillServiceClientImpl(); 287} 288 289} // namespace chromeos 290