settings/
service_context.rs

1// Copyright 2019 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::event::{Event, Publisher};
6use crate::message::base::MessengerType;
7use crate::service;
8use anyhow::Error;
9use fidl::endpoints::DiscoverableProtocolMarker;
10use futures::future::OptionFuture;
11use settings_common::service_context::{
12    EventPublisher, ExternalServiceEvent, ExternalServiceProxy as InnerExternalServiceProxy,
13    ServiceContext as InnerServiceContext,
14};
15use std::rc::Rc;
16
17#[cfg(test)]
18use settings_common::service_context::GenerateService;
19
20/// A wrapper around service operations, allowing redirection to a nested
21/// environment.
22pub struct ServiceContext {
23    inner: Rc<InnerServiceContext>,
24    delegate: Option<service::message::Delegate>,
25}
26
27impl ServiceContext {
28    #[cfg(test)]
29    pub(crate) fn new(
30        generate_service: Option<GenerateService>,
31        delegate: Option<service::message::Delegate>,
32    ) -> Self {
33        let inner = Rc::new(InnerServiceContext::new(generate_service));
34        Self { inner, delegate }
35    }
36
37    pub(crate) fn new_from_common(
38        inner: Rc<InnerServiceContext>,
39        delegate: Option<service::message::Delegate>,
40    ) -> Self {
41        Self { inner, delegate }
42    }
43
44    pub(crate) fn common_context(&self) -> Rc<InnerServiceContext> {
45        self.inner.clone()
46    }
47
48    async fn make_publisher(&self) -> Option<Publisher> {
49        let maybe: OptionFuture<_> = self
50            .delegate
51            .as_ref()
52            .map(|delegate| Publisher::create(delegate, MessengerType::Unbound))
53            .into();
54        maybe.await
55    }
56
57    /// Connect to a service with the given ProtocolMarker.
58    ///
59    /// If a GenerateService was specified at creation, the name of the service marker will be used
60    /// to generate a service.
61    pub(crate) async fn connect<P: DiscoverableProtocolMarker>(
62        &self,
63    ) -> Result<ExternalServiceProxy<P::Proxy>, Error> {
64        self.inner.connect::<P, Publisher, _>(|| self.make_publisher()).await
65    }
66
67    pub(crate) async fn connect_with_publisher<P: DiscoverableProtocolMarker>(
68        &self,
69        publisher: Publisher,
70    ) -> Result<ExternalServiceProxy<P::Proxy>, Error> {
71        self.inner.connect_with_publisher::<P, Publisher>(publisher).await
72    }
73}
74
75impl EventPublisher for Publisher {
76    fn send_event(&self, event: ExternalServiceEvent) {
77        Publisher::send_event(self, Event::ExternalServiceEvent(event))
78    }
79}
80
81pub(crate) type ExternalServiceProxy<P> = InnerExternalServiceProxy<P, Publisher>;