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/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 "chromeos/dbus/shill_service_client_stub.h" 13#include "dbus/bus.h" 14#include "dbus/message.h" 15#include "dbus/object_proxy.h" 16#include "third_party/cros_system_api/dbus/service_constants.h" 17 18namespace chromeos { 19 20namespace { 21 22#ifndef DBUS_ERROR_UNKNOWN_OBJECT 23// The linux_chromeos ASAN builder has an older version of dbus-protocol.h 24// so make sure this is defined. 25#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject" 26#endif 27 28// Error callback for GetProperties. 29void OnGetDictionaryError( 30 const std::string& method_name, 31 const dbus::ObjectPath& service_path, 32 const ShillServiceClient::DictionaryValueCallback& callback, 33 const std::string& error_name, 34 const std::string& error_message) { 35 const std::string log_string = 36 "Failed to call org.chromium.shill.Service." + method_name + 37 " for: " + service_path.value() + ": " + 38 error_name + ": " + error_message; 39 40 // Suppress ERROR messages for UnknownMethod/Object" since this can 41 // happen under normal conditions. See crbug.com/130660 and crbug.com/222210. 42 if (error_name == DBUS_ERROR_UNKNOWN_METHOD || 43 error_name == DBUS_ERROR_UNKNOWN_OBJECT) 44 VLOG(1) << log_string; 45 else 46 LOG(ERROR) << log_string; 47 48 base::DictionaryValue empty_dictionary; 49 callback.Run(DBUS_METHOD_CALL_FAILURE, empty_dictionary); 50} 51 52// The ShillServiceClient implementation. 53class ShillServiceClientImpl : public ShillServiceClient { 54 public: 55 explicit ShillServiceClientImpl(dbus::Bus* bus) 56 : bus_(bus), 57 helpers_deleter_(&helpers_) { 58 } 59 60 ///////////////////////////////////// 61 // ShillServiceClient overrides. 62 virtual void AddPropertyChangedObserver( 63 const dbus::ObjectPath& service_path, 64 ShillPropertyChangedObserver* observer) OVERRIDE { 65 GetHelper(service_path)->AddPropertyChangedObserver(observer); 66 } 67 68 virtual void RemovePropertyChangedObserver( 69 const dbus::ObjectPath& service_path, 70 ShillPropertyChangedObserver* observer) OVERRIDE { 71 GetHelper(service_path)->RemovePropertyChangedObserver(observer); 72 } 73 74 virtual void GetProperties(const dbus::ObjectPath& service_path, 75 const DictionaryValueCallback& callback) OVERRIDE { 76 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 77 flimflam::kGetPropertiesFunction); 78 GetHelper(service_path)->CallDictionaryValueMethodWithErrorCallback( 79 &method_call, 80 base::Bind(callback, DBUS_METHOD_CALL_SUCCESS), 81 base::Bind(&OnGetDictionaryError, "GetProperties", 82 service_path, callback)); 83 } 84 85 virtual void SetProperty(const dbus::ObjectPath& service_path, 86 const std::string& name, 87 const base::Value& value, 88 const base::Closure& callback, 89 const ErrorCallback& error_callback) OVERRIDE { 90 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 91 flimflam::kSetPropertyFunction); 92 dbus::MessageWriter writer(&method_call); 93 writer.AppendString(name); 94 ShillClientHelper::AppendValueDataAsVariant(&writer, value); 95 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 96 callback, 97 error_callback); 98 } 99 100 virtual void SetProperties(const dbus::ObjectPath& service_path, 101 const base::DictionaryValue& properties, 102 const base::Closure& callback, 103 const ErrorCallback& error_callback) OVERRIDE { 104 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 105 shill::kSetPropertiesFunction); 106 dbus::MessageWriter writer(&method_call); 107 ShillClientHelper::AppendServicePropertiesDictionary(&writer, properties); 108 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 109 callback, 110 error_callback); 111 } 112 113 virtual void ClearProperty(const dbus::ObjectPath& service_path, 114 const std::string& name, 115 const base::Closure& callback, 116 const ErrorCallback& error_callback) OVERRIDE { 117 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 118 flimflam::kClearPropertyFunction); 119 dbus::MessageWriter writer(&method_call); 120 writer.AppendString(name); 121 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 122 callback, 123 error_callback); 124 } 125 126 127 virtual void ClearProperties(const dbus::ObjectPath& service_path, 128 const std::vector<std::string>& names, 129 const ListValueCallback& callback, 130 const ErrorCallback& error_callback) OVERRIDE { 131 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 132 shill::kClearPropertiesFunction); 133 dbus::MessageWriter writer(&method_call); 134 writer.AppendArrayOfStrings(names); 135 GetHelper(service_path)->CallListValueMethodWithErrorCallback( 136 &method_call, 137 callback, 138 error_callback); 139 } 140 141 virtual void Connect(const dbus::ObjectPath& service_path, 142 const base::Closure& callback, 143 const ErrorCallback& error_callback) OVERRIDE { 144 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 145 flimflam::kConnectFunction); 146 GetHelper(service_path)->CallVoidMethodWithErrorCallback( 147 &method_call, callback, error_callback); 148 } 149 150 virtual void Disconnect(const dbus::ObjectPath& service_path, 151 const base::Closure& callback, 152 const ErrorCallback& error_callback) OVERRIDE { 153 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 154 flimflam::kDisconnectFunction); 155 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 156 callback, 157 error_callback); 158 } 159 160 virtual void Remove(const dbus::ObjectPath& service_path, 161 const base::Closure& callback, 162 const ErrorCallback& error_callback) OVERRIDE { 163 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 164 flimflam::kRemoveServiceFunction); 165 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 166 callback, 167 error_callback); 168 } 169 170 virtual void ActivateCellularModem( 171 const dbus::ObjectPath& service_path, 172 const std::string& carrier, 173 const base::Closure& callback, 174 const ErrorCallback& error_callback) OVERRIDE { 175 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 176 flimflam::kActivateCellularModemFunction); 177 dbus::MessageWriter writer(&method_call); 178 writer.AppendString(carrier); 179 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 180 callback, 181 error_callback); 182 } 183 184 virtual void CompleteCellularActivation( 185 const dbus::ObjectPath& service_path, 186 const base::Closure& callback, 187 const ErrorCallback& error_callback) OVERRIDE { 188 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 189 shill::kCompleteCellularActivationFunction); 190 dbus::MessageWriter writer(&method_call); 191 GetHelper(service_path)->CallVoidMethodWithErrorCallback(&method_call, 192 callback, 193 error_callback); 194 } 195 196 virtual bool CallActivateCellularModemAndBlock( 197 const dbus::ObjectPath& service_path, 198 const std::string& carrier) OVERRIDE { 199 dbus::MethodCall method_call(flimflam::kFlimflamServiceInterface, 200 flimflam::kActivateCellularModemFunction); 201 dbus::MessageWriter writer(&method_call); 202 writer.AppendString(carrier); 203 return GetHelper(service_path)->CallVoidMethodAndBlock(&method_call); 204 } 205 206 virtual void GetLoadableProfileEntries( 207 const dbus::ObjectPath& service_path, 208 const DictionaryValueCallback& callback) OVERRIDE { 209 dbus::MethodCall method_call(flimflam::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 private: 223 typedef std::map<std::string, ShillClientHelper*> HelperMap; 224 225 // Returns the corresponding ShillClientHelper for the profile. 226 ShillClientHelper* GetHelper(const dbus::ObjectPath& service_path) { 227 HelperMap::iterator it = helpers_.find(service_path.value()); 228 if (it != helpers_.end()) 229 return it->second; 230 231 // There is no helper for the profile, create it. 232 dbus::ObjectProxy* object_proxy = 233 bus_->GetObjectProxy(flimflam::kFlimflamServiceName, service_path); 234 ShillClientHelper* helper = new ShillClientHelper(bus_, object_proxy); 235 helper->MonitorPropertyChanged(flimflam::kFlimflamServiceInterface); 236 helpers_.insert(HelperMap::value_type(service_path.value(), helper)); 237 return helper; 238 } 239 240 dbus::Bus* bus_; 241 HelperMap helpers_; 242 STLValueDeleter<HelperMap> helpers_deleter_; 243 244 DISALLOW_COPY_AND_ASSIGN(ShillServiceClientImpl); 245}; 246 247} // namespace 248 249ShillServiceClient::ShillServiceClient() {} 250 251ShillServiceClient::~ShillServiceClient() {} 252 253// static 254ShillServiceClient* ShillServiceClient::Create( 255 DBusClientImplementationType type, 256 dbus::Bus* bus) { 257 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) 258 return new ShillServiceClientImpl(bus); 259 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); 260 return new ShillServiceClientStub(); 261} 262 263} // namespace chromeos 264