blob: 762a4468ac0512fa651888a4e55d58e6e9e07353 [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 "hermes/dbus_adaptor.h"
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/callback.h>
#include <chromeos/dbus/service_constants.h>
#include <google-lpa/lpa/core/lpa.h>
namespace {
const char kErrorDomain[] = "Hermes";
const char kErrorCodeUnknown[] = "Unknown";
const char kErrorCodeWrongState[] = "WrongState";
const char kErrorCodeInvalidIccid[] = "InvalidIccid";
const char kErrorCodeProfileNotEnabled[] = "ProfileNotEnabled";
const char kErrorCodeNeedConfirmationCode[] = "NeedConfirmationCode";
const char kErrorCodeInvalidActivationCode[] = "InvalidActivationCode";
const char kErrorCodeSendNotificationError[] = "SendNotificationError";
bool HandleLpaError(
int error,
const std::map<int, std::unique_ptr<brillo::Error>>* error_map,
brillo::dbus_utils::DBusMethodResponseBase* response) {
CHECK(error_map);
if (error != lpa::core::Lpa::kNoError) {
auto iter = error_map->find(error);
if (iter != error_map->end()) {
response->ReplyWithError(iter->second.get());
} else {
response->ReplyWithError(FROM_HERE, kErrorDomain, kErrorCodeUnknown,
"Unknown error");
}
return false;
}
return true;
}
// Function to return from a D-Bus hermes method that has no output parameters.
//
// Note the use of a shared_ptr rather than unique_ptr. The google-lpa API takes
// std::function parameters as callbacks. Since the standard states that
// std::functions must be CopyConstructible, bind states or lambdas that gain
// ownership of a unique_ptr may not be used as a std::function. As the
// org::chromium::HermesInterface interface is passed a unique_ptr, the options
// are either to maintain DBusMethodResponse lifetimes separately or to convert
// unique_ptrs to shared_ptrs.
void DefaultCallback(
const std::map<int, std::unique_ptr<brillo::Error>>* error_map,
std::shared_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
int error) {
if (!HandleLpaError(error, error_map, response.get())) {
return;
}
response->Return();
}
} // namespace
namespace hermes {
using lpa::proto::ProfileInfo;
using lpa::proto::ProfileInfoList;
DBusAdaptor::DBusAdaptor(lpa::core::Lpa* lpa, Executor* executor)
: org::chromium::HermesAdaptor(this), lpa_(lpa), executor_(executor) {
// Create mapping from google-lpa error to brillo error.
error_map_[lpa::core::Lpa::kWrongState] =
brillo::Error::Create(FROM_HERE, kErrorDomain, kErrorCodeWrongState,
"Invalid state for requested method");
error_map_[lpa::core::Lpa::kIccidNotFound] = brillo::Error::Create(
FROM_HERE, kErrorDomain, kErrorCodeInvalidIccid, "Invalid iccid");
error_map_[lpa::core::Lpa::kProfileNotEnabled] = brillo::Error::Create(
FROM_HERE, kErrorDomain, kErrorCodeProfileNotEnabled,
"Requested method needs an enabled profile");
error_map_[lpa::core::Lpa::kNeedConfirmationCode] = brillo::Error::Create(
FROM_HERE, kErrorDomain, kErrorCodeNeedConfirmationCode,
"Need confirmation code");
error_map_[lpa::core::Lpa::kInvalidActivationCode] = brillo::Error::Create(
FROM_HERE, kErrorDomain, kErrorCodeInvalidActivationCode,
"Invalid activation code");
error_map_[lpa::core::Lpa::kFailedToSendNotifications] =
brillo::Error::Create(FROM_HERE, kErrorDomain,
kErrorCodeSendNotificationError,
"Failed to send notifications");
}
void DBusAdaptor::InstallProfile(
std::unique_ptr<DBusResponse<ProfileInfo>> response,
const std::string& in_activation_code) {
auto profile_cb = [response{std::shared_ptr<DBusResponse<ProfileInfo>>(
std::move(response))},
this](lpa::proto::ProfileInfo& profile, int error) {
if (!HandleLpaError(error, &error_map_, response.get())) {
return;
}
response->Return(profile);
};
if (in_activation_code.empty()) {
lpa_->GetDefaultProfileFromSmdp("", executor_, std::move(profile_cb));
return;
}
auto simple_cb = [response{std::shared_ptr<DBusResponse<ProfileInfo>>(
std::move(response))},
cb{std::move(profile_cb)}, in_activation_code,
this](int error) {
if (!HandleLpaError(error, &error_map_, response.get())) {
return;
}
// TODO(crbug.com/963555) Return valid ProfileInfo
lpa::proto::ProfileInfo empty;
cb(empty, error);
};
lpa::core::Lpa::DownloadOptions options;
options.enable_profile = false;
options.allow_policy_rules = false;
lpa_->DownloadProfile(in_activation_code, std::move(options), executor_,
std::move(simple_cb));
}
void DBusAdaptor::UninstallProfile(std::unique_ptr<DBusResponse<>> response,
const std::string& in_iccid) {
lpa_->DeleteProfile(
in_iccid, executor_,
std::bind(&DefaultCallback, &error_map_,
std::shared_ptr<DBusResponse<>>(std::move(response)),
std::placeholders::_1));
}
void DBusAdaptor::EnableProfile(std::unique_ptr<DBusResponse<>> response,
const std::string& in_iccid) {
lpa_->EnableProfile(
in_iccid, executor_,
std::bind(&DefaultCallback, &error_map_,
std::shared_ptr<DBusResponse<>>(std::move(response)),
std::placeholders::_1));
}
void DBusAdaptor::DisableProfile(std::unique_ptr<DBusResponse<>> response,
const std::string& in_iccid) {
lpa_->DisableProfile(
in_iccid, executor_,
std::bind(&DefaultCallback, &error_map_,
std::shared_ptr<DBusResponse<>>(std::move(response)),
std::placeholders::_1));
}
void DBusAdaptor::SetProfileNickname(std::unique_ptr<DBusResponse<>> response,
const std::string& in_iccid,
const std::string& in_nickname) {
lpa_->SetProfileNickname(
in_iccid, in_nickname, executor_,
std::bind(&DefaultCallback, &error_map_,
std::shared_ptr<DBusResponse<>>(std::move(response)),
std::placeholders::_1));
}
void DBusAdaptor::GetInstalledProfiles(
std::unique_ptr<DBusResponse<ProfileInfoList>> response) {
auto cb = [response{std::shared_ptr<DBusResponse<ProfileInfoList>>(
std::move(response))},
this](std::vector<lpa::proto::ProfileInfo>& profiles, int error) {
if (!HandleLpaError(error, &error_map_, response.get())) {
return;
}
ProfileInfoList profile_list;
VLOG(2) << "Installed profiles:";
for (auto profile : profiles) {
*profile_list.add_profile_info() = profile;
VLOG(2) << "";
VLOG(2) << " ICCID: " << profile.iccid();
VLOG_IF(2, profile.has_activation_code())
<< " Activation code: " << profile.activation_code();
VLOG_IF(2, profile.has_profile_name())
<< " Profile name: " << profile.profile_name();
}
response->Return(profile_list);
};
lpa_->GetInstalledProfiles(executor_, std::move(cb));
}
void DBusAdaptor::SetTestMode(bool /*in_is_test_mode*/) {
// TODO(akhouderchah) This is a no-op until the Lpa interface allows for
// switching certificate directory without recreating the Lpa object.
NOTIMPLEMENTED();
}
} // namespace hermes