settings_privacy/
privacy_controller.rs1use crate::privacy_fidl_handler::Publisher;
6use crate::types::PrivacyInfo;
7use anyhow::Error;
8use fuchsia_async as fasync;
9use futures::StreamExt;
10use futures::channel::mpsc::UnboundedReceiver;
11use futures::channel::oneshot::Sender;
12use settings_common::inspect::event::{ResponseType, SettingValuePublisher};
13use settings_storage::UpdateState;
14use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
15use settings_storage::storage_factory::{NoneT, StorageAccess, StorageFactory};
16use std::rc::Rc;
17
18impl DeviceStorageCompatible for PrivacyInfo {
19 type Loader = NoneT;
20 const KEY: &'static str = "privacy_info";
21}
22
23#[derive(thiserror::Error, Debug)]
24pub(crate) enum PrivacyError {
25 #[error("Write failed for Setup: {0:?}")]
26 WriteFailure(Error),
27}
28
29impl From<&PrivacyError> for ResponseType {
30 fn from(error: &PrivacyError) -> Self {
31 match error {
32 PrivacyError::WriteFailure(..) => ResponseType::StorageFailure,
33 }
34 }
35}
36
37pub(crate) enum Request {
38 Set(Option<bool>, Sender<Result<(), PrivacyError>>),
39}
40
41pub struct PrivacyController {
42 store: Rc<DeviceStorage>,
43 publisher: Option<Publisher>,
44 setting_value_publisher: SettingValuePublisher<PrivacyInfo>,
45}
46
47impl PrivacyController {
48 pub(super) async fn new<F>(
49 storage_factory: Rc<F>,
50 setting_value_publisher: SettingValuePublisher<PrivacyInfo>,
51 ) -> Self
52 where
53 F: StorageFactory<Storage = DeviceStorage>,
54 {
55 PrivacyController {
56 store: storage_factory.get_store().await,
57 publisher: None,
58 setting_value_publisher,
59 }
60 }
61
62 pub(super) fn register_publisher(&mut self, publisher: Publisher) {
63 self.publisher = Some(publisher);
64 }
65
66 fn publish(&self, info: PrivacyInfo) {
67 let _ = self.setting_value_publisher.publish(&info);
68 if let Some(publisher) = self.publisher.as_ref() {
69 publisher.set(info);
70 }
71 }
72
73 pub(super) async fn handle(
74 self,
75 mut request_rx: UnboundedReceiver<Request>,
76 ) -> fasync::Task<()> {
77 fasync::Task::local(async move {
78 while let Some(request) = request_rx.next().await {
79 let Request::Set(user_data_sharing_consent, tx) = request;
80 let res = self.set(user_data_sharing_consent).await.map(|info| {
81 if let Some(info) = info {
82 self.publish(info);
83 }
84 });
85 let _ = tx.send(res);
86 }
87 })
88 }
89
90 async fn set(
91 &self,
92 user_data_sharing_consent: Option<bool>,
93 ) -> Result<Option<PrivacyInfo>, PrivacyError> {
94 let mut info = self.store.get::<PrivacyInfo>().await;
95 if let Some(user_data_sharing_consent) = user_data_sharing_consent {
96 info.user_data_sharing_consent = Some(user_data_sharing_consent);
97 }
98
99 self.store
100 .write(&info)
101 .await
102 .map(|state| (UpdateState::Updated == state).then_some(info))
103 .map_err(PrivacyError::WriteFailure)
104 }
105
106 pub(super) async fn restore(&self) -> PrivacyInfo {
107 self.store.get::<PrivacyInfo>().await
108 }
109}
110
111impl StorageAccess for PrivacyController {
112 type Storage = DeviceStorage;
113 type Data = PrivacyInfo;
114 const STORAGE_KEY: &'static str = PrivacyInfo::KEY;
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use futures::channel::mpsc;
121 use settings_test_common::storage::InMemoryStorageFactory;
122
123 #[fuchsia::test(allow_stalls = false)]
124 async fn test_privacy_storage() {
125 let factory = Rc::new(InMemoryStorageFactory::new());
126 let (tx, _) = mpsc::unbounded();
127 let setting_value_publisher = SettingValuePublisher::new(tx);
128
129 factory.initialize::<PrivacyController>().await.expect("can initialize privacy storage");
130
131 let privacy_controller =
132 PrivacyController::new(Rc::clone(&factory), setting_value_publisher).await;
133 let store = factory.get_store().await;
134
135 let result = privacy_controller.set(None).await.expect("set successful");
137 assert_eq!(result, None);
138 assert_eq!(store.get::<PrivacyInfo>().await.user_data_sharing_consent, None);
139
140 let expected_true = PrivacyInfo { user_data_sharing_consent: Some(true) };
142 let result = privacy_controller
143 .set(Some(true))
144 .await
145 .expect("set successful")
146 .expect("privacy info changed");
147 assert_eq!(result, expected_true);
148 assert_eq!(store.get::<PrivacyInfo>().await, expected_true);
149
150 let result = privacy_controller.set(None).await.expect("set successful");
152 assert_eq!(result, None);
153 assert_eq!(store.get::<PrivacyInfo>().await, expected_true);
154
155 let expected_false = PrivacyInfo { user_data_sharing_consent: Some(false) };
157 let result = privacy_controller
158 .set(Some(false))
159 .await
160 .expect("set successful")
161 .expect("privacy info changed");
162 assert_eq!(result, expected_false);
163 assert_eq!(store.get::<PrivacyInfo>().await, expected_false);
164
165 let result = privacy_controller.set(None).await.expect("set successful");
167 assert_eq!(result, None);
168 assert_eq!(store.get::<PrivacyInfo>().await, expected_false);
169 }
170}