blob: 90b0535a2ed38661ee47449d6c01ff9072da6072 [file] [log] [blame]
// Copyright 2016 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 "src/sys/appmgr/namespace.h"
#include <fuchsia/process/cpp/fidl.h>
#include <fuchsia/sys/internal/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <utility>
#include <trace/event.h>
#include "fbl/ref_ptr.h"
#include "src/sys/appmgr/job_provider_impl.h"
#include "src/sys/appmgr/realm.h"
#include "src/sys/appmgr/util.h"
namespace component {
Namespace::Namespace(fxl::RefPtr<Namespace> parent, fxl::WeakPtr<Realm> realm,
fuchsia::sys::ServiceListPtr additional_services,
const std::vector<std::string>* service_whitelist)
: vfs_(async_get_default_dispatcher()) {
fbl::RefPtr<LogConnectorImpl> connector;
if (realm) {
connector = realm->log_connector();
}
services_ = fbl::AdoptRef(new ServiceProviderDirImpl(connector, service_whitelist));
job_provider_ = fbl::AdoptRef(new JobProviderImpl(realm.get()));
realm_ = std::move(realm);
// WARNING! Do not add new services here! This makes services available in all
// component namespaces ambiently without requiring proper routing between
// realms, and this list should not be expanded.
services_->AddService(
fuchsia::sys::Environment::Name_, fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
environment_bindings_.AddBinding(
this, fidl::InterfaceRequest<fuchsia::sys::Environment>(std::move(channel)));
return ZX_OK;
})));
services_->AddService(Launcher::Name_, fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
launcher_bindings_.AddBinding(
this, fidl::InterfaceRequest<Launcher>(std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::process::Launcher::Name_, fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
realm_->environment_services()->Connect(
fidl::InterfaceRequest<fuchsia::process::Launcher>(std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::process::Resolver::Name_, fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
resolver_bindings_.AddBinding(
this, fidl::InterfaceRequest<fuchsia::process::Resolver>(std::move(channel)));
return ZX_OK;
})));
// WARNING! Do not add new services here! This makes services available in all
// component namespaces ambiently without requiring proper routing between
// realms, and this list should not be expanded.
if (additional_services) {
auto& names = additional_services->names;
service_provider_ = additional_services->provider.Bind();
service_host_directory_ = std::move(additional_services->host_directory);
for (auto& name : names) {
if (service_host_directory_) {
services_->AddService(name,
fbl::AdoptRef(new fs::Service([this, name](zx::channel channel) {
fdio_service_connect_at(service_host_directory_.get(), name.c_str(),
channel.release());
return ZX_OK;
})));
} else {
services_->AddService(name,
fbl::AdoptRef(new fs::Service([this, name](zx::channel channel) {
service_provider_->ConnectToService(name, std::move(channel));
return ZX_OK;
})));
}
}
}
// If any services in |parent| share a name with |additional_services|,
// |additional_services| takes priority.
if (parent) {
services_->set_parent(parent->services());
}
services_->InitLogging();
}
Namespace::~Namespace() {}
void Namespace::AddBinding(fidl::InterfaceRequest<fuchsia::sys::Environment> environment) {
environment_bindings_.AddBinding(this, std::move(environment));
}
void Namespace::CreateNestedEnvironment(
fidl::InterfaceRequest<fuchsia::sys::Environment> environment,
fidl::InterfaceRequest<fuchsia::sys::EnvironmentController> controller, std::string label,
fuchsia::sys::ServiceListPtr additional_services, fuchsia::sys::EnvironmentOptions options) {
realm_->CreateNestedEnvironment(std::move(environment), std::move(controller), std::move(label),
std::move(additional_services), options);
}
void Namespace::GetLauncher(fidl::InterfaceRequest<Launcher> launcher) {
launcher_bindings_.AddBinding(this, std::move(launcher));
}
void Namespace::GetServices(fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
services_->AddBinding(std::move(services));
}
zx_status_t Namespace::ServeServiceDirectory(zx::channel directory_request) {
return vfs_.ServeDirectory(services_, std::move(directory_request));
}
void Namespace::CreateComponent(
fuchsia::sys::LaunchInfo launch_info,
fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
auto cc_trace_id = TRACE_NONCE();
TRACE_ASYNC_BEGIN("appmgr", "Namespace::CreateComponent", cc_trace_id, "launch_info.url",
launch_info.url);
realm_->CreateComponent(std::move(launch_info), std::move(controller),
[cc_trace_id](std::weak_ptr<ComponentControllerImpl> component) {
TRACE_ASYNC_END("appmgr", "Namespace::CreateComponent", cc_trace_id);
});
}
zx::channel Namespace::OpenServicesAsDirectory() { return Util::OpenAsDirectory(&vfs_, services_); }
void Namespace::Resolve(std::string name, fuchsia::process::Resolver::ResolveCallback callback) {
realm_->Resolve(name, std::move(callback));
}
void Namespace::NotifyComponentDiagnosticsDirReady(
const std::string& component_url, const std::string& component_name,
const std::string& component_id, fidl::InterfaceHandle<fuchsia::io::Directory> directory) {
if (realm_) {
realm_->NotifyComponentDiagnosticsDirReady(component_url, component_name, component_id,
std::move(directory));
}
}
void Namespace::NotifyComponentStarted(const std::string& component_url,
const std::string& component_name,
const std::string& component_id) {
if (realm_) {
realm_->NotifyComponentStarted(component_url, component_name, component_id);
}
}
void Namespace::NotifyComponentStopped(const std::string& component_url,
const std::string& component_name,
const std::string& component_id) {
if (realm_) {
realm_->NotifyComponentStopped(component_url, component_name, component_id);
}
}
void Namespace::MaybeAddComponentEventProvider() {
if (services_->IsServiceWhitelisted(fuchsia::sys::internal::ComponentEventProvider::Name_)) {
services_->AddService(
fuchsia::sys::internal::ComponentEventProvider::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
return realm_->BindComponentEventProvider(
fidl::InterfaceRequest<fuchsia::sys::internal::ComponentEventProvider>(
std::move(channel)));
})));
}
}
} // namespace component