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