Skip to main content

routing/
component_instance.rs

1// Copyright 2021 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::bedrock::sandbox_construction::ComponentSandbox;
6use crate::error::ComponentInstanceError;
7use crate::policy::GlobalPolicyChecker;
8use crate::resolving::{ComponentAddress, ComponentResolutionContext, ResolverError};
9use async_trait::async_trait;
10use capability_source::{BuiltinCapabilities, NamespaceCapabilities};
11use cm_types::Url;
12use derivative::Derivative;
13use moniker::{BorrowedChildName, ExtendedMoniker, Moniker};
14use runtime_capabilities::{WeakInstanceToken, WeakInstanceTokenAny};
15use std::clone::Clone;
16use std::sync::{Arc, Weak};
17
18/// A trait providing a representation of a component instance.
19#[async_trait]
20pub trait ComponentInstanceInterface: Sized + Send + Sync {
21    type TopInstance: TopInstanceInterface + Send + Sync;
22
23    /// Returns a new `WeakComponentInstanceInterface<Self>` pointing to `self`.
24    fn as_weak(self: &Arc<Self>) -> WeakComponentInstanceInterface<Self> {
25        WeakComponentInstanceInterface::new(self)
26    }
27
28    /// Returns this `ComponentInstanceInterface`'s child moniker, if it is
29    /// not the root instance.
30    fn child_moniker(&self) -> Option<&BorrowedChildName> {
31        self.moniker().leaf()
32    }
33
34    /// Returns this `ComponentInstanceInterface`'s moniker.
35    fn moniker(&self) -> &Moniker;
36
37    /// Returns this `ComponentInstanceInterface`'s component URL.
38    fn url(&self) -> &Url;
39
40    /// Returns configuration overrides applied to this component by its parent.
41    fn config_parent_overrides(&self) -> Option<&[cm_rust::ConfigOverride]>;
42
43    /// Returns the `GlobalPolicyChecker` for this component instance.
44    fn policy_checker(&self) -> &GlobalPolicyChecker;
45
46    /// Returns the component ID index for this component instance.
47    fn component_id_index(&self) -> &component_id_index::Index;
48
49    /// Gets the parent, if it still exists, or returns an `InstanceNotFound` error.
50    fn try_get_parent(&self) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError>;
51
52    /// Returns a clone of this component's sandbox. This may resolve the component if necessary.
53    async fn component_sandbox(
54        self: &Arc<Self>,
55    ) -> Result<ComponentSandbox, ComponentInstanceError>;
56
57    /// Returns a live child of this instance. This may resolve the component if necessary.
58    async fn get_child_maybe_resolve(
59        self: &Arc<Self>,
60        moniker: &BorrowedChildName,
61    ) -> Result<Option<Arc<Self>>, ComponentInstanceError>;
62
63    /// Returns the resolver-ready location of the component, which is either
64    /// an absolute component URL or a relative path URL with context. This may
65    /// resolve the component if necessary.
66    async fn address_maybe_resolve(self: &Arc<Self>) -> Result<ComponentAddress, ResolverError>;
67
68    /// Returns the context to be used to resolve a component from a path
69    /// relative to this component (for example, a component in a subpackage).
70    /// If `None`, the resolver cannot resolve relative path component URLs.
71    /// This may resolve the component if necessary.
72    async fn context_to_resolve_children(
73        self: &Arc<Self>,
74    ) -> Result<Option<ComponentResolutionContext>, ComponentInstanceError>;
75
76    /// Attempts to walk the component tree (up and/or down) from the current component to find the
77    /// extended instance represented by the given extended moniker. Intermediate components will
78    /// be resolved as needed. Functionally this calls into `find_absolute` or `find_above_root`
79    /// depending on the extended moniker.
80    async fn find_extended_instance(
81        self: &Arc<Self>,
82        moniker: &ExtendedMoniker,
83    ) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError> {
84        match moniker {
85            ExtendedMoniker::ComponentInstance(moniker) => {
86                Ok(ExtendedInstanceInterface::Component(self.find_absolute(moniker).await?))
87            }
88            ExtendedMoniker::ComponentManager => {
89                Ok(ExtendedInstanceInterface::AboveRoot(self.find_above_root()?))
90            }
91        }
92    }
93
94    /// Attempts to walk the component tree (up and/or down) from the current component to find the
95    /// component instance represented by the given moniker. Intermediate components will be
96    /// resolved as needed.
97    async fn find_absolute(
98        self: &Arc<Self>,
99        target_moniker: &Moniker,
100    ) -> Result<Arc<Self>, ComponentInstanceError> {
101        let mut current = self.clone();
102        while !target_moniker.has_prefix(current.moniker()) {
103            match current.try_get_parent()? {
104                ExtendedInstanceInterface::AboveRoot(_) => panic!(
105                    "the current component ({}) must be root, but it's not a prefix for {}",
106                    current.moniker(),
107                    target_moniker
108                ),
109                ExtendedInstanceInterface::Component(parent) => current = parent,
110            }
111        }
112        while current.moniker() != target_moniker {
113            let remaining_path = target_moniker.strip_prefix(current.moniker()).expect(
114                "previous loop will only exit when current.moniker() is a prefix of target_moniker",
115            );
116            for moniker_part in remaining_path.path() {
117                let child = current.get_child_maybe_resolve(moniker_part).await?.ok_or(
118                    ComponentInstanceError::InstanceNotFound {
119                        moniker: current.moniker().child(moniker_part.into()),
120                    },
121                )?;
122                current = child;
123            }
124        }
125        Ok(current)
126    }
127
128    /// Attempts to walk the component tree up to the above root instance. Intermediate components
129    /// will be resolved as needed.
130    fn find_above_root(self: &Arc<Self>) -> Result<Arc<Self::TopInstance>, ComponentInstanceError> {
131        let mut current = self.clone();
132        loop {
133            match current.try_get_parent()? {
134                ExtendedInstanceInterface::AboveRoot(top_instance) => return Ok(top_instance),
135                ExtendedInstanceInterface::Component(parent) => current = parent,
136            }
137        }
138    }
139}
140
141/// A wrapper for a weak reference to a type implementing `ComponentInstanceInterface`. Provides the
142/// moniker of the component instance, which is useful for error reporting if the original
143/// component instance has been destroyed.
144#[derive(Derivative)]
145#[derivative(Clone(bound = ""), Default(bound = ""), Debug)]
146pub struct WeakComponentInstanceInterface<C: ComponentInstanceInterface> {
147    #[derivative(Debug = "ignore")]
148    inner: Weak<C>,
149    pub moniker: Moniker,
150}
151
152impl<C: ComponentInstanceInterface> WeakComponentInstanceInterface<C> {
153    pub fn new(component: &Arc<C>) -> Self {
154        Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
155    }
156
157    /// Returns a new weak component instance that will always fail to upgrade.
158    pub fn invalid() -> Self {
159        Self { inner: Weak::new(), moniker: Moniker::new(&[]) }
160    }
161
162    /// Attempts to upgrade this `WeakComponentInterface<C>` into an `Arc<C>`, if the
163    /// original component instance interface `C` has not been destroyed.
164    pub fn upgrade(&self) -> Result<Arc<C>, ComponentInstanceError> {
165        self.inner
166            .upgrade()
167            .ok_or_else(|| ComponentInstanceError::instance_not_found(self.moniker.clone()))
168    }
169}
170
171impl<C: ComponentInstanceInterface> From<&Arc<C>> for WeakComponentInstanceInterface<C> {
172    fn from(component: &Arc<C>) -> Self {
173        Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
174    }
175}
176
177impl<C: ComponentInstanceInterface + 'static> TryFrom<Arc<WeakInstanceToken>>
178    for WeakComponentInstanceInterface<C>
179{
180    type Error = ();
181
182    fn try_from(
183        weak_component_token: Arc<WeakInstanceToken>,
184    ) -> Result<WeakComponentInstanceInterface<C>, Self::Error> {
185        let weak_extended: WeakExtendedInstanceInterface<C> = weak_component_token.try_into()?;
186        match weak_extended {
187            WeakExtendedInstanceInterface::Component(weak_component) => Ok(weak_component),
188            WeakExtendedInstanceInterface::AboveRoot(_) => Err(()),
189        }
190    }
191}
192
193impl<C: ComponentInstanceInterface + 'static> PartialEq for WeakComponentInstanceInterface<C> {
194    fn eq(&self, other: &Self) -> bool {
195        self.inner.ptr_eq(&other.inner) && self.moniker == other.moniker
196    }
197}
198
199/// Either a type implementing `ComponentInstanceInterface` or its `TopInstance`.
200#[derive(Debug, Clone)]
201pub enum ExtendedInstanceInterface<C: ComponentInstanceInterface> {
202    Component(Arc<C>),
203    AboveRoot(Arc<C::TopInstance>),
204}
205
206/// A type implementing `ComponentInstanceInterface` or its `TopInstance`, as a weak pointer.
207#[derive(Derivative)]
208#[derivative(Clone(bound = ""), Debug(bound = ""))]
209pub enum WeakExtendedInstanceInterface<C: ComponentInstanceInterface> {
210    Component(WeakComponentInstanceInterface<C>),
211    AboveRoot(Weak<C::TopInstance>),
212}
213
214impl<C: ComponentInstanceInterface + 'static> WeakInstanceTokenAny
215    for WeakExtendedInstanceInterface<C>
216{
217    fn as_any(&self) -> &dyn std::any::Any {
218        self
219    }
220}
221
222impl<C: ComponentInstanceInterface> WeakExtendedInstanceInterface<C> {
223    /// Attempts to upgrade this `WeakExtendedInstanceInterface<C>` into an
224    /// `ExtendedInstanceInterface<C>`, if the original extended instance has not been destroyed.
225    pub fn upgrade(&self) -> Result<ExtendedInstanceInterface<C>, ComponentInstanceError> {
226        match self {
227            WeakExtendedInstanceInterface::Component(p) => {
228                Ok(ExtendedInstanceInterface::Component(p.upgrade()?))
229            }
230            WeakExtendedInstanceInterface::AboveRoot(p) => {
231                Ok(ExtendedInstanceInterface::AboveRoot(
232                    p.upgrade().ok_or_else(ComponentInstanceError::cm_instance_unavailable)?,
233                ))
234            }
235        }
236    }
237
238    pub fn extended_moniker(&self) -> ExtendedMoniker {
239        match self {
240            Self::Component(p) => ExtendedMoniker::ComponentInstance(p.moniker.clone()),
241            Self::AboveRoot(_) => ExtendedMoniker::ComponentManager,
242        }
243    }
244}
245
246impl<C: ComponentInstanceInterface> From<&ExtendedInstanceInterface<C>>
247    for WeakExtendedInstanceInterface<C>
248{
249    fn from(extended: &ExtendedInstanceInterface<C>) -> Self {
250        match extended {
251            ExtendedInstanceInterface::Component(component) => {
252                WeakExtendedInstanceInterface::Component(WeakComponentInstanceInterface::new(
253                    component,
254                ))
255            }
256            ExtendedInstanceInterface::AboveRoot(top_instance) => {
257                WeakExtendedInstanceInterface::AboveRoot(Arc::downgrade(top_instance))
258            }
259        }
260    }
261}
262
263impl<C: ComponentInstanceInterface + 'static> TryFrom<Arc<WeakInstanceToken>>
264    for WeakExtendedInstanceInterface<C>
265{
266    type Error = ();
267
268    fn try_from(
269        weak_component_token: Arc<WeakInstanceToken>,
270    ) -> Result<WeakExtendedInstanceInterface<C>, Self::Error> {
271        weak_component_token
272            .inner
273            .as_any()
274            .downcast_ref::<WeakExtendedInstanceInterface<C>>()
275            .cloned()
276            .ok_or(())
277    }
278}
279
280/// A special instance identified with the top of the tree, i.e. component manager's instance.
281pub trait TopInstanceInterface: Sized + std::fmt::Debug {
282    fn namespace_capabilities(&self) -> &NamespaceCapabilities;
283
284    fn builtin_capabilities(&self) -> &BuiltinCapabilities;
285}
286
287#[cfg(test)]
288pub mod tests {
289    use super::*;
290    use crate::bedrock::sandbox_construction::ComponentSandbox;
291
292    #[derive(Debug)]
293    pub struct TestTopInstance {}
294
295    impl TopInstanceInterface for TestTopInstance {
296        fn namespace_capabilities(&self) -> &NamespaceCapabilities {
297            todo!()
298        }
299
300        fn builtin_capabilities(&self) -> &BuiltinCapabilities {
301            todo!()
302        }
303    }
304
305    pub struct TestComponent {}
306
307    #[async_trait]
308    impl ComponentInstanceInterface for TestComponent {
309        type TopInstance = TestTopInstance;
310
311        fn child_moniker(&self) -> Option<&BorrowedChildName> {
312            todo!()
313        }
314
315        fn moniker(&self) -> &Moniker {
316            todo!()
317        }
318
319        fn url(&self) -> &Url {
320            todo!()
321        }
322
323        fn config_parent_overrides(&self) -> Option<&[cm_rust::ConfigOverride]> {
324            todo!()
325        }
326
327        fn policy_checker(&self) -> &GlobalPolicyChecker {
328            todo!()
329        }
330
331        fn component_id_index(&self) -> &component_id_index::Index {
332            todo!()
333        }
334
335        fn try_get_parent(
336            &self,
337        ) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError> {
338            todo!()
339        }
340
341        async fn component_sandbox(
342            self: &Arc<Self>,
343        ) -> Result<ComponentSandbox, ComponentInstanceError> {
344            todo!()
345        }
346
347        async fn get_child_maybe_resolve(
348            self: &Arc<Self>,
349            _moniker: &BorrowedChildName,
350        ) -> Result<Option<Arc<Self>>, ComponentInstanceError> {
351            todo!()
352        }
353
354        async fn address_maybe_resolve(
355            self: &Arc<Self>,
356        ) -> Result<ComponentAddress, ResolverError> {
357            todo!()
358        }
359
360        async fn context_to_resolve_children(
361            self: &Arc<Self>,
362        ) -> Result<Option<ComponentResolutionContext>, ComponentInstanceError> {
363            todo!()
364        }
365    }
366}