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/modem_messaging_client.h" 5 6 #include <map> 7 #include <utility> 8 9 #include "base/bind.h" 10 #include "base/memory/weak_ptr.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/stl_util.h" 13 #include "base/values.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 19 namespace chromeos { 20 21 namespace { 22 23 // A class which makes method calls for SMS services via the 24 // org.freedesktop.ModemManager1.Messaging object. 25 class ModemMessagingProxy { 26 public: 27 typedef ModemMessagingClient::SmsReceivedHandler SmsReceivedHandler; 28 typedef ModemMessagingClient::ListCallback ListCallback; 29 typedef ModemMessagingClient::DeleteCallback DeleteCallback; 30 31 ModemMessagingProxy(dbus::Bus* bus, 32 const std::string& service_name, 33 const dbus::ObjectPath& object_path) 34 : bus_(bus), 35 proxy_(bus->GetObjectProxy(service_name, object_path)), 36 service_name_(service_name), 37 weak_ptr_factory_(this) { 38 proxy_->ConnectToSignal( 39 modemmanager::kModemManager1MessagingInterface, 40 modemmanager::kSMSAddedSignal, 41 base::Bind(&ModemMessagingProxy::OnSmsAdded, 42 weak_ptr_factory_.GetWeakPtr()), 43 base::Bind(&ModemMessagingProxy::OnSignalConnected, 44 weak_ptr_factory_.GetWeakPtr())); 45 } 46 virtual ~ModemMessagingProxy() {} 47 48 // Sets SmsReceived signal handler. 49 void SetSmsReceivedHandler(const SmsReceivedHandler& handler) { 50 DCHECK(sms_received_handler_.is_null()); 51 sms_received_handler_ = handler; 52 } 53 54 // Resets SmsReceived signal handler. 55 void ResetSmsReceivedHandler() { 56 sms_received_handler_.Reset(); 57 } 58 59 // Calls Delete method. 60 void Delete(const dbus::ObjectPath& message_path, 61 const DeleteCallback& callback) { 62 dbus::MethodCall method_call(modemmanager::kModemManager1MessagingInterface, 63 modemmanager::kSMSDeleteFunction); 64 dbus::MessageWriter writer(&method_call); 65 writer.AppendObjectPath(message_path); 66 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 67 base::Bind(&ModemMessagingProxy::OnDelete, 68 weak_ptr_factory_.GetWeakPtr(), 69 callback)); 70 } 71 72 // Calls List method. 73 virtual void List(const ListCallback& callback) { 74 dbus::MethodCall method_call(modemmanager::kModemManager1MessagingInterface, 75 modemmanager::kSMSListFunction); 76 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 77 base::Bind(&ModemMessagingProxy::OnList, 78 weak_ptr_factory_.GetWeakPtr(), 79 callback)); 80 } 81 82 private: 83 // Handles SmsAdded signal. 84 void OnSmsAdded(dbus::Signal* signal) { 85 dbus::ObjectPath message_path; 86 bool complete = false; 87 dbus::MessageReader reader(signal); 88 if (!reader.PopObjectPath(&message_path) || 89 !reader.PopBool(&complete)) { 90 LOG(ERROR) << "Invalid signal: " << signal->ToString(); 91 return; 92 } 93 if (!sms_received_handler_.is_null()) { 94 sms_received_handler_.Run(message_path, complete); 95 } 96 } 97 98 // Handles responses of Delete method calls. 99 void OnDelete(const DeleteCallback& callback, dbus::Response* response) { 100 if (!response) 101 return; 102 callback.Run(); 103 } 104 105 // Handles responses of List method calls. 106 void OnList(const ListCallback& callback, dbus::Response* response) { 107 if (!response) 108 return; 109 dbus::MessageReader reader(response); 110 std::vector<dbus::ObjectPath> sms_paths; 111 if (!reader.PopArrayOfObjectPaths(&sms_paths)) 112 LOG(WARNING) << "Invalid response: " << response->ToString(); 113 callback.Run(sms_paths); 114 } 115 116 // Handles the result of signal connection setup. 117 void OnSignalConnected(const std::string& interface, 118 const std::string& signal, 119 bool succeeded) { 120 LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " 121 << signal << " failed."; 122 } 123 124 dbus::Bus* bus_; 125 dbus::ObjectProxy* proxy_; 126 std::string service_name_; 127 SmsReceivedHandler sms_received_handler_; 128 129 // Note: This should remain the last member so it'll be destroyed and 130 // invalidate its weak pointers before any other members are destroyed. 131 base::WeakPtrFactory<ModemMessagingProxy> weak_ptr_factory_; 132 133 DISALLOW_COPY_AND_ASSIGN(ModemMessagingProxy); 134 }; 135 136 class CHROMEOS_EXPORT ModemMessagingClientImpl : public ModemMessagingClient { 137 public: 138 ModemMessagingClientImpl() 139 : bus_(NULL), 140 proxies_deleter_(&proxies_) { 141 } 142 143 virtual void SetSmsReceivedHandler( 144 const std::string& service_name, 145 const dbus::ObjectPath& object_path, 146 const SmsReceivedHandler& handler) OVERRIDE { 147 GetProxy(service_name, object_path)->SetSmsReceivedHandler(handler); 148 } 149 150 virtual void ResetSmsReceivedHandler( 151 const std::string& service_name, 152 const dbus::ObjectPath& object_path) OVERRIDE { 153 GetProxy(service_name, object_path)->ResetSmsReceivedHandler(); 154 } 155 156 virtual void Delete(const std::string& service_name, 157 const dbus::ObjectPath& object_path, 158 const dbus::ObjectPath& sms_path, 159 const DeleteCallback& callback) OVERRIDE { 160 GetProxy(service_name, object_path)->Delete(sms_path, callback); 161 } 162 163 virtual void List(const std::string& service_name, 164 const dbus::ObjectPath& object_path, 165 const ListCallback& callback) OVERRIDE { 166 GetProxy(service_name, object_path)->List(callback); 167 } 168 169 protected: 170 virtual void Init(dbus::Bus* bus) OVERRIDE { 171 bus_ = bus; 172 }; 173 174 private: 175 typedef std::map<std::pair<std::string, std::string>, ModemMessagingProxy*> 176 ProxyMap; 177 178 // Returns a SMSProxy for the given service name and object path. 179 ModemMessagingProxy* GetProxy(const std::string& service_name, 180 const dbus::ObjectPath& object_path) { 181 const ProxyMap::key_type key(service_name, object_path.value()); 182 ProxyMap::iterator it = proxies_.find(key); 183 if (it != proxies_.end()) 184 return it->second; 185 186 // There is no proxy for the service_name and object_path, create it. 187 ModemMessagingProxy* proxy 188 = new ModemMessagingProxy(bus_, service_name, object_path); 189 proxies_.insert(ProxyMap::value_type(key, proxy)); 190 return proxy; 191 } 192 193 dbus::Bus* bus_; 194 ProxyMap proxies_; 195 STLValueDeleter<ProxyMap> proxies_deleter_; 196 197 DISALLOW_COPY_AND_ASSIGN(ModemMessagingClientImpl); 198 }; 199 200 } // namespace 201 202 //////////////////////////////////////////////////////////////////////////////// 203 // ModemMessagingClient 204 205 ModemMessagingClient::ModemMessagingClient() {} 206 207 ModemMessagingClient::~ModemMessagingClient() {} 208 209 210 // static 211 ModemMessagingClient* ModemMessagingClient::Create() { 212 return new ModemMessagingClientImpl(); 213 } 214 215 216 } // namespace chromeos 217