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, 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::DirEntry(s) => s.into_fsandbox_capability(token),
19            Capability::DictionaryRouter(s) => s.into_fsandbox_capability(token),
20            Capability::ConnectorRouter(s) => s.into_fsandbox_capability(token),
21            Capability::DirEntryRouter(s) => s.into_fsandbox_capability(token),
22            Capability::DirConnectorRouter(s) => s.into_fsandbox_capability(token),
23            Capability::DataRouter(s) => s.into_fsandbox_capability(token),
24            Capability::Dictionary(s) => s.into_fsandbox_capability(token),
25            Capability::Data(s) => s.into_fsandbox_capability(token),
26            Capability::Unit(s) => s.into_fsandbox_capability(token),
27            Capability::Directory(s) => s.into_fsandbox_capability(token),
28            Capability::Handle(s) => s.into_fsandbox_capability(token),
29            Capability::Instance(s) => s.into_fsandbox_capability(token),
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        token: WeakInstanceToken,
118    ) -> Result<Arc<dyn DirectoryEntry>, ConversionError> {
119        match self {
120            Self::Connector(s) => s.try_into_directory_entry(scope, token),
121            Self::DirConnector(s) => s.try_into_directory_entry(scope, token),
122            Self::DirEntry(s) => s.try_into_directory_entry(scope, token),
123            Self::ConnectorRouter(s) => s.try_into_directory_entry(scope, token),
124            Self::DictionaryRouter(s) => s.try_into_directory_entry(scope, token),
125            Self::DirEntryRouter(s) => s.try_into_directory_entry(scope, token),
126            Self::DirConnectorRouter(s) => s.try_into_directory_entry(scope, token),
127            Self::DataRouter(s) => s.try_into_directory_entry(scope, token),
128            Self::Dictionary(s) => s.try_into_directory_entry(scope, token),
129            Self::Data(s) => s.try_into_directory_entry(scope, token),
130            Self::Unit(s) => s.try_into_directory_entry(scope, token),
131            Self::Directory(s) => s.try_into_directory_entry(scope, token),
132            Self::Handle(s) => s.try_into_directory_entry(scope, token),
133            Self::Instance(s) => s.try_into_directory_entry(scope, token),
134        }
135    }
136}