summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 01:45:36 +0000
committerstevenjb@google.com <stevenjb@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-15 01:45:36 +0000
commit9c0991fb61244d17082aa86eb98756c660bba08e (patch)
tree297cd6f54aa7f44631f59db0f9a10863dd885c50
parent42bc70aa115c29b2ae3adcb58a306f4cbf1ac4fe (diff)
downloadchromium_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.gyp3
-rw-r--r--chromeos/dbus/dbus_thread_manager.cc16
-rw-r--r--chromeos/dbus/dbus_thread_manager.h5
-rw-r--r--chromeos/dbus/flimflam_device_client.cc60
-rw-r--r--chromeos/dbus/flimflam_manager_client.cc18
-rw-r--r--chromeos/dbus/gsm_sms_client.cc70
-rw-r--r--chromeos/network/network_sms_handler.cc232
-rw-r--r--chromeos/network/network_sms_handler.h69
-rw-r--r--chromeos/network/network_sms_handler_unittest.cc64
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