15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/network/network_sms_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/shill_device_client.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/shill_manager_client.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/gsm_sms_client.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/modem_messaging_client.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/sms_client.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Not exposed/exported:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSmscKey[] = "smsc";
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kValidityKey[] = "validity";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kClassKey[] = "class";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kIndexKey[] = "index";
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Keys from ModemManager1
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kModemManager1NumberKey[] = "Number";
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kModemManager1TextKey[] = "Text";
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kModemManager1TimestampKey[] = "Timestamp";
352385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
362385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Maximum number of messages stored for RequestUpdate(true).
372385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochconst size_t kMaxReceivedMessages = 100;
382385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char NetworkSmsHandler::kNumberKey[] = "number";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char NetworkSmsHandler::kTextKey[] = "text";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char NetworkSmsHandler::kTimestampKey[] = "timestamp";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NetworkSmsHandler::NetworkSmsDeviceHandler {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkSmsDeviceHandler() {}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~NetworkSmsDeviceHandler() {}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestUpdate() = 0;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public NetworkSmsHandler::NetworkSmsDeviceHandler {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModemManagerNetworkSmsDeviceHandler(NetworkSmsHandler* host,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string dbus_connection,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      dbus::ObjectPath object_path);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestUpdate() OVERRIDE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ListCallback(const base::ListValue& message_list);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SmsReceivedCallback(uint32 index, bool complete);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetCallback(uint32 index, const base::DictionaryValue& dictionary);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DeleteMessages();
702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  void MessageReceived(const base::DictionaryValue& dictionary);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkSmsHandler* host_;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dbus_connection_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectPath object_path_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool deleting_messages_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ModemManagerNetworkSmsDeviceHandler> weak_ptr_factory_;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint32> delete_queue_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ModemManagerNetworkSmsDeviceHandler);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkSmsHandler::
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModemManagerNetworkSmsDeviceHandler::ModemManagerNetworkSmsDeviceHandler(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkSmsHandler* host,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string dbus_connection,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::ObjectPath object_path)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : host_(host),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_(dbus_connection),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      object_path_(object_path),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deleting_messages_(false),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_ptr_factory_(this) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the handler for received Sms messaages.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetGsmSMSClient()->SetSmsReceivedHandler(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ModemManagerNetworkSmsDeviceHandler::SmsReceivedCallback,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // List the existing messages.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetGsmSMSClient()->List(
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ModemManagerNetworkSmsDeviceHandler::ListCallback,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::RequestUpdate() {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetGsmSMSClient()->RequestUpdate(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::ListCallback(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::ListValue& message_list) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This receives all messages, so clear any pending deletes.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete_queue_.clear();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (base::ListValue::const_iterator iter = message_list.begin();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != message_list.end(); ++iter) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::DictionaryValue* message = NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(*iter)->GetAsDictionary(&message))
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    MessageReceived(*message);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double index = 0;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (message->GetDoubleWithoutPathExpansion(kIndexKey, &index))
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete_queue_.push_back(static_cast<uint32>(index));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteMessages();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Messages must be deleted one at a time, since we can not guarantee
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the order the deletion will be executed in. Delete messages from
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the back of the list so that the indices are valid.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::DeleteMessages() {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delete_queue_.empty()) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deleting_messages_ = false;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deleting_messages_ = true;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 index = delete_queue_.back();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete_queue_.pop_back();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetGsmSMSClient()->Delete(
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_, index,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ModemManagerNetworkSmsDeviceHandler::DeleteMessages,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModemManagerNetworkSmsDeviceHandler::SmsReceivedCallback(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 index,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool complete) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only handle complete messages.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!complete)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetGsmSMSClient()->Get(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_, index,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ModemManagerNetworkSmsDeviceHandler::GetCallback,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(), index));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::GetCallback(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 index,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& dictionary) {
1632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  MessageReceived(dictionary);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete_queue_.push_back(index);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!deleting_messages_)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeleteMessages();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::
1702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochModemManagerNetworkSmsDeviceHandler::MessageReceived(
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& dictionary) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The keys of the ModemManager.Modem.Gsm.SMS interface match the
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exported keys, so the dictionary used as a notification argument
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unchanged.
1752385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  host_->MessageReceived(dictionary);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public NetworkSmsHandler::NetworkSmsDeviceHandler {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModemManager1NetworkSmsDeviceHandler(NetworkSmsHandler* host,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       std::string dbus_connection,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       dbus::ObjectPath object_path);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RequestUpdate() OVERRIDE;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ListCallback(const std::vector<dbus::ObjectPath>& paths);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SmsReceivedCallback(const dbus::ObjectPath& path, bool complete);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetCallback(const base::DictionaryValue& dictionary);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DeleteMessages();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetMessages();
1932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  void MessageReceived(const base::DictionaryValue& dictionary);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkSmsHandler* host_;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dbus_connection_;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectPath object_path_;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool deleting_messages_;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool retrieving_messages_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ModemManager1NetworkSmsDeviceHandler> weak_ptr_factory_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<dbus::ObjectPath> delete_queue_;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::deque<dbus::ObjectPath> retrieval_queue_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ModemManager1NetworkSmsDeviceHandler);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkSmsHandler::
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModemManager1NetworkSmsDeviceHandler::ModemManager1NetworkSmsDeviceHandler(
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkSmsHandler* host,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string dbus_connection,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus::ObjectPath object_path)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : host_(host),
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_(dbus_connection),
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      object_path_(object_path),
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deleting_messages_(false),
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      retrieving_messages_(false),
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_ptr_factory_(this) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the handler for received Sms messaages.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetModemMessagingClient()->SetSmsReceivedHandler(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &NetworkSmsHandler::
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ModemManager1NetworkSmsDeviceHandler::SmsReceivedCallback,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          weak_ptr_factory_.GetWeakPtr()));
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // List the existing messages.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetModemMessagingClient()->List(
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ModemManager1NetworkSmsDeviceHandler::ListCallback,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::RequestUpdate() {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calling List using the service "AddSMS" causes the stub
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // implementation to deliver new sms messages.
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetModemMessagingClient()->List(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string("AddSMS"), dbus::ObjectPath("/"),
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ModemManager1NetworkSmsDeviceHandler::ListCallback,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::ListCallback(
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<dbus::ObjectPath>& paths) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This receives all messages, so clear any pending gets and deletes.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retrieval_queue_.clear();
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete_queue_.clear();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retrieval_queue_.resize(paths.size());
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::copy(paths.begin(), paths.end(), retrieval_queue_.begin());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!retrieving_messages_)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetMessages();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Messages must be deleted one at a time, since we can not guarantee
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the order the deletion will be executed in. Delete messages from
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the back of the list so that the indices are valid.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::DeleteMessages() {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delete_queue_.empty()) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deleting_messages_ = false;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deleting_messages_ = true;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectPath sms_path = delete_queue_.back();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete_queue_.pop_back();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetModemMessagingClient()->Delete(
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, object_path_, sms_path,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ModemManager1NetworkSmsDeviceHandler::DeleteMessages,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Messages must be fetched one at a time, so that we do not queue too
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// many requests to a single threaded server.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::GetMessages() {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (retrieval_queue_.empty()) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    retrieving_messages_ = false;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!deleting_messages_)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DeleteMessages();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retrieving_messages_ = true;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectPath sms_path = retrieval_queue_.front();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retrieval_queue_.pop_front();
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetSMSClient()->GetAll(
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dbus_connection_, sms_path,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ModemManager1NetworkSmsDeviceHandler::GetCallback,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete_queue_.push_back(sms_path);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModemManager1NetworkSmsDeviceHandler::SmsReceivedCallback(
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const dbus::ObjectPath& sms_path,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool complete) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only handle complete messages.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!complete)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retrieval_queue_.push_back(sms_path);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!retrieving_messages_)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetMessages();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::GetCallback(
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& dictionary) {
3082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  MessageReceived(dictionary);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetMessages();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::
3132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochModemManager1NetworkSmsDeviceHandler::MessageReceived(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& dictionary) {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The keys of the ModemManager1.SMS interface do not match the
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exported keys, so a new dictionary is created with the expected
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // key namaes.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::DictionaryValue new_dictionary;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string text, number, timestamp;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dictionary.GetStringWithoutPathExpansion(kModemManager1NumberKey,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               &number))
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_dictionary.SetString(kNumberKey, number);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dictionary.GetStringWithoutPathExpansion(kModemManager1TextKey, &text))
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_dictionary.SetString(kTextKey, text);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jglasgow): consider normalizing timestamp.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dictionary.GetStringWithoutPathExpansion(kModemManager1TimestampKey,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               &timestamp))
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_dictionary.SetString(kTimestampKey, timestamp);
3292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  host_->MessageReceived(new_dictionary);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NetworkSmsHandler
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkSmsHandler::NetworkSmsHandler()
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : weak_ptr_factory_(this) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkSmsHandler::~NetworkSmsHandler() {
3402385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DBusThreadManager::Get()->GetShillManagerClient()->
3412385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      RemovePropertyChangedObserver(this);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::Init() {
3452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Add as an observer here so that new devices added after this call are
3462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // recognized.
3472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DBusThreadManager::Get()->GetShillManagerClient()->AddPropertyChangedObserver(
3482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      this);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Request network manager properties so that we can get the list of devices.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&NetworkSmsHandler::ManagerPropertiesCallback,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NetworkSmsHandler::RequestUpdate(bool request_existing) {
3562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // If we already received messages and |request_existing| is true, send
3572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // updates for existing messages.
3582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (ScopedVector<base::DictionaryValue>::iterator iter =
3592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch           received_messages_.begin();
3602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch       iter != received_messages_.end(); ++iter) {
3612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    base::DictionaryValue* message = *iter;
3622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    NotifyMessageReceived(*message);
3632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
3642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Request updates from each device.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ScopedVector<NetworkSmsDeviceHandler>::iterator iter =
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           device_handlers_.begin(); iter != device_handlers_.end(); ++iter) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*iter)->RequestUpdate();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::AddObserver(Observer* observer) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::RemoveObserver(Observer* observer) {
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NetworkSmsHandler::OnPropertyChanged(const std::string& name,
3802385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch                                          const base::Value& value) {
3812385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (name != flimflam::kDevicesProperty)
3822385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return;
3832385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  const base::ListValue* devices = NULL;
3842385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (!value.GetAsList(&devices) || !devices)
3852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    return;
3862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  UpdateDevices(devices);
3872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
3882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Private methods
3902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NetworkSmsHandler::AddReceivedMessage(
3922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const base::DictionaryValue& message) {
3932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  base::DictionaryValue* new_message = message.DeepCopy();
3942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  if (received_messages_.size() >= kMaxReceivedMessages)
3952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    received_messages_.erase(received_messages_.begin());
3962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  received_messages_.push_back(new_message);
3972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
3982385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::NotifyMessageReceived(
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& message) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(Observer, observers_, MessageReceived(message));
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NetworkSmsHandler::MessageReceived(const base::DictionaryValue& message) {
4052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  AddReceivedMessage(message);
4062385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  NotifyMessageReceived(message);
4072385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
4082385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::ManagerPropertiesCallback(
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusMethodCallStatus call_status,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& properties) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (call_status != DBUS_METHOD_CALL_SUCCESS) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "NetworkSmsHandler: Failed to get manager properties.";
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::Value* value;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!properties.GetWithoutPathExpansion(flimflam::kDevicesProperty, &value) ||
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value->GetType() != base::Value::TYPE_LIST) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "NetworkSmsHandler: No list value for: "
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << flimflam::kDevicesProperty;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::ListValue* devices = static_cast<const base::ListValue*>(value);
4242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  UpdateDevices(devices);
4252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
4262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
4272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochvoid NetworkSmsHandler::UpdateDevices(const base::ListValue* devices) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (base::ListValue::const_iterator iter = devices->begin();
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != devices->end(); ++iter) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string device_path;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*iter)->GetAsString(&device_path);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!device_path.empty()) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Request device properties.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "GetDeviceProperties: " << device_path;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          dbus::ObjectPath(device_path),
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&NetworkSmsHandler::DevicePropertiesCallback,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr(),
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     device_path));
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NetworkSmsHandler::DevicePropertiesCallback(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& device_path,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DBusMethodCallStatus call_status,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue& properties) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (call_status != DBUS_METHOD_CALL_SUCCESS) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "NetworkSmsHandler: ERROR: " << call_status
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " For: " << device_path;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string device_type;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!properties.GetStringWithoutPathExpansion(
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          flimflam::kTypeProperty, &device_type)) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "NetworkSmsHandler: No type for: " << device_path;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_type != flimflam::kTypeCellular)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dbus_connection;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!properties.GetStringWithoutPathExpansion(
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          flimflam::kDBusConnectionProperty, &dbus_connection)) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Device has no DBusConnection Property: " << device_path;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string object_path_string;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!properties.GetStringWithoutPathExpansion(
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          flimflam::kDBusObjectProperty, &object_path_string)) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Device has no DBusObject Property: " << device_path;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::ObjectPath object_path(object_path_string);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (object_path_string.compare(
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          0, sizeof(modemmanager::kModemManager1ServicePath) - 1,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          modemmanager::kModemManager1ServicePath) == 0) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_handlers_.push_back(
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new ModemManager1NetworkSmsDeviceHandler(
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            this, dbus_connection, object_path));
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_handlers_.push_back(
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new ModemManagerNetworkSmsDeviceHandler(
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            this, dbus_connection, object_path));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
492