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::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::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 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        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.
144    fn uses(&self) -> Box<[UseDecl]>;
145
146    /// Current view of this component's `exposes` declarations.
147    fn exposes(&self) -> Box<[ExposeDecl]>;
148
149    /// Current view of this component's `offers` declarations. Does not include any dynamic
150    /// offers between children of this component.
151    fn offers(&self) -> Box<[OfferDecl]>;
152
153    /// Current view of this component's `capabilities` declarations.
154    fn capabilities(&self) -> Box<[CapabilityDecl]>;
155
156    /// Current view of this component's `collections` declarations.
157    fn collections(&self) -> Box<[CollectionDecl]>;
158
159    /// Returns a live child of this instance.
160    fn get_child(&self, moniker: &BorrowedChildName) -> Option<Arc<Self::Component>>;
161
162    /// Returns a vector of the live children in `collection`.
163    fn children_in_collection(&self, collection: &Name) -> Vec<(ChildName, Arc<Self::Component>)>;
164
165    /// Returns the resolver-ready location of the component, which is either
166    /// an absolute component URL or a relative path URL with context.
167    async fn address(&self) -> Result<ComponentAddress, ResolverError>;
168
169    /// Returns the context to be used to resolve a component from a path
170    /// relative to this component (for example, a component in a subpackage).
171    /// If `None`, the resolver cannot resolve relative path component URLs.
172    fn context_to_resolve_children(&self) -> Option<ComponentResolutionContext>;
173}
174
175/// An extension trait providing functionality for any model of a resolved
176/// component.
177pub trait ResolvedInstanceInterfaceExt: ResolvedInstanceInterface {
178    /// Returns true if the given offer source refers to a valid entity, e.g., a
179    /// child that exists, a declared collection, etc.
180    fn offer_source_exists(&self, source: &OfferSource) -> bool {
181        match source {
182            OfferSource::Framework
183            | OfferSource::Self_
184            | OfferSource::Parent
185            | OfferSource::Void => true,
186            OfferSource::Child(cm_rust::ChildRef { name, collection }) => {
187                let child_moniker = match ChildName::try_new(
188                    name.as_str(),
189                    collection.as_ref().map(|c| c.as_str()),
190                ) {
191                    Ok(m) => m,
192                    Err(_) => return false,
193                };
194                self.get_child(&child_moniker).is_some()
195            }
196            OfferSource::Collection(collection_name) => IntoIterator::into_iter(self.collections())
197                .any(|collection| collection.name == *collection_name),
198            OfferSource::Capability(capability_name) => {
199                IntoIterator::into_iter(self.capabilities())
200                    .any(|capability| capability.name() == capability_name)
201            }
202        }
203    }
204}
205
206impl<T: ResolvedInstanceInterface> ResolvedInstanceInterfaceExt for T {}
207
208// Elsewhere we need to implement `ResolvedInstanceInterface` for `&T` and
209// `MappedMutexGuard<_, _, T>`, where `T : ResolvedComponentInstance`. We can't
210// implement the latter outside of this crate because of the "orphan rule". So
211// here we implement it for all `Deref`s.
212#[async_trait]
213impl<T> ResolvedInstanceInterface for T
214where
215    T: std::ops::Deref + Send + Sync,
216    T::Target: ResolvedInstanceInterface,
217{
218    type Component = <T::Target as ResolvedInstanceInterface>::Component;
219
220    fn uses(&self) -> Box<[UseDecl]> {
221        T::Target::uses(&*self)
222    }
223
224    fn exposes(&self) -> Box<[ExposeDecl]> {
225        T::Target::exposes(&*self)
226    }
227
228    fn offers(&self) -> Box<[cm_rust::offer::OfferDecl]> {
229        T::Target::offers(&*self)
230    }
231
232    fn capabilities(&self) -> Box<[cm_rust::CapabilityDecl]> {
233        T::Target::capabilities(&*self)
234    }
235
236    fn collections(&self) -> Box<[cm_rust::CollectionDecl]> {
237        T::Target::collections(&*self)
238    }
239
240    fn get_child(&self, moniker: &BorrowedChildName) -> Option<Arc<Self::Component>> {
241        T::Target::get_child(&*self, moniker)
242    }
243
244    fn children_in_collection(&self, collection: &Name) -> Vec<(ChildName, Arc<Self::Component>)> {
245        T::Target::children_in_collection(&*self, collection)
246    }
247
248    async fn address(&self) -> Result<ComponentAddress, ResolverError> {
249        T::Target::address(&*self).await
250    }
251
252    fn context_to_resolve_children(&self) -> Option<ComponentResolutionContext> {
253        T::Target::context_to_resolve_children(&*self)
254    }
255}
256
257/// A wrapper for a weak reference to a type implementing `ComponentInstanceInterface`. Provides the
258/// moniker of the component instance, which is useful for error reporting if the original
259/// component instance has been destroyed.
260#[derive(Derivative)]
261#[derivative(Clone(bound = ""), Default(bound = ""), Debug)]
262pub struct WeakComponentInstanceInterface<C: ComponentInstanceInterface> {
263    #[derivative(Debug = "ignore")]
264    inner: Weak<C>,
265    pub moniker: Moniker,
266}
267
268impl<C: ComponentInstanceInterface> WeakComponentInstanceInterface<C> {
269    pub fn new(component: &Arc<C>) -> Self {
270        Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
271    }
272
273    /// Returns a new weak component instance that will always fail to upgrade.
274    pub fn invalid() -> Self {
275        Self { inner: Weak::new(), moniker: Moniker::new(&[]) }
276    }
277
278    /// Attempts to upgrade this `WeakComponentInterface<C>` into an `Arc<C>`, if the
279    /// original component instance interface `C` has not been destroyed.
280    pub fn upgrade(&self) -> Result<Arc<C>, ComponentInstanceError> {
281        self.inner
282            .upgrade()
283            .ok_or_else(|| ComponentInstanceError::instance_not_found(self.moniker.clone()))
284    }
285}
286
287impl<C: ComponentInstanceInterface> From<&Arc<C>> for WeakComponentInstanceInterface<C> {
288    fn from(component: &Arc<C>) -> Self {
289        Self { inner: Arc::downgrade(component), moniker: component.moniker().clone() }
290    }
291}
292
293impl<C: ComponentInstanceInterface + 'static> TryFrom<WeakInstanceToken>
294    for WeakComponentInstanceInterface<C>
295{
296    type Error = ();
297
298    fn try_from(
299        weak_component_token: WeakInstanceToken,
300    ) -> Result<WeakComponentInstanceInterface<C>, Self::Error> {
301        let weak_extended: WeakExtendedInstanceInterface<C> = weak_component_token.try_into()?;
302        match weak_extended {
303            WeakExtendedInstanceInterface::Component(weak_component) => Ok(weak_component),
304            WeakExtendedInstanceInterface::AboveRoot(_) => Err(()),
305        }
306    }
307}
308
309impl<C: ComponentInstanceInterface + 'static> PartialEq for WeakComponentInstanceInterface<C> {
310    fn eq(&self, other: &Self) -> bool {
311        self.inner.ptr_eq(&other.inner) && self.moniker == other.moniker
312    }
313}
314
315/// Either a type implementing `ComponentInstanceInterface` or its `TopInstance`.
316#[derive(Debug, Clone)]
317pub enum ExtendedInstanceInterface<C: ComponentInstanceInterface> {
318    Component(Arc<C>),
319    AboveRoot(Arc<C::TopInstance>),
320}
321
322/// A type implementing `ComponentInstanceInterface` or its `TopInstance`, as a weak pointer.
323#[derive(Derivative)]
324#[derivative(Clone(bound = ""), Debug(bound = ""))]
325pub enum WeakExtendedInstanceInterface<C: ComponentInstanceInterface> {
326    Component(WeakComponentInstanceInterface<C>),
327    AboveRoot(Weak<C::TopInstance>),
328}
329
330impl<C: ComponentInstanceInterface + 'static> WeakInstanceTokenAny
331    for WeakExtendedInstanceInterface<C>
332{
333    fn as_any(&self) -> &dyn std::any::Any {
334        self
335    }
336}
337
338impl<C: ComponentInstanceInterface> WeakExtendedInstanceInterface<C> {
339    /// Attempts to upgrade this `WeakExtendedInstanceInterface<C>` into an
340    /// `ExtendedInstanceInterface<C>`, if the original extended instance has not been destroyed.
341    pub fn upgrade(&self) -> Result<ExtendedInstanceInterface<C>, ComponentInstanceError> {
342        match self {
343            WeakExtendedInstanceInterface::Component(p) => {
344                Ok(ExtendedInstanceInterface::Component(p.upgrade()?))
345            }
346            WeakExtendedInstanceInterface::AboveRoot(p) => {
347                Ok(ExtendedInstanceInterface::AboveRoot(
348                    p.upgrade().ok_or_else(ComponentInstanceError::cm_instance_unavailable)?,
349                ))
350            }
351        }
352    }
353
354    pub fn extended_moniker(&self) -> ExtendedMoniker {
355        match self {
356            Self::Component(p) => ExtendedMoniker::ComponentInstance(p.moniker.clone()),
357            Self::AboveRoot(_) => ExtendedMoniker::ComponentManager,
358        }
359    }
360}
361
362impl<C: ComponentInstanceInterface> From<&ExtendedInstanceInterface<C>>
363    for WeakExtendedInstanceInterface<C>
364{
365    fn from(extended: &ExtendedInstanceInterface<C>) -> Self {
366        match extended {
367            ExtendedInstanceInterface::Component(component) => {
368                WeakExtendedInstanceInterface::Component(WeakComponentInstanceInterface::new(
369                    component,
370                ))
371            }
372            ExtendedInstanceInterface::AboveRoot(top_instance) => {
373                WeakExtendedInstanceInterface::AboveRoot(Arc::downgrade(top_instance))
374            }
375        }
376    }
377}
378
379impl<C: ComponentInstanceInterface + 'static> TryFrom<WeakInstanceToken>
380    for WeakExtendedInstanceInterface<C>
381{
382    type Error = ();
383
384    fn try_from(
385        weak_component_token: WeakInstanceToken,
386    ) -> Result<WeakExtendedInstanceInterface<C>, Self::Error> {
387        weak_component_token
388            .inner
389            .as_any()
390            .downcast_ref::<WeakExtendedInstanceInterface<C>>()
391            .cloned()
392            .ok_or(())
393    }
394}
395
396/// A special instance identified with the top of the tree, i.e. component manager's instance.
397pub trait TopInstanceInterface: Sized + std::fmt::Debug {
398    fn namespace_capabilities(&self) -> &NamespaceCapabilities;
399
400    fn builtin_capabilities(&self) -> &BuiltinCapabilities;
401}
402
403#[cfg(test)]
404pub mod tests {
405    use super::*;
406    use crate::bedrock::sandbox_construction::ComponentSandbox;
407
408    #[derive(Debug)]
409    pub struct TestTopInstance {}
410
411    impl TopInstanceInterface for TestTopInstance {
412        fn namespace_capabilities(&self) -> &NamespaceCapabilities {
413            todo!()
414        }
415
416        fn builtin_capabilities(&self) -> &BuiltinCapabilities {
417            todo!()
418        }
419    }
420
421    pub struct TestComponent {}
422
423    #[async_trait]
424    impl ComponentInstanceInterface for TestComponent {
425        type TopInstance = TestTopInstance;
426
427        fn child_moniker(&self) -> Option<&BorrowedChildName> {
428            todo!()
429        }
430
431        fn moniker(&self) -> &Moniker {
432            todo!()
433        }
434
435        fn url(&self) -> &Url {
436            todo!()
437        }
438
439        fn config_parent_overrides(&self) -> Option<&[cm_rust::ConfigOverride]> {
440            todo!()
441        }
442
443        fn policy_checker(&self) -> &GlobalPolicyChecker {
444            todo!()
445        }
446
447        fn component_id_index(&self) -> &component_id_index::Index {
448            todo!()
449        }
450
451        fn try_get_parent(
452            &self,
453        ) -> Result<ExtendedInstanceInterface<Self>, ComponentInstanceError> {
454            todo!()
455        }
456
457        async fn lock_resolved_state<'a>(
458            self: &'a Arc<Self>,
459        ) -> Result<Box<dyn ResolvedInstanceInterface<Component = Self> + 'a>, ComponentInstanceError>
460        {
461            todo!()
462        }
463
464        async fn component_sandbox(
465            self: &Arc<Self>,
466        ) -> Result<ComponentSandbox, ComponentInstanceError> {
467            todo!()
468        }
469    }
470}