blob: e1eb066d2683038373ffd36421d3a229c055a121 [file] [log] [blame]
// 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/shill/shill_device_client.h"
#include <map>
#include <utility>
#include "base/bind.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chromeos/dbus/shill/fake_shill_device_client.h"
#include "chromeos/dbus/shill/shill_property_changed_observer.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
#include "dbus/values_util.h"
#include "net/base/ip_endpoint.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
ShillDeviceClient* g_instance = nullptr;
// The ShillDeviceClient implementation.
class ShillDeviceClientImpl : public ShillDeviceClient {
public:
explicit ShillDeviceClientImpl(dbus::Bus* bus) : bus_(bus) {}
~ShillDeviceClientImpl() override {
for (HelperMap::iterator iter = helpers_.begin(); iter != helpers_.end();
++iter) {
// This *should* never happen, yet we're getting crash reports that
// seem to imply that it does happen sometimes. Adding CHECKs here
// so we can determine more accurately where the problem lies.
// See: http://crbug.com/170541
CHECK(iter->second) << "null Helper found in helper list.";
delete iter->second;
}
helpers_.clear();
}
///////////////////////////////////////
// ShillDeviceClient overrides.
void AddPropertyChangedObserver(
const dbus::ObjectPath& device_path,
ShillPropertyChangedObserver* observer) override {
GetHelper(device_path)->AddPropertyChangedObserver(observer);
}
void RemovePropertyChangedObserver(
const dbus::ObjectPath& device_path,
ShillPropertyChangedObserver* observer) override {
GetHelper(device_path)->RemovePropertyChangedObserver(observer);
}
void GetProperties(const dbus::ObjectPath& device_path,
const DictionaryValueCallback& callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kGetPropertiesFunction);
GetHelper(device_path)->CallDictionaryValueMethod(&method_call, callback);
}
void SetProperty(const dbus::ObjectPath& device_path,
const std::string& name,
const base::Value& value,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kSetPropertyFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(name);
ShillClientHelper::AppendValueDataAsVariant(&writer, value);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void ClearProperty(const dbus::ObjectPath& device_path,
const std::string& name,
VoidDBusMethodCallback callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kClearPropertyFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(name);
GetHelper(device_path)->CallVoidMethod(&method_call, std::move(callback));
}
void RequirePin(const dbus::ObjectPath& device_path,
const std::string& pin,
bool require,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kRequirePinFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(pin);
writer.AppendBool(require);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void EnterPin(const dbus::ObjectPath& device_path,
const std::string& pin,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kEnterPinFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(pin);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void UnblockPin(const dbus::ObjectPath& device_path,
const std::string& puk,
const std::string& pin,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kUnblockPinFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(puk);
writer.AppendString(pin);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void ChangePin(const dbus::ObjectPath& device_path,
const std::string& old_pin,
const std::string& new_pin,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kChangePinFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(old_pin);
writer.AppendString(new_pin);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void Register(const dbus::ObjectPath& device_path,
const std::string& network_id,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kRegisterFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(network_id);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void Reset(const dbus::ObjectPath& device_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kResetFunction);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void PerformTDLSOperation(const dbus::ObjectPath& device_path,
const std::string& operation,
const std::string& peer,
const StringCallback& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kPerformTDLSOperationFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(operation);
writer.AppendString(peer);
GetHelper(device_path)
->CallStringMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void AddWakeOnPacketConnection(const dbus::ObjectPath& device_path,
const net::IPEndPoint& ip_endpoint,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
if (ip_endpoint.address().empty()) {
LOG(ERROR) << "AddWakeOnPacketConnection: null address";
return;
}
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kAddWakeOnPacketConnectionFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(ip_endpoint.ToStringWithoutPort());
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void AddWakeOnPacketOfTypes(const dbus::ObjectPath& device_path,
const std::vector<std::string>& types,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kAddWakeOnPacketOfTypesFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendArrayOfStrings(types);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void RemoveWakeOnPacketConnection(
const dbus::ObjectPath& device_path,
const net::IPEndPoint& ip_endpoint,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
if (ip_endpoint.address().empty()) {
LOG(ERROR) << "RemoveWakeOnPacketConnection: null address";
return;
}
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kRemoveWakeOnPacketConnectionFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(ip_endpoint.ToStringWithoutPort());
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void RemoveWakeOnPacketOfTypes(const dbus::ObjectPath& device_path,
const std::vector<std::string>& types,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamDeviceInterface,
shill::kRemoveWakeOnPacketOfTypesFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendArrayOfStrings(types);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
void RemoveAllWakeOnPacketConnections(
const dbus::ObjectPath& device_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(
shill::kFlimflamDeviceInterface,
shill::kRemoveAllWakeOnPacketConnectionsFunction);
GetHelper(device_path)
->CallVoidMethodWithErrorCallback(&method_call, callback,
error_callback);
}
TestInterface* GetTestInterface() override { return nullptr; }
private:
typedef std::map<std::string, ShillClientHelper*> HelperMap;
// Returns the corresponding ShillClientHelper for the profile.
ShillClientHelper* GetHelper(const dbus::ObjectPath& device_path) {
HelperMap::iterator it = helpers_.find(device_path.value());
if (it != helpers_.end()) {
CHECK(it->second) << "Found a null helper in the list.";
return it->second;
}
// There is no helper for the profile, create it.
dbus::ObjectProxy* object_proxy =
bus_->GetObjectProxy(shill::kFlimflamServiceName, device_path);
ShillClientHelper* helper = new ShillClientHelper(object_proxy);
CHECK(helper) << "Unable to create Shill client helper.";
helper->MonitorPropertyChanged(shill::kFlimflamDeviceInterface);
helpers_.insert(HelperMap::value_type(device_path.value(), helper));
return helper;
}
dbus::Bus* bus_;
HelperMap helpers_;
DISALLOW_COPY_AND_ASSIGN(ShillDeviceClientImpl);
};
} // namespace
ShillDeviceClient::ShillDeviceClient() {
DCHECK(!g_instance);
g_instance = this;
}
ShillDeviceClient::~ShillDeviceClient() {
DCHECK_EQ(this, g_instance);
g_instance = nullptr;
}
// static
void ShillDeviceClient::Initialize(dbus::Bus* bus) {
DCHECK(bus);
new ShillDeviceClientImpl(bus);
}
// static
void ShillDeviceClient::InitializeFake() {
new FakeShillDeviceClient();
}
// static
void ShillDeviceClient::Shutdown() {
DCHECK(g_instance);
delete g_instance;
}
// static
ShillDeviceClient* ShillDeviceClient::Get() {
return g_instance;
}
} // namespace chromeos