blob: e54abd5f10cbb47c6fb751ce78502ff3402fce13 [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 "garnet/bin/appmgr/namespace.h"
#include <fuchsia/process/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <trace/event.h>
#include <utility>
#include "garnet/bin/appmgr/job_provider_impl.h"
#include "garnet/bin/appmgr/realm.h"
#include "garnet/bin/appmgr/storage_watchdog.h"
#include "garnet/bin/appmgr/util.h"
namespace component {
Namespace::Namespace(fxl::RefPtr<Namespace> parent, Realm* realm,
fuchsia::sys::ServiceListPtr additional_services,
const std::vector<std::string>* service_whitelist)
: vfs_(async_get_default_dispatcher()),
services_(fbl::AdoptRef(new ServiceProviderDirImpl(service_whitelist))),
job_provider_(fbl::AdoptRef(new JobProviderImpl(realm))),
realm_(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());
}
// If any of these services aren't in additional_services or the parent
// namespace, add them here directly. (AddService skips duplicate services)
// TODO: Add to RootRealmServices in main.cc instead of adding automatically
// to all namespaces here.
services_->AddService(
CacheControl::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
test_cache_bindings_.AddBinding(
this, fidl::InterfaceRequest<CacheControl>(std::move(channel)));
return ZX_OK;
})));
}
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);
});
}
void Namespace::Clear(ClearCallback callback) {
auto cc_trace_id = TRACE_NONCE();
TRACE_ASYNC_BEGIN("appmgr", "Namespace::Clear", cc_trace_id);
StorageWatchdog storage_watchdog = StorageWatchdog("/data", "/data/cache");
storage_watchdog.PurgeCache();
callback();
}
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));
}
} // namespace component