blob: 62a9f02aa8e3048fc525358226d3487665e25401 [file] [log] [blame]
//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "shill/dbus/chromeos_manager_dbus_adaptor.h"
#include <map>
#include <string>
#include <vector>
#include "shill/callbacks.h"
#include "shill/dbus/dbus_service_watcher_factory.h"
#include "shill/device.h"
#include "shill/error.h"
#include "shill/geolocation_info.h"
#include "shill/key_value_store.h"
#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/property_store.h"
using base::Unretained;
using std::map;
using std::string;
using std::vector;
namespace shill {
namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDBus;
static string ObjectID(ChromeosManagerDBusAdaptor* m) {
return m->GetRpcIdentifier();
}
}
// static
const char ChromeosManagerDBusAdaptor::kPath[] = "/";
ChromeosManagerDBusAdaptor::ChromeosManagerDBusAdaptor(
const scoped_refptr<dbus::Bus>& adaptor_bus,
const scoped_refptr<dbus::Bus> proxy_bus,
Manager* manager)
: org::chromium::flimflam::ManagerAdaptor(this),
ChromeosDBusAdaptor(adaptor_bus, kPath),
manager_(manager),
proxy_bus_(proxy_bus),
dbus_service_watcher_factory_(DBusServiceWatcherFactory::GetInstance()) {}
ChromeosManagerDBusAdaptor::~ChromeosManagerDBusAdaptor() {
manager_ = nullptr;
}
void ChromeosManagerDBusAdaptor::RegisterAsync(
const base::Callback<void(bool)>& completion_callback) {
RegisterWithDBusObject(dbus_object());
dbus_object()->RegisterAsync(completion_callback);
}
void ChromeosManagerDBusAdaptor::EmitBoolChanged(const string& name,
bool value) {
SLOG(this, 2) << __func__ << ": " << name;
SendPropertyChangedSignal(name, brillo::Any(value));
}
void ChromeosManagerDBusAdaptor::EmitUintChanged(const string& name,
uint32_t value) {
SLOG(this, 2) << __func__ << ": " << name;
SendPropertyChangedSignal(name, brillo::Any(value));
}
void ChromeosManagerDBusAdaptor::EmitIntChanged(const string& name, int value) {
SLOG(this, 2) << __func__ << ": " << name;
SendPropertyChangedSignal(name, brillo::Any(value));
}
void ChromeosManagerDBusAdaptor::EmitStringChanged(const string& name,
const string& value) {
SLOG(this, 2) << __func__ << ": " << name;
SendPropertyChangedSignal(name, brillo::Any(value));
}
void ChromeosManagerDBusAdaptor::EmitStringsChanged(const string& name,
const vector<string>& value) {
SLOG(this, 2) << __func__ << ": " << name;
SendPropertyChangedSignal(name, brillo::Any(value));
}
void ChromeosManagerDBusAdaptor::EmitRpcIdentifierChanged(
const string& name,
const string& value) {
SLOG(this, 2) << __func__ << ": " << name;
SendPropertyChangedSignal(name, brillo::Any(dbus::ObjectPath(value)));
}
void ChromeosManagerDBusAdaptor::EmitRpcIdentifierArrayChanged(
const string& name,
const vector<string>& value) {
SLOG(this, 2) << __func__ << ": " << name;
vector<dbus::ObjectPath> paths;
for (const auto& element : value) {
paths.push_back(dbus::ObjectPath(element));
}
SendPropertyChangedSignal(name, brillo::Any(paths));
}
bool ChromeosManagerDBusAdaptor::GetProperties(
brillo::ErrorPtr* error, brillo::VariantDictionary* properties) {
SLOG(this, 2) << __func__;
return ChromeosDBusAdaptor::GetProperties(manager_->store(),
properties,
error);
}
bool ChromeosManagerDBusAdaptor::SetProperty(brillo::ErrorPtr* error,
const string& name,
const brillo::Any& value) {
SLOG(this, 2) << __func__ << ": " << name;
return ChromeosDBusAdaptor::SetProperty(manager_->mutable_store(),
name,
value,
error);
}
bool ChromeosManagerDBusAdaptor::GetState(brillo::ErrorPtr* /*error*/,
string* state) {
SLOG(this, 2) << __func__;
*state = manager_->CalculateState(nullptr);
return true;
}
bool ChromeosManagerDBusAdaptor::CreateProfile(brillo::ErrorPtr* error,
const string& name,
dbus::ObjectPath* profile_path) {
SLOG(this, 2) << __func__ << ": " << name;
Error e;
string path;
manager_->CreateProfile(name, &path, &e);
if (e.ToChromeosError(error)) {
return false;
}
*profile_path = dbus::ObjectPath(path);
return true;
}
bool ChromeosManagerDBusAdaptor::RemoveProfile(brillo::ErrorPtr* error,
const string& name) {
SLOG(this, 2) << __func__ << ": " << name;
Error e;
manager_->RemoveProfile(name, &e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::PushProfile(brillo::ErrorPtr* error,
const string& name,
dbus::ObjectPath* profile_path) {
SLOG(this, 2) << __func__ << ": " << name;
Error e;
string path;
manager_->PushProfile(name, &path, &e);
if (e.ToChromeosError(error)) {
return false;
}
*profile_path = dbus::ObjectPath(path);
return true;
}
bool ChromeosManagerDBusAdaptor::InsertUserProfile(
brillo::ErrorPtr* error,
const string& name,
const string& user_hash,
dbus::ObjectPath* profile_path) {
SLOG(this, 2) << __func__ << ": " << name;
Error e;
string path;
manager_->InsertUserProfile(name, user_hash, &path, &e);
if (e.ToChromeosError(error)) {
return false;
}
*profile_path = dbus::ObjectPath(path);
return true;;
}
bool ChromeosManagerDBusAdaptor::PopProfile(brillo::ErrorPtr* error,
const string& name) {
SLOG(this, 2) << __func__ << ": " << name;
Error e;
manager_->PopProfile(name, &e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::PopAnyProfile(brillo::ErrorPtr* error) {
SLOG(this, 2) << __func__;
Error e;
manager_->PopAnyProfile(&e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::PopAllUserProfiles(brillo::ErrorPtr* error) {
SLOG(this, 2) << __func__;
Error e;
manager_->PopAllUserProfiles(&e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::RecheckPortal(brillo::ErrorPtr* error) {
SLOG(this, 2) << __func__;
Error e;
manager_->RecheckPortal(&e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::RequestScan(brillo::ErrorPtr* error,
const string& technology) { // NOLINT
SLOG(this, 2) << __func__ << ": " << technology;
Error e;
manager_->RequestScan(Device::kFullScan, technology, &e);
return !e.ToChromeosError(error);
}
void ChromeosManagerDBusAdaptor::EnableTechnology(
DBusMethodResponsePtr<> response, const string& technology_name) {
SLOG(this, 2) << __func__ << ": " << technology_name;
Error e(Error::kOperationInitiated);
ResultCallback callback = GetMethodReplyCallback(std::move(response));
const bool kPersistentSave = true;
manager_->SetEnabledStateForTechnology(technology_name, true,
kPersistentSave, &e, callback);
ReturnResultOrDefer(callback, e);
}
void ChromeosManagerDBusAdaptor::DisableTechnology(
DBusMethodResponsePtr<> response, const string& technology_name) {
SLOG(this, 2) << __func__ << ": " << technology_name;
Error e(Error::kOperationInitiated);
ResultCallback callback = GetMethodReplyCallback(std::move(response));
const bool kPersistentSave = true;
manager_->SetEnabledStateForTechnology(technology_name, false,
kPersistentSave, &e, callback);
ReturnResultOrDefer(callback, e);
}
// Called, e.g., to get WiFiService handle for a hidden SSID.
bool ChromeosManagerDBusAdaptor::GetService(
brillo::ErrorPtr* error,
const brillo::VariantDictionary& args,
dbus::ObjectPath* service_path) {
SLOG(this, 2) << __func__;
ServiceRefPtr service;
KeyValueStore args_store;
Error e;
KeyValueStore::ConvertFromVariantDictionary(args, &args_store);
service = manager_->GetService(args_store, &e);
if (e.ToChromeosError(error)) {
return false;
}
*service_path = dbus::ObjectPath(service->GetRpcIdentifier());
return true;
}
// Obsolete, use GetService instead.
bool ChromeosManagerDBusAdaptor::GetVPNService(
brillo::ErrorPtr* error,
const brillo::VariantDictionary& args,
dbus::ObjectPath* service_path) {
SLOG(this, 2) << __func__;
return GetService(error, args, service_path);
}
// Obsolete, use GetService instead.
bool ChromeosManagerDBusAdaptor::GetWifiService(
brillo::ErrorPtr* error,
const brillo::VariantDictionary& args,
dbus::ObjectPath* service_path) {
SLOG(this, 2) << __func__;
return GetService(error, args, service_path);
}
bool ChromeosManagerDBusAdaptor::ConfigureService(
brillo::ErrorPtr* error,
const brillo::VariantDictionary& args,
dbus::ObjectPath* service_path) {
SLOG(this, 2) << __func__;
ServiceRefPtr service;
KeyValueStore args_store;
KeyValueStore::ConvertFromVariantDictionary(args, &args_store);
Error configure_error;
service = manager_->ConfigureService(args_store, &configure_error);
if (configure_error.ToChromeosError(error)) {
return false;
}
*service_path = dbus::ObjectPath(service->GetRpcIdentifier());
return true;
}
bool ChromeosManagerDBusAdaptor::ConfigureServiceForProfile(
brillo::ErrorPtr* error,
const dbus::ObjectPath& profile_rpcid,
const brillo::VariantDictionary& args,
dbus::ObjectPath* service_path) {
SLOG(this, 2) << __func__;
ServiceRefPtr service;
KeyValueStore args_store;
KeyValueStore::ConvertFromVariantDictionary(args, &args_store);
Error configure_error;
service = manager_->ConfigureServiceForProfile(
profile_rpcid.value(), args_store, &configure_error);
if (!service || configure_error.ToChromeosError(error)) {
return false;
}
*service_path = dbus::ObjectPath(service->GetRpcIdentifier());
return true;
}
bool ChromeosManagerDBusAdaptor::FindMatchingService(
brillo::ErrorPtr* error,
const brillo::VariantDictionary& args,
dbus::ObjectPath* service_path) { // NOLINT
SLOG(this, 2) << __func__;
KeyValueStore args_store;
KeyValueStore::ConvertFromVariantDictionary(args, &args_store);
Error find_error;
ServiceRefPtr service =
manager_->FindMatchingService(args_store, &find_error);
if (find_error.ToChromeosError(error)) {
return false;
}
*service_path = dbus::ObjectPath(service->GetRpcIdentifier());
return true;
}
bool ChromeosManagerDBusAdaptor::GetDebugLevel(brillo::ErrorPtr* /*error*/,
int32_t* level) {
SLOG(this, 2) << __func__;
*level = logging::GetMinLogLevel();
return true;
}
bool ChromeosManagerDBusAdaptor::SetDebugLevel(brillo::ErrorPtr* /*error*/,
int32_t level) {
SLOG(this, 2) << __func__ << ": " << level;
if (level < logging::LOG_NUM_SEVERITIES) {
logging::SetMinLogLevel(level);
// Like VLOG, SLOG uses negative verbose level.
ScopeLogger::GetInstance()->set_verbose_level(-level);
} else {
LOG(WARNING) << "Ignoring attempt to set log level to " << level;
}
return true;
}
bool ChromeosManagerDBusAdaptor::GetServiceOrder(brillo::ErrorPtr* /*error*/,
string* order) {
SLOG(this, 2) << __func__;
*order = manager_->GetTechnologyOrder();
return true;
}
bool ChromeosManagerDBusAdaptor::SetServiceOrder(brillo::ErrorPtr* error,
const string& order) {
SLOG(this, 2) << __func__ << ": " << order;
Error e;
manager_->SetTechnologyOrder(order, &e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::GetDebugTags(brillo::ErrorPtr* /*error*/,
string* tags) {
SLOG(this, 2) << __func__;
*tags = ScopeLogger::GetInstance()->GetEnabledScopeNames();
return true;
}
bool ChromeosManagerDBusAdaptor::SetDebugTags(brillo::ErrorPtr* /*error*/,
const string& tags) {
SLOG(this, 2) << __func__ << ": " << tags;
ScopeLogger::GetInstance()->EnableScopesByName(tags);
return true;
}
bool ChromeosManagerDBusAdaptor::ListDebugTags(brillo::ErrorPtr* /*error*/,
string* tags) {
SLOG(this, 2) << __func__;
*tags = ScopeLogger::GetInstance()->GetAllScopeNames();
return true;
}
bool ChromeosManagerDBusAdaptor::GetNetworksForGeolocation(
brillo::ErrorPtr* /*error*/,
brillo::VariantDictionary* networks) {
SLOG(this, 2) << __func__;
for (const auto& network : manager_->GetNetworksForGeolocation()) {
Stringmaps value;
// Convert GeolocationInfos to their Stringmaps equivalent.
for (const auto& info : network.second) {
value.push_back(info.properties());
}
networks->insert(std::make_pair(network.first, brillo::Any(value)));
}
return true;
}
void ChromeosManagerDBusAdaptor::VerifyDestination(
DBusMethodResponsePtr<bool> response,
const string& certificate,
const string& public_key,
const string& nonce,
const string& signed_data,
const string& destination_udn,
const string& hotspot_ssid,
const string& hotspot_bssid) {
SLOG(this, 2) << __func__;
ResultBoolCallback callback = GetBoolMethodReplyCallback(std::move(response));
#if !defined(DISABLE_WIFI)
Error e(Error::kOperationInitiated);
manager_->VerifyDestination(certificate, public_key, nonce,
signed_data, destination_udn,
hotspot_ssid, hotspot_bssid,
callback, &e);
#else
Error e(Error::kNotImplemented);
#endif // DISABLE_WIFI
if (e.IsOngoing()) {
return;
}
// Command failed synchronously.
CHECK(e.IsFailure()) << __func__ << " should only return directly on error.";
callback.Run(e, false);
}
void ChromeosManagerDBusAdaptor::VerifyAndEncryptCredentials(
DBusMethodResponsePtr<string> response,
const string& certificate,
const string& public_key,
const string& nonce,
const string& signed_data,
const string& destination_udn,
const string& hotspot_ssid,
const string& hotspot_bssid,
const dbus::ObjectPath& network) {
SLOG(this, 2) << __func__;
ResultStringCallback callback =
GetStringMethodReplyCallback(std::move(response));
#if !defined(DISABLE_WIFI)
Error e(Error::kOperationInitiated);
manager_->VerifyAndEncryptCredentials(certificate, public_key, nonce,
signed_data, destination_udn,
hotspot_ssid, hotspot_bssid,
network.value(),
callback,
&e);
#else
Error e(Error::kNotImplemented);
#endif // DISABLE_WIFI
if (e.IsOngoing()) {
return;
}
// Command failed synchronously.
CHECK(e.IsFailure()) << __func__ << " should only return directly on error.";
callback.Run(e, "");
}
void ChromeosManagerDBusAdaptor::VerifyAndEncryptData(
DBusMethodResponsePtr<string> response,
const string& certificate,
const string& public_key,
const string& nonce,
const string& signed_data,
const string& destination_udn,
const string& hotspot_ssid,
const string& hotspot_bssid,
const string& data) {
SLOG(this, 2) << __func__;
ResultStringCallback callback =
GetStringMethodReplyCallback(std::move(response));
#if !defined(DISABLE_WIFI)
Error e(Error::kOperationInitiated);
manager_->VerifyAndEncryptData(certificate, public_key, nonce,
signed_data, destination_udn,
hotspot_ssid, hotspot_bssid,
data, callback,
&e);
#else
Error e(Error::kNotImplemented);
#endif // DISABLE_WIFI
if (e.IsOngoing()) {
return;
}
// Command failed synchronously.
CHECK(e.IsFailure()) << __func__ << " should only return directly on error.";
callback.Run(e, "");
}
bool ChromeosManagerDBusAdaptor::ConnectToBestServices(
brillo::ErrorPtr* error) {
SLOG(this, 2) << __func__;
Error e;
manager_->ConnectToBestServices(&e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::CreateConnectivityReport(
brillo::ErrorPtr* error) {
SLOG(this, 2) << __func__;
Error e;
manager_->CreateConnectivityReport(&e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::ClaimInterface(
brillo::ErrorPtr* error,
dbus::Message* message,
const string& claimer_name,
const string& interface_name) {
SLOG(this, 2) << __func__;
Error e;
// Empty claimer name is used to indicate default claimer.
// TODO(samueltan): update this API or make a new API to use a flag to
// indicate default claimer instead (b/27924738).
string claimer = (claimer_name == "" ? "" : message->GetSender());
manager_->ClaimDevice(claimer, interface_name, &e);
if (e.IsSuccess() && claimer_name != "") {
// Only setup watcher for non-default claimer.
watcher_for_device_claimer_.reset(
dbus_service_watcher_factory_->CreateDBusServiceWatcher(
proxy_bus_, claimer,
Bind(&ChromeosManagerDBusAdaptor::OnDeviceClaimerVanished,
Unretained(this))));
}
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::ReleaseInterface(
brillo::ErrorPtr* error,
dbus::Message* message,
const string& claimer_name,
const string& interface_name) {
SLOG(this, 2) << __func__;
Error e;
bool claimer_removed;
// Empty claimer name is used to indicate default claimer.
// TODO(samueltan): update this API or make a new API to use a flag to
// indicate default claimer instead (b/27924738).
manager_->ReleaseDevice(
claimer_name == "" ? "" : message->GetSender(),
interface_name,
&claimer_removed,
&e);
if (claimer_removed) {
watcher_for_device_claimer_.reset();
}
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::SetSchedScan(brillo::ErrorPtr* error,
bool enable) {
SLOG(this, 2) << __func__ << ": " << enable;
Error e;
manager_->SetSchedScan(enable, &e);
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::SetupApModeInterface(
brillo::ErrorPtr* error,
dbus::Message* message,
string* out_interface_name) {
SLOG(this, 2) << __func__;
Error e;
#if !defined(DISABLE_WIFI) && defined(__BRILLO__)
manager_->SetupApModeInterface(out_interface_name, &e);
if (e.IsSuccess()) {
// Setup a service watcher for the caller. This will restore interface mode
// back to station mode if the caller vanished.
watcher_for_ap_mode_setter_.reset(
dbus_service_watcher_factory_->CreateDBusServiceWatcher(
proxy_bus_, message->GetSender(),
Bind(&ChromeosManagerDBusAdaptor::OnApModeSetterVanished,
Unretained(this))));
}
#else
e.Populate(Error::kNotSupported);
#endif // !DISABLE_WIFI && __BRILLO__
return !e.ToChromeosError(error);
}
bool ChromeosManagerDBusAdaptor::SetupStationModeInterface(
brillo::ErrorPtr* error,
string* out_interface_name) {
SLOG(this, 2) << __func__;
Error e;
#if !defined(DISABLE_WIFI) && defined(__BRILLO__)
manager_->SetupStationModeInterface(out_interface_name, &e);
// Remove the service watcher for the AP mode setter.
watcher_for_ap_mode_setter_.reset();
#else
e.Populate(Error::kNotSupported);
#endif // !DISABLE_WIFI && __BRILLO__
return !e.ToChromeosError(error);
}
void ChromeosManagerDBusAdaptor::OnApModeSetterVanished() {
SLOG(this, 3) << __func__;
#if !defined(DISABLE_WIFI) && defined(__BRILLO__)
manager_->OnApModeSetterVanished();
#endif // !DISABLE_WIFI && __BRILLO__
watcher_for_ap_mode_setter_.reset();
}
void ChromeosManagerDBusAdaptor::OnDeviceClaimerVanished() {
SLOG(this, 3) << __func__;
manager_->OnDeviceClaimerVanished();
watcher_for_device_claimer_.reset();
}
} // namespace shill