Commit 88d6fc25 authored by benchan@chromium.org's avatar benchan@chromium.org

Support the ModemManager1 interfaces for SMS messages

Add dbus support the org.freedesktop.ModemManager1.SMS and
org.freedesktop.ModemManager1.Modem.Messaging interfaces.

This CL is authored by Jason Glasgow <jglasgow@chromium.org> and
reviewed on https://chromiumcodereview.appspot.com/10533006

BUG=chromium-os:28421
TEST=chromeos_unittests

Review URL: https://chromiumcodereview.appspot.com/10545133
Patch from Jason Glasgow <jglasgow@chromium.org>.

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141634 0039d316-1c4b-4281-b951-d872f2087c98
parent 7a81ea6e
......@@ -85,6 +85,8 @@
'dbus/image_burner_client.h',
'dbus/introspectable_client.cc',
'dbus/introspectable_client.h',
'dbus/modem_messaging_client.cc',
'dbus/modem_messaging_client.h',
'dbus/power_manager_client.cc',
'dbus/power_manager_client.h',
'dbus/power_supply_status.cc',
......@@ -93,6 +95,8 @@
'dbus/session_manager_client.h',
'dbus/speech_synthesizer_client.cc',
'dbus/speech_synthesizer_client.h',
'dbus/sms_client.cc',
'dbus/sms_client.h',
'dbus/update_engine_client.cc',
'dbus/update_engine_client.h',
'monitor/output_configurator.cc',
......@@ -158,10 +162,14 @@
'dbus/mock_image_burner_client.h',
'dbus/mock_introspectable_client.cc',
'dbus/mock_introspectable_client.h',
'dbus/mock_modem_messaging_client.cc',
'dbus/mock_modem_messaging_client.h',
'dbus/mock_power_manager_client.cc',
'dbus/mock_power_manager_client.h',
'dbus/mock_session_manager_client.cc',
'dbus/mock_session_manager_client.h',
'dbus/mock_sms_client.cc',
'dbus/mock_sms_client.h',
'dbus/mock_speech_synthesizer_client.cc',
'dbus/mock_speech_synthesizer_client.h',
'dbus/mock_update_engine_client.cc',
......@@ -202,6 +210,7 @@
'dbus/ibus/ibus_text_unittest.cc',
'dbus/ibus/ibus_input_context_client_unittest.cc',
'dbus/introspectable_client_unittest.cc',
'dbus/modem_messaging_client_unittest.cc',
'network/network_sms_handler_unittest.cc',
],
'include_dirs': [
......
......@@ -29,8 +29,10 @@
#include "chromeos/dbus/ibus/ibus_input_context_client.h"
#include "chromeos/dbus/image_burner_client.h"
#include "chromeos/dbus/introspectable_client.h"
#include "chromeos/dbus/modem_messaging_client.h"
#include "chromeos/dbus/power_manager_client.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/dbus/sms_client.h"
#include "chromeos/dbus/speech_synthesizer_client.h"
#include "chromeos/dbus/update_engine_client.h"
#include "dbus/bus.h"
......@@ -104,7 +106,7 @@ class DBusThreadManagerImpl : public DBusThreadManager {
// Create the Flimflam Service client.
flimflam_service_client_.reset(
FlimflamServiceClient::Create(client_type, system_bus_.get()));
// Create the SMS cilent.
// Create the Gsm SMS client.
gsm_sms_client_.reset(
GsmSMSClient::Create(client_type, system_bus_.get()));
// Create the image burner client.
......@@ -113,12 +115,18 @@ class DBusThreadManagerImpl : public DBusThreadManager {
// Create the introspectable object client.
introspectable_client_.reset(
IntrospectableClient::Create(client_type, system_bus_.get()));
// Create the ModemMessaging client.
modem_messaging_client_.reset(
ModemMessagingClient::Create(client_type, system_bus_.get()));
// Create the power manager client.
power_manager_client_.reset(
PowerManagerClient::Create(client_type_maybe_stub, system_bus_.get()));
// Create the session manager client.
session_manager_client_.reset(
SessionManagerClient::Create(client_type, system_bus_.get()));
// Create the SMS client.
sms_client_.reset(
SMSClient::Create(client_type, system_bus_.get()));
// Create the speech synthesizer client.
speech_synthesizer_client_.reset(
SpeechSynthesizerClient::Create(client_type, system_bus_.get()));
......@@ -264,6 +272,11 @@ class DBusThreadManagerImpl : public DBusThreadManager {
return introspectable_client_.get();
}
// DBusThreadManager override.
virtual ModemMessagingClient* GetModemMessagingClient() OVERRIDE {
return modem_messaging_client_.get();
}
// DBusThreadManager override.
virtual PowerManagerClient* GetPowerManagerClient() OVERRIDE {
return power_manager_client_.get();
......@@ -274,6 +287,11 @@ class DBusThreadManagerImpl : public DBusThreadManager {
return session_manager_client_.get();
}
// DBusThreadManager override.
virtual SMSClient* GetSMSClient() OVERRIDE {
return sms_client_.get();
}
// DBusThreadManager override.
virtual SpeechSynthesizerClient* GetSpeechSynthesizerClient() OVERRIDE {
return speech_synthesizer_client_.get();
......@@ -315,8 +333,10 @@ class DBusThreadManagerImpl : public DBusThreadManager {
scoped_ptr<GsmSMSClient> gsm_sms_client_;
scoped_ptr<ImageBurnerClient> image_burner_client_;
scoped_ptr<IntrospectableClient> introspectable_client_;
scoped_ptr<ModemMessagingClient> modem_messaging_client_;
scoped_ptr<PowerManagerClient> power_manager_client_;
scoped_ptr<SessionManagerClient> session_manager_client_;
scoped_ptr<SMSClient> sms_client_;
scoped_ptr<SpeechSynthesizerClient> speech_synthesizer_client_;
scoped_ptr<UpdateEngineClient> update_engine_client_;
scoped_ptr<IBusClient> ibus_client_;
......
......@@ -43,8 +43,10 @@ class IBusClient;
class IBusInputContextClient;
class ImageBurnerClient;
class IntrospectableClient;
class ModemMessagingClient;
class PowerManagerClient;
class SessionManagerClient;
class SMSClient;
class SpeechSynthesizerClient;
class UpdateEngineClient;
......@@ -189,6 +191,11 @@ class CHROMEOS_EXPORT DBusThreadManager {
// down.
virtual IntrospectableClient* GetIntrospectableClient() = 0;
// Returns the Modem Messaging client, owned by DBusThreadManager.
// Do not cache this pointer and use it after DBusThreadManager is shut
// down.
virtual ModemMessagingClient* GetModemMessagingClient() = 0;
// Returns the power manager client, owned by DBusThreadManager.
// See also comments at session_manager_client().
virtual PowerManagerClient* GetPowerManagerClient() = 0;
......@@ -198,6 +205,11 @@ class CHROMEOS_EXPORT DBusThreadManager {
// down.
virtual SessionManagerClient* GetSessionManagerClient() = 0;
// Returns the SMS client, owned by DBusThreadManager.
// Do not cache this pointer and use it after DBusThreadManager is shut
// down.
virtual SMSClient* GetSMSClient() = 0;
// Returns the speech synthesizer client, owned by DBusThreadManager.
// Do not cache this pointer and use it after DBusThreadManager is shut
// down.
......
......@@ -225,6 +225,23 @@ class FlimflamDeviceClientStubImpl : public FlimflamDeviceClient {
flimflam::kDBusObjectProperty,
base::Value::CreateStringValue("/device/cellular1"));
stub_devices_.Set(kStubCellular1, cellular_properties);
// Create a second device stubbing a modem managed by
// ModemManager1 interfaces.
// Note: name matches Manager entry.
const char kStubCellular2[] = "stub_cellular2";
cellular_properties = new base::DictionaryValue;
cellular_properties->SetWithoutPathExpansion(
flimflam::kTypeProperty,
base::Value::CreateStringValue(flimflam::kTypeCellular));
cellular_properties->SetWithoutPathExpansion(
flimflam::kDBusConnectionProperty,
base::Value::CreateStringValue(":stub.0"));
cellular_properties->SetWithoutPathExpansion(
flimflam::kDBusObjectProperty,
base::Value::CreateStringValue(
"/org/freedesktop/ModemManager1/stub/0"));
stub_devices_.Set(kStubCellular2, cellular_properties);
}
virtual ~FlimflamDeviceClientStubImpl() {}
......
......@@ -149,9 +149,11 @@ class FlimflamManagerClientStubImpl : public FlimflamManagerClient {
public:
FlimflamManagerClientStubImpl() : weak_ptr_factory_(this) {
base::ListValue* device_list = new base::ListValue;
// Note: name matches Device stub map.
// Note: names match Device stub map.
const char kStubCellular1[] = "stub_cellular1";
const char kStubCellular2[] = "stub_cellular2";
device_list->Append(base::Value::CreateStringValue(kStubCellular1));
device_list->Append(base::Value::CreateStringValue(kStubCellular2));
stub_properties_.Set(flimflam::kDevicesProperty, device_list);
}
......
......@@ -3,6 +3,10 @@
// found in the LICENSE file.
#include "chromeos/dbus/gsm_sms_client.h"
#include <map>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
......@@ -21,7 +25,7 @@ namespace chromeos {
namespace {
// A class actually making method calls for SMS services, used by
// GsmSMSClietnImpl.
// GsmSMSClientImpl.
class SMSProxy {
public:
typedef GsmSMSClient::SmsReceivedHandler SmsReceivedHandler;
......
......@@ -25,7 +25,7 @@ class ObjectPath;
namespace chromeos {
// GsmSMSClient is used to communicate with
// GsmSMSClient is used to communicate with the
// org.freedesktop.ModemManager.Modem.Gsm.SMS service.
// All methods should be called from the origin thread (UI thread) which
// initializes the DBusThreadManager instance.
......@@ -43,12 +43,12 @@ class CHROMEOS_EXPORT GsmSMSClient {
static GsmSMSClient* Create(DBusClientImplementationType type,
dbus::Bus* bus);
// Sets DataPlansUpdate signal handler.
// Sets SmsReceived signal handler.
virtual void SetSmsReceivedHandler(const std::string& service_name,
const dbus::ObjectPath& object_path,
const SmsReceivedHandler& handler) = 0;
// Resets DataPlansUpdate signal handler.
// Resets SmsReceived signal handler.
virtual void ResetSmsReceivedHandler(const std::string& service_name,
const dbus::ObjectPath& object_path) = 0;
......
......@@ -312,7 +312,7 @@ TEST_F(GsmSMSClientTest, List) {
kTextKey, base::Value::CreateStringValue(kExampleText));
expected_result.Append(sms);
expected_result_ = &expected_result;
// Call Delete.
// Call List.
client_->List(kServiceName, dbus::ObjectPath(kObjectPath),
base::Bind(&MockListCallback::Run,
base::Unretained(&callback)));
......
......@@ -24,8 +24,10 @@
#include "chromeos/dbus/mock_gsm_sms_client.h"
#include "chromeos/dbus/mock_image_burner_client.h"
#include "chromeos/dbus/mock_introspectable_client.h"
#include "chromeos/dbus/mock_modem_messaging_client.h"
#include "chromeos/dbus/mock_power_manager_client.h"
#include "chromeos/dbus/mock_session_manager_client.h"
#include "chromeos/dbus/mock_sms_client.h"
#include "chromeos/dbus/mock_speech_synthesizer_client.h"
#include "chromeos/dbus/mock_update_engine_client.h"
......@@ -54,8 +56,10 @@ MockDBusThreadManager::MockDBusThreadManager()
mock_gsm_sms_client_(new MockGsmSMSClient),
mock_image_burner_client_(new MockImageBurnerClient),
mock_introspectable_client_(new MockIntrospectableClient),
mock_modem_messaging_client_(new MockModemMessagingClient),
mock_power_manager_client_(new MockPowerManagerClient),
mock_session_manager_client_(new MockSessionManagerClient),
mock_sms_client_(new MockSMSClient),
mock_speech_synthesizer_client_(new MockSpeechSynthesizerClient),
mock_update_engine_client_(new MockUpdateEngineClient),
mock_ibus_client_(new MockIBusClient),
......@@ -96,10 +100,14 @@ MockDBusThreadManager::MockDBusThreadManager()
.WillRepeatedly(Return(mock_image_burner_client()));
EXPECT_CALL(*this, GetIntrospectableClient())
.WillRepeatedly(Return(mock_introspectable_client()));
EXPECT_CALL(*this, GetModemMessagingClient())
.WillRepeatedly(Return(mock_modem_messaging_client()));
EXPECT_CALL(*this, GetPowerManagerClient())
.WillRepeatedly(Return(mock_power_manager_client_.get()));
EXPECT_CALL(*this, GetSessionManagerClient())
.WillRepeatedly(Return(mock_session_manager_client_.get()));
EXPECT_CALL(*this, GetSMSClient())
.WillRepeatedly(Return(mock_sms_client_.get()));
EXPECT_CALL(*this, GetSpeechSynthesizerClient())
.WillRepeatedly(Return(mock_speech_synthesizer_client_.get()));
EXPECT_CALL(*this, GetUpdateEngineClient())
......
......@@ -38,8 +38,10 @@ class MockIBusClient;
class MockIBusInputContextClient;
class MockImageBurnerClient;
class MockIntrospectableClient;
class MockModemMessagingClient;
class MockPowerManagerClient;
class MockSessionManagerClient;
class MockSMSClient;
class MockSpeechSynthesizerClient;
class MockUpdateEngineClient;
......@@ -72,8 +74,10 @@ class MockDBusThreadManager : public DBusThreadManager {
MOCK_METHOD0(GetGsmSMSClient, GsmSMSClient*(void));
MOCK_METHOD0(GetImageBurnerClient, ImageBurnerClient*(void));
MOCK_METHOD0(GetIntrospectableClient, IntrospectableClient*(void));
MOCK_METHOD0(GetModemMessagingClient, ModemMessagingClient*(void));
MOCK_METHOD0(GetPowerManagerClient, PowerManagerClient*(void));
MOCK_METHOD0(GetSessionManagerClient, SessionManagerClient*(void));
MOCK_METHOD0(GetSMSClient, SMSClient*(void));
MOCK_METHOD0(GetSpeechSynthesizerClient, SpeechSynthesizerClient*(void));
MOCK_METHOD0(GetUpdateEngineClient, UpdateEngineClient*(void));
MOCK_METHOD0(GetIBusClient, IBusClient*(void));
......@@ -133,12 +137,18 @@ class MockDBusThreadManager : public DBusThreadManager {
MockIntrospectableClient* mock_introspectable_client() {
return mock_introspectable_client_.get();
}
MockModemMessagingClient* mock_modem_messaging_client() {
return mock_modem_messaging_client_.get();
}
MockPowerManagerClient* mock_power_manager_client() {
return mock_power_manager_client_.get();
}
MockSessionManagerClient* mock_session_manager_client() {
return mock_session_manager_client_.get();
}
MockSMSClient* mock_sms_client() {
return mock_sms_client_.get();
}
MockSpeechSynthesizerClient* mock_speech_synthesizer_client() {
return mock_speech_synthesizer_client_.get();
}
......@@ -171,8 +181,10 @@ class MockDBusThreadManager : public DBusThreadManager {
scoped_ptr<MockGsmSMSClient> mock_gsm_sms_client_;
scoped_ptr<MockImageBurnerClient> mock_image_burner_client_;
scoped_ptr<MockIntrospectableClient> mock_introspectable_client_;
scoped_ptr<MockModemMessagingClient> mock_modem_messaging_client_;
scoped_ptr<MockPowerManagerClient> mock_power_manager_client_;
scoped_ptr<MockSessionManagerClient> mock_session_manager_client_;
scoped_ptr<MockSMSClient> mock_sms_client_;
scoped_ptr<MockSpeechSynthesizerClient> mock_speech_synthesizer_client_;
scoped_ptr<MockUpdateEngineClient> mock_update_engine_client_;
scoped_ptr<MockIBusClient> mock_ibus_client_;
......
......@@ -6,6 +6,8 @@
#define CHROMEOS_DBUS_MOCK_GSM_SMS_CLIENT_H_
#pragma once
#include <string>
#include "base/values.h"
#include "chromeos/dbus/gsm_sms_client.h"
#include "dbus/object_path.h"
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/mock_modem_messaging_client.h"
namespace chromeos {
MockModemMessagingClient::MockModemMessagingClient() {}
MockModemMessagingClient::~MockModemMessagingClient() {}
} // namespace chromeos
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_DBUS_MOCK_MODEM_MESSAGING_CLIENT_H_
#define CHROMEOS_DBUS_MOCK_MODEM_MESSAGING_CLIENT_H_
#pragma once
#include <string>
#include "base/values.h"
#include "chromeos/dbus/modem_messaging_client.h"
#include "dbus/object_path.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace chromeos {
class MockModemMessagingClient : public ModemMessagingClient {
public:
MockModemMessagingClient();
virtual ~MockModemMessagingClient();
MOCK_METHOD3(SetSmsReceivedHandler, void(const std::string& service_name,
const dbus::ObjectPath& object_path,
const SmsReceivedHandler& handler));
MOCK_METHOD2(ResetSmsReceivedHandler,
void(const std::string& service_name,
const dbus::ObjectPath& object_path));
MOCK_METHOD4(Delete, void(const std::string& service_name,
const dbus::ObjectPath& object_path,
const dbus::ObjectPath& sms_path,
const DeleteCallback& callback));
MOCK_METHOD3(List, void(const std::string& service_name,
const dbus::ObjectPath& object_path,
const ListCallback& callback));
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_MOCK_MODEM_MESSAGING_CLIENT_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/mock_sms_client.h"
namespace chromeos {
MockSMSClient::MockSMSClient() {}
MockSMSClient::~MockSMSClient() {}
} // namespace chromeos
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_DBUS_MOCK_SMS_CLIENT_H_
#define CHROMEOS_DBUS_MOCK_SMS_CLIENT_H_
#pragma once
#include <string>
#include "base/values.h"
#include "chromeos/dbus/sms_client.h"
#include "dbus/object_path.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace chromeos {
class MockSMSClient : public SMSClient {
public:
MockSMSClient();
virtual ~MockSMSClient();
MOCK_METHOD3(GetAll, void(const std::string& service_name,
const dbus::ObjectPath& object_path,
const GetAllCallback& callback));
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_MOCK_SMS_CLIENT_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/modem_messaging_client.h"
#include <map>
#include <utility>
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
// A class which makes method calls for SMS services via the
// org.freedesktop.ModemManager1.Messaging object.
class ModemMessagingProxy {
public:
typedef ModemMessagingClient::SmsReceivedHandler SmsReceivedHandler;
typedef ModemMessagingClient::ListCallback ListCallback;
typedef ModemMessagingClient::DeleteCallback DeleteCallback;
ModemMessagingProxy(dbus::Bus* bus,
const std::string& service_name,
const dbus::ObjectPath& object_path)
: bus_(bus),
proxy_(bus->GetObjectProxy(service_name, object_path)),
weak_ptr_factory_(this),
service_name_(service_name) {
proxy_->ConnectToSignal(
modemmanager::kModemManager1MessagingInterface,
modemmanager::kSMSAddedSignal,
base::Bind(&ModemMessagingProxy::OnSmsAdded,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&ModemMessagingProxy::OnSignalConnected,
weak_ptr_factory_.GetWeakPtr()));
}
virtual ~ModemMessagingProxy() {}
// Sets SmsReceived signal handler.
void SetSmsReceivedHandler(const SmsReceivedHandler& handler) {
DCHECK(sms_received_handler_.is_null());
sms_received_handler_ = handler;
}
// Resets SmsReceived signal handler.
void ResetSmsReceivedHandler() {
sms_received_handler_.Reset();
}
// Calls Delete method.
void Delete(const dbus::ObjectPath& message_path,
const DeleteCallback& callback) {
dbus::MethodCall method_call(modemmanager::kModemManager1MessagingInterface,
modemmanager::kSMSDeleteFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendObjectPath(message_path);
proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::Bind(&ModemMessagingProxy::OnDelete,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
// Calls List method.
virtual void List(const ListCallback& callback) {
dbus::MethodCall method_call(modemmanager::kModemManager1MessagingInterface,
modemmanager::kSMSListFunction);
proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::Bind(&ModemMessagingProxy::OnList,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
private:
// Handles SmsAdded signal.
void OnSmsAdded(dbus::Signal* signal) {
dbus::ObjectPath message_path;
bool complete = false;
dbus::MessageReader reader(signal);
if (!reader.PopObjectPath(&message_path) ||
!reader.PopBool(&complete)) {
LOG(ERROR) << "Invalid signal: " << signal->ToString();
return;
}
if (!sms_received_handler_.is_null()) {
sms_received_handler_.Run(message_path, complete);
}
}
// Handles responses of Delete method calls.
void OnDelete(const DeleteCallback& callback, dbus::Response* response) {
if (!response)
return;
callback.Run();
}
// Handles responses of List method calls.
void OnList(const ListCallback& callback, dbus::Response* response) {
if (!response)
return;
dbus::MessageReader reader(response);
std::vector<dbus::ObjectPath> sms_paths;
if (!reader.PopArrayOfObjectPaths(&sms_paths))
LOG(WARNING) << "Invalid response: " << response->ToString();
callback.Run(sms_paths);
}
// Handles the result of signal connection setup.
void OnSignalConnected(const std::string& interface,
const std::string& signal,
bool successed) {
LOG_IF(ERROR, !successed) << "Connect to " << interface << " "
<< signal << " failed.";
}
dbus::Bus* bus_;
dbus::ObjectProxy* proxy_;
base::WeakPtrFactory<ModemMessagingProxy> weak_ptr_factory_;
std::string service_name_;
SmsReceivedHandler sms_received_handler_;
DISALLOW_COPY_AND_ASSIGN(ModemMessagingProxy);
};
class CHROMEOS_EXPORT ModemMessagingClientImpl : public ModemMessagingClient {
public:
explicit ModemMessagingClientImpl(dbus::Bus *bus)
: bus_(bus),
proxies_deleter_(&proxies_) {
}
// ModemMessagingClient override.
virtual void SetSmsReceivedHandler(
const std::string& service_name,
const dbus::ObjectPath& object_path,
const SmsReceivedHandler& handler) OVERRIDE {
GetProxy(service_name, object_path)->SetSmsReceivedHandler(handler);
}
// ModemMessagingClient override.
virtual void ResetSmsReceivedHandler(
const std::string& service_name,
const dbus::ObjectPath& object_path) OVERRIDE {
GetProxy(service_name, object_path)->ResetSmsReceivedHandler();
}
// ModemMessagingClient override.
virtual void Delete(const std::string& service_name,
const dbus::ObjectPath& object_path,
const dbus::ObjectPath& sms_path,
const DeleteCallback& callback) OVERRIDE {
GetProxy(service_name, object_path)->Delete(sms_path, callback);
}
// ModemMessagingClient override.
virtual void List(const std::string& service_name,
const dbus::ObjectPath& object_path,
const ListCallback& callback) OVERRIDE {
GetProxy(service_name, object_path)->List(callback);
}
private:
typedef std::map<std::pair<std::string, std::string>, ModemMessagingProxy*>
ProxyMap;
// Returns a SMSProxy for the given service name and object path.
ModemMessagingProxy* GetProxy(const std::string& service_name,
const dbus::ObjectPath& object_path) {
const ProxyMap::key_type key(service_name, object_path.value());
ProxyMap::iterator it = proxies_.find(key);
if (it != proxies_.end())
return it->second;
// There is no proxy for the service_name and object_path, create it.
ModemMessagingProxy* proxy
= new ModemMessagingProxy(bus_, service_name, object_path);
proxies_.insert(ProxyMap::value_type(key, proxy));
return proxy;
}
dbus::Bus* bus_;
ProxyMap proxies_;
STLValueDeleter<ProxyMap> proxies_deleter_;
DISALLOW_COPY_AND_ASSIGN(ModemMessagingClientImpl);
};
class CHROMEOS_EXPORT ModemMessagingClientStubImpl
: public ModemMessagingClient {
public:
ModemMessagingClientStubImpl() {}
virtual ~ModemMessagingClientStubImpl() {}
// ModemMessagingClient override.
virtual void SetSmsReceivedHandler(
const std::string& service_name,
const dbus::ObjectPath& object_path,
const SmsReceivedHandler& handler) OVERRIDE {
DCHECK(sms_received_handler_.is_null());
sms_received_handler_ = handler;
}
// ModemMessagingClient override.
virtual void ResetSmsReceivedHandler(
const std::string& service_name,
const dbus::ObjectPath& object_path) OVERRIDE {
sms_received_handler_.Reset();
}
// ModemMessagingClient override.
virtual void Delete(const std::string& service_name,
const dbus::ObjectPath& object_path,
const dbus::ObjectPath& sms_path,
const DeleteCallback& callback) OVERRIDE {
std::vector<dbus::ObjectPath>::iterator it(
find(message_paths_.begin(), message_paths_.end(), sms_path));
if (it != message_paths_.end())
message_paths_.erase(it);
callback.Run();
}
// ModemMessagingClient override.
virtual void List(const std::string& service_name,
const dbus::ObjectPath& object_path,
const ListCallback& callback) OVERRIDE {
// This entire ModemMessagingClientStubImpl is for testing.
// Calling List with |service_name| equal to "AddSMS" allows unit
// tests to confirm that the sms_received_handler is functioning.
if (service_name == "AddSMS") {
std::vector<dbus::ObjectPath> no_paths;
const dbus::ObjectPath kSmsPath("/SMS/0");
message_paths_.push_back(kSmsPath);
if (!sms_received_handler_.is_null())
sms_received_handler_.Run(kSmsPath, true);
callback.Run(no_paths);
} else {
callback.Run(message_paths_);
}
}
private:
SmsReceivedHandler sms_received_handler_;
std::vector<dbus::ObjectPath> message_paths_;
DISALLOW_COPY_AND_ASSIGN(ModemMessagingClientStubImpl);
};
} // namespace
////////////////////////////////////////////////////////////////////////////////
// ModemMessagingClient
ModemMessagingClient::ModemMessagingClient() {}
ModemMessagingClient::~ModemMessagingClient() {}
// static
ModemMessagingClient* ModemMessagingClient::Create(
DBusClientImplementationType type,
dbus::Bus* bus) {
if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) {
return new ModemMessagingClientImpl(bus);
}
DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
return new ModemMessagingClientStubImpl();
}
} // namespace chromeos
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_DBUS_MODEM_MESSAGING_CLIENT_H_
#define CHROMEOS_DBUS_MODEM_MESSAGING_CLIENT_H_
#pragma once
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/dbus/dbus_client_implementation_type.h"
namespace dbus {
class Bus;
class ObjectPath;
}
namespace chromeos {
// ModemMessagingClient is used to communicate with the
// org.freedesktop.ModemManager1.Modem.Messaging service. All methods
// should be called from the origin thread (UI thread) which
// initializes the DBusThreadManager instance.
class CHROMEOS_EXPORT ModemMessagingClient {
public:
typedef base::Callback<void()> DeleteCallback;
typedef base::Callback<void(const dbus::ObjectPath& message_path,
bool complete)> SmsReceivedHandler;
typedef base::Callback<void(const std::vector<dbus::ObjectPath>& paths)>
ListCallback;
virtual ~ModemMessagingClient();
// Factory function, creates a new instance and returns ownership.
// For normal usage, access the singleton via DBusThreadManager::Get().
static ModemMessagingClient* Create(DBusClientImplementationType type,
dbus::Bus* bus);
// Sets SmsReceived signal handler.
virtual void SetSmsReceivedHandler(const std::string& service_name,
const dbus::ObjectPath& object_path,
const SmsReceivedHandler& handler) = 0;
// Resets SmsReceived signal handler.
virtual void ResetSmsReceivedHandler(const std::string& service_name,
const dbus::ObjectPath& object_path) = 0;
// Calls Delete method. |callback| is called after the method call succeeds.
virtual void Delete(const std::string& service_name,
const dbus::ObjectPath& object_path,
const dbus::ObjectPath& sms_path,
const DeleteCallback& callback) = 0;
// Calls List method. |callback| is called after the method call succeeds.
virtual void List(const std::string& service_name,
const dbus::ObjectPath& object_path,
const ListCallback& callback) = 0;
protected:
// Create() should be used instead.
ModemMessagingClient();
private:
DISALLOW_COPY_AND_ASSIGN(ModemMessagingClient);
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_MODEM_MESSAGING_CLIENT_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/modem_messaging_client.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/values.h"
#include "dbus/message.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_object_proxy.h"
#include "dbus/object_path.h"
#include "dbus/values_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;
namespace chromeos {
namespace {
// A mock SmsReceivedHandler.
class MockSmsReceivedHandler {
public:
MOCK_METHOD2(Run, void(const dbus::ObjectPath &sms, bool complete));
};
// A mock DeleteCallback.
class MockDeleteCallback {
public:
MOCK_METHOD0(Run, void());
};
// A mock ListCallback.
class MockListCallback {
public:
MOCK_METHOD1(Run, void(const std::vector<dbus::ObjectPath>& result));
};
// D-Bus service name used by test.
const char kServiceName[] = "service.name";
// D-Bus object path used by test.
const char kObjectPath[] = "/object/path";
// Keys of SMS dictionary.
const char kNumberKey[] = "number";
const char kTextKey[] = "text";
// Example values of SMS dictionary.
const char kExampleNumber[] = "00012345678";
const char kExampleText[] = "Hello.";
} // namespace
class ModemMessagingClientTest : public testing::Test {
public:
ModemMessagingClientTest() : response_(NULL),
expected_result_(NULL) {}
virtual void SetUp() OVERRIDE {
// Create a mock bus.
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
mock_bus_ = new dbus::MockBus(options);
// Create a mock proxy.
mock_proxy_ = new dbus::MockObjectProxy(mock_bus_.get(),
kServiceName,
dbus::ObjectPath(kObjectPath));
// Set an expectation so mock_proxy's ConnectToSignal() will use
// OnConnectToSignal() to run the callback.
EXPECT_CALL(*mock_proxy_, ConnectToSignal(
modemmanager::kModemManager1MessagingInterface,
modemmanager::kSMSAddedSignal, _, _))
.WillRepeatedly(
Invoke(this, &ModemMessagingClientTest::OnConnectToSignal));
// Set an expectation so mock_bus's GetObjectProxy() for the given
// service name and the object path will return mock_proxy_.
EXPECT_CALL(*mock_bus_, GetObjectProxy(kServiceName,
dbus::ObjectPath(kObjectPath)))
.WillOnce(Return(mock_proxy_.get()));
// ShutdownAndBlock() will be called in TearDown().
EXPECT_CALL(*mock_bus_, ShutdownAndBlock()).WillOnce(Return());
// Create a client with the mock bus.
client_.reset(ModemMessagingClient::Create(REAL_DBUS_CLIENT_IMPLEMENTATION,
mock_bus_));
}
virtual void TearDown() OVERRIDE {
mock_bus_->ShutdownAndBlock();
}
// Handles Delete method call.
void OnDelete(dbus::MethodCall* method_call,
int timeout_ms,
const dbus::ObjectProxy::ResponseCallback& callback) {
EXPECT_EQ(modemmanager::kModemManager1MessagingInterface,
method_call->GetInterface());
EXPECT_EQ(modemmanager::kSMSDeleteFunction, method_call->GetMember());
dbus::ObjectPath sms_path;
dbus::MessageReader reader(method_call);
EXPECT_TRUE(reader.PopObjectPath(&sms_path));
EXPECT_EQ(expected_sms_path_, sms_path);
EXPECT_FALSE(reader.HasMoreData());
message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
}
// Handles List method call.
void OnList(dbus::MethodCall* method_call,
int timeout_ms,
const dbus::ObjectProxy::ResponseCallback& callback) {
EXPECT_EQ(modemmanager::kModemManager1MessagingInterface,
method_call->GetInterface());
EXPECT_EQ(modemmanager::kSMSListFunction, method_call->GetMember());
dbus::MessageReader reader(method_call);
EXPECT_FALSE(reader.HasMoreData());
message_loop_.PostTask(FROM_HERE, base::Bind(callback, response_));
}
// Checks the results of List.
void CheckResult(const std::vector<dbus::ObjectPath>& result) {
EXPECT_EQ(result, *expected_result_);
}
protected:
// The client to be tested.
scoped_ptr<ModemMessagingClient> client_;
// A message loop to emulate asynchronous behavior.
MessageLoop message_loop_;
// The mock bus.
scoped_refptr<dbus::MockBus> mock_bus_;
// The mock object proxy.
scoped_refptr<dbus::MockObjectProxy> mock_proxy_;
// The SmsReceived signal handler given by the tested client.
dbus::ObjectProxy::SignalCallback sms_received_callback_;
// Expected argument for Delete method.
dbus::ObjectPath expected_sms_path_;
// Response returned by mock methods.
dbus::Response* response_;
// Expected result of List method.
std::vector<dbus::ObjectPath>* expected_result_;
private:
// Used to implement the mock proxy.
void OnConnectToSignal(
const std::string& interface_name,
const std::string& signal_name,
const dbus::ObjectProxy::SignalCallback& signal_callback,
const dbus::ObjectProxy::OnConnectedCallback& on_connected_callback) {
sms_received_callback_ = signal_callback;
const bool success = true;
message_loop_.PostTask(FROM_HERE, base::Bind(on_connected_callback,
interface_name,
signal_name,
success));
}
};
TEST_F(ModemMessagingClientTest, SmsReceived) {
// Set expectations.
const dbus::ObjectPath kSmsPath("/SMS/0");
const bool kComplete = true;
MockSmsReceivedHandler handler;
EXPECT_CALL(handler, Run(kSmsPath, kComplete)).Times(1);
// Set handler.
client_->SetSmsReceivedHandler(kServiceName, dbus::ObjectPath(kObjectPath),
base::Bind(&MockSmsReceivedHandler::Run,
base::Unretained(&handler)));
// Run the message loop to run the signal connection result callback.
message_loop_.RunAllPending();
// Send signal.
dbus::Signal signal(modemmanager::kModemManager1MessagingInterface,
modemmanager::kSMSAddedSignal);
dbus::MessageWriter writer(&signal);
writer.AppendObjectPath(kSmsPath);
writer.AppendBool(kComplete);
ASSERT_FALSE(sms_received_callback_.is_null());
sms_received_callback_.Run(&signal);
// Reset handler.
client_->ResetSmsReceivedHandler(kServiceName, dbus::ObjectPath(kObjectPath));
// Send signal again.
sms_received_callback_.Run(&signal);
}
TEST_F(ModemMessagingClientTest, Delete) {
// Set expectations.
const dbus::ObjectPath kSmsPath("/SMS/0");
expected_sms_path_ = kSmsPath;
EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _))
.WillOnce(Invoke(this, &ModemMessagingClientTest::OnDelete));
MockDeleteCallback callback;
EXPECT_CALL(callback, Run()).Times(1);
// Create response.
scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
response_ = response.get();
// Call Delete.
client_->Delete(kServiceName, dbus::ObjectPath(kObjectPath), kSmsPath,
base::Bind(&MockDeleteCallback::Run,
base::Unretained(&callback)));
// Run the message loop.
message_loop_.RunAllPending();
}
TEST_F(ModemMessagingClientTest, List) {
// Set expectations.
EXPECT_CALL(*mock_proxy_, CallMethod(_, _, _))
.WillOnce(Invoke(this, &ModemMessagingClientTest::OnList));
MockListCallback callback;
EXPECT_CALL(callback, Run(_))
.WillOnce(Invoke(this, &ModemMessagingClientTest::CheckResult));
// Create response.
scoped_ptr<dbus::Response> response(dbus::Response::CreateEmpty());
dbus::ObjectPath path1("/SMS/1");
dbus::ObjectPath path2("/SMS/2");
std::vector<dbus::ObjectPath> expected_result;
expected_result.push_back(path1);
expected_result.push_back(path2);
dbus::MessageWriter writer(response.get());
writer.AppendArrayOfObjectPaths(expected_result);
response_ = response.get();
// Save expected result.
expected_result_ = &expected_result;
// Call List.
client_->List(kServiceName, dbus::ObjectPath(kObjectPath),
base::Bind(&MockListCallback::Run,
base::Unretained(&callback)));
// Run the message loop.
message_loop_.RunAllPending();
}
} // namespace chromeos
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/sms_client.h"
#include <map>
#include <utility>
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/stringprintf.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "dbus/values_util.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
// SMSClient is used to communicate with the
// org.freedesktop.ModemManager1.SMS service. All methods should be
// called from the origin thread (UI thread) which initializes the
// DBusThreadManager instance.
class SMSClientImpl : public SMSClient {
public:
explicit SMSClientImpl(dbus::Bus* bus) : bus_(bus), weak_ptr_factory_(this) {}
virtual ~SMSClientImpl() {}
// Calls GetAll method. |callback| is called after the method call succeeds.
virtual void GetAll(const std::string& service_name,
const dbus::ObjectPath& object_path,
const GetAllCallback& callback) OVERRIDE {
dbus::ObjectProxy *proxy = bus_->GetObjectProxy(service_name, object_path);
dbus::MethodCall method_call(dbus::kDBusPropertiesInterface,
dbus::kDBusPropertiesGetAll);
dbus::MessageWriter writer(&method_call);
writer.AppendString(modemmanager::kModemManager1SmsInterface);
proxy->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::Bind(&SMSClientImpl::OnGetAll,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
private:
// Handles responses of GetAll method calls.
void OnGetAll(const GetAllCallback& callback, dbus::Response* response) {
if (!response) {
// Must invoke the callback, even if there is no message.
callback.Run(base::DictionaryValue());
return;
}
dbus::MessageReader reader(response);
scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
base::DictionaryValue* dictionary_value = NULL;
if (!value.get() || !value->GetAsDictionary(&dictionary_value)) {
LOG(WARNING) << "Invalid response: " << response->ToString();
callback.Run(base::DictionaryValue());
return;
}
callback.Run(*dictionary_value);
}
dbus::Bus* bus_;
base::WeakPtrFactory<SMSClientImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SMSClientImpl);
};
class SMSClientStubImpl : public SMSClient {
public:
SMSClientStubImpl() : weak_ptr_factory_(this) {}
virtual ~SMSClientStubImpl() {}
virtual void GetAll(const std::string& service_name,
const dbus::ObjectPath& object_path,
const GetAllCallback& callback) OVERRIDE {
// Ownership passed to callback
base::DictionaryValue *sms = new base::DictionaryValue();
sms->SetString("Number", "000-000-0000");
sms->SetString("Text",
"SMSClientStubImpl: Test Message: " + object_path.value());
sms->SetString("Timestamp", "Fri Jun 8 13:26:04 EDT 2012");
// Run callback asynchronously.
MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&SMSClientStubImpl::OnGetAll,
weak_ptr_factory_.GetWeakPtr(),
base::Owned(sms),
callback));
}
private:
void OnGetAll(base::DictionaryValue *sms,
const GetAllCallback& callback) {
callback.Run(*sms);
}
base::WeakPtrFactory<SMSClientStubImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SMSClientStubImpl);
};
} // namespace
////////////////////////////////////////////////////////////////////////////////
// SMSClient
SMSClient::SMSClient() {}
SMSClient::~SMSClient() {}
// static
SMSClient* SMSClient::Create(DBusClientImplementationType type,
dbus::Bus* bus) {
if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) {
return new SMSClientImpl(bus);
}
DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
return new SMSClientStubImpl();
}
} // namespace chromeos
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_DBUS_SMS_CLIENT_H_
#define CHROMEOS_DBUS_SMS_CLIENT_H_
#pragma once
#include <string>
#include "base/basictypes.h"
#include "base/callback.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/dbus/dbus_client_implementation_type.h"
namespace base {
class DictionaryValue;
}
namespace dbus {
class Bus;
class ObjectPath;
}
namespace chromeos {
// SMSMessageClient is used to communicate with the
// org.freedesktop.ModemManager1.SMS service. All methods should be
// called from the origin thread (UI thread) which initializes the
// DBusThreadManager instance.
class CHROMEOS_EXPORT SMSClient {
public:
typedef base::Callback<void(const base::DictionaryValue& sms)> GetAllCallback;
virtual ~SMSClient();
// Factory function, creates a new instance and returns ownership.
// For normal usage, access the singleton via DBusThreadManager::Get().
static SMSClient* Create(DBusClientImplementationType type,
dbus::Bus* bus);
// Calls GetAll method. |callback| is called after the method call succeeds.
virtual void GetAll(const std::string& service_name,
const dbus::ObjectPath& object_path,
const GetAllCallback& callback) = 0;
protected:
// Create() should be used instead.
SMSClient();
private:
DISALLOW_COPY_AND_ASSIGN(SMSClient);
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_SMS_CLIENT_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment