sandbox/
handle.rs

1// Copyright 2023 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::CapabilityBound;
6use fidl::handle::{self, HandleBased};
7
8/// A capability that wraps a single Zircon handle.
9#[derive(Debug)]
10pub struct Handle(handle::Handle);
11
12impl Handle {
13    /// Creates a new [Handle] containing a Zircon `handle`.
14    pub fn new(handle: handle::Handle) -> Self {
15        Self(handle)
16    }
17}
18
19impl From<handle::Handle> for Handle {
20    fn from(handle: handle::Handle) -> Self {
21        Handle(handle)
22    }
23}
24
25impl CapabilityBound for Handle {
26    fn debug_typename() -> &'static str {
27        "Handle"
28    }
29}
30
31impl Handle {
32    pub fn try_clone(&self) -> Result<Self, ()> {
33        Ok(Self(self.0.duplicate_handle(fidl::Rights::SAME_RIGHTS).map_err(|_| ())?))
34    }
35}
36
37impl From<Handle> for handle::Handle {
38    fn from(value: Handle) -> Self {
39        value.0
40    }
41}
42
43#[cfg(target_os = "fuchsia")]
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use crate::Capability;
48    use assert_matches::assert_matches;
49    use fidl::handle::{AsHandleRef, HandleBased};
50    use fidl_fuchsia_component_sandbox as fsandbox;
51
52    // Tests converting the Handle to FIDL and back.
53    #[fuchsia::test]
54    async fn handle_into_fidl() {
55        let event = zx::Event::create();
56        let expected_koid = event.get_koid().unwrap();
57
58        let handle = Handle::from(event.into_handle());
59
60        // Convert the OneShotHandle to FIDL and back.
61        let fidl_capability: fsandbox::Capability = handle.into();
62        assert_matches!(&fidl_capability, fsandbox::Capability::Handle(_));
63
64        let any: Capability = fidl_capability.try_into().unwrap();
65        let handle = assert_matches!(any, Capability::Handle(h) => h);
66
67        // Get the handle.
68        let handle: zx::Handle = handle.into();
69
70        // The handle should be for same Event that was in the original OneShotHandle.
71        let got_koid = handle.get_koid().unwrap();
72        assert_eq!(got_koid, expected_koid);
73    }
74
75    /// Tests that a Handle can be cloned by duplicating the handle.
76    #[fuchsia::test]
77    async fn try_clone() {
78        let event = zx::Event::create();
79        let expected_koid = event.get_koid().unwrap();
80
81        let handle = Handle::from(event.into_handle());
82        let handle = handle.try_clone().unwrap();
83        let handle: zx::Handle = handle.into();
84
85        let got_koid = handle.get_koid().unwrap();
86        assert_eq!(got_koid, expected_koid);
87
88        let (ch, _) = zx::Channel::create();
89        let handle = Handle::from(ch.into_handle());
90        assert_matches!(handle.try_clone(), Err(()));
91    }
92}