blob: 5a64309ca6108e1b16c759dfc948da98088a4d52 [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 "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