blob: 87c4e80d264425d2abac22808a517682f19214d3 [file] [log] [blame]
// Copyright 2023 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.
use crate::model::resolver;
use async_trait::async_trait;
use fuchsia_url::builtin_url::BuiltinUrl;
use include_bytes_from_working_dir::include_bytes_from_working_dir_env;
use routing::resolving::{ComponentAddress, ResolvedComponent, ResolverError};
use thiserror::Error;
use crate::model::resolver::Resolver;
pub static SCHEME: &str = "fuchsia-builtin";
/// The builtin resolver resolves components defined inside component_manager.
///
/// It accepts a URL scheme of the form `fuchsia-builtin://#elf_runner.cm`.
///
/// Builtin component declarations are used to bootstrap the ELF runner.
/// They are never packaged.
///
/// Only absolute URLs are supported.
#[derive(Debug)]
pub struct BuiltinResolver {}
#[async_trait]
impl Resolver for BuiltinResolver {
async fn resolve(
&self,
component_address: &ComponentAddress,
) -> Result<ResolvedComponent, ResolverError> {
if component_address.is_relative_path() {
return Err(ResolverError::UnexpectedRelativePath(component_address.url().to_string()));
}
let url = BuiltinUrl::parse(component_address.url())
.map_err(|e| ResolverError::malformed_url(e))?;
let Some(resource) = url.resource() else {
return Err(ResolverError::manifest_not_found(ManifestNotFoundError(url.clone())));
};
let cm = match resource {
"elf_runner.cm" => Ok(ELF_RUNNER_CM),
_ => Err(ResolverError::manifest_not_found(ManifestNotFoundError(url.clone()))),
}?;
let decl = resolver::read_and_validate_manifest_bytes(cm)?;
// Unpackaged components built into component_manager are assigned the
// platform abi revision.
let abi_revision = version_history::HISTORY.get_abi_revision_for_platform_components();
Ok(ResolvedComponent {
resolved_url: url.to_string(),
context_to_resolve_children: None,
decl,
package: None,
config_values: None,
abi_revision: Some(abi_revision),
})
}
}
/// A compiled `.cm` binary blob corresponding to the ELF runner component declaration.
static ELF_RUNNER_CM: &'static [u8] = include_bytes_from_working_dir_env!("ELF_RUNNER_CM_PATH");
#[derive(Error, Debug, Clone)]
#[error("{0} does not reference a known manifest. Try fuchsia-builtin://#elf_runner.cm")]
struct ManifestNotFoundError(pub BuiltinUrl);
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
use fidl_fuchsia_data as fdata;
#[fuchsia::test]
fn elf_runner_cm_smoke_test() {
let decl = resolver::read_and_validate_manifest_bytes(ELF_RUNNER_CM).unwrap();
let program = decl.program.unwrap();
assert_eq!(program.runner.unwrap().as_str(), "builtin");
let entries = program.info.entries.unwrap();
let program_type = entries.iter().find(|entry| entry.key == "type").unwrap();
let value = *program_type.value.clone().unwrap();
assert_matches!(
value,
fdata::DictionaryValue::Str(s)
if &s == "elf_runner"
);
}
}