blob: b5dfc4a3b85a456be9446c287bd1405ba5c2e873 [file] [log] [blame]
// Copyright 2017 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/sysmgr/delegating_loader.h"
#include "lib/fidl/cpp/clone.h"
#include "lib/svc/cpp/services.h"
namespace sysmgr {
namespace {
std::string GetScheme(const std::string& url) {
size_t pos = url.find(':');
if (pos == std::string::npos)
return std::string();
return url.substr(0, pos);
}
} // namespace
DelegatingLoader::DelegatingLoader(Config::ServiceMap delegates,
fuchsia::sys::Launcher* delegate_launcher,
fuchsia::sys::LoaderPtr fallback)
: delegate_launcher_(delegate_launcher), fallback_(std::move(fallback)) {
for (auto& pair : delegates) {
auto& record = delegate_instances_[pair.second->url];
record.launch_info = std::move(pair.second);
delegates_by_scheme_[pair.first] = &record;
}
}
DelegatingLoader::~DelegatingLoader() = default;
void DelegatingLoader::LoadComponent(fidl::StringPtr url,
LoadComponentCallback callback) {
std::string scheme = GetScheme(url);
if (!scheme.empty()) {
auto it = delegates_by_scheme_.find(scheme);
if (it != delegates_by_scheme_.end()) {
auto* record = it->second;
if (!record->loader) {
StartDelegate(record);
}
record->loader->LoadComponent(url, std::move(callback));
return;
}
}
fallback_->LoadComponent(url, std::move(callback));
}
void DelegatingLoader::StartDelegate(LoaderRecord* record) {
component::Services services;
fuchsia::sys::LaunchInfo dup_launch_info;
dup_launch_info.url = record->launch_info->url;
fidl::Clone(record->launch_info->arguments, &dup_launch_info.arguments);
dup_launch_info.directory_request = services.NewRequest();
delegate_launcher_->CreateComponent(std::move(dup_launch_info),
record->controller.NewRequest());
record->loader = services.ConnectToService<fuchsia::sys::Loader>();
record->loader.set_error_handler([this, record] {
// proactively kill the loader app entirely if its Loader died on
// us
record->controller.Unbind();
});
}
} // namespace sysmgr