OLD | NEW |
---|---|
(Empty) | |
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.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 weak_ptr_factory_(this), | |
37 service_name_(service_name) { | |
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 successed) { | |
120 LOG_IF(ERROR, !successed) << "Connect to " << interface << " " | |
121 << signal << " failed."; | |
122 } | |
123 | |
124 dbus::Bus* bus_; | |
125 dbus::ObjectProxy* proxy_; | |
126 base::WeakPtrFactory<ModemMessagingProxy> weak_ptr_factory_; | |
127 std::string service_name_; | |
128 SmsReceivedHandler sms_received_handler_; | |
129 | |
130 DISALLOW_COPY_AND_ASSIGN(ModemMessagingProxy); | |
131 }; | |
132 | |
133 class CHROMEOS_EXPORT ModemMessagingClientImpl : public ModemMessagingClient { | |
134 public: | |
135 explicit ModemMessagingClientImpl(dbus::Bus *bus) | |
136 : bus_(bus), | |
137 proxies_deleter_(&proxies_) { | |
138 } | |
139 | |
140 // ModemMessagingClient override. | |
141 virtual void SetSmsReceivedHandler( | |
142 const std::string& service_name, | |
143 const dbus::ObjectPath& object_path, | |
144 const SmsReceivedHandler& handler) OVERRIDE { | |
145 GetProxy(service_name, object_path)->SetSmsReceivedHandler(handler); | |
146 } | |
147 | |
148 // ModemMessagingClient override. | |
149 virtual void ResetSmsReceivedHandler( | |
150 const std::string& service_name, | |
151 const dbus::ObjectPath& object_path) OVERRIDE { | |
152 GetProxy(service_name, object_path)->ResetSmsReceivedHandler(); | |
153 } | |
154 | |
155 // ModemMessagingClient override. | |
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 // ModemMessagingClient override. | |
164 virtual void List(const std::string& service_name, | |
165 const dbus::ObjectPath& object_path, | |
166 const ListCallback& callback) OVERRIDE { | |
167 GetProxy(service_name, object_path)->List(callback); | |
168 } | |
169 | |
170 private: | |
171 typedef std::map<std::pair<std::string, std::string>, ModemMessagingProxy*> | |
172 ProxyMap; | |
173 | |
174 // Returns a SMSProxy for the given service name and object path. | |
175 ModemMessagingProxy* GetProxy(const std::string& service_name, | |
176 const dbus::ObjectPath& object_path) { | |
177 const ProxyMap::key_type key(service_name, object_path.value()); | |
178 ProxyMap::iterator it = proxies_.find(key); | |
179 if (it != proxies_.end()) | |
180 return it->second; | |
181 | |
182 // There is no proxy for the service_name and object_path, create it. | |
183 ModemMessagingProxy* proxy | |
184 = new ModemMessagingProxy(bus_, service_name, object_path); | |
185 proxies_.insert(ProxyMap::value_type(key, proxy)); | |
186 return proxy; | |
187 } | |
188 | |
189 dbus::Bus* bus_; | |
190 ProxyMap proxies_; | |
191 STLValueDeleter<ProxyMap> proxies_deleter_; | |
192 | |
193 DISALLOW_COPY_AND_ASSIGN(ModemMessagingClientImpl); | |
194 }; | |
195 | |
196 class CHROMEOS_EXPORT ModemMessagingClientStubImpl | |
197 : public ModemMessagingClient { | |
198 public: | |
199 ModemMessagingClientStubImpl() { | |
200 message_paths_.push_back(dbus::ObjectPath("/SMS/0")); | |
201 message_paths_.push_back(dbus::ObjectPath("/SMS/1")); | |
202 } | |
203 | |
204 virtual ~ModemMessagingClientStubImpl() {} | |
205 | |
206 // ModemMessagingClient override. | |
207 virtual void SetSmsReceivedHandler( | |
208 const std::string& service_name, | |
209 const dbus::ObjectPath& object_path, | |
210 const SmsReceivedHandler& handler) OVERRIDE { | |
211 DCHECK(sms_received_handler_.is_null()); | |
212 sms_received_handler_ = handler; | |
213 } | |
214 | |
215 // ModemMessagingClient override. | |
216 virtual void ResetSmsReceivedHandler( | |
217 const std::string& service_name, | |
218 const dbus::ObjectPath& object_path) OVERRIDE { | |
219 sms_received_handler_.Reset(); | |
220 } | |
221 | |
222 // ModemMessagingClient override. | |
223 virtual void Delete(const std::string& service_name, | |
224 const dbus::ObjectPath& object_path, | |
225 const dbus::ObjectPath& sms_path, | |
226 const DeleteCallback& callback) OVERRIDE { | |
227 std::vector<dbus::ObjectPath>::iterator it( | |
228 find(message_paths_.begin(), message_paths_.end(), sms_path)); | |
229 if (it != message_paths_.end()) | |
230 message_paths_.erase(it); | |
231 callback.Run(); | |
232 } | |
233 | |
234 // ModemMessagingClient override. | |
235 virtual void List(const std::string& service_name, | |
236 const dbus::ObjectPath& object_path, | |
237 const ListCallback& callback) OVERRIDE { | |
238 // This entire ModemMessagingClientStubImpl is for testing. | |
239 // Calling List with |service_name| equal to "AddSMS" allows unit | |
240 // tests to confirm that the sms_received_handler is functioning. | |
241 if (service_name == "AddSMS") { | |
242 std::vector<dbus::ObjectPath> no_paths; | |
243 const dbus::ObjectPath kSmsPath("/SMS/2"); | |
244 message_paths_.push_back(kSmsPath); | |
245 if (!sms_received_handler_.is_null()) | |
246 sms_received_handler_.Run(kSmsPath, true); | |
247 callback.Run(no_paths); | |
stevenjb (google-dont-use)
2012/06/11 18:14:26
Here is how we would like the NetworkSmsHandler to
Jason Glasgow
2012/06/11 21:09:48
Done.
| |
248 } else { | |
249 callback.Run(message_paths_); | |
250 } | |
251 } | |
252 | |
253 private: | |
254 SmsReceivedHandler sms_received_handler_; | |
255 std::vector<dbus::ObjectPath> message_paths_; | |
256 | |
257 DISALLOW_COPY_AND_ASSIGN(ModemMessagingClientStubImpl); | |
258 }; | |
259 | |
260 } // namespace | |
261 | |
262 //////////////////////////////////////////////////////////////////////////////// | |
263 // ModemMessagingClient | |
264 | |
265 ModemMessagingClient::ModemMessagingClient() {} | |
266 | |
267 ModemMessagingClient::~ModemMessagingClient() {} | |
268 | |
269 | |
270 // static | |
271 ModemMessagingClient* ModemMessagingClient::Create( | |
272 DBusClientImplementationType type, | |
273 dbus::Bus* bus) { | |
274 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) { | |
275 return new ModemMessagingClientImpl(bus); | |
276 } | |
277 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); | |
278 return new ModemMessagingClientStubImpl(); | |
279 } | |
280 | |
281 | |
282 } // namespace chromeos | |
OLD | NEW |