blob: 1b8e89adb6b8912a94fd120c7563161a48da44a9 [file] [log] [blame]
// Copyright 2018 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 "sandbox.h"
#include <fcntl.h>
#include <lib/async/default.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/component/cpp/testing/test_util.h>
#include <lib/fdio/watcher.h>
#include <lib/fsl/io/fd.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/concatenate.h>
#include <lib/pkg_url/fuchsia_pkg_url.h>
#include <zircon/status.h>
#include "garnet/lib/cmx/cmx.h"
namespace netemul {
Sandbox::Sandbox(SandboxArgs args) : args_(std::move(args)) {
auto startup_context = component::StartupContext::CreateFromStartupInfo();
startup_context->ConnectToEnvironmentService(parent_env_.NewRequest());
startup_context->ConnectToEnvironmentService(loader_.NewRequest());
}
void Sandbox::Start() {
if (!parent_env_ || !loader_) {
Terminate(TerminationReason::INTERNAL_ERROR);
}
loader_->LoadUrl(args_.package, [this](fuchsia::sys::PackagePtr package) {
if (!package) {
Terminate(TerminationReason::PACKAGE_NOT_FOUND);
return;
} else if (!package->directory) {
Terminate(TerminationReason::INTERNAL_ERROR);
}
LoadPackage(std::move(package));
});
}
void Sandbox::Terminate(int64_t exit_code, Sandbox::TerminationReason reason) {
if (termination_callback_) {
termination_callback_(exit_code, reason);
}
}
void Sandbox::Terminate(Sandbox::TerminationReason reason) {
Terminate(-1, reason);
}
void Sandbox::LoadPackage(fuchsia::sys::PackagePtr package) {
// package is loaded, proceed to parsing cmx and starting child env
component::FuchsiaPkgUrl pkgUrl;
if (!pkgUrl.Parse(package->resolved_url)) {
FXL_LOG(ERROR) << "Can't parse fuchsia url: " << package->resolved_url;
Terminate(TerminationReason::INTERNAL_ERROR);
return;
}
fxl::UniqueFD dirfd =
fsl::OpenChannelAsFileDescriptor(std::move(package->directory));
sandbox_env_ = std::make_shared<SandboxEnv>(args_.package, std::move(dirfd));
component::CmxMetadata cmx;
json::JSONParser json_parser;
if (!cmx.ParseFromFileAt(sandbox_env_->dir().get(), pkgUrl.resource_path(),
&json_parser)) {
FXL_LOG(ERROR) << "cmx file failed to parse: " << json_parser.error_str();
Terminate(TerminationReason::INTERNAL_ERROR);
return;
}
root_ = ManagedEnvironment::CreateRoot(parent_env_, sandbox_env_);
// TODO(brunodalbo) parameterize environment based on
// facets in cmx file
root_->SetRunningCallback([this] {
root_proc_.events().OnTerminated = [this](int64_t code,
TerminationReason reason) {
Terminate(code, reason); // mimic termination of root process
};
// start root test process:
fuchsia::sys::LaunchInfo linfo;
linfo.url = sandbox_env_->name();
linfo.out = component::testing::CloneFileDescriptor(STDOUT_FILENO);
linfo.err = component::testing::CloneFileDescriptor(STDERR_FILENO);
root_->launcher().CreateComponent(std::move(linfo),
root_proc_.NewRequest());
});
}
} // namespace netemul