blob: 49357d4c20459937753c0d1befd7783da1cbfbf8 [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/lib/fidl/app_client.h"
#include <fcntl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/limits.h>
#include <lib/fsl/io/fd.h>
#include <zircon/processargs.h>
#include "src/lib/files/directory.h"
#include "src/lib/files/unique_fd.h"
namespace modular {
AppClientBase::AppClientBase(fuchsia::sys::Launcher* const launcher,
fuchsia::modular::AppConfig config,
std::string data_origin,
fuchsia::sys::ServiceListPtr additional_services,
fuchsia::sys::FlatNamespacePtr flat_namespace)
: AsyncHolderBase(config.url) {
fuchsia::sys::LaunchInfo launch_info;
launch_info.directory_request = services_.NewRequest();
launch_info.url = config.url;
std::vector<std::string> args;
for (const auto& arg : *config.args) {
launch_info.arguments.push_back(arg);
}
if (!data_origin.empty()) {
if (!files::CreateDirectory(data_origin)) {
FXL_LOG(ERROR) << "Unable to create directory at " << data_origin;
return;
}
launch_info.flat_namespace = fuchsia::sys::FlatNamespace::New();
launch_info.flat_namespace->paths.push_back("/data");
fxl::UniqueFD dir(open(data_origin.c_str(), O_DIRECTORY | O_RDONLY));
if (!dir.is_valid()) {
FXL_LOG(ERROR) << "Unable to open directory at " << data_origin
<< ". errno: " << errno;
return;
}
launch_info.flat_namespace->directories.push_back(
fsl::CloneChannelFromFileDescriptor(dir.get()));
if (!launch_info.flat_namespace->directories.at(0)) {
FXL_LOG(ERROR) << "Unable create a handle from " << data_origin;
return;
}
}
if (additional_services) {
launch_info.additional_services = std::move(additional_services);
}
if (flat_namespace) {
if (!launch_info.flat_namespace) {
launch_info.flat_namespace = fuchsia::sys::FlatNamespace::New();
}
for (size_t i = 0; i < flat_namespace->paths.size(); ++i) {
launch_info.flat_namespace->paths.push_back(flat_namespace->paths[i]);
launch_info.flat_namespace->directories.push_back(
std::move(flat_namespace->directories[i]));
}
}
launcher->CreateComponent(std::move(launch_info), app_.NewRequest());
}
AppClientBase::~AppClientBase() = default;
void AppClientBase::ImplTeardown(fit::function<void()> done) {
ServiceTerminate(std::move(done));
}
void AppClientBase::ImplReset() {
app_.Unbind();
ServiceUnbind();
}
void AppClientBase::SetAppErrorHandler(fit::function<void()> error_handler) {
app_.set_error_handler([error_handler = std::move(error_handler)](
zx_status_t status) { error_handler(); });
}
void AppClientBase::ServiceTerminate(fit::function<void()> /* done */) {}
void AppClientBase::ServiceUnbind() {}
template <>
void AppClient<fuchsia::modular::Lifecycle>::ServiceTerminate(
fit::function<void()> done) {
SetAppErrorHandler(std::move(done));
if (primary_service())
primary_service()->Terminate();
}
} // namespace modular