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/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