| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "fuchsia_web/runners/cast/cast_resolver.h" |
| |
| #include <fidl/fuchsia.component.decl/cpp/fidl.h> |
| #include <fidl/fuchsia.component/cpp/fidl.h> |
| #include <fidl/fuchsia.ui.app/cpp/wire_messaging.h> |
| #include <lib/fidl/cpp/natural_types.h> |
| #include <stdint.h> |
| |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/files/file_util.h" |
| #include "base/fuchsia/fuchsia_logging.h" |
| #include "base/notimplemented.h" |
| #include "base/numerics/byte_conversions.h" |
| |
| namespace { |
| |
| using fuchsia_component_decl::Ref; |
| |
| template <typename Protocol> |
| void DeclareAndExposeProtocol(fuchsia_component_decl::Component& decl) { |
| constexpr const char* kProtocolName = |
| fidl::DiscoverableProtocolName<Protocol>; |
| if (!decl.capabilities()) { |
| decl.capabilities().emplace(); |
| } |
| decl.capabilities()->push_back( |
| fuchsia_component_decl::Capability::WithProtocol({{ |
| .name = kProtocolName, |
| .source_path = fidl::DiscoverableProtocolDefaultPath<Protocol>, |
| }})); |
| CHECK(decl.exposes()); |
| decl.exposes()->push_back(fuchsia_component_decl::Expose::WithProtocol({{ |
| .source = Ref::WithSelf({}), |
| .source_name = kProtocolName, |
| .target = Ref::WithParent({}), |
| .target_name = kProtocolName, |
| }})); |
| } |
| |
| uint64_t FetchAbiRevision() { |
| constexpr char kPkgAbiRevisionPath[] = "/pkg/meta/fuchsia.abi/abi-revision"; |
| |
| // Read the Little Endian representation of the unsigned 64-bit integer ABI |
| // revision from the file in the metadata directory. |
| std::array<uint8_t, 8u> abi_revision_le = {}; |
| std::optional<uint64_t> read_bytes = |
| base::ReadFile(base::FilePath(kPkgAbiRevisionPath), abi_revision_le); |
| CHECK_EQ(read_bytes.value(), sizeof(abi_revision_le)); |
| return base::U64FromLittleEndian(abi_revision_le); |
| } |
| |
| } // namespace |
| |
| CastResolver::CastResolver() = default; |
| |
| CastResolver::~CastResolver() = default; |
| |
| void CastResolver::Resolve(CastResolver::ResolveRequest& request, |
| CastResolver::ResolveCompleter::Sync& completer) { |
| fuchsia_component_decl::Component decl{{ |
| .program = fuchsia_component_decl::Program{{ |
| .runner = "cast-runner", |
| .info = fuchsia_data::Dictionary{{ |
| .entries = {}, |
| }}, |
| }}, |
| |
| // TODO(crbug.com/40875550): Replace with attributed-capability expose |
| // rules for each protocol, when supported by the framework. |
| .uses = |
| std::vector{ |
| fuchsia_component_decl::Use::WithDirectory({{ |
| .source = Ref::WithParent({}), |
| .source_name = "svc", |
| .target_path = "/svc", |
| .rights = fuchsia_io::wire::kRStarDir, |
| .dependency_type = |
| fuchsia_component_decl::DependencyType::kStrong, |
| }}), |
| }, |
| |
| // Expose the Binder, from the framework, to allow callers to explicitly |
| // start the component. |
| .exposes = std::vector{fuchsia_component_decl::Expose::WithProtocol({{ |
| .source = Ref::WithFramework({}), |
| .source_name = |
| fidl::DiscoverableProtocolName<fuchsia_component::Binder>, |
| .target = Ref::WithParent({}), |
| .target_name = |
| fidl::DiscoverableProtocolName<fuchsia_component::Binder>, |
| }})}, |
| }}; |
| |
| // Declare and expose capabilities implemented by the component. |
| DeclareAndExposeProtocol<fuchsia_ui_app::ViewProvider>(decl); |
| |
| fit::result<fidl::Error, std::vector<uint8_t>> persisted_decl = |
| fidl::Persist(decl); |
| if (persisted_decl.is_error()) { |
| ZX_DLOG(ERROR, persisted_decl.error_value().status()) |
| << "Error creating persisted decl"; |
| completer.Reply( |
| fit::error(fuchsia_component_resolution::ResolverError::kInternal)); |
| return; |
| } |
| |
| // Encode the component manifest into the resolver result. |
| static const uint64_t abi_revision = FetchAbiRevision(); |
| fuchsia_component_resolution::ResolverResolveResponse result{{ |
| .component = fuchsia_component_resolution::Component{{ |
| .decl = |
| fuchsia_mem::Data::WithBytes(std::move(persisted_decl.value())), |
| .abi_revision = abi_revision, |
| }}, |
| }}; |
| |
| completer.Reply(fit::ok(std::move(result))); |
| } |
| |
| void CastResolver::ResolveWithContext( |
| CastResolver::ResolveWithContextRequest& request, |
| CastResolver::ResolveWithContextCompleter::Sync& completer) { |
| NOTIMPLEMENTED(); |
| |
| completer.Reply( |
| fit::error(fuchsia_component_resolution::ResolverError::kNotSupported)); |
| } |
| |
| void CastResolver::handle_unknown_method( |
| fidl::UnknownMethodMetadata<fuchsia_component_resolution::Resolver> |
| metadata, |
| fidl::UnknownMethodCompleter::Sync& completer) { |
| LOG(ERROR) << "Unknown method called on CastResolver. Ordinal: " |
| << metadata.method_ordinal; |
| completer.Close(ZX_ERR_NOT_SUPPORTED); |
| } |