| // 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 "lib/component/cpp/startup_context.h" |
| |
| #include <lib/async/default.h> |
| #include <lib/fdio/util.h> |
| #include <zircon/process.h> |
| #include <zircon/processargs.h> |
| |
| #include "lib/component/cpp/connect.h" |
| #include "lib/fxl/logging.h" |
| |
| namespace component { |
| |
| namespace { |
| |
| constexpr char kServiceRootPath[] = "/svc"; |
| |
| } // namespace |
| |
| StartupContext::StartupContext(zx::channel service_root, |
| zx::channel directory_request) |
| : incoming_services_(std::make_shared<Services>()) { |
| incoming_services_->Bind(std::move(service_root)); |
| outgoing_.Serve(std::move(directory_request)); |
| } |
| |
| StartupContext::~StartupContext() = default; |
| |
| // static |
| std::unique_ptr<StartupContext> StartupContext::CreateFromStartupInfo() { |
| zx_handle_t directory_request = zx_take_startup_handle(PA_DIRECTORY_REQUEST); |
| return std::make_unique<StartupContext>( |
| subtle::CreateStaticServiceRootHandle(), zx::channel(directory_request)); |
| } |
| |
| // static |
| std::unique_ptr<StartupContext> |
| StartupContext::CreateFromStartupInfoNotChecked() { |
| return CreateFromStartupInfo(); |
| } |
| |
| std::unique_ptr<StartupContext> StartupContext::CreateFrom( |
| fuchsia::sys::StartupInfo startup_info) { |
| fuchsia::sys::FlatNamespace& flat = startup_info.flat_namespace; |
| if (flat.paths.size() != flat.directories.size()) |
| return nullptr; |
| |
| zx::channel service_root; |
| for (size_t i = 0; i < flat.paths.size(); ++i) { |
| if (flat.paths.at(i) == kServiceRootPath) { |
| service_root = std::move(flat.directories.at(i)); |
| break; |
| } |
| } |
| |
| return std::make_unique<StartupContext>( |
| std::move(service_root), |
| std::move(startup_info.launch_info.directory_request)); |
| } |
| |
| const fuchsia::sys::EnvironmentPtr& StartupContext::environment() const { |
| std::lock_guard<std::mutex> guard(services_mutex_); |
| if (!environment_) { |
| incoming_services_->ConnectToService(environment_.NewRequest()); |
| } |
| return environment_; |
| } |
| |
| const fuchsia::sys::LauncherPtr& StartupContext::launcher() const { |
| std::lock_guard<std::mutex> guard(services_mutex_); |
| if (!launcher_) { |
| incoming_services_->ConnectToService(launcher_.NewRequest()); |
| } |
| return launcher_; |
| } |
| |
| void StartupContext::ConnectToEnvironmentService( |
| const std::string& interface_name, zx::channel channel) { |
| incoming_services()->ConnectToService(std::move(channel), interface_name); |
| } |
| |
| namespace subtle { |
| |
| // static |
| zx::channel CreateStaticServiceRootHandle() { |
| zx::channel h1, h2; |
| if (zx::channel::create(0, &h1, &h2) != ZX_OK) |
| return zx::channel(); |
| // TODO(abarth): Use kServiceRootPath once that actually works. |
| if (fdio_service_connect("/svc/.", h1.release()) != ZX_OK) |
| return zx::channel(); |
| return h2; |
| } |
| |
| } // namespace subtle |
| |
| } // namespace component |