| // 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 <fuchsia/sys2/cpp/fidl.h> |
| #include <lib/async/default.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/fdio.h> |
| #include <lib/trace/event.h> |
| |
| #include <utility> |
| |
| #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_allowlist) |
| : vfs_(async_get_default_dispatcher()) { |
| fbl::RefPtr<LogConnectorImpl> connector; |
| if (realm) { |
| connector = realm->log_connector(); |
| } |
| services_ = fbl::AdoptRef(new ServiceProviderDirImpl(connector, service_allowlist)); |
| 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_->IsServiceAllowlisted(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 |