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::capability_source::{BuiltinCapabilities, NamespaceCapabilities};
7use crate::error::ComponentInstanceError;
8use crate::policy::GlobalPolicyChecker;
9use crate::resolving::{ComponentAddress, ComponentResolutionContext, ResolverError};
10use async_trait::async_trait;
11use cm_rust::{CapabilityDecl, CollectionDecl, ExposeDecl, OfferDecl, OfferSource, UseDecl};
12use cm_types::{Name, Url};
13use derivative::Derivative;
14use moniker::{BorrowedChildName, ChildName, ExtendedMoniker, Moniker};
15use sandbox::{WeakInstanceToken, WeakInstanceTokenAny};
16use std::clone::Clone;
17use std::sync::{Arc, Weak};
18
19/// A trait providing a representation of a component instance.
20#[async_trait]
21pub trait ComponentInstanceInterface: Sized + Send + Sync {
22    type TopInstance: TopInstanceInterface + Send + Sync;
23
24    /// Returns a new `WeakComponentInstanceInterface<Self>` pointing to `self`.
25    fn as_weak(self: &Arc<Self>) -> WeakComponentInstanceInterface<Self> {
26        WeakComponentInstanceInterface::new(self)
27    }
28
29    /// Returns this `ComponentInstanceInterface`'s child moniker, if it is
30    /// not the root instance.
31    fn child_moniker(&self) -> Option<&BorrowedChildName> {
32        self.moniker().leaf()
33    }
34
35    /// Returns this `ComponentInstanceInterface`'s moniker.
36    fn moniker(&self) -> &Moniker;
37
38    /// Returns this `ComponentInstanceInterface`'s component URL.
39    fn url(&self) -> &Url;
40
41    /// Returns configuration overrides applied to this component by its parent.
42    fn config_parent_overrides(&self) -> Option<&[cm_rust::ConfigOverride]>;
43
44    /// Returns the `GlobalPolicyChecker` for this component instance.
45    fn policy_checker(&self) -> &GlobalPolicyChecker;
46
47    /// Returns the component ID index for this component instance.
48    fn component_id_index(&self) -> &component_id_index::Index;
49
50    /// Gets the parent, if it still exists, or returns an `InstanceNotFound` error.
51    fn try_get_parent(&self) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError>;
52
53    /// Locks and returns a lazily-resolved and populated
54    /// `ResolvedInstanceInterface`.  Returns an `InstanceNotFound` error if the
55    /// instance is destroyed. The instance will remain locked until the result
56    /// is dropped.
57    ///
58    /// NOTE: The `Box<dyn>` in the return type is necessary, because the type
59    /// of the result depends on the lifetime of the `self` reference. The
60    /// proposed "generic associated types" feature would let us define this
61    /// statically.
62    async fn lock_resolved_state<'a>(
63        self: &'a Arc<Self>,
64    ) -> Result<Box<dyn ResolvedInstanceInterface<Component = Self> + 'a>, ComponentInstanceError>;
65
66    /// Returns a clone of this component's sandbox. This may resolve the component if necessary.
67    async fn component_sandbox(
68        self: &Arc<Self>,
69    ) -> Result<ComponentSandbox, ComponentInstanceError>;
70
71    /// Attempts to walk the component tree (up and/or down) from the current component to find the
72    /// extended instance represented by the given extended moniker. Intermediate components will
73    /// be resolved as needed. Functionally this calls into `find_absolute` or `find_above_root`
74    /// depending on the extended moniker.
75    async fn find_extended_instance(
76        self: &Arc<Self>,
77        moniker: &ExtendedMoniker,
78    ) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError> {
79        match moniker {
80            ExtendedMoniker::ComponentInstance(moniker) => {
81                Ok(ExtendedInstanceInterface::Component(self.find_absolute(moniker).await?))
82            }
83            ExtendedMoniker::ComponentManager => {
84                Ok(ExtendedInstanceInterface::AboveRoot(self.find_above_root()?))
85            }
86        }
87    }
88
89    /// Attempts to walk the component tree (up and/or down) from the current component to find the
90    /// component instance represented by the given moniker. Intermediate components will be
91    /// resolved as needed.
92    async fn find_absolute(
93        self: &Arc<Self>,
94        target_moniker: &Moniker,
95    ) -> Result<Arc<Self>, ComponentInstanceError> {
96        let mut current = self.clone();
97        while !target_moniker.has_prefix(current.moniker()) {
98            match current.try_get_parent()? {
99                ExtendedInstanceInterface::AboveRoot(_) => panic!(
100                    "the current component ({}) must be root, but it's not a prefix for {}",
101                    current.moniker(),
102                    &target_moniker
103                ),
104                ExtendedInstanceInterface::Component(parent) => current = parent,
105            }
106        }
107        while current.moniker() != target_moniker {
108            let remaining_path = target_moniker.strip_prefix(current.moniker()).expect(
109                "previous loop will only exit when current.moniker() is a prefix of target_moniker",
110            );
111            for moniker_part in remaining_path.path() {
112                let child = current.lock_resolved_state().await?.get_child(moniker_part).ok_or(
113                    ComponentInstanceError::InstanceNotFound {
114                        moniker: current.moniker().child(moniker_part.into()),
115                    },
116                )?;
117                current = child;
118            }
119        }
120        Ok(current)
121    }
122
123    /// Attempts to walk the component tree up to the above root instance. Intermediate components
124    /// will be resolved as needed.
125    fn find_above_root(self: &Arc<Self>) -> Result<Arc<Self::TopInstance>, ComponentInstanceError> {
126        let mut current = self.clone();
127        loop {
128            match current.try_get_parent()? {
129                ExtendedInstanceInterface::AboveRoot(top_instance) => return Ok(top_instance),
130                ExtendedInstanceInterface::Component(parent) => current = parent,
131            }
132        }
133    }
134}
135
136/// A trait providing a representation of a resolved component instance.
137#[async_trait]
138pub trait ResolvedInstanceInterface: Send + Sync {
139    /// Type representing a (unlocked and potentially unresolved) component instance.
140    type Component;
141
142    /// Current view of this component's `uses` declarations.
143    fn uses(&self) -> Box<[UseDecl]>;
144
145    /// Current view of this component's `exposes` declarations.
146    fn exposes(&self) -> Box<[ExposeDecl]>;
147
148    /// Current view of this component's `offers` declarations. Does not include any dynamic
149    /// offers between children of this component.
150    fn offers(&self) -> Box<[OfferDecl]>;
151
152    /// Current view of this component's `capabilities` declarations.
153    fn capabilities(&self) -> Box<[CapabilityDecl]>;
154
155    /// Current view of this component's `collections` declarations.
156    fn collections(&self) -> Box<[CollectionDecl]>;
157
158    /// Returns a live child of this instance.
159    fn get_child(&self, moniker: &BorrowedChildName) -> Option<Arc<Self::Component>>;
160
161    /// Returns a vector of the live children in `collection`.
162    fn children_in_collection(&self, collection: &Name) -> Vec<(ChildName, Arc<Self::Component>)>;
163
164    /// Returns the resolver-ready location of the component, which is either
165    /// an absolute component URL or a relative path URL with context.
166    async fn address(&self) -> Result<ComponentAddress, ResolverError>;
167
168    /// Returns the context to be used to resolve a component from a path
169    /// relative to this component (for example, a component in a subpackage).
170    /// If `None`, the resolver cannot resolve relative path component URLs.
171    fn context_to_resolve_children(&self) -> Option<ComponentResolutionContext>;
172}
173
174/// An extension trait providing functionality for any model of a resolved
175/// component.
176pub trait ResolvedInstanceInterfaceExt: ResolvedInstanceInterface {
177    /// Returns true if the given offer source refers to a valid entity, e.g., a
178    /// child that exists, a declared collection, etc.
179    fn offer_source_exists(&self, source: &OfferSource) -> bool {
180        match source {
181            OfferSource::Framework
182            | OfferSource::Self_
183            | OfferSource::Parent
184            | OfferSource::Void => true,
185            OfferSource::Child(cm_rust::ChildRef { name, collection }) => {
186                let child_moniker = match ChildName::try_new(
187                    name.as_str(),
188                    collection.as_ref().map(|c| c.as_str()),
189                ) {
190                    Ok(m) => m,
191                    Err(_) => return false,
192                };
193                self.get_child(&child_moniker).is_some()
194            }
195            OfferSource::Collection(collection_name) => IntoIterator::into_iter(self.collections())
196                .any(|collection| collection.name == *collection_name),
197            OfferSource::Capability(capability_name) => {
198                IntoIterator::into_iter(self.capabilities())
199                    .any(|capability| capability.name() == capability_name)
200            }
201        }
202    }
203}
204
205impl<T: ResolvedInstanceInterface> ResolvedInstanceInterfaceExt for T {}
206
207// Elsewhere we need to implement `ResolvedInstanceInterface` for `&T` and
208// `MappedMutexGuard<_, _, T>`, where `T : ResolvedComponentInstance`. We can't
209// implement the latter outside of this crate because of the "orphan rule". So
210// here we implement it for all `Deref`s.
211#[async_trait]
212impl<T> ResolvedInstanceInterface for T
213where
214    T: std::ops::Deref + Send + Sync,
215    T::Target: ResolvedInstanceInterface,
216{
217    type Component = <T::Target as ResolvedInstanceInterface>::Component;
218
219    fn uses(&self) -> Box<[UseDecl]> {
220        T::Target::uses(&*self)
221    }
222
223    fn exposes(&self) -> Box<[ExposeDecl]> {
224        T::Target::exposes(&*self)
225    }
226
227    fn offers(&self) -> Box<[cm_rust::OfferDecl]> {
228        T::Target::offers(&*self)
229    }
230
231    fn capabilities(&self) -> Box<[cm_rust::CapabilityDecl]> {
232        T::Target::capabilities(&*self)
233    }
234
235    fn collections(&self) -> Box<[cm_rust::CollectionDecl]> {
236        T::Target::collections(&*self)
237    }
238
239    fn get_child(&self, moniker: &BorrowedChildName) -> Option<Arc<Self::Component>> {
240        T::Target::get_child(&*self, moniker)
241    }
242
243    fn children_in_collection(&self, collection: &Name) -> Vec<(ChildName, Arc<Self::Component>)> {
244        T::Target::children_in_collection(&*self, collection)
245    }
246
247    async fn address(&self) -> Result<ComponentAddress, ResolverError> {
248        T::Target::address(&*self).await
249    }
250
251    fn context_to_resolve_children(&self) -> Option<ComponentResolutionContext> {
252        T::Target::context_to_resolve_children(&*self)
253    }
254}
255
256/// A wrapper for a weak reference to a type implementing `ComponentInstanceInterface`. Provides the
257/// moniker of the component instance, which is useful for error reporting if the original
258/// component instance has been destroyed.
259#[derive(Derivative)]
260#[derivative(Clone(bound = ""), Default(bound = ""), Debug)]
261pub struct WeakComponentInstanceInterface<C: ComponentInstanceInterface> {
262    #[derivative(Debug = "ignore")]
263    inner: Weak<C>,
264    pub moniker: Moniker,
265}
266
267impl<C: ComponentInstanceInterface> WeakComponentInstanceInterface<C> {
268    pub fn new(component: &Arc<C>) -> Self {
269        Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
270    }
271
272    /// Returns a new weak component instance that will always fail to upgrade.
273    pub fn invalid() -> Self {
274        Self { inner: Weak::new(), moniker: Moniker::new(&[]) }
275    }
276
277    /// Attempts to upgrade this `WeakComponentInterface<C>` into an `Arc<C>`, if the
278    /// original component instance interface `C` has not been destroyed.
279    pub fn upgrade(&self) -> Result<Arc<C>, ComponentInstanceError> {
280        self.inner
281            .upgrade()
282            .ok_or_else(|| ComponentInstanceError::instance_not_found(self.moniker.clone()))
283    }
284}
285
286impl<C: ComponentInstanceInterface> From<&Arc<C>> for WeakComponentInstanceInterface<C> {
287    fn from(component: &Arc<C>) -> Self {
288        Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
289    }
290}
291
292impl<C: ComponentInstanceInterface + 'static> TryFrom<WeakInstanceToken>
293    for WeakComponentInstanceInterface<C>
294{
295    type Error = ();
296
297    fn try_from(
298        weak_component_token: WeakInstanceToken,
299    ) -> Result<WeakComponentInstanceInterface<C>, Self::Error> {
300        let weak_extended: WeakExtendedInstanceInterface<C> = weak_component_token.try_into()?;
301        match weak_extended {
302            WeakExtendedInstanceInterface::Component(weak_component) => Ok(weak_component),
303            WeakExtendedInstanceInterface::AboveRoot(_) => Err(()),
304        }
305    }
306}
307
308impl<C: ComponentInstanceInterface + 'static> PartialEq for WeakComponentInstanceInterface<C> {
309    fn eq(&self, other: &Self) -> bool {
310        self.inner.ptr_eq(&other.inner) && self.moniker == other.moniker
311    }
312}
313
314/// Either a type implementing `ComponentInstanceInterface` or its `TopInstance`.
315#[derive(Debug, Clone)]
316pub enum ExtendedInstanceInterface<C: ComponentInstanceInterface> {
317    Component(Arc<C>),
318    AboveRoot(Arc<C::TopInstance>),
319}
320
321/// A type implementing `ComponentInstanceInterface` or its `TopInstance`, as a weak pointer.
322#[derive(Derivative)]
323#[derivative(Clone(bound = ""), Debug(bound = ""))]
324pub enum WeakExtendedInstanceInterface<C: ComponentInstanceInterface> {
325    Component(WeakComponentInstanceInterface<C>),
326    AboveRoot(Weak<C::TopInstance>),
327}
328
329impl<C: ComponentInstanceInterface + 'static> WeakInstanceTokenAny
330    for WeakExtendedInstanceInterface<C>
331{
332    fn as_any(&self) -> &dyn std::any::Any {
333        self
334    }
335}
336
337impl<C: ComponentInstanceInterface> WeakExtendedInstanceInterface<C> {
338    /// Attempts to upgrade this `WeakExtendedInstanceInterface<C>` into an
339    /// `ExtendedInstanceInterface<C>`, if the original extended instance has not been destroyed.
340    pub fn upgrade(&self) -> Result<ExtendedInstanceInterface<C>, ComponentInstanceError> {
341        match self {
342            WeakExtendedInstanceInterface::Component(p) => {
343                Ok(ExtendedInstanceInterface::Component(p.upgrade()?))
344            }
345            WeakExtendedInstanceInterface::AboveRoot(p) => {
346                Ok(ExtendedInstanceInterface::AboveRoot(
347                    p.upgrade().ok_or_else(ComponentInstanceError::cm_instance_unavailable)?,
348                ))
349            }
350        }
351    }
352
353    pub fn extended_moniker(&self) -> ExtendedMoniker {
354        match self {
355            Self::Component(p) => ExtendedMoniker::ComponentInstance(p.moniker.clone()),
356            Self::AboveRoot(_) => ExtendedMoniker::ComponentManager,
357        }
358    }
359}
360
361impl<C: ComponentInstanceInterface> From<&ExtendedInstanceInterface<C>>
362    for WeakExtendedInstanceInterface<C>
363{
364    fn from(extended: &ExtendedInstanceInterface<C>) -> Self {
365        match extended {
366            ExtendedInstanceInterface::Component(component) => {
367                WeakExtendedInstanceInterface::Component(WeakComponentInstanceInterface::new(
368                    component,
369                ))
370            }
371            ExtendedInstanceInterface::AboveRoot(top_instance) => {
372                WeakExtendedInstanceInterface::AboveRoot(Arc::downgrade(top_instance))
373            }
374        }
375    }
376}
377
378impl<C: ComponentInstanceInterface + 'static> TryFrom<WeakInstanceToken>
379    for WeakExtendedInstanceInterface<C>
380{
381    type Error = ();
382
383    fn try_from(
384        weak_component_token: WeakInstanceToken,
385    ) -> Result<WeakExtendedInstanceInterface<C>, Self::Error> {
386        weak_component_token
387            .inner
388            .as_any()
389            .downcast_ref::<WeakExtendedInstanceInterface<C>>()
390            .cloned()
391            .ok_or(())
392    }
393}
394
395/// A special instance identified with the top of the tree, i.e. component manager's instance.
396pub trait TopInstanceInterface: Sized + std::fmt::Debug {
397    fn namespace_capabilities(&self) -> &NamespaceCapabilities;
398
399    fn builtin_capabilities(&self) -> &BuiltinCapabilities;
400}
401
402#[cfg(test)]
403pub mod tests {
404    use super::*;
405    use crate::bedrock::sandbox_construction::ComponentSandbox;
406
407    #[derive(Debug)]
408    pub struct TestTopInstance {}
409
410    impl TopInstanceInterface for TestTopInstance {
411        fn namespace_capabilities(&self) -> &NamespaceCapabilities {
412            todo!()
413        }
414
415        fn builtin_capabilities(&self) -> &BuiltinCapabilities {
416            todo!()
417        }
418    }
419
420    pub struct TestComponent {}
421
422    #[async_trait]
423    impl ComponentInstanceInterface for TestComponent {
424        type TopInstance = TestTopInstance;
425
426        fn child_moniker(&self) -> Option<&BorrowedChildName> {
427            todo!()
428        }
429
430        fn moniker(&self) -> &Moniker {
431            todo!()
432        }
433
434        fn url(&self) -> &Url {
435            todo!()
436        }
437
438        fn config_parent_overrides(&self) -> Option<&[cm_rust::ConfigOverride]> {
439            todo!()
440        }
441
442        fn policy_checker(&self) -> &GlobalPolicyChecker {
443            todo!()
444        }
445
446        fn component_id_index(&self) -> &component_id_index::Index {
447            todo!()
448        }
449
450        fn try_get_parent(
451            &self,
452        ) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError> {
453            todo!()
454        }
455
456        async fn lock_resolved_state<'a>(
457            self: &'a Arc<Self>,
458        ) -> Result<Box<dyn ResolvedInstanceInterface<Component = Self> + 'a>, ComponentInstanceError>
459        {
460            todo!()
461        }
462
463        async fn component_sandbox(
464            self: &Arc<Self>,
465        ) -> Result<ComponentSandbox, ComponentInstanceError> {
466            todo!()
467        }
468    }
469}