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"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/message_loop.h"
15 #include "base/stringprintf.h"
16 #include "base/stl_util.h"
17 #include "base/values.h"
18 #include "chromeos/chromeos_switches.h"
19 #include "chromeos/dbus/fake_gsm_sms_client.h"
21 #include "dbus/message.h"
22 #include "dbus/object_proxy.h"
23 #include "dbus/values_util.h"
24 #include "third_party/cros_system_api/dbus/service_constants.h"
30 // A class actually making method calls for SMS services, used by
34 typedef GsmSMSClient::SmsReceivedHandler SmsReceivedHandler
;
35 typedef GsmSMSClient::DeleteCallback DeleteCallback
;
36 typedef GsmSMSClient::GetCallback GetCallback
;
37 typedef GsmSMSClient::ListCallback ListCallback
;
39 SMSProxy(dbus::Bus
* bus
,
40 const std::string
& service_name
,
41 const dbus::ObjectPath
& object_path
)
42 : proxy_(bus
->GetObjectProxy(service_name
, object_path
)),
43 weak_ptr_factory_(this) {
44 proxy_
->ConnectToSignal(
45 modemmanager::kModemManagerSMSInterface
,
46 modemmanager::kSMSReceivedSignal
,
47 base::Bind(&SMSProxy::OnSmsReceived
, weak_ptr_factory_
.GetWeakPtr()),
48 base::Bind(&SMSProxy::OnSignalConnected
,
49 weak_ptr_factory_
.GetWeakPtr()));
52 // Sets SmsReceived signal handler.
53 void SetSmsReceivedHandler(const SmsReceivedHandler
& handler
) {
54 DCHECK(sms_received_handler_
.is_null());
55 sms_received_handler_
= handler
;
58 // Resets SmsReceived signal handler.
59 void ResetSmsReceivedHandler() {
60 sms_received_handler_
.Reset();
63 // Calls Delete method.
64 void Delete(uint32 index
, const DeleteCallback
& callback
) {
65 dbus::MethodCall
method_call(modemmanager::kModemManagerSMSInterface
,
66 modemmanager::kSMSDeleteFunction
);
67 dbus::MessageWriter
writer(&method_call
);
68 writer
.AppendUint32(index
);
69 proxy_
->CallMethod(&method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
70 base::Bind(&SMSProxy::OnDelete
,
71 weak_ptr_factory_
.GetWeakPtr(),
76 void Get(uint32 index
, const GetCallback
& callback
) {
77 dbus::MethodCall
method_call(modemmanager::kModemManagerSMSInterface
,
78 modemmanager::kSMSGetFunction
);
79 dbus::MessageWriter
writer(&method_call
);
80 writer
.AppendUint32(index
);
81 proxy_
->CallMethod(&method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
82 base::Bind(&SMSProxy::OnGet
,
83 weak_ptr_factory_
.GetWeakPtr(),
88 void List(const ListCallback
& callback
) {
89 dbus::MethodCall
method_call(modemmanager::kModemManagerSMSInterface
,
90 modemmanager::kSMSListFunction
);
91 proxy_
->CallMethod(&method_call
, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
92 base::Bind(&SMSProxy::OnList
,
93 weak_ptr_factory_
.GetWeakPtr(),
98 // Handles SmsReceived signal.
99 void OnSmsReceived(dbus::Signal
* signal
) {
101 bool complete
= false;
102 dbus::MessageReader
reader(signal
);
103 if (!reader
.PopUint32(&index
) ||
104 !reader
.PopBool(&complete
)) {
105 LOG(ERROR
) << "Invalid signal: " << signal
->ToString();
108 if (!sms_received_handler_
.is_null())
109 sms_received_handler_
.Run(index
, complete
);
112 // Handles the result of signal connection setup.
113 void OnSignalConnected(const std::string
& interface
,
114 const std::string
& signal
,
116 LOG_IF(ERROR
, !succeeded
) << "Connect to " << interface
<< " " <<
117 signal
<< " failed.";
120 // Handles responses of Delete method calls.
121 void OnDelete(const DeleteCallback
& callback
, dbus::Response
* response
) {
127 // Handles responses of Get method calls.
128 void OnGet(const GetCallback
& callback
, dbus::Response
* response
) {
131 dbus::MessageReader
reader(response
);
132 scoped_ptr
<base::Value
> value(dbus::PopDataAsValue(&reader
));
133 base::DictionaryValue
* dictionary_value
= NULL
;
134 if (!value
.get() || !value
->GetAsDictionary(&dictionary_value
)) {
135 LOG(WARNING
) << "Invalid response: " << response
->ToString();
138 callback
.Run(*dictionary_value
);
141 // Handles responses of List method calls.
142 void OnList(const ListCallback
& callback
, dbus::Response
* response
) {
145 dbus::MessageReader
reader(response
);
146 scoped_ptr
<base::Value
> value(dbus::PopDataAsValue(&reader
));
147 base::ListValue
* list_value
= NULL
;
148 if (!value
.get() || !value
->GetAsList(&list_value
)) {
149 LOG(WARNING
) << "Invalid response: " << response
->ToString();
152 callback
.Run(*list_value
);
155 dbus::ObjectProxy
* proxy_
;
156 SmsReceivedHandler sms_received_handler_
;
158 // Note: This should remain the last member so it'll be destroyed and
159 // invalidate its weak pointers before any other members are destroyed.
160 base::WeakPtrFactory
<SMSProxy
> weak_ptr_factory_
;
162 DISALLOW_COPY_AND_ASSIGN(SMSProxy
);
165 // The GsmSMSClient implementation.
166 class GsmSMSClientImpl
: public GsmSMSClient
{
168 explicit GsmSMSClientImpl(dbus::Bus
* bus
)
170 proxies_deleter_(&proxies_
) {
173 // GsmSMSClient override.
174 virtual void SetSmsReceivedHandler(
175 const std::string
& service_name
,
176 const dbus::ObjectPath
& object_path
,
177 const SmsReceivedHandler
& handler
) OVERRIDE
{
178 GetProxy(service_name
, object_path
)->SetSmsReceivedHandler(handler
);
181 // GsmSMSClient override.
182 virtual void ResetSmsReceivedHandler(
183 const std::string
& service_name
,
184 const dbus::ObjectPath
& object_path
) OVERRIDE
{
185 GetProxy(service_name
, object_path
)->ResetSmsReceivedHandler();
188 // GsmSMSClient override.
189 virtual void Delete(const std::string
& service_name
,
190 const dbus::ObjectPath
& object_path
,
192 const DeleteCallback
& callback
) OVERRIDE
{
193 GetProxy(service_name
, object_path
)->Delete(index
, callback
);
196 // GsmSMSClient override.
197 virtual void Get(const std::string
& service_name
,
198 const dbus::ObjectPath
& object_path
,
200 const GetCallback
& callback
) OVERRIDE
{
201 GetProxy(service_name
, object_path
)->Get(index
, callback
);
204 // GsmSMSClient override.
205 virtual void List(const std::string
& service_name
,
206 const dbus::ObjectPath
& object_path
,
207 const ListCallback
& callback
) OVERRIDE
{
208 GetProxy(service_name
, object_path
)->List(callback
);
211 // GsmSMSClient override.
212 virtual void RequestUpdate(const std::string
& service_name
,
213 const dbus::ObjectPath
& object_path
) OVERRIDE
{
217 typedef std::map
<std::pair
<std::string
, std::string
>, SMSProxy
*> ProxyMap
;
219 // Returns a SMSProxy for the given service name and object path.
220 SMSProxy
* GetProxy(const std::string
& service_name
,
221 const dbus::ObjectPath
& object_path
) {
222 const ProxyMap::key_type
key(service_name
, object_path
.value());
223 ProxyMap::iterator it
= proxies_
.find(key
);
224 if (it
!= proxies_
.end())
227 // There is no proxy for the service_name and object_path, create it.
228 SMSProxy
* proxy
= new SMSProxy(bus_
, service_name
, object_path
);
229 proxies_
.insert(ProxyMap::value_type(key
, proxy
));
235 STLValueDeleter
<ProxyMap
> proxies_deleter_
;
237 DISALLOW_COPY_AND_ASSIGN(GsmSMSClientImpl
);
242 ////////////////////////////////////////////////////////////////////////////////
245 GsmSMSClient::GsmSMSClient() {}
247 GsmSMSClient::~GsmSMSClient() {}
250 GsmSMSClient
* GsmSMSClient::Create(DBusClientImplementationType type
,
252 if (type
== REAL_DBUS_CLIENT_IMPLEMENTATION
)
253 return new GsmSMSClientImpl(bus
);
254 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION
, type
);
256 FakeGsmSMSClient
* fake
= new FakeGsmSMSClient();
257 fake
->set_sms_test_message_switch_present(
258 CommandLine::ForCurrentProcess()->HasSwitch(
259 chromeos::switches::kSmsTestMessages
));
263 } // namespace chromeos