Skip to main content

runtime_capabilities/fidl/
capability.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::fidl::registry::try_from_handle_in_registry;
6use crate::{Capability, ConversionError, RemotableCapability, RemoteError, WeakInstanceToken};
7use fidl::AsHandleRef;
8use fidl_fuchsia_component_sandbox as fsandbox;
9use std::sync::Arc;
10use vfs::directory::entry::DirectoryEntry;
11use vfs::execution_scope::ExecutionScope;
12
13impl crate::fidl::IntoFsandboxCapability for Capability {
14    fn into_fsandbox_capability(self, token: WeakInstanceToken) -> fsandbox::Capability {
15        match self {
16            Capability::Connector(s) => s.into_fsandbox_capability(token),
17            Capability::DirConnector(s) => s.into_fsandbox_capability(token),
18            Capability::DictionaryRouter(s) => s.into_fsandbox_capability(token),
19            Capability::ConnectorRouter(s) => s.into_fsandbox_capability(token),
20            Capability::DirConnectorRouter(s) => s.into_fsandbox_capability(token),
21            Capability::DataRouter(s) => s.into_fsandbox_capability(token),
22            Capability::Dictionary(s) => s.into_fsandbox_capability(token),
23            Capability::Data(s) => s.into_fsandbox_capability(token),
24            Capability::Handle(s) => s.into_fsandbox_capability(token),
25            Capability::Instance(s) => s.into_fsandbox_capability(token),
26        }
27    }
28}
29
30impl TryFrom<fsandbox::Capability> for Capability {
31    type Error = RemoteError;
32
33    /// Converts the FIDL capability back to a Rust Capability.
34    ///
35    /// In most cases, the Capability was previously inserted into the registry when it
36    /// was converted to a FIDL capability. This method takes it out of the registry.
37    fn try_from(capability: fsandbox::Capability) -> Result<Self, Self::Error> {
38        match capability {
39            fsandbox::Capability::Unit(_) => Err(RemoteError::UnknownVariant),
40            fsandbox::Capability::Handle(handle) => Ok(crate::Handle::new(handle).into()),
41            fsandbox::Capability::Data(data_capability) => {
42                Ok(crate::Data::try_from(data_capability)?.into())
43            }
44            fsandbox::Capability::Dictionary(dict) => Ok(crate::Dictionary::try_from(dict)?.into()),
45            fsandbox::Capability::Connector(connector) => {
46                let any = try_from_handle_in_registry(connector.token.as_handle_ref())?;
47                match &any {
48                    Capability::Connector(_) => (),
49                    _ => return Err(RemoteError::BadCapability),
50                };
51                Ok(any)
52            }
53            fsandbox::Capability::DirConnector(connector) => {
54                let any = try_from_handle_in_registry(connector.token.as_handle_ref())?;
55                match &any {
56                    Capability::DirConnector(_) => (),
57                    _ => return Err(RemoteError::BadCapability),
58                };
59                Ok(any)
60            }
61            fsandbox::Capability::ConnectorRouter(client_end) => {
62                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
63                match &any {
64                    Capability::ConnectorRouter(_) => (),
65                    _ => return Err(RemoteError::BadCapability),
66                };
67                Ok(any)
68            }
69            fsandbox::Capability::DictionaryRouter(client_end) => {
70                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
71                match &any {
72                    Capability::DictionaryRouter(_) => (),
73                    _ => return Err(RemoteError::BadCapability),
74                };
75                Ok(any)
76            }
77            fsandbox::Capability::DirEntryRouter(_) => Err(RemoteError::UnknownVariant),
78            fsandbox::Capability::DataRouter(client_end) => {
79                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
80                match &any {
81                    Capability::DataRouter(_) => (),
82                    _ => return Err(RemoteError::BadCapability),
83                };
84                Ok(any)
85            }
86            fsandbox::Capability::DirEntry(_) => Err(RemoteError::UnknownVariant),
87            fsandbox::CapabilityUnknown!() => Err(RemoteError::UnknownVariant),
88        }
89    }
90}
91
92impl RemotableCapability for Capability {
93    fn try_into_directory_entry(
94        self,
95        scope: ExecutionScope,
96        token: WeakInstanceToken,
97    ) -> Result<Arc<dyn DirectoryEntry>, ConversionError> {
98        match self {
99            Self::Connector(s) => s.try_into_directory_entry(scope, token),
100            Self::DirConnector(s) => s.try_into_directory_entry(scope, token),
101            Self::ConnectorRouter(s) => s.try_into_directory_entry(scope, token),
102            Self::DictionaryRouter(s) => s.try_into_directory_entry(scope, token),
103            Self::DirConnectorRouter(s) => s.try_into_directory_entry(scope, token),
104            Self::DataRouter(s) => s.try_into_directory_entry(scope, token),
105            Self::Dictionary(s) => s.try_into_directory_entry(scope, token),
106            Self::Data(s) => s.try_into_directory_entry(scope, token),
107            Self::Handle(s) => s.try_into_directory_entry(scope, token),
108            Self::Instance(s) => s.try_into_directory_entry(scope, token),
109        }
110    }
111}