This source file includes following definitions.
- NetworkSmsDeviceHandler
- NetworkSmsDeviceHandler
- weak_ptr_factory_
- RequestUpdate
- ListCallback
- DeleteMessages
- SmsReceivedCallback
- GetCallback
- MessageReceived
- weak_ptr_factory_
- RequestUpdate
- ListCallback
- DeleteMessages
- GetMessages
- SmsReceivedCallback
- GetCallback
- MessageReceived
- Init
- RequestUpdate
- AddObserver
- RemoveObserver
- OnPropertyChanged
- AddReceivedMessage
- NotifyMessageReceived
- MessageReceived
- ManagerPropertiesCallback
- UpdateDevices
- DevicePropertiesCallback
#include "chromeos/network/network_sms_handler.h"
#include <algorithm>
#include <deque>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/gsm_sms_client.h"
#include "chromeos/dbus/modem_messaging_client.h"
#include "chromeos/dbus/sms_client.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace {
const char kIndexKey[] = "index";
const char kModemManager1NumberKey[] = "Number";
const char kModemManager1TextKey[] = "Text";
const char kModemManager1TimestampKey[] = "Timestamp";
const size_t kMaxReceivedMessages = 100;
}
namespace chromeos {
const char NetworkSmsHandler::kNumberKey[] = "number";
const char NetworkSmsHandler::kTextKey[] = "text";
const char NetworkSmsHandler::kTimestampKey[] = "timestamp";
class NetworkSmsHandler::NetworkSmsDeviceHandler {
public:
NetworkSmsDeviceHandler() {}
virtual ~NetworkSmsDeviceHandler() {}
virtual void RequestUpdate() = 0;
};
class NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler
: public NetworkSmsHandler::NetworkSmsDeviceHandler {
public:
ModemManagerNetworkSmsDeviceHandler(NetworkSmsHandler* host,
const std::string& service_name,
const dbus::ObjectPath& object_path);
virtual void RequestUpdate() OVERRIDE;
private:
void ListCallback(const base::ListValue& message_list);
void SmsReceivedCallback(uint32 index, bool complete);
void GetCallback(uint32 index, const base::DictionaryValue& dictionary);
void DeleteMessages();
void MessageReceived(const base::DictionaryValue& dictionary);
NetworkSmsHandler* host_;
std::string service_name_;
dbus::ObjectPath object_path_;
bool deleting_messages_;
base::WeakPtrFactory<ModemManagerNetworkSmsDeviceHandler> weak_ptr_factory_;
std::vector<uint32> delete_queue_;
DISALLOW_COPY_AND_ASSIGN(ModemManagerNetworkSmsDeviceHandler);
};
NetworkSmsHandler::
ModemManagerNetworkSmsDeviceHandler::ModemManagerNetworkSmsDeviceHandler(
NetworkSmsHandler* host,
const std::string& service_name,
const dbus::ObjectPath& object_path)
: host_(host),
service_name_(service_name),
object_path_(object_path),
deleting_messages_(false),
weak_ptr_factory_(this) {
DBusThreadManager::Get()->GetGsmSMSClient()->SetSmsReceivedHandler(
service_name_, object_path_,
base::Bind(&ModemManagerNetworkSmsDeviceHandler::SmsReceivedCallback,
weak_ptr_factory_.GetWeakPtr()));
DBusThreadManager::Get()->GetGsmSMSClient()->List(
service_name_, object_path_,
base::Bind(&NetworkSmsHandler::
ModemManagerNetworkSmsDeviceHandler::ListCallback,
weak_ptr_factory_.GetWeakPtr()));
}
void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::RequestUpdate() {
DBusThreadManager::Get()->GetGsmSMSClient()->RequestUpdate(
service_name_, object_path_);
}
void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::ListCallback(
const base::ListValue& message_list) {
delete_queue_.clear();
for (base::ListValue::const_iterator iter = message_list.begin();
iter != message_list.end(); ++iter) {
base::DictionaryValue* message = NULL;
if (!(*iter)->GetAsDictionary(&message))
continue;
MessageReceived(*message);
double index = 0;
if (message->GetDoubleWithoutPathExpansion(kIndexKey, &index))
delete_queue_.push_back(static_cast<uint32>(index));
}
DeleteMessages();
}
void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::DeleteMessages() {
if (delete_queue_.empty()) {
deleting_messages_ = false;
return;
}
deleting_messages_ = true;
uint32 index = delete_queue_.back();
delete_queue_.pop_back();
DBusThreadManager::Get()->GetGsmSMSClient()->Delete(
service_name_, object_path_, index,
base::Bind(&NetworkSmsHandler::
ModemManagerNetworkSmsDeviceHandler::DeleteMessages,
weak_ptr_factory_.GetWeakPtr()));
}
void NetworkSmsHandler::
ModemManagerNetworkSmsDeviceHandler::SmsReceivedCallback(
uint32 index,
bool complete) {
if (!complete)
return;
DBusThreadManager::Get()->GetGsmSMSClient()->Get(
service_name_, object_path_, index,
base::Bind(&NetworkSmsHandler::
ModemManagerNetworkSmsDeviceHandler::GetCallback,
weak_ptr_factory_.GetWeakPtr(), index));
}
void NetworkSmsHandler::ModemManagerNetworkSmsDeviceHandler::GetCallback(
uint32 index,
const base::DictionaryValue& dictionary) {
MessageReceived(dictionary);
delete_queue_.push_back(index);
if (!deleting_messages_)
DeleteMessages();
}
void NetworkSmsHandler::
ModemManagerNetworkSmsDeviceHandler::MessageReceived(
const base::DictionaryValue& dictionary) {
host_->MessageReceived(dictionary);
}
class NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler
: public NetworkSmsHandler::NetworkSmsDeviceHandler {
public:
ModemManager1NetworkSmsDeviceHandler(NetworkSmsHandler* host,
const std::string& service_name,
const dbus::ObjectPath& object_path);
virtual void RequestUpdate() OVERRIDE;
private:
void ListCallback(const std::vector<dbus::ObjectPath>& paths);
void SmsReceivedCallback(const dbus::ObjectPath& path, bool complete);
void GetCallback(const base::DictionaryValue& dictionary);
void DeleteMessages();
void GetMessages();
void MessageReceived(const base::DictionaryValue& dictionary);
NetworkSmsHandler* host_;
std::string service_name_;
dbus::ObjectPath object_path_;
bool deleting_messages_;
bool retrieving_messages_;
base::WeakPtrFactory<ModemManager1NetworkSmsDeviceHandler> weak_ptr_factory_;
std::vector<dbus::ObjectPath> delete_queue_;
std::deque<dbus::ObjectPath> retrieval_queue_;
DISALLOW_COPY_AND_ASSIGN(ModemManager1NetworkSmsDeviceHandler);
};
NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::ModemManager1NetworkSmsDeviceHandler(
NetworkSmsHandler* host,
const std::string& service_name,
const dbus::ObjectPath& object_path)
: host_(host),
service_name_(service_name),
object_path_(object_path),
deleting_messages_(false),
retrieving_messages_(false),
weak_ptr_factory_(this) {
DBusThreadManager::Get()->GetModemMessagingClient()->SetSmsReceivedHandler(
service_name_, object_path_,
base::Bind(
&NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::SmsReceivedCallback,
weak_ptr_factory_.GetWeakPtr()));
DBusThreadManager::Get()->GetModemMessagingClient()->List(
service_name_, object_path_,
base::Bind(&NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::ListCallback,
weak_ptr_factory_.GetWeakPtr()));
}
void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::RequestUpdate() {
DBusThreadManager::Get()->GetModemMessagingClient()->List(
std::string("AddSMS"), dbus::ObjectPath("/"),
base::Bind(&NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::ListCallback,
weak_ptr_factory_.GetWeakPtr()));
}
void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::ListCallback(
const std::vector<dbus::ObjectPath>& paths) {
retrieval_queue_.clear();
delete_queue_.clear();
retrieval_queue_.resize(paths.size());
std::copy(paths.begin(), paths.end(), retrieval_queue_.begin());
if (!retrieving_messages_)
GetMessages();
}
void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::DeleteMessages() {
if (delete_queue_.empty()) {
deleting_messages_ = false;
return;
}
deleting_messages_ = true;
dbus::ObjectPath sms_path = delete_queue_.back();
delete_queue_.pop_back();
DBusThreadManager::Get()->GetModemMessagingClient()->Delete(
service_name_, object_path_, sms_path,
base::Bind(&NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::DeleteMessages,
weak_ptr_factory_.GetWeakPtr()));
}
void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::GetMessages() {
if (retrieval_queue_.empty()) {
retrieving_messages_ = false;
if (!deleting_messages_)
DeleteMessages();
return;
}
retrieving_messages_ = true;
dbus::ObjectPath sms_path = retrieval_queue_.front();
retrieval_queue_.pop_front();
DBusThreadManager::Get()->GetSMSClient()->GetAll(
service_name_, sms_path,
base::Bind(&NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::GetCallback,
weak_ptr_factory_.GetWeakPtr()));
delete_queue_.push_back(sms_path);
}
void NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::SmsReceivedCallback(
const dbus::ObjectPath& sms_path,
bool complete) {
if (!complete)
return;
retrieval_queue_.push_back(sms_path);
if (!retrieving_messages_)
GetMessages();
}
void NetworkSmsHandler::ModemManager1NetworkSmsDeviceHandler::GetCallback(
const base::DictionaryValue& dictionary) {
MessageReceived(dictionary);
GetMessages();
}
void NetworkSmsHandler::
ModemManager1NetworkSmsDeviceHandler::MessageReceived(
const base::DictionaryValue& dictionary) {
base::DictionaryValue new_dictionary;
std::string text, number, timestamp;
if (dictionary.GetStringWithoutPathExpansion(kModemManager1NumberKey,
&number))
new_dictionary.SetString(kNumberKey, number);
if (dictionary.GetStringWithoutPathExpansion(kModemManager1TextKey, &text))
new_dictionary.SetString(kTextKey, text);
if (dictionary.GetStringWithoutPathExpansion(kModemManager1TimestampKey,
×tamp))
new_dictionary.SetString(kTimestampKey, timestamp);
host_->MessageReceived(new_dictionary);
}
NetworkSmsHandler::NetworkSmsHandler()
: weak_ptr_factory_(this) {
}
NetworkSmsHandler::~NetworkSmsHandler() {
DBusThreadManager::Get()->GetShillManagerClient()->
RemovePropertyChangedObserver(this);
}
void NetworkSmsHandler::Init() {
DBusThreadManager::Get()->GetShillManagerClient()->AddPropertyChangedObserver(
this);
DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
base::Bind(&NetworkSmsHandler::ManagerPropertiesCallback,
weak_ptr_factory_.GetWeakPtr()));
}
void NetworkSmsHandler::RequestUpdate(bool request_existing) {
for (ScopedVector<base::DictionaryValue>::iterator iter =
received_messages_.begin();
iter != received_messages_.end(); ++iter) {
base::DictionaryValue* message = *iter;
NotifyMessageReceived(*message);
}
for (ScopedVector<NetworkSmsDeviceHandler>::iterator iter =
device_handlers_.begin(); iter != device_handlers_.end(); ++iter) {
(*iter)->RequestUpdate();
}
}
void NetworkSmsHandler::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void NetworkSmsHandler::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void NetworkSmsHandler::OnPropertyChanged(const std::string& name,
const base::Value& value) {
if (name != shill::kDevicesProperty)
return;
const base::ListValue* devices = NULL;
if (!value.GetAsList(&devices) || !devices)
return;
UpdateDevices(devices);
}
void NetworkSmsHandler::AddReceivedMessage(
const base::DictionaryValue& message) {
base::DictionaryValue* new_message = message.DeepCopy();
if (received_messages_.size() >= kMaxReceivedMessages)
received_messages_.erase(received_messages_.begin());
received_messages_.push_back(new_message);
}
void NetworkSmsHandler::NotifyMessageReceived(
const base::DictionaryValue& message) {
FOR_EACH_OBSERVER(Observer, observers_, MessageReceived(message));
}
void NetworkSmsHandler::MessageReceived(const base::DictionaryValue& message) {
AddReceivedMessage(message);
NotifyMessageReceived(message);
}
void NetworkSmsHandler::ManagerPropertiesCallback(
DBusMethodCallStatus call_status,
const base::DictionaryValue& properties) {
if (call_status != DBUS_METHOD_CALL_SUCCESS) {
LOG(ERROR) << "NetworkSmsHandler: Failed to get manager properties.";
return;
}
const base::Value* value;
if (!properties.GetWithoutPathExpansion(shill::kDevicesProperty, &value) ||
value->GetType() != base::Value::TYPE_LIST) {
LOG(ERROR) << "NetworkSmsHandler: No list value for: "
<< shill::kDevicesProperty;
return;
}
const base::ListValue* devices = static_cast<const base::ListValue*>(value);
UpdateDevices(devices);
}
void NetworkSmsHandler::UpdateDevices(const base::ListValue* devices) {
for (base::ListValue::const_iterator iter = devices->begin();
iter != devices->end(); ++iter) {
std::string device_path;
(*iter)->GetAsString(&device_path);
if (!device_path.empty()) {
VLOG(1) << "GetDeviceProperties: " << device_path;
DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
dbus::ObjectPath(device_path),
base::Bind(&NetworkSmsHandler::DevicePropertiesCallback,
weak_ptr_factory_.GetWeakPtr(),
device_path));
}
}
}
void NetworkSmsHandler::DevicePropertiesCallback(
const std::string& device_path,
DBusMethodCallStatus call_status,
const base::DictionaryValue& properties) {
if (call_status != DBUS_METHOD_CALL_SUCCESS) {
LOG(ERROR) << "NetworkSmsHandler: ERROR: " << call_status
<< " For: " << device_path;
return;
}
std::string device_type;
if (!properties.GetStringWithoutPathExpansion(
shill::kTypeProperty, &device_type)) {
LOG(ERROR) << "NetworkSmsHandler: No type for: " << device_path;
return;
}
if (device_type != shill::kTypeCellular)
return;
std::string service_name;
if (!properties.GetStringWithoutPathExpansion(
shill::kDBusServiceProperty, &service_name)) {
LOG(ERROR) << "Device has no DBusService Property: " << device_path;
return;
}
std::string object_path_string;
if (!properties.GetStringWithoutPathExpansion(
shill::kDBusObjectProperty, &object_path_string)) {
LOG(ERROR) << "Device has no DBusObject Property: " << device_path;
return;
}
dbus::ObjectPath object_path(object_path_string);
if (service_name == modemmanager::kModemManager1) {
device_handlers_.push_back(
new ModemManager1NetworkSmsDeviceHandler(
this, service_name, object_path));
} else {
device_handlers_.push_back(
new ModemManagerNetworkSmsDeviceHandler(
this, service_name, object_path));
}
}
}