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 #include "chromeos/dbus/gsm_sms_client.h" 5 6 #include <map> 7 #include <utility> 8 #include <vector> 9 10 #include "base/bind.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/message_loop/message_loop.h" 14 #include "base/stl_util.h" 15 #include "base/strings/stringprintf.h" 16 #include "base/values.h" 17 #include "dbus/bus.h" 18 #include "dbus/message.h" 19 #include "dbus/object_proxy.h" 20 #include "dbus/values_util.h" 21 #include "third_party/cros_system_api/dbus/service_constants.h" 22 23 namespace chromeos { 24 25 namespace { 26 27 // A class actually making method calls for SMS services, used by 28 // GsmSMSClientImpl. 29 class SMSProxy { 30 public: 31 typedef GsmSMSClient::SmsReceivedHandler SmsReceivedHandler; 32 typedef GsmSMSClient::DeleteCallback DeleteCallback; 33 typedef GsmSMSClient::GetCallback GetCallback; 34 typedef GsmSMSClient::ListCallback ListCallback; 35 36 SMSProxy(dbus::Bus* bus, 37 const std::string& service_name, 38 const dbus::ObjectPath& object_path) 39 : proxy_(bus->GetObjectProxy(service_name, object_path)), 40 weak_ptr_factory_(this) { 41 proxy_->ConnectToSignal( 42 modemmanager::kModemManagerSMSInterface, 43 modemmanager::kSMSReceivedSignal, 44 base::Bind(&SMSProxy::OnSmsReceived, weak_ptr_factory_.GetWeakPtr()), 45 base::Bind(&SMSProxy::OnSignalConnected, 46 weak_ptr_factory_.GetWeakPtr())); 47 } 48 49 // Sets SmsReceived signal handler. 50 void SetSmsReceivedHandler(const SmsReceivedHandler& handler) { 51 DCHECK(sms_received_handler_.is_null()); 52 sms_received_handler_ = handler; 53 } 54 55 // Resets SmsReceived signal handler. 56 void ResetSmsReceivedHandler() { 57 sms_received_handler_.Reset(); 58 } 59 60 // Calls Delete method. 61 void Delete(uint32 index, const DeleteCallback& callback) { 62 dbus::MethodCall method_call(modemmanager::kModemManagerSMSInterface, 63 modemmanager::kSMSDeleteFunction); 64 dbus::MessageWriter writer(&method_call); 65 writer.AppendUint32(index); 66 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 67 base::Bind(&SMSProxy::OnDelete, 68 weak_ptr_factory_.GetWeakPtr(), 69 callback)); 70 } 71 72 // Calls Get method. 73 void Get(uint32 index, const GetCallback& callback) { 74 dbus::MethodCall method_call(modemmanager::kModemManagerSMSInterface, 75 modemmanager::kSMSGetFunction); 76 dbus::MessageWriter writer(&method_call); 77 writer.AppendUint32(index); 78 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 79 base::Bind(&SMSProxy::OnGet, 80 weak_ptr_factory_.GetWeakPtr(), 81 callback)); 82 } 83 84 // Calls List method. 85 void List(const ListCallback& callback) { 86 dbus::MethodCall method_call(modemmanager::kModemManagerSMSInterface, 87 modemmanager::kSMSListFunction); 88 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 89 base::Bind(&SMSProxy::OnList, 90 weak_ptr_factory_.GetWeakPtr(), 91 callback)); 92 } 93 94 private: 95 // Handles SmsReceived signal. 96 void OnSmsReceived(dbus::Signal* signal) { 97 uint32 index = 0; 98 bool complete = false; 99 dbus::MessageReader reader(signal); 100 if (!reader.PopUint32(&index) || 101 !reader.PopBool(&complete)) { 102 LOG(ERROR) << "Invalid signal: " << signal->ToString(); 103 return; 104 } 105 if (!sms_received_handler_.is_null()) 106 sms_received_handler_.Run(index, complete); 107 } 108 109 // Handles the result of signal connection setup. 110 void OnSignalConnected(const std::string& interface, 111 const std::string& signal, 112 bool succeeded) { 113 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " << 114 signal << " failed."; 115 } 116 117 // Handles responses of Delete method calls. 118 void OnDelete(const DeleteCallback& callback, dbus::Response* response) { 119 if (!response) 120 return; 121 callback.Run(); 122 } 123 124 // Handles responses of Get method calls. 125 void OnGet(const GetCallback& callback, dbus::Response* response) { 126 if (!response) 127 return; 128 dbus::MessageReader reader(response); 129 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); 130 base::DictionaryValue* dictionary_value = NULL; 131 if (!value.get() || !value->GetAsDictionary(&dictionary_value)) { 132 LOG(WARNING) << "Invalid response: " << response->ToString(); 133 return; 134 } 135 callback.Run(*dictionary_value); 136 } 137 138 // Handles responses of List method calls. 139 void OnList(const ListCallback& callback, dbus::Response* response) { 140 if (!response) 141 return; 142 dbus::MessageReader reader(response); 143 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); 144 base::ListValue* list_value = NULL; 145 if (!value.get() || !value->GetAsList(&list_value)) { 146 LOG(WARNING) << "Invalid response: " << response->ToString(); 147 return; 148 } 149 callback.Run(*list_value); 150 } 151 152 dbus::ObjectProxy* proxy_; 153 SmsReceivedHandler sms_received_handler_; 154 155 // Note: This should remain the last member so it'll be destroyed and 156 // invalidate its weak pointers before any other members are destroyed. 157 base::WeakPtrFactory<SMSProxy> weak_ptr_factory_; 158 159 DISALLOW_COPY_AND_ASSIGN(SMSProxy); 160 }; 161 162 // The GsmSMSClient implementation. 163 class GsmSMSClientImpl : public GsmSMSClient { 164 public: 165 GsmSMSClientImpl() : bus_(NULL), proxies_deleter_(&proxies_) {} 166 167 // GsmSMSClient override. 168 virtual void SetSmsReceivedHandler( 169 const std::string& service_name, 170 const dbus::ObjectPath& object_path, 171 const SmsReceivedHandler& handler) OVERRIDE { 172 GetProxy(service_name, object_path)->SetSmsReceivedHandler(handler); 173 } 174 175 // GsmSMSClient override. 176 virtual void ResetSmsReceivedHandler( 177 const std::string& service_name, 178 const dbus::ObjectPath& object_path) OVERRIDE { 179 GetProxy(service_name, object_path)->ResetSmsReceivedHandler(); 180 } 181 182 // GsmSMSClient override. 183 virtual void Delete(const std::string& service_name, 184 const dbus::ObjectPath& object_path, 185 uint32 index, 186 const DeleteCallback& callback) OVERRIDE { 187 GetProxy(service_name, object_path)->Delete(index, callback); 188 } 189 190 // GsmSMSClient override. 191 virtual void Get(const std::string& service_name, 192 const dbus::ObjectPath& object_path, 193 uint32 index, 194 const GetCallback& callback) OVERRIDE { 195 GetProxy(service_name, object_path)->Get(index, callback); 196 } 197 198 // GsmSMSClient override. 199 virtual void List(const std::string& service_name, 200 const dbus::ObjectPath& object_path, 201 const ListCallback& callback) OVERRIDE { 202 GetProxy(service_name, object_path)->List(callback); 203 } 204 205 // GsmSMSClient override. 206 virtual void RequestUpdate(const std::string& service_name, 207 const dbus::ObjectPath& object_path) OVERRIDE { 208 } 209 210 protected: 211 virtual void Init(dbus::Bus* bus) OVERRIDE { bus_ = bus; } 212 213 private: 214 typedef std::map<std::pair<std::string, std::string>, SMSProxy*> ProxyMap; 215 216 // Returns a SMSProxy for the given service name and object path. 217 SMSProxy* GetProxy(const std::string& service_name, 218 const dbus::ObjectPath& object_path) { 219 const ProxyMap::key_type key(service_name, object_path.value()); 220 ProxyMap::iterator it = proxies_.find(key); 221 if (it != proxies_.end()) 222 return it->second; 223 224 // There is no proxy for the service_name and object_path, create it. 225 SMSProxy* proxy = new SMSProxy(bus_, service_name, object_path); 226 proxies_.insert(ProxyMap::value_type(key, proxy)); 227 return proxy; 228 } 229 230 dbus::Bus* bus_; 231 ProxyMap proxies_; 232 STLValueDeleter<ProxyMap> proxies_deleter_; 233 234 DISALLOW_COPY_AND_ASSIGN(GsmSMSClientImpl); 235 }; 236 237 } // namespace 238 239 //////////////////////////////////////////////////////////////////////////////// 240 // GsmSMSClient 241 242 GsmSMSClient::GsmSMSClient() {} 243 244 GsmSMSClient::~GsmSMSClient() {} 245 246 // static 247 GsmSMSClient* GsmSMSClient::Create() { 248 return new GsmSMSClientImpl(); 249 } 250 251 } // namespace chromeos 252