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