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