Home | History | Annotate | Download | only in dbus
      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/command_line.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/memory/weak_ptr.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "base/stl_util.h"
     16 #include "base/strings/stringprintf.h"
     17 #include "base/values.h"
     18 #include "chromeos/chromeos_switches.h"
     19 #include "chromeos/dbus/fake_gsm_sms_client.h"
     20 #include "dbus/bus.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"
     25 
     26 namespace chromeos {
     27 
     28 namespace {
     29 
     30 // A class actually making method calls for SMS services, used by
     31 // GsmSMSClientImpl.
     32 class SMSProxy {
     33  public:
     34   typedef GsmSMSClient::SmsReceivedHandler SmsReceivedHandler;
     35   typedef GsmSMSClient::DeleteCallback DeleteCallback;
     36   typedef GsmSMSClient::GetCallback GetCallback;
     37   typedef GsmSMSClient::ListCallback ListCallback;
     38 
     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()));
     50   }
     51 
     52   // Sets SmsReceived signal handler.
     53   void SetSmsReceivedHandler(const SmsReceivedHandler& handler) {
     54     DCHECK(sms_received_handler_.is_null());
     55     sms_received_handler_ = handler;
     56   }
     57 
     58   // Resets SmsReceived signal handler.
     59   void ResetSmsReceivedHandler() {
     60     sms_received_handler_.Reset();
     61   }
     62 
     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(),
     72                                   callback));
     73   }
     74 
     75   // Calls Get method.
     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(),
     84                                   callback));
     85   }
     86 
     87   // Calls List method.
     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(),
     94                                   callback));
     95   }
     96 
     97  private:
     98   // Handles SmsReceived signal.
     99   void OnSmsReceived(dbus::Signal* signal) {
    100     uint32 index = 0;
    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();
    106       return;
    107     }
    108     if (!sms_received_handler_.is_null())
    109       sms_received_handler_.Run(index, complete);
    110   }
    111 
    112   // Handles the result of signal connection setup.
    113   void OnSignalConnected(const std::string& interface,
    114                          const std::string& signal,
    115                          bool succeeded) {
    116     LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
    117         signal << " failed.";
    118   }
    119 
    120   // Handles responses of Delete method calls.
    121   void OnDelete(const DeleteCallback& callback, dbus::Response* response) {
    122     if (!response)
    123       return;
    124     callback.Run();
    125   }
    126 
    127   // Handles responses of Get method calls.
    128   void OnGet(const GetCallback& callback, dbus::Response* response) {
    129     if (!response)
    130       return;
    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();
    136       return;
    137     }
    138     callback.Run(*dictionary_value);
    139   }
    140 
    141   // Handles responses of List method calls.
    142   void OnList(const ListCallback& callback, dbus::Response* response) {
    143     if (!response)
    144       return;
    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();
    150       return;
    151     }
    152     callback.Run(*list_value);
    153   }
    154 
    155   dbus::ObjectProxy* proxy_;
    156   SmsReceivedHandler sms_received_handler_;
    157 
    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_;
    161 
    162   DISALLOW_COPY_AND_ASSIGN(SMSProxy);
    163 };
    164 
    165 // The GsmSMSClient implementation.
    166 class GsmSMSClientImpl : public GsmSMSClient {
    167  public:
    168   explicit GsmSMSClientImpl(dbus::Bus* bus)
    169       : bus_(bus),
    170         proxies_deleter_(&proxies_) {
    171   }
    172 
    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);
    179   }
    180 
    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();
    186   }
    187 
    188   // GsmSMSClient override.
    189   virtual void Delete(const std::string& service_name,
    190                       const dbus::ObjectPath& object_path,
    191                       uint32 index,
    192                       const DeleteCallback& callback) OVERRIDE {
    193     GetProxy(service_name, object_path)->Delete(index, callback);
    194   }
    195 
    196   // GsmSMSClient override.
    197   virtual void Get(const std::string& service_name,
    198                    const dbus::ObjectPath& object_path,
    199                    uint32 index,
    200                    const GetCallback& callback) OVERRIDE {
    201     GetProxy(service_name, object_path)->Get(index, callback);
    202   }
    203 
    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);
    209   }
    210 
    211   // GsmSMSClient override.
    212   virtual void RequestUpdate(const std::string& service_name,
    213                              const dbus::ObjectPath& object_path) OVERRIDE {
    214   }
    215 
    216  private:
    217   typedef std::map<std::pair<std::string, std::string>, SMSProxy*> ProxyMap;
    218 
    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())
    225       return it->second;
    226 
    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));
    230     return proxy;
    231   }
    232 
    233   dbus::Bus* bus_;
    234   ProxyMap proxies_;
    235   STLValueDeleter<ProxyMap> proxies_deleter_;
    236 
    237   DISALLOW_COPY_AND_ASSIGN(GsmSMSClientImpl);
    238 };
    239 
    240 }  // namespace
    241 
    242 ////////////////////////////////////////////////////////////////////////////////
    243 // GsmSMSClient
    244 
    245 GsmSMSClient::GsmSMSClient() {}
    246 
    247 GsmSMSClient::~GsmSMSClient() {}
    248 
    249 // static
    250 GsmSMSClient* GsmSMSClient::Create(DBusClientImplementationType type,
    251                                    dbus::Bus* bus) {
    252   if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
    253     return new GsmSMSClientImpl(bus);
    254   DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
    255 
    256   FakeGsmSMSClient* fake = new FakeGsmSMSClient();
    257   fake->set_sms_test_message_switch_present(
    258       CommandLine::ForCurrentProcess()->HasSwitch(
    259           chromeos::switches::kSmsTestMessages));
    260   return fake;
    261 }
    262 
    263 }  // namespace chromeos
    264