sandbox/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};
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 From<Capability> for fsandbox::Capability {
14    fn from(capability: Capability) -> Self {
15        match capability {
16            Capability::Connector(s) => s.into(),
17            Capability::DirConnector(s) => s.into(),
18            Capability::DirEntry(s) => s.into(),
19            Capability::DictionaryRouter(s) => s.into(),
20            Capability::ConnectorRouter(s) => s.into(),
21            Capability::DirEntryRouter(s) => s.into(),
22            Capability::DirConnectorRouter(s) => s.into(),
23            Capability::DataRouter(s) => s.into(),
24            Capability::Dictionary(s) => s.into(),
25            Capability::Data(s) => s.into(),
26            Capability::Unit(s) => s.into(),
27            Capability::Directory(s) => s.into(),
28            Capability::Handle(s) => s.into(),
29            Capability::Instance(s) => s.into(),
30        }
31    }
32}
33
34impl TryFrom<fsandbox::Capability> for Capability {
35    type Error = RemoteError;
36
37    /// Converts the FIDL capability back to a Rust Capability.
38    ///
39    /// In most cases, the Capability was previously inserted into the registry when it
40    /// was converted to a FIDL capability. This method takes it out of the registry.
41    fn try_from(capability: fsandbox::Capability) -> Result<Self, Self::Error> {
42        match capability {
43            fsandbox::Capability::Unit(_) => Ok(crate::Unit::default().into()),
44            fsandbox::Capability::Handle(handle) => Ok(crate::Handle::new(handle).into()),
45            fsandbox::Capability::Data(data_capability) => {
46                Ok(crate::Data::try_from(data_capability)?.into())
47            }
48            fsandbox::Capability::Dictionary(dict) => Ok(crate::Dict::try_from(dict)?.into()),
49            fsandbox::Capability::Connector(connector) => {
50                let any = try_from_handle_in_registry(connector.token.as_handle_ref())?;
51                match &any {
52                    Capability::Connector(_) => (),
53                    _ => return Err(RemoteError::BadCapability),
54                };
55                Ok(any)
56            }
57            fsandbox::Capability::DirConnector(connector) => {
58                let any = try_from_handle_in_registry(connector.token.as_handle_ref())?;
59                match &any {
60                    Capability::DirConnector(_) => (),
61                    _ => return Err(RemoteError::BadCapability),
62                };
63                Ok(any)
64            }
65            fsandbox::Capability::Directory(client_end) => {
66                Ok(crate::Directory::new(client_end).into())
67            }
68            fsandbox::Capability::ConnectorRouter(client_end) => {
69                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
70                match &any {
71                    Capability::ConnectorRouter(_) => (),
72                    _ => return Err(RemoteError::BadCapability),
73                };
74                Ok(any)
75            }
76            fsandbox::Capability::DictionaryRouter(client_end) => {
77                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
78                match &any {
79                    Capability::DictionaryRouter(_) => (),
80                    _ => return Err(RemoteError::BadCapability),
81                };
82                Ok(any)
83            }
84            fsandbox::Capability::DirEntryRouter(client_end) => {
85                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
86                match &any {
87                    Capability::DirEntryRouter(_) => (),
88                    _ => return Err(RemoteError::BadCapability),
89                };
90                Ok(any)
91            }
92            fsandbox::Capability::DataRouter(client_end) => {
93                let any = try_from_handle_in_registry(client_end.as_handle_ref())?;
94                match &any {
95                    Capability::DataRouter(_) => (),
96                    _ => return Err(RemoteError::BadCapability),
97                };
98                Ok(any)
99            }
100            fsandbox::Capability::DirEntry(dir_entry) => {
101                let any = try_from_handle_in_registry(dir_entry.token.as_handle_ref())?;
102                match &any {
103                    Capability::DirEntry(_) => (),
104                    _ => return Err(RemoteError::BadCapability),
105                };
106                Ok(any)
107            }
108            fsandbox::CapabilityUnknown!() => Err(RemoteError::UnknownVariant),
109        }
110    }
111}
112
113impl RemotableCapability for Capability {
114    fn try_into_directory_entry(
115        self,
116        scope: ExecutionScope,
117    ) -> Result<Arc<dyn DirectoryEntry>, ConversionError> {
118        match self {
119            Self::Connector(s) => s.try_into_directory_entry(scope),
120            Self::DirConnector(s) => s.try_into_directory_entry(scope),
121            Self::DirEntry(s) => s.try_into_directory_entry(scope),
122            Self::ConnectorRouter(s) => s.try_into_directory_entry(scope),
123            Self::DictionaryRouter(s) => s.try_into_directory_entry(scope),
124            Self::DirEntryRouter(s) => s.try_into_directory_entry(scope),
125            Self::DirConnectorRouter(s) => s.try_into_directory_entry(scope),
126            Self::DataRouter(s) => s.try_into_directory_entry(scope),
127            Self::Dictionary(s) => s.try_into_directory_entry(scope),
128            Self::Data(s) => s.try_into_directory_entry(scope),
129            Self::Unit(s) => s.try_into_directory_entry(scope),
130            Self::Directory(s) => s.try_into_directory_entry(scope),
131            Self::Handle(s) => s.try_into_directory_entry(scope),
132            Self::Instance(s) => s.try_into_directory_entry(scope),
133        }
134    }
135}