diff options
author | stevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-15 01:45:36 +0000 |
---|---|---|
committer | stevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-15 01:45:36 +0000 |
commit | 9c0991fb61244d17082aa86eb98756c660bba08e (patch) | |
tree | 297cd6f54aa7f44631f59db0f9a10863dd885c50 | |
parent | 42bc70aa115c29b2ae3adcb58a306f4cbf1ac4fe (diff) | |
download | chromium_src-9c0991fb61244d17082aa86eb98756c660bba08e.zip chromium_src-9c0991fb61244d17082aa86eb98756c660bba08e.tar.gz chromium_src-9c0991fb61244d17082aa86eb98756c660bba08e.tar.bz2 |
Add NetworkSmsHandler to chromoes/ for tracking SMS messages.
Includes stub implementations for flimflam Device and Manager to support SMS.
BUG=124724
TEST=Run NetworkSmsHandlerTest in chromeos_unittests
Review URL: https://chromiumcodereview.appspot.com/10310095
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137049 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chromeos/chromeos.gyp | 3 | ||||
-rw-r--r-- | chromeos/dbus/dbus_thread_manager.cc | 16 | ||||
-rw-r--r-- | chromeos/dbus/dbus_thread_manager.h | 5 | ||||
-rw-r--r-- | chromeos/dbus/flimflam_device_client.cc | 60 | ||||
-rw-r--r-- | chromeos/dbus/flimflam_manager_client.cc | 18 | ||||
-rw-r--r-- | chromeos/dbus/gsm_sms_client.cc | 70 | ||||
-rw-r--r-- | chromeos/network/network_sms_handler.cc | 232 | ||||
-rw-r--r-- | chromeos/network/network_sms_handler.h | 69 | ||||
-rw-r--r-- | chromeos/network/network_sms_handler_unittest.cc | 64 |
9 files changed, 505 insertions, 32 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 5c7fc60..4e836d3 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -87,6 +87,8 @@ 'dbus/speech_synthesizer_client.h', 'dbus/update_engine_client.cc', 'dbus/update_engine_client.h', + 'network/network_sms_handler.cc', + 'network/network_sms_handler.h', ], }, { @@ -178,6 +180,7 @@ 'dbus/ibus/ibus_client_unittest.cc', 'dbus/ibus/ibus_object_unittest.cc', 'dbus/ibus/ibus_text_unittest.cc', + 'network/network_sms_handler_unittest.cc', ], 'include_dirs': [ '..', diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index ca436a2..05ac8fd 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc @@ -48,7 +48,7 @@ class DBusThreadManagerImpl : public DBusThreadManager { chromeos::switches::kDbusStub)) client_type_maybe_stub = STUB_DBUS_CLIENT_IMPLEMENTATION; - // Create the D-Bus thread. + // Create the D-Bus thread. base::Thread::Options thread_options; thread_options.message_loop_type = MessageLoop::TYPE_IO; dbus_thread_.reset(new base::Thread("D-Bus thread")); @@ -300,14 +300,16 @@ void DBusThreadManager::InitializeForTesting( LOG(WARNING) << "DBusThreadManager was already initialized"; return; } - if (dbus_thread_manager) { - g_dbus_thread_manager = dbus_thread_manager; - VLOG(1) << "DBusThreadManager initialized with test implementation"; - } else { - g_dbus_thread_manager = + CHECK(dbus_thread_manager); + g_dbus_thread_manager = dbus_thread_manager; + VLOG(1) << "DBusThreadManager initialized with test implementation"; +} + +// static +void DBusThreadManager::InitializeWithStub() { + g_dbus_thread_manager = new DBusThreadManagerImpl(STUB_DBUS_CLIENT_IMPLEMENTATION); VLOG(1) << "DBusThreadManager initialized with stub implementation"; - } } // static diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index 742bb09..fa7b108 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h @@ -72,9 +72,12 @@ class CHROMEOS_EXPORT DBusThreadManager { // Similar to Initialize(), but can inject an alternative // DBusThreadManager such as MockDBusThreadManager for testing. // The injected object will be owned by the internal pointer and deleted - // by Shutdown(). If NULL, a stub implementation will be constructed. + // by Shutdown(). static void InitializeForTesting(DBusThreadManager* dbus_thread_manager); + // Initialize with stub implementations for tests based on stubs. + static void InitializeWithStub(); + // Destroys the global instance. static void Shutdown(); diff --git a/chromeos/dbus/flimflam_device_client.cc b/chromeos/dbus/flimflam_device_client.cc index eccc7ef..29f59bc 100644 --- a/chromeos/dbus/flimflam_device_client.cc +++ b/chromeos/dbus/flimflam_device_client.cc @@ -208,9 +208,24 @@ class FlimflamDeviceClientImpl : public FlimflamDeviceClient { }; // A stub implementation of FlimflamDeviceClient. +// Implemented: Stub cellular device for SMS testing. class FlimflamDeviceClientStubImpl : public FlimflamDeviceClient { public: - FlimflamDeviceClientStubImpl() : weak_ptr_factory_(this) {} + FlimflamDeviceClientStubImpl() : weak_ptr_factory_(this) { + // Add a cellular device for SMS. Note: name matches Manager entry. + const char kStubCellular1[] = "stub_cellular1"; + base::DictionaryValue* cellular_properties = new base::DictionaryValue; + cellular_properties->SetWithoutPathExpansion( + flimflam::kTypeProperty, + base::Value::CreateStringValue(flimflam::kTypeCellular)); + cellular_properties->SetWithoutPathExpansion( + flimflam::kDBusConnectionProperty, + base::Value::CreateStringValue("/stub")); + cellular_properties->SetWithoutPathExpansion( + flimflam::kDBusObjectProperty, + base::Value::CreateStringValue("/device/cellular1")); + stub_devices_.Set(kStubCellular1, cellular_properties); + } virtual ~FlimflamDeviceClientStubImpl() {} @@ -228,9 +243,9 @@ class FlimflamDeviceClientStubImpl : public FlimflamDeviceClient { const DictionaryValueCallback& callback) OVERRIDE { MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&FlimflamDeviceClientStubImpl::PassEmptyDictionaryValue, + base::Bind(&FlimflamDeviceClientStubImpl::PassStubDevicePrperties, weak_ptr_factory_.GetWeakPtr(), - callback)); + device_path, callback)); } // FlimflamDeviceClient override. @@ -242,7 +257,7 @@ class FlimflamDeviceClientStubImpl : public FlimflamDeviceClient { // FlimflamProfileClient override. virtual void ProposeScan(const dbus::ObjectPath& device_path, const VoidCallback& callback) OVERRIDE { - PostSuccessVoidCallback(callback); + PostVoidCallback(callback, DBUS_METHOD_CALL_SUCCESS); } // FlimflamDeviceClient override. @@ -250,14 +265,26 @@ class FlimflamDeviceClientStubImpl : public FlimflamDeviceClient { const std::string& name, const base::Value& value, const VoidCallback& callback) OVERRIDE { - PostSuccessVoidCallback(callback); + base::DictionaryValue* device_properties = NULL; + if (!stub_devices_.GetDictionary(device_path.value(), &device_properties)) { + PostVoidCallback(callback, DBUS_METHOD_CALL_FAILURE); + return; + } + device_properties->Set(name, value.DeepCopy()); + PostVoidCallback(callback, DBUS_METHOD_CALL_SUCCESS); } // FlimflamDeviceClient override. virtual void ClearProperty(const dbus::ObjectPath& device_path, const std::string& name, const VoidCallback& callback) OVERRIDE { - PostSuccessVoidCallback(callback); + base::DictionaryValue* device_properties = NULL; + if (!stub_devices_.GetDictionary(device_path.value(), &device_properties)) { + PostVoidCallback(callback, DBUS_METHOD_CALL_FAILURE); + return; + } + device_properties->Remove(name, NULL); + PostVoidCallback(callback, DBUS_METHOD_CALL_SUCCESS); } // FlimflamDeviceClient override. @@ -321,19 +348,26 @@ class FlimflamDeviceClientStubImpl : public FlimflamDeviceClient { } private: - void PassEmptyDictionaryValue(const DictionaryValueCallback& callback) const { - base::DictionaryValue dictionary; - callback.Run(DBUS_METHOD_CALL_SUCCESS, dictionary); + void PassStubDevicePrperties(const dbus::ObjectPath& device_path, + const DictionaryValueCallback& callback) const { + base::DictionaryValue* device_properties = NULL; + if (!stub_devices_.GetDictionary(device_path.value(), &device_properties)) { + callback.Run(DBUS_METHOD_CALL_FAILURE, base::DictionaryValue()); + return; + } + callback.Run(DBUS_METHOD_CALL_SUCCESS, *device_properties); } - // Posts a task to run a void callback with success status code. - void PostSuccessVoidCallback(const VoidCallback& callback) { + // Posts a task to run a void callback with status code |status|. + void PostVoidCallback(const VoidCallback& callback, + DBusMethodCallStatus status) { MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(callback, - DBUS_METHOD_CALL_SUCCESS)); + base::Bind(callback, status)); } base::WeakPtrFactory<FlimflamDeviceClientStubImpl> weak_ptr_factory_; + // Dictionary of <device_name, Dictionary>. + base::DictionaryValue stub_devices_; DISALLOW_COPY_AND_ASSIGN(FlimflamDeviceClientStubImpl); }; diff --git a/chromeos/dbus/flimflam_manager_client.cc b/chromeos/dbus/flimflam_manager_client.cc index 984e7e1..7c52ff6 100644 --- a/chromeos/dbus/flimflam_manager_client.cc +++ b/chromeos/dbus/flimflam_manager_client.cc @@ -144,9 +144,16 @@ class FlimflamManagerClientImpl : public FlimflamManagerClient { }; // A stub implementation of FlimflamManagerClient. +// Implemented: Stub cellular DeviceList entry for SMS testing. class FlimflamManagerClientStubImpl : public FlimflamManagerClient { public: - FlimflamManagerClientStubImpl() : weak_ptr_factory_(this) {} + FlimflamManagerClientStubImpl() : weak_ptr_factory_(this) { + base::ListValue* device_list = new base::ListValue; + // Note: name matches Device stub map. + const char kStubCellular1[] = "stub_cellular1"; + device_list->Append(base::Value::CreateStringValue(kStubCellular1)); + stub_properties_.Set(flimflam::kDevicesProperty, device_list); + } virtual ~FlimflamManagerClientStubImpl() {} @@ -161,7 +168,7 @@ class FlimflamManagerClientStubImpl : public FlimflamManagerClient { virtual void GetProperties(const DictionaryValueCallback& callback) OVERRIDE { MessageLoop::current()->PostTask( FROM_HERE, base::Bind( - &FlimflamManagerClientStubImpl::PassEmptyDictionaryValue, + &FlimflamManagerClientStubImpl::PassStubProperties, weak_ptr_factory_.GetWeakPtr(), callback)); } @@ -175,6 +182,7 @@ class FlimflamManagerClientStubImpl : public FlimflamManagerClient { virtual void SetProperty(const std::string& name, const base::Value& value, const VoidCallback& callback) OVERRIDE { + stub_properties_.Set(name, value.DeepCopy()); MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS)); @@ -222,12 +230,12 @@ class FlimflamManagerClientStubImpl : public FlimflamManagerClient { } private: - void PassEmptyDictionaryValue(const DictionaryValueCallback& callback) const { - base::DictionaryValue dictionary; - callback.Run(DBUS_METHOD_CALL_SUCCESS, dictionary); + void PassStubProperties(const DictionaryValueCallback& callback) const { + callback.Run(DBUS_METHOD_CALL_SUCCESS, stub_properties_); } base::WeakPtrFactory<FlimflamManagerClientStubImpl> weak_ptr_factory_; + base::DictionaryValue stub_properties_; DISALLOW_COPY_AND_ASSIGN(FlimflamManagerClientStubImpl); }; diff --git a/chromeos/dbus/gsm_sms_client.cc b/chromeos/dbus/gsm_sms_client.cc index 3dae2ea..0e25ef7 100644 --- a/chromeos/dbus/gsm_sms_client.cc +++ b/chromeos/dbus/gsm_sms_client.cc @@ -6,6 +6,8 @@ #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" @@ -223,7 +225,13 @@ class GsmSMSClientImpl : public GsmSMSClient { // A stub implementaion of GsmSMSClient. class GsmSMSClientStubImpl : public GsmSMSClient { public: - GsmSMSClientStubImpl() {} + GsmSMSClientStubImpl() : test_index_(0), weak_ptr_factory_(this) { + test_messages_.push_back("Test Message 0"); + test_messages_.push_back("Test Message 1"); + test_messages_.push_back("Test a relatively long message 2"); + test_messages_.push_back("Test a very, the quick brown fox jumped" + " over the lazy dog, long message 3"); + } virtual ~GsmSMSClientStubImpl() {} @@ -231,31 +239,81 @@ class GsmSMSClientStubImpl : public GsmSMSClient { virtual void SetSmsReceivedHandler( const std::string& service_name, const dbus::ObjectPath& object_path, - const SmsReceivedHandler& handler) OVERRIDE {} + const SmsReceivedHandler& handler) OVERRIDE { + handler_ = handler; + } // GsmSMSClient override. virtual void ResetSmsReceivedHandler( const std::string& service_name, - const dbus::ObjectPath& object_path) OVERRIDE {} + const dbus::ObjectPath& object_path) OVERRIDE { + handler_.Reset(); + } // GsmSMSClient override. virtual void Delete(const std::string& service_name, const dbus::ObjectPath& object_path, uint32 index, - const DeleteCallback& callback) OVERRIDE {} + const DeleteCallback& callback) OVERRIDE { + message_list_.Remove(index, NULL); + callback.Run(); + } // GsmSMSClient override. virtual void Get(const std::string& service_name, const dbus::ObjectPath& object_path, uint32 index, - const GetCallback& callback) OVERRIDE {} + const GetCallback& callback) OVERRIDE { + base::DictionaryValue* dictionary = NULL; + if (message_list_.GetDictionary(index, &dictionary)) { + callback.Run(*dictionary); + return; + } + callback.Run(base::DictionaryValue()); + } // GsmSMSClient override. virtual void List(const std::string& service_name, const dbus::ObjectPath& object_path, - const ListCallback& callback) OVERRIDE {} + const ListCallback& callback) OVERRIDE { + PushTestMessageChain(); + callback.Run(message_list_); + } private: + void PushTestMessageChain() { + if (PushTestMessage()) { + // Queue up the next message. + const int kSmsMessageDelaySeconds = 5; + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&GsmSMSClientStubImpl::PushTestMessageChain, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromSeconds(kSmsMessageDelaySeconds)); + } + } + + bool PushTestMessage() { + if (test_index_ >= test_messages_.size()) + return false; + base::DictionaryValue* message = new base::DictionaryValue; + message->SetString("number", "000-000-0000"); + message->SetString("text", test_messages_[test_index_]); + message->SetInteger("index", test_index_); + int msg_index = message_list_.GetSize(); + message_list_.Append(message); + if (!handler_.is_null()) + handler_.Run(msg_index, true); + ++test_index_; + return true; + } + + size_t test_index_; + std::vector<std::string> test_messages_; + base::ListValue message_list_; + SmsReceivedHandler handler_; + base::WeakPtrFactory<GsmSMSClientStubImpl> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(GsmSMSClientStubImpl); }; diff --git a/chromeos/network/network_sms_handler.cc b/chromeos/network/network_sms_handler.cc new file mode 100644 index 0000000..e28e5d3 --- /dev/null +++ b/chromeos/network/network_sms_handler.cc @@ -0,0 +1,232 @@ +// 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/network/network_sms_handler.h" + +#include <string> + +#include "base/bind.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/flimflam_device_client.h" +#include "chromeos/dbus/flimflam_manager_client.h" +#include "chromeos/dbus/gsm_sms_client.h" +#include "dbus/object_path.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +// Not exposed/exported. +namespace { +const char kSmscKey[] = "smsc"; +const char kValidityKey[] = "validity"; +const char kClassKey[] = "class"; +const char kIndexKey[] = "index"; +} // namespace + +namespace chromeos { + +// static +const char NetworkSmsHandler::kNumberKey[] = "number"; +const char NetworkSmsHandler::kTextKey[] = "text"; +const char NetworkSmsHandler::kTimestampKey[] = "timestamp"; + +class NetworkSmsHandler::NetworkSmsDeviceHandler { + public: + NetworkSmsDeviceHandler(NetworkSmsHandler* host, + std::string dbus_connection, + dbus::ObjectPath object_path); + + 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 NotifyMessageReceived(const base::DictionaryValue& dictionary); + + NetworkSmsHandler* host_; + std::string dbus_connection_; + dbus::ObjectPath object_path_; + bool deleting_messages_; + base::WeakPtrFactory<NetworkSmsDeviceHandler> weak_ptr_factory_; + std::vector<uint32> delete_queue_; + + DISALLOW_COPY_AND_ASSIGN(NetworkSmsDeviceHandler); +}; + +NetworkSmsHandler::NetworkSmsDeviceHandler::NetworkSmsDeviceHandler( + NetworkSmsHandler* host, + std::string dbus_connection, + dbus::ObjectPath object_path) + : host_(host), + dbus_connection_(dbus_connection), + object_path_(object_path), + deleting_messages_(false), + weak_ptr_factory_(this) { + // Set the handler for received Sms messaages. + DBusThreadManager::Get()->GetGsmSMSClient()->SetSmsReceivedHandler( + dbus_connection_, object_path_, + base::Bind(&NetworkSmsDeviceHandler::SmsReceivedCallback, + weak_ptr_factory_.GetWeakPtr())); + + // List the existing messages. + DBusThreadManager::Get()->GetGsmSMSClient()->List( + dbus_connection_, object_path_, + base::Bind(&NetworkSmsDeviceHandler::ListCallback, + weak_ptr_factory_.GetWeakPtr())); +} + +void NetworkSmsHandler::NetworkSmsDeviceHandler::ListCallback( + const base::ListValue& message_list) { + // This receives all messages, so clear any pending deletes. + 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; + NotifyMessageReceived(*message); + double index = 0; + if (message->GetDoubleWithoutPathExpansion(kIndexKey, &index)) + delete_queue_.push_back(static_cast<uint32>(index)); + } + DeleteMessages(); +} + +// Messages must be deleted one at a time, since we can not gaurantee the order +// the deletion will be executed in. Delete messages from the back of the list +// so that the indices are valid. +void NetworkSmsHandler::NetworkSmsDeviceHandler::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( + dbus_connection_, object_path_, index, + base::Bind(&NetworkSmsDeviceHandler::DeleteMessages, + weak_ptr_factory_.GetWeakPtr())); +} + +void NetworkSmsHandler::NetworkSmsDeviceHandler::SmsReceivedCallback( + uint32 index, + bool complete) { + // Only handle complete messages. + if (!complete) + return; + DBusThreadManager::Get()->GetGsmSMSClient()->Get( + dbus_connection_, object_path_, index, + base::Bind(&NetworkSmsDeviceHandler::GetCallback, + weak_ptr_factory_.GetWeakPtr(), index)); +} + +void NetworkSmsHandler::NetworkSmsDeviceHandler::GetCallback( + uint32 index, + const base::DictionaryValue& dictionary) { + NotifyMessageReceived(dictionary); + delete_queue_.push_back(index); + if (!deleting_messages_) + DeleteMessages(); +} + +void NetworkSmsHandler::NetworkSmsDeviceHandler::NotifyMessageReceived( + const base::DictionaryValue& dictionary) { + host_->NotifyMessageReceived(dictionary); +} + +/////////////////////////////////////////////////////////////////////////////// +// NetworkSmsHandler + +NetworkSmsHandler::NetworkSmsHandler() + : weak_ptr_factory_(this) { +} + +NetworkSmsHandler::~NetworkSmsHandler() { +} + +void NetworkSmsHandler::Init() { + // Request network manager properties so that we can get the list of devices. + DBusThreadManager::Get()->GetFlimflamManagerClient()->GetProperties( + base::Bind(&NetworkSmsHandler::ManagerPropertiesCallback, + weak_ptr_factory_.GetWeakPtr())); +} + +void NetworkSmsHandler::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void NetworkSmsHandler::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +void NetworkSmsHandler::NotifyMessageReceived( + const base::DictionaryValue& message) { + FOR_EACH_OBSERVER(Observer, observers_, MessageReceived(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; + } + base::Value* value; + if (!properties.GetWithoutPathExpansion(flimflam::kDevicesProperty, &value) || + value->GetType() != base::Value::TYPE_LIST) { + LOG(ERROR) << "NetworkSmsDeviceHandler: No list value for: " + << flimflam::kDevicesProperty; + return; + } + const base::ListValue* devices = static_cast<const base::ListValue*>(value); + for (base::ListValue::const_iterator iter = devices->begin(); + iter != devices->end(); ++iter) { + std::string device_path; + (*iter)->GetAsString(&device_path); + if (!device_path.empty()) { + // Request device properties. + DBusThreadManager::Get()->GetFlimflamDeviceClient()->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) + return; + + std::string device_type; + if (!properties.GetStringWithoutPathExpansion( + flimflam::kTypeProperty, &device_type)) { + LOG(ERROR) << "NetworkSmsDeviceHandler: No type for: " << device_path; + return; + } + if (device_type != flimflam::kTypeCellular) + return; + + std::string dbus_connection; + if (!properties.GetStringWithoutPathExpansion( + flimflam::kDBusConnectionProperty, &dbus_connection)) { + LOG(ERROR) << "Device has no DBusConnection Property: " << device_path; + return; + } + + std::string object_path_string; + if (!properties.GetStringWithoutPathExpansion( + flimflam::kDBusObjectProperty, &object_path_string)) { + LOG(ERROR) << "Device has no DBusObject Property: " << device_path; + return; + } + dbus::ObjectPath object_path(object_path_string); + device_handlers_.push_back( + new NetworkSmsDeviceHandler(this, dbus_connection, object_path)); +} + + +} // namespace chromeos diff --git a/chromeos/network/network_sms_handler.h b/chromeos/network/network_sms_handler.h new file mode 100644 index 0000000..9430e30 --- /dev/null +++ b/chromeos/network/network_sms_handler.h @@ -0,0 +1,69 @@ +// 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_NETWORK_NETWORK_SMS_HANDLER_H_ +#define CHROMEOS_NETWORK_NETWORK_SMS_HANDLER_H_ + +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/values.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_method_call_status.h" + +namespace chromeos { + +// Class to watch sms without Libcros. +class CHROMEOS_EXPORT NetworkSmsHandler { + public: + static const char kNumberKey[]; + static const char kTextKey[]; + static const char kTimestampKey[]; + + class Observer { + public: + virtual ~Observer() {} + + // Called when a new message arrives. |message| contains the message. + // The contents of the dictionary include the keys listed above. + virtual void MessageReceived(const base::DictionaryValue& message) = 0; + }; + + NetworkSmsHandler(); + ~NetworkSmsHandler(); + + // Requests the devices from the netowork manager, sets up observers, and + // requests the initial list of messages. Any observers that wish to be + // notified with initial messages should be added before calling this. + void Init(); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + private: + class NetworkSmsDeviceHandler; + + // Called from NetworkSmsDeviceHandler when a message is received. + void NotifyMessageReceived(const base::DictionaryValue& message); + + // Callback to handle the manager properties with the list of devices. + void ManagerPropertiesCallback(DBusMethodCallStatus call_status, + const base::DictionaryValue& properties); + + // Callback to handle the device properties for |device_path|. + // A NetworkSmsDeviceHandler will be instantiated for each cellular device. + void DevicePropertiesCallback(const std::string& device_path, + DBusMethodCallStatus call_status, + const base::DictionaryValue& properties); + + ObserverList<Observer> observers_; + ScopedVector<NetworkSmsDeviceHandler> device_handlers_; + base::WeakPtrFactory<NetworkSmsHandler> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(NetworkSmsHandler); +}; + +} // namespace + +#endif // CHROMEOS_NETWORK_NETWORK_SMS_HANDLER_H_ diff --git a/chromeos/network/network_sms_handler_unittest.cc b/chromeos/network/network_sms_handler_unittest.cc new file mode 100644 index 0000000..4205954 --- /dev/null +++ b/chromeos/network/network_sms_handler_unittest.cc @@ -0,0 +1,64 @@ +// 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/network/network_sms_handler.h" + +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace { + +class TestObserver : public NetworkSmsHandler::Observer { + public: + TestObserver() : message_count_(0) {} + virtual ~TestObserver() {} + + virtual void MessageReceived(const base::DictionaryValue& message) OVERRIDE { + ++message_count_; + } + + int message_count() { return message_count_; } + + private: + int message_count_; +}; + +} // namespace + +class NetworkSmsHandlerTest : public testing::Test { + public: + NetworkSmsHandlerTest() {} + virtual ~NetworkSmsHandlerTest() {} + + virtual void SetUp() OVERRIDE { + // Initialize DBusThreadManager with a stub implementation. + DBusThreadManager::InitializeWithStub(); + } + + virtual void TearDown() OVERRIDE { + DBusThreadManager::Shutdown(); + } + + protected: + MessageLoopForUI message_loop_; +}; + +TEST_F(NetworkSmsHandlerTest, SmsHandlerDbusStub) { + // This relies on the stub dbus implementations for FlimflamManagerClient, + // FlimflamDeviceClient, and GsmSMSClient. + // Initialize a sms handler. The stub dbus clients will send the first test + // message when Gsm.SMS.List is called in NetworkSmsHandler::Init. + scoped_ptr<NetworkSmsHandler> sms_handler(new NetworkSmsHandler()); + scoped_ptr<TestObserver> test_observer(new TestObserver()); + sms_handler->AddObserver(test_observer.get()); + sms_handler->Init(); + message_loop_.RunAllPending(); + EXPECT_GE(test_observer->message_count(), 1); +} + +} // namespace chromeos |