settings/privacy/
privacy_fidl_handler.rs1use super::privacy_controller::{PrivacyController, PrivacyError, Request};
6use super::types::PrivacyInfo;
7use async_utils::hanging_get::server;
8use fidl_fuchsia_settings::{
9    Error as SettingsError, PrivacyRequest, PrivacyRequestStream, PrivacySettings,
10    PrivacyWatchResponder,
11};
12use fuchsia_async as fasync;
13use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
14use futures::channel::oneshot;
15use futures::StreamExt;
16use settings_common::inspect::event::{
17    RequestType, ResponseType, UsagePublisher, UsageResponsePublisher,
18};
19
20impl From<PrivacyInfo> for PrivacySettings {
21    fn from(info: PrivacyInfo) -> Self {
22        PrivacySettings {
23            user_data_sharing_consent: info.user_data_sharing_consent,
24            ..Default::default()
25        }
26    }
27}
28
29pub(super) type SubscriberObject = (UsageResponsePublisher<PrivacyInfo>, PrivacyWatchResponder);
30type HangingFn = fn(&PrivacyInfo, SubscriberObject) -> bool;
31pub(super) type HangingGet = server::HangingGet<PrivacyInfo, SubscriberObject, HangingFn>;
32pub(super) type Publisher = server::Publisher<PrivacyInfo, SubscriberObject, HangingFn>;
33pub(super) type Subscriber = server::Subscriber<PrivacyInfo, SubscriberObject, HangingFn>;
34
35pub struct PrivacyFidlHandler {
36    hanging_get: HangingGet,
37    controller_tx: UnboundedSender<Request>,
38    usage_publisher: UsagePublisher<PrivacyInfo>,
39}
40
41impl PrivacyFidlHandler {
42    pub(crate) fn new(
43        privacy_controller: &mut PrivacyController,
44        usage_publisher: UsagePublisher<PrivacyInfo>,
45        initial_value: PrivacyInfo,
46    ) -> (Self, UnboundedReceiver<Request>) {
47        let hanging_get = HangingGet::new(initial_value, PrivacyFidlHandler::hanging_get);
48        privacy_controller.register_publisher(hanging_get.new_publisher());
49        let (controller_tx, request_rx) = mpsc::unbounded();
50        (Self { hanging_get, controller_tx, usage_publisher }, request_rx)
51    }
52
53    fn hanging_get(info: &PrivacyInfo, (usage_responder, responder): SubscriberObject) -> bool {
54        usage_responder.respond(format!("{info:?}"), ResponseType::OkSome);
55        if let Err(e) = responder.send(&PrivacySettings::from(*info)) {
56            log::warn!("Failed to respond to watch request: {e:?}");
57            return false;
58        }
59        true
60    }
61
62    pub fn handle_stream(&mut self, mut stream: PrivacyRequestStream) {
63        let request_handler = RequestHandler {
64            subscriber: self.hanging_get.new_subscriber(),
65            controller_tx: self.controller_tx.clone(),
66            usage_publisher: self.usage_publisher.clone(),
67        };
68        fasync::Task::local(async move {
69            while let Some(Ok(request)) = stream.next().await {
70                request_handler.handle_request(request).await;
71            }
72        })
73        .detach();
74    }
75}
76
77#[derive(Debug)]
78enum HandlerError {
79    AlreadySubscribed,
80    ControllerStopped,
81    Controller(PrivacyError),
82}
83
84impl From<&HandlerError> for ResponseType {
85    fn from(error: &HandlerError) -> Self {
86        match error {
87            HandlerError::AlreadySubscribed => ResponseType::AlreadySubscribed,
88            HandlerError::ControllerStopped => ResponseType::UnexpectedError,
89            HandlerError::Controller(e) => ResponseType::from(e),
90        }
91    }
92}
93
94struct RequestHandler {
95    subscriber: Subscriber,
96    controller_tx: UnboundedSender<Request>,
97    usage_publisher: UsagePublisher<PrivacyInfo>,
98}
99
100impl RequestHandler {
101    async fn handle_request(&self, request: PrivacyRequest) {
102        match request {
103            PrivacyRequest::Watch { responder } => {
104                let usage_res = self.usage_publisher.request("Watch".to_string(), RequestType::Get);
105                if let Err((usage_res, responder)) =
106                    self.subscriber.register2((usage_res, responder))
107                {
108                    let e = HandlerError::AlreadySubscribed;
109                    usage_res.respond(format!("Err({e:?})"), ResponseType::from(&e));
110                    drop(responder);
111                }
112            }
113            PrivacyRequest::Set { settings, responder } => {
114                let usage_res = self
115                    .usage_publisher
116                    .request(format!("Set{{settings:{settings:?}}}"), RequestType::Set);
117                if let Err(e) = self.set(settings).await {
118                    usage_res.respond(format!("Err({e:?}"), ResponseType::from(&e));
119                    let _ = responder.send(Err(SettingsError::Failed));
120                } else {
121                    usage_res.respond("Ok(())".to_string(), ResponseType::OkNone);
122                    let _ = responder.send(Ok(()));
123                }
124            }
125        }
126    }
127
128    async fn set(&self, settings: PrivacySettings) -> Result<(), HandlerError> {
129        let (set_tx, set_rx) = oneshot::channel();
130        self.controller_tx
131            .unbounded_send(Request::Set(settings.user_data_sharing_consent, set_tx))
132            .map_err(|_| HandlerError::ControllerStopped)?;
133        set_rx
134            .await
135            .map_err(|_| HandlerError::ControllerStopped)
136            .and_then(|res| res.map_err(HandlerError::Controller))
137    }
138}