blob: 403516fc86e4c8cf8c6c7fcfb7ca0a396479a6c6 [file] [log] [blame]
// Copyright 2018 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.
//! Main entry point for the font service.
#![warn(missing_docs)]
mod font_service;
use {
self::font_service::{FontServiceBuilder, ProviderRequestStream},
anyhow::{format_err, Error},
argh::FromArgs,
fuchsia_async as fasync,
fuchsia_component::server::ServiceFs,
fuchsia_inspect::component::inspector,
fuchsia_syslog::{self as syslog, *},
fuchsia_trace as trace, fuchsia_trace_provider as trace_provider,
std::path::PathBuf,
};
const FONT_MANIFEST_PATH: &str = "/config/data/all.font_manifest.json";
/// TODO(fxbug.dev/43936): Remove after Chromium tests are made hermetic.
const TEST_COMPATIBILITY_FONT_MANIFEST_PATH: &str =
"/config/data/downstream_test_fonts.font_manifest.json";
/// Default capacity of the in-memory font cache when not specified in manifest.
///
/// 4 MB is enough to fit several smaller fonts; large fonts will never be cached.
///
/// TODO(fxbug.dev/48654): Listen for memory pressure events and trim cache.
const DEFAULT_CACHE_CAPACITY_BYTES: u64 = 4_000_000;
#[derive(FromArgs)]
/// Font Server
struct Args {
/// load fonts from the specified font manifest file instead of the default
#[argh(option, short = 'm')]
font_manifest: Option<String>,
/// no-op, deprecated
#[argh(switch, short = 'n')]
no_default_fonts: bool,
}
#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
syslog::init_with_tags(&["fonts"])?;
trace_provider::trace_provider_create_with_fdio();
trace::instant!("fonts", "startup", trace::Scope::Process);
// We have to convert legacy uses of "--font-manifest=<PATH>" to "--font-manifest <PATH>".
let arg_strings: Vec<String> = std::env::args()
.collect::<Vec<String>>()
.iter()
.flat_map(|s| s.split("=").map(|s| s.to_owned()))
.collect();
let arg_strs: Vec<&str> = arg_strings.iter().map(|s| s.as_str()).collect();
let args: Args = Args::from_args(&[arg_strs[0]], &arg_strs[1..])
.map_err(|early_exit| format_err!("{}", early_exit.output))?;
if args.no_default_fonts {
fx_log_warn!("--no-default-fonts is deprecated and is treated as a no-op")
}
let font_manifest_paths = select_manifests(&args)?;
let mut service_builder = FontServiceBuilder::with_default_asset_loader(
DEFAULT_CACHE_CAPACITY_BYTES,
inspector().root(),
);
fx_vlog!(1, "Building service with manifest(s) {:?}", &font_manifest_paths);
for path in &font_manifest_paths {
service_builder.add_manifest_from_file(path);
}
let service = service_builder.build().await.map_err(|err| {
fx_log_err!(
"Failed to build service with manifest(s) {:?}: {:#?}",
&font_manifest_paths,
&err
);
err
})?;
fx_vlog!(1, "Built service with manifest(s) {:?}", &font_manifest_paths);
fx_vlog!(1, "Adding FIDL services");
let mut fs = ServiceFs::new();
fs.dir("svc")
.add_fidl_service(ProviderRequestStream::Stable)
.add_fidl_service(ProviderRequestStream::Experimental);
fs.take_and_serve_directory_handle()?;
inspector().serve(&mut fs)?;
let fs = fs;
service.run(fs).await;
Ok(())
}
/// Negotiate which manifest(s) to load.
/// TODO(fxbug.dev/43936): Remove compatibility manifest after Chromium tests are made hermetic.
fn select_manifests(args: &Args) -> Result<Vec<PathBuf>, Error> {
let mut manifest_paths: Vec<PathBuf> = vec![];
let main_manifest_path = match &args.font_manifest {
Some(path) => PathBuf::from(path),
None => PathBuf::from(FONT_MANIFEST_PATH),
};
if main_manifest_path.is_file() {
manifest_paths.push(main_manifest_path);
} else {
fx_log_warn!(
concat!(
"Specified manifest file {:?} does not exist. ",
"Looking for test compatibility manifest instead."
),
main_manifest_path
);
}
// Support legacy non-hermetic tests (e.g. Chromium) that expect some minimum set of fonts but
// don't specify what it should be.
if args.font_manifest.is_none() {
let compatibility_manifest_path = PathBuf::from(TEST_COMPATIBILITY_FONT_MANIFEST_PATH);
if compatibility_manifest_path.is_file() {
manifest_paths.push(compatibility_manifest_path);
}
}
if manifest_paths.is_empty() {
Err(format_err!("Either no font manifests were specified, or they do not exist"))
} else {
Ok(manifest_paths)
}
}