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, CapabilityBound, ConversionError, 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: Arc<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) => {
41                Ok(Capability::Handle(crate::Handle::new(handle)))
42            }
43            fsandbox::Capability::Data(data_capability) => {
44                Ok(Capability::Data(Arc::new(<crate::Data as std::convert::TryFrom<
45                    fsandbox::Data,
46                >>::try_from(data_capability)?)))
47            }
48            fsandbox::Capability::Dictionary(dict) => {
49                let any = try_from_handle_in_registry(dict.token.as_handle_ref())?;
50                match &any {
51                    Capability::Dictionary(_) => (),
52                    _ => return Err(RemoteError::BadCapability),
53                };
54                Ok(any)
55            }
56            fsandbox::Capability::Connector(connector) => {
57                let any = try_from_handle_in_registry(connector.token.as_handle_ref())?;
58                match &any {
59                    Capability::Connector(_) => (),
60                    _ => return Err(RemoteError::BadCapability),
61                };
62                Ok(any)
63            }
64            fsandbox::Capability::DirConnector(connector) => {
65                let any = try_from_handle_in_registry(connector.token.as_handle_ref())?;
66                match &any {
67                    Capability::DirConnector(_) => (),
68                    _ => return Err(RemoteError::BadCapability),
69                };
70                Ok(any)
71            }
72            fsandbox::Capability::ConnectorRouter(client_end) => {
73                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
74                match &any {
75                    Capability::ConnectorRouter(_) => (),
76                    _ => return Err(RemoteError::BadCapability),
77                };
78                Ok(any)
79            }
80            fsandbox::Capability::DictionaryRouter(client_end) => {
81                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
82                match &any {
83                    Capability::DictionaryRouter(_) => (),
84                    _ => return Err(RemoteError::BadCapability),
85                };
86                Ok(any)
87            }
88            fsandbox::Capability::DirEntryRouter(_) => Err(RemoteError::UnknownVariant),
89            fsandbox::Capability::DataRouter(client_end) => {
90                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
91                match &any {
92                    Capability::DataRouter(_) => (),
93                    _ => return Err(RemoteError::BadCapability),
94                };
95                Ok(any)
96            }
97            fsandbox::Capability::DirEntry(_) => Err(RemoteError::UnknownVariant),
98            fsandbox::CapabilityUnknown!() => Err(RemoteError::UnknownVariant),
99        }
100    }
101}
102
103impl Capability {
104    pub fn try_into_directory_entry(
105        self,
106        scope: ExecutionScope,
107        token: Arc<WeakInstanceToken>,
108    ) -> Result<Arc<dyn DirectoryEntry>, ConversionError> {
109        match self {
110            Self::Connector(s) => s.try_into_directory_entry(scope, token),
111            Self::DirConnector(s) => s.try_into_directory_entry(scope, token),
112            Self::ConnectorRouter(s) => s.try_into_directory_entry(scope, token),
113            Self::DictionaryRouter(s) => s.try_into_directory_entry(scope, token),
114            Self::DirConnectorRouter(s) => s.try_into_directory_entry(scope, token),
115            Self::DataRouter(s) => s.try_into_directory_entry(scope, token),
116            Self::Dictionary(s) => s.try_into_directory_entry(scope, token),
117            Self::Data(s) => s.try_into_directory_entry(scope, token),
118            Self::Handle(s) => s.try_into_directory_entry(scope, token),
119            Self::Instance(s) => s.try_into_directory_entry(scope, token),
120        }
121    }
122}