// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/components/dbus/shill/shill_manager_client.h"
#include <ios>
#include <memory>
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "chromeos/ash/components/dbus/shill/fake_shill_manager_client.h"
#include "chromeos/ash/components/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"
namespace ash {
ShillManagerClient::CreateP2PGroupParameter::CreateP2PGroupParameter(
const std::optional<std::string> ssid,
const std::optional<std::string> passphrase,
const std::optional<uint32_t> frequency,
const std::optional<shill::WiFiInterfacePriority> priority)
: ssid(ssid),
passphrase(passphrase),
frequency(frequency),
priority(priority) {}
ShillManagerClient::CreateP2PGroupParameter::CreateP2PGroupParameter(
const std::optional<std::string> ssid,
const std::optional<std::string> passphrase)
: ssid(ssid),
passphrase(passphrase),
frequency(std::nullopt),
priority(std::nullopt) {}
ShillManagerClient::CreateP2PGroupParameter::~CreateP2PGroupParameter() =
default;
ShillManagerClient::ConnectP2PGroupParameter::ConnectP2PGroupParameter(
const std::string ssid,
const std::string passphrase,
const std::optional<uint32_t> frequency,
const std::optional<shill::WiFiInterfacePriority> priority)
: ssid(ssid),
passphrase(passphrase),
frequency(frequency),
priority(priority) {}
ShillManagerClient::ConnectP2PGroupParameter::~ConnectP2PGroupParameter() =
default;
namespace {
ShillManagerClient* g_instance = nullptr;
// The ShillManagerClient implementation.
class ShillManagerClientImpl : public ShillManagerClient {
public:
ShillManagerClientImpl() = default;
ShillManagerClientImpl(const ShillManagerClientImpl&) = delete;
ShillManagerClientImpl& operator=(const ShillManagerClientImpl&) = delete;
~ShillManagerClientImpl() override = default;
////////////////////////////////////
// ShillManagerClient overrides.
void AddPropertyChangedObserver(
ShillPropertyChangedObserver* observer) override {
helper_->AddPropertyChangedObserver(observer);
}
void RemovePropertyChangedObserver(
ShillPropertyChangedObserver* observer) override {
helper_->RemovePropertyChangedObserver(observer);
}
void GetProperties(
chromeos::DBusMethodCallback<base::Value::Dict> callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kGetPropertiesFunction);
helper_->CallDictValueMethod(&method_call, std::move(callback));
}
void GetNetworksForGeolocation(
chromeos::DBusMethodCallback<base::Value::Dict> callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kGetNetworksForGeolocation);
helper_->CallDictValueMethod(&method_call, std::move(callback));
}
void SetProperty(const std::string& name,
const base::Value& value,
base::OnceClosure callback,
ErrorCallback error_callback) override {
// This property is read-only and can only be mutated by the specialized
// method exposed in DBus API.
if (name == shill::kDNSProxyDOHProvidersProperty) {
SetDNSProxyDOHProviders(value.GetDict(), std::move(callback),
std::move(error_callback));
return;
}
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kSetPropertyFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(name);
ShillClientHelper::AppendValueDataAsVariant(&writer, name, value);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void RequestScan(const std::string& type,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kRequestScanFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(type);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void EnableTechnology(const std::string& type,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kEnableTechnologyFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(type);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void SetNetworkThrottlingStatus(const NetworkThrottlingStatus& status,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kSetNetworkThrottlingFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendBool(status.enabled);
writer.AppendUint32(status.upload_rate_kbits);
writer.AppendUint32(status.download_rate_kbits);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void DisableTechnology(const std::string& type,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kDisableTechnologyFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendString(type);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void ConfigureService(const base::Value::Dict& properties,
chromeos::ObjectPathCallback callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kConfigureServiceFunction);
dbus::MessageWriter writer(&method_call);
ShillClientHelper::AppendServiceProperties(&writer, properties);
helper_->CallObjectPathMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void ConfigureServiceForProfile(const dbus::ObjectPath& profile_path,
const base::Value::Dict& properties,
chromeos::ObjectPathCallback callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kConfigureServiceForProfileFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendObjectPath(dbus::ObjectPath(profile_path));
ShillClientHelper::AppendServiceProperties(&writer, properties);
helper_->CallObjectPathMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void GetService(const base::Value::Dict& properties,
chromeos::ObjectPathCallback callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kGetServiceFunction);
dbus::MessageWriter writer(&method_call);
ShillClientHelper::AppendServiceProperties(&writer, properties);
helper_->CallObjectPathMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void ScanAndConnectToBestServices(base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kScanAndConnectToBestServicesFunction);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void AddPasspointCredentials(const dbus::ObjectPath& profile_path,
const base::Value::Dict& properties,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kAddPasspointCredentialsFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendObjectPath(profile_path);
ShillClientHelper::AppendServiceProperties(&writer, properties);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void RemovePasspointCredentials(const dbus::ObjectPath& profile_path,
const base::Value::Dict& properties,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kRemovePasspointCredentialsFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendObjectPath(profile_path);
ShillClientHelper::AppendServiceProperties(&writer, properties);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void SetTetheringEnabled(bool enabled,
StringCallback callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kSetTetheringEnabledFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendBool(enabled);
helper_->CallStringMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void EnableTethering(const shill::WiFiInterfacePriority& priority,
StringCallback callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kEnableTetheringFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendUint32(static_cast<uint32_t>(priority));
helper_->CallStringMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void DisableTethering(StringCallback callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kDisableTetheringFunction);
helper_->CallStringMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void CheckTetheringReadiness(StringCallback callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kCheckTetheringReadinessFunction);
helper_->CallStringMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void SetLOHSEnabled(bool enabled,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kSetLOHSEnabledFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendBool(enabled);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
void CreateP2PGroup(
const CreateP2PGroupParameter& create_group_argument,
base::OnceCallback<void(base::Value::Dict result)> callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kCreateP2PGroupFunction);
dbus::MessageWriter writer(&method_call);
base::Value::Dict properties;
const shill::WiFiInterfacePriority priority =
create_group_argument.priority.has_value()
? create_group_argument.priority.value()
: shill::WiFiInterfacePriority::FOREGROUND_WITH_FALLBACK;
properties.Set(shill::kP2PDevicePriority, static_cast<int>(priority));
if (create_group_argument.ssid.has_value()) {
properties.Set(shill::kP2PDeviceSSID, create_group_argument.ssid.value());
}
if (create_group_argument.passphrase.has_value()) {
properties.Set(shill::kP2PDevicePassphrase,
create_group_argument.passphrase.value());
}
if (create_group_argument.frequency.has_value()) {
properties.Set(shill::kP2PDeviceFrequency,
static_cast<int>(create_group_argument.frequency.value()));
}
ShillClientHelper::AppendServiceProperties(&writer, properties);
helper_->CallDictValueMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void ConnectToP2PGroup(
const ConnectP2PGroupParameter& connect_group_argument,
base::OnceCallback<void(base::Value::Dict result)> callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kConnectToP2PGroupFunction);
dbus::MessageWriter writer(&method_call);
base::Value::Dict properties;
properties.Set(shill::kP2PDeviceSSID, connect_group_argument.ssid);
properties.Set(shill::kP2PDevicePassphrase,
connect_group_argument.passphrase);
const shill::WiFiInterfacePriority priority =
connect_group_argument.priority.has_value()
? connect_group_argument.priority.value()
: shill::WiFiInterfacePriority::FOREGROUND_WITH_FALLBACK;
properties.Set(shill::kP2PDevicePriority, static_cast<int>(priority));
if (connect_group_argument.frequency.has_value()) {
properties.Set(
shill::kP2PGroupInfoFrequencyProperty,
static_cast<int>(connect_group_argument.frequency.value()));
}
ShillClientHelper::AppendServiceProperties(&writer, properties);
helper_->CallDictValueMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void DestroyP2PGroup(
const int shill_id,
base::OnceCallback<void(base::Value::Dict result)> callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kDestroyP2PGroupFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendInt32(shill_id);
helper_->CallDictValueMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
void DisconnectFromP2PGroup(
const int shill_id,
base::OnceCallback<void(base::Value::Dict result)> callback,
ErrorCallback error_callback) override {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kDisconnectFromP2PGroupFunction);
dbus::MessageWriter writer(&method_call);
writer.AppendInt32(shill_id);
helper_->CallDictValueMethodWithErrorCallback(
&method_call, std::move(callback), std::move(error_callback));
}
TestInterface* GetTestInterface() override { return nullptr; }
void Init(dbus::Bus* bus) {
proxy_ = bus->GetObjectProxy(shill::kFlimflamServiceName,
dbus::ObjectPath(shill::kFlimflamServicePath));
helper_ = std::make_unique<ShillClientHelper>(proxy_);
helper_->MonitorPropertyChanged(shill::kFlimflamManagerInterface);
}
private:
// Used by SetProperty call to reroute kDNSProxyDOHProviders to the underlying
// specialized method in the DBus API.
void SetDNSProxyDOHProviders(const base::Value::Dict& providers,
base::OnceClosure callback,
ErrorCallback error_callback) {
dbus::MethodCall method_call(shill::kFlimflamManagerInterface,
shill::kSetDNSProxyDOHProvidersFunction);
dbus::MessageWriter writer(&method_call);
ShillClientHelper::AppendServiceProperties(&writer, providers);
helper_->CallVoidMethodWithErrorCallback(&method_call, std::move(callback),
std::move(error_callback));
}
raw_ptr<dbus::ObjectProxy> proxy_ = nullptr;
std::unique_ptr<ShillClientHelper> helper_;
};
} // namespace
ShillManagerClient::ShillManagerClient() {
DCHECK(!g_instance);
g_instance = this;
}
ShillManagerClient::~ShillManagerClient() {
DCHECK_EQ(this, g_instance);
g_instance = nullptr;
}
// static
void ShillManagerClient::Initialize(dbus::Bus* bus) {
DCHECK(bus);
(new ShillManagerClientImpl)->Init(bus);
}
// static
void ShillManagerClient::InitializeFake() {
new FakeShillManagerClient();
}
// static
void ShillManagerClient::Shutdown() {
DCHECK(g_instance);
delete g_instance;
}
// static
ShillManagerClient* ShillManagerClient::Get() {
return g_instance;
}
} // namespace ash