blob: 0fc71fa03e5f9136aa065b16e683b89d95c52e5a [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "peridot/bin/cloud_provider_firestore/testing/cloud_provider_factory.h"
#include <utility>
#include <fuchsia/net/oldhttp/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/backoff/exponential_backoff.h>
#include <lib/fit/function.h>
#include <lib/fxl/functional/make_copyable.h>
#include <lib/svc/cpp/services.h>
#include "peridot/lib/convert/convert.h"
namespace cloud_provider_firestore {
namespace {
namespace http = ::fuchsia::net::oldhttp;
constexpr char kAppUrl[] =
"fuchsia-pkg://fuchsia.com/cloud_provider_firestore"
"#meta/cloud_provider_firestore.cmx";
std::string GenerateUserId() {
// Always use a real random generator for user ids.
rng::SystemRandom system_random;
return convert::ToHex(system_random.RandomUniqueBytes());
}
} // namespace
CloudProviderFactory::UserId::UserId(const UserId& user_id) = default;
CloudProviderFactory::UserId::UserId(UserId&& user_id) = default;
CloudProviderFactory::UserId& CloudProviderFactory::UserId::operator=(
const UserId& user_id) = default;
CloudProviderFactory::UserId& CloudProviderFactory::UserId::operator=(
UserId&& user_id) = default;
CloudProviderFactory::UserId CloudProviderFactory::UserId::New() {
return UserId();
}
CloudProviderFactory::UserId::UserId() : user_id_(GenerateUserId()) {}
class CloudProviderFactory::TokenManagerContainer {
public:
TokenManagerContainer(
component::StartupContext* startup_context,
async_dispatcher_t* dispatcher, rng::Random* random,
std::unique_ptr<service_account::Credentials> credentials,
std::string user_id,
fidl::InterfaceRequest<fuchsia::auth::TokenManager> request)
: startup_context_(startup_context),
network_wrapper_(
dispatcher,
std::make_unique<backoff::ExponentialBackoff>(
random->NewBitGenerator<uint64_t>()),
[this] {
return startup_context_
->ConnectToEnvironmentService<http::HttpService>();
}),
token_manager_(&network_wrapper_, std::move(credentials),
std::move(user_id)),
binding_(&token_manager_, std::move(request)) {}
void set_on_empty(fit::closure on_empty) {
binding_.set_error_handler(
[on_empty = std::move(on_empty)](zx_status_t status) { on_empty(); });
}
private:
component::StartupContext* const startup_context_;
network_wrapper::NetworkWrapperImpl network_wrapper_;
service_account::ServiceAccountTokenManager token_manager_;
fidl::Binding<fuchsia::auth::TokenManager> binding_;
FXL_DISALLOW_COPY_AND_ASSIGN(TokenManagerContainer);
};
CloudProviderFactory::CloudProviderFactory(
component::StartupContext* startup_context, rng::Random* random,
std::string api_key,
std::unique_ptr<service_account::Credentials> credentials)
: startup_context_(startup_context),
random_(random),
api_key_(std::move(api_key)),
credentials_(std::move(credentials)),
services_loop_(&kAsyncLoopConfigNoAttachToThread) {
FXL_DCHECK(startup_context);
FXL_DCHECK(!api_key_.empty());
}
CloudProviderFactory::~CloudProviderFactory() { services_loop_.Shutdown(); }
void CloudProviderFactory::Init() {
services_loop_.StartThread();
component::Services child_services;
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kAppUrl;
launch_info.directory_request = child_services.NewRequest();
startup_context_->launcher()->CreateComponent(
std::move(launch_info), cloud_provider_controller_.NewRequest());
child_services.ConnectToService(cloud_provider_factory_.NewRequest());
}
void CloudProviderFactory::MakeCloudProvider(
UserId user_id,
fidl::InterfaceRequest<cloud_provider::CloudProvider> request) {
fuchsia::auth::TokenManagerPtr token_manager;
MakeTokenManager(std::move(user_id), token_manager.NewRequest());
cloud_provider_firestore::Config firebase_config;
firebase_config.server_id = credentials_->project_id();
firebase_config.api_key = api_key_;
cloud_provider_factory_->GetCloudProvider(
std::move(firebase_config), std::move(token_manager), std::move(request),
[](cloud_provider::Status status) {
if (status != cloud_provider::Status::OK) {
FXL_LOG(ERROR) << "Failed to create a cloud provider: "
<< fidl::ToUnderlying(status);
}
});
}
void CloudProviderFactory::MakeTokenManager(
UserId user_id,
fidl::InterfaceRequest<fuchsia::auth::TokenManager> request) {
async::PostTask(services_loop_.dispatcher(),
fxl::MakeCopyable([this, user_id = std::move(user_id),
request = std::move(request)]() mutable {
token_managers_.emplace(
startup_context_, services_loop_.dispatcher(), random_,
credentials_->Clone(), std::move(user_id.user_id()),
std::move(request));
}));
}
} // namespace cloud_provider_firestore