1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #include "chromeos/dbus/sms_client.h" 5 6 #include <map> 7 #include <utility> 8 9 #include "base/bind.h" 10 #include "base/command_line.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/message_loop/message_loop.h" 14 #include "base/stl_util.h" 15 #include "base/strings/stringprintf.h" 16 #include "base/values.h" 17 #include "chromeos/chromeos_switches.h" 18 #include "dbus/bus.h" 19 #include "dbus/message.h" 20 #include "dbus/object_proxy.h" 21 #include "dbus/values_util.h" 22 #include "third_party/cros_system_api/dbus/service_constants.h" 23 24 namespace chromeos { 25 26 namespace { 27 28 // SMSClient is used to communicate with the 29 // org.freedesktop.ModemManager1.SMS service. All methods should be 30 // called from the origin thread (UI thread) which initializes the 31 // DBusThreadManager instance. 32 class SMSClientImpl : public SMSClient { 33 public: 34 explicit SMSClientImpl(dbus::Bus* bus) : bus_(bus), weak_ptr_factory_(this) {} 35 virtual ~SMSClientImpl() {} 36 37 // Calls GetAll method. |callback| is called after the method call succeeds. 38 virtual void GetAll(const std::string& service_name, 39 const dbus::ObjectPath& object_path, 40 const GetAllCallback& callback) OVERRIDE { 41 dbus::ObjectProxy *proxy = bus_->GetObjectProxy(service_name, object_path); 42 dbus::MethodCall method_call(dbus::kDBusPropertiesInterface, 43 dbus::kDBusPropertiesGetAll); 44 dbus::MessageWriter writer(&method_call); 45 writer.AppendString(modemmanager::kModemManager1SmsInterface); 46 proxy->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 47 base::Bind(&SMSClientImpl::OnGetAll, 48 weak_ptr_factory_.GetWeakPtr(), 49 callback)); 50 } 51 52 private: 53 // Handles responses of GetAll method calls. 54 void OnGetAll(const GetAllCallback& callback, dbus::Response* response) { 55 if (!response) { 56 // Must invoke the callback, even if there is no message. 57 base::DictionaryValue empty_dictionary; 58 callback.Run(empty_dictionary); 59 return; 60 } 61 dbus::MessageReader reader(response); 62 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); 63 base::DictionaryValue* dictionary_value = NULL; 64 if (!value.get() || !value->GetAsDictionary(&dictionary_value)) { 65 LOG(WARNING) << "Invalid response: " << response->ToString(); 66 base::DictionaryValue empty_dictionary; 67 callback.Run(empty_dictionary); 68 return; 69 } 70 callback.Run(*dictionary_value); 71 } 72 73 dbus::Bus* bus_; 74 75 // Note: This should remain the last member so it'll be destroyed and 76 // invalidate its weak pointers before any other members are destroyed. 77 base::WeakPtrFactory<SMSClientImpl> weak_ptr_factory_; 78 79 DISALLOW_COPY_AND_ASSIGN(SMSClientImpl); 80 }; 81 82 class SMSClientStubImpl : public SMSClient { 83 public: 84 SMSClientStubImpl() : weak_ptr_factory_(this) {} 85 virtual ~SMSClientStubImpl() {} 86 87 virtual void GetAll(const std::string& service_name, 88 const dbus::ObjectPath& object_path, 89 const GetAllCallback& callback) OVERRIDE { 90 if (!CommandLine::ForCurrentProcess()->HasSwitch( 91 chromeos::switches::kSmsTestMessages)) 92 return; 93 94 // Ownership passed to callback 95 base::DictionaryValue *sms = new base::DictionaryValue(); 96 sms->SetString("Number", "000-000-0000"); 97 sms->SetString("Text", 98 "SMSClientStubImpl: Test Message: " + object_path.value()); 99 sms->SetString("Timestamp", "Fri Jun 8 13:26:04 EDT 2012"); 100 101 // Run callback asynchronously. 102 if (callback.is_null()) 103 return; 104 base::MessageLoop::current()->PostTask( 105 FROM_HERE, 106 base::Bind(&SMSClientStubImpl::OnGetAll, 107 weak_ptr_factory_.GetWeakPtr(), 108 base::Owned(sms), 109 callback)); 110 } 111 112 private: 113 void OnGetAll(base::DictionaryValue *sms, 114 const GetAllCallback& callback) { 115 callback.Run(*sms); 116 } 117 118 base::WeakPtrFactory<SMSClientStubImpl> weak_ptr_factory_; 119 120 DISALLOW_COPY_AND_ASSIGN(SMSClientStubImpl); 121 }; 122 123 } // namespace 124 125 //////////////////////////////////////////////////////////////////////////////// 126 // SMSClient 127 128 SMSClient::SMSClient() {} 129 130 SMSClient::~SMSClient() {} 131 132 133 // static 134 SMSClient* SMSClient::Create(DBusClientImplementationType type, 135 dbus::Bus* bus) { 136 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) { 137 return new SMSClientImpl(bus); 138 } 139 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type); 140 return new SMSClientStubImpl(); 141 } 142 143 } // namespace chromeos 144