1use crate::db::models::address::{Address, UpdatableAddressFields};
6use crate::db::models::credit_card::{CreditCard, UpdatableCreditCardFields};
7use crate::db::models::passport::{Passport, UpdatablePassportFields};
8use crate::db::{
9 addresses, credit_cards, credit_cards::CreditCardsDeletionMetrics, passports, AutofillDb,
10};
11use crate::error::*;
12use error_support::handle_error;
13use rusqlite::{
14 types::{FromSql, ToSql},
15 Connection,
16};
17use sql_support::{self, run_maintenance, ConnExt};
18use std::path::Path;
19use std::sync::{Arc, Mutex, Weak};
20use sync15::engine::{SyncEngine, SyncEngineId};
21use sync_guid::Guid;
22
23lazy_static::lazy_static! {
25 static ref STORE_FOR_MANAGER: Mutex<Weak<Store>> = Mutex::new(Weak::new());
29}
30
31pub fn get_registered_sync_engine(engine_id: &SyncEngineId) -> Option<Box<dyn SyncEngine>> {
34 let weak = STORE_FOR_MANAGER.lock().unwrap();
35 match weak.upgrade() {
36 None => None,
37 Some(store) => match engine_id {
38 SyncEngineId::Addresses => Some(Box::new(crate::sync::address::create_engine(store))),
39 SyncEngineId::CreditCards => {
40 Some(Box::new(crate::sync::credit_card::create_engine(store)))
41 }
42 _ => unreachable!("can't provide unknown engine: {}", engine_id),
45 },
46 }
47}
48
49pub struct Store {
51 pub(crate) db: Mutex<AutofillDb>,
52}
53
54impl Store {
55 #[handle_error(Error)]
56 pub fn new(db_path: impl AsRef<Path>) -> ApiResult<Self> {
57 Ok(Self {
58 db: Mutex::new(AutofillDb::new(db_path)?),
59 })
60 }
61
62 #[cfg(test)]
64 pub fn new_memory() -> Self {
65 Self {
66 db: Mutex::new(crate::db::test::new_mem_db()),
67 }
68 }
69
70 #[handle_error(Error)]
72 pub fn new_shared_memory(db_name: &str) -> ApiResult<Self> {
73 Ok(Self {
74 db: Mutex::new(AutofillDb::new_memory(db_name)?),
75 })
76 }
77
78 #[handle_error(Error)]
79 pub fn add_credit_card(&self, fields: UpdatableCreditCardFields) -> ApiResult<CreditCard> {
80 let credit_card = credit_cards::add_credit_card(&self.db.lock().unwrap().writer, fields)?;
81 Ok(credit_card.into())
82 }
83
84 #[handle_error(Error)]
85 pub fn get_credit_card(&self, guid: String) -> ApiResult<CreditCard> {
86 let credit_card =
87 credit_cards::get_credit_card(&self.db.lock().unwrap().writer, &Guid::new(&guid))?;
88 Ok(credit_card.into())
89 }
90
91 #[handle_error(Error)]
92 pub fn get_all_credit_cards(&self) -> ApiResult<Vec<CreditCard>> {
93 let credit_cards = credit_cards::get_all_credit_cards(&self.db.lock().unwrap().writer)?
94 .into_iter()
95 .map(|x| x.into())
96 .collect();
97 Ok(credit_cards)
98 }
99
100 #[handle_error(Error)]
101 pub fn count_all_credit_cards(&self) -> ApiResult<i64> {
102 let count = credit_cards::count_all_credit_cards(&self.db.lock().unwrap().writer)?;
103 Ok(count)
104 }
105
106 #[handle_error(Error)]
107 pub fn update_credit_card(
108 &self,
109 guid: String,
110 credit_card: UpdatableCreditCardFields,
111 ) -> ApiResult<()> {
112 credit_cards::update_credit_card(
113 &self.db.lock().unwrap().writer,
114 &Guid::new(&guid),
115 &credit_card,
116 )
117 }
118
119 #[handle_error(Error)]
120 pub fn delete_credit_card(&self, guid: String) -> ApiResult<bool> {
121 credit_cards::delete_credit_card(&self.db.lock().unwrap().writer, &Guid::new(&guid))
122 }
123
124 #[handle_error(Error)]
125 pub fn touch_credit_card(&self, guid: String) -> ApiResult<()> {
126 credit_cards::touch(&self.db.lock().unwrap().writer, &Guid::new(&guid))
127 }
128
129 #[handle_error(Error)]
130 pub fn add_address(&self, new_address: UpdatableAddressFields) -> ApiResult<Address> {
131 Ok(addresses::add_address(&self.db.lock().unwrap().writer, new_address)?.into())
132 }
133
134 #[handle_error(Error)]
135 pub fn get_address(&self, guid: String) -> ApiResult<Address> {
136 Ok(addresses::get_address(&self.db.lock().unwrap().writer, &Guid::new(&guid))?.into())
137 }
138
139 #[handle_error(Error)]
140 pub fn get_all_addresses(&self) -> ApiResult<Vec<Address>> {
141 let addresses = addresses::get_all_addresses(&self.db.lock().unwrap().writer)?
142 .into_iter()
143 .map(|x| x.into())
144 .collect();
145 Ok(addresses)
146 }
147
148 #[handle_error(Error)]
149 pub fn count_all_addresses(&self) -> ApiResult<i64> {
150 let count = addresses::count_all_addresses(&self.db.lock().unwrap().writer)?;
151 Ok(count)
152 }
153
154 #[handle_error(Error)]
155 pub fn update_address(&self, guid: String, address: UpdatableAddressFields) -> ApiResult<()> {
156 addresses::update_address(&self.db.lock().unwrap().writer, &Guid::new(&guid), &address)
157 }
158
159 #[handle_error(Error)]
160 pub fn delete_address(&self, guid: String) -> ApiResult<bool> {
161 addresses::delete_address(&self.db.lock().unwrap().writer, &Guid::new(&guid))
162 }
163
164 #[handle_error(Error)]
165 pub fn touch_address(&self, guid: String) -> ApiResult<()> {
166 addresses::touch(&self.db.lock().unwrap().writer, &Guid::new(&guid))
167 }
168
169 #[handle_error(Error)]
170 pub fn add_passport(&self, fields: UpdatablePassportFields) -> ApiResult<Passport> {
171 Ok(passports::add_passport(&self.db.lock().unwrap().writer, fields)?.into())
172 }
173
174 #[handle_error(Error)]
175 pub fn get_passport(&self, guid: String) -> ApiResult<Passport> {
176 Ok(passports::get_passport(&self.db.lock().unwrap().writer, &Guid::new(&guid))?.into())
177 }
178
179 #[handle_error(Error)]
180 pub fn get_all_passports(&self) -> ApiResult<Vec<Passport>> {
181 let passports = passports::get_all_passports(&self.db.lock().unwrap().writer)?
182 .into_iter()
183 .map(|x| x.into())
184 .collect();
185 Ok(passports)
186 }
187
188 #[handle_error(Error)]
189 pub fn count_all_passports(&self) -> ApiResult<i64> {
190 passports::count_all_passports(&self.db.lock().unwrap().writer)
191 }
192
193 #[handle_error(Error)]
194 pub fn update_passport(
195 &self,
196 guid: String,
197 passport: UpdatablePassportFields,
198 ) -> ApiResult<()> {
199 passports::update_passport(
200 &self.db.lock().unwrap().writer,
201 &Guid::new(&guid),
202 &passport,
203 )
204 }
205
206 #[handle_error(Error)]
207 pub fn delete_passport(&self, guid: String) -> ApiResult<bool> {
208 passports::delete_passport(&self.db.lock().unwrap().writer, &Guid::new(&guid))
209 }
210
211 #[handle_error(Error)]
212 pub fn touch_passport(&self, guid: String) -> ApiResult<()> {
213 passports::touch(&self.db.lock().unwrap().writer, &Guid::new(&guid))
214 }
215
216 #[handle_error(Error)]
217 pub fn scrub_encrypted_data(self: Arc<Self>) -> ApiResult<()> {
218 credit_cards::scrub_encrypted_credit_card_data(&self.db.lock().unwrap().writer)?;
221 crate::sync::credit_card::create_engine(self).reset_local_sync_data()?;
224 Ok(())
225 }
226
227 #[handle_error(Error)]
228 pub fn scrub_undecryptable_credit_card_data_for_remote_replacement(
229 self: Arc<Self>,
230 local_encryption_key: String,
231 ) -> ApiResult<CreditCardsDeletionMetrics> {
232 let db = &self.db.lock().unwrap().writer;
233 let deletion_stats =
234 credit_cards::scrub_undecryptable_credit_card_data_for_remote_replacement(
235 db,
236 local_encryption_key,
237 )?;
238
239 crate::sync::credit_card::create_engine(self.clone())
244 .reset_local_sync_data_for_verification(db)?;
245 Ok(deletion_stats)
246 }
247
248 #[handle_error(Error)]
249 pub fn run_maintenance(&self) -> ApiResult<()> {
250 let conn = self.db.lock().unwrap();
251 run_maintenance(&conn)?;
252 Ok(())
253 }
254
255 pub fn register_with_sync_manager(self: Arc<Self>) {
261 let mut state = STORE_FOR_MANAGER.lock().unwrap();
262 *state = Arc::downgrade(&self);
263 }
264
265 pub fn create_credit_cards_sync_engine(self: Arc<Self>) -> Box<dyn SyncEngine> {
272 Box::new(crate::sync::credit_card::create_engine(self))
273 }
274
275 pub fn create_addresses_sync_engine(self: Arc<Self>) -> Box<dyn SyncEngine> {
276 Box::new(crate::sync::address::create_engine(self))
277 }
278}
279
280pub(crate) fn put_meta(conn: &Connection, key: &str, value: &dyn ToSql) -> Result<()> {
281 conn.execute_cached(
282 "REPLACE INTO moz_meta (key, value) VALUES (:key, :value)",
283 &[(":key", &key as &dyn ToSql), (":value", value)],
284 )?;
285 Ok(())
286}
287
288pub(crate) fn get_meta<T: FromSql>(conn: &Connection, key: &str) -> Result<Option<T>> {
289 let res = conn.try_query_one(
290 "SELECT value FROM moz_meta WHERE key = :key",
291 &[(":key", &key)],
292 true,
293 )?;
294 Ok(res)
295}
296
297pub(crate) fn delete_meta(conn: &Connection, key: &str) -> Result<()> {
298 conn.execute_cached("DELETE FROM moz_meta WHERE key = :key", &[(":key", &key)])?;
299 Ok(())
300}
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305 use crate::db::test::new_mem_db;
306 use crate::encryption::EncryptorDecryptor;
307 use nss_as::ensure_initialized;
308
309 #[test]
310 fn test_autofill_meta() -> Result<()> {
311 let db = new_mem_db();
312 let test_key = "TEST KEY A";
313 let test_value = "TEST VALUE A";
314 let test_key2 = "TEST KEY B";
315 let test_value2 = "TEST VALUE B";
316
317 put_meta(&db, test_key, &test_value)?;
318 put_meta(&db, test_key2, &test_value2)?;
319
320 let retrieved_value: String = get_meta(&db, test_key)?.expect("test value");
321 let retrieved_value2: String = get_meta(&db, test_key2)?.expect("test value 2");
322
323 assert_eq!(retrieved_value, test_value);
324 assert_eq!(retrieved_value2, test_value2);
325
326 let test_value3 = "TEST VALUE C";
328 put_meta(&db, test_key, &test_value3)?;
329
330 let retrieved_value3: String = get_meta(&db, test_key)?.expect("test value 3");
331
332 assert_eq!(retrieved_value3, test_value3);
333
334 delete_meta(&db, test_key)?;
336 let retrieved_value4: Option<String> = get_meta(&db, test_key)?;
337 assert!(retrieved_value4.is_none());
338
339 db.writer.execute("DELETE FROM moz_meta", [])?;
340
341 Ok(())
342 }
343
344 #[test]
345 fn test_sync_manager_registration() {
346 let store = Arc::new(Store::new_shared_memory("sync-mgr-test").unwrap());
347 assert_eq!(Arc::strong_count(&store), 1);
348 assert_eq!(Arc::weak_count(&store), 0);
349 Arc::clone(&store).register_with_sync_manager();
350 assert_eq!(Arc::strong_count(&store), 1);
351 assert_eq!(Arc::weak_count(&store), 1);
352 let registered = STORE_FOR_MANAGER
353 .lock()
354 .unwrap()
355 .upgrade()
356 .expect("should upgrade");
357 assert!(Arc::ptr_eq(&store, ®istered));
358 drop(registered);
359 assert_eq!(Arc::strong_count(&store), 1);
361 assert_eq!(Arc::weak_count(&store), 1);
362 drop(store);
364 assert!(STORE_FOR_MANAGER.lock().unwrap().upgrade().is_none());
365 }
366
367 #[test]
368 fn test_scrub_undecryptable_credit_card_data_for_remote_replacement() {
369 ensure_initialized();
370 let store = Arc::new(Store::new_shared_memory("sync-mgr-test").expect("create store"));
371 let key = EncryptorDecryptor::create_key().expect("create key");
372 let encdec = EncryptorDecryptor::new(&key).expect("create EncryptorDecryptor");
373
374 store
375 .add_credit_card(UpdatableCreditCardFields {
376 cc_name: "john deer".to_string(),
377 cc_number_enc: encdec
378 .encrypt("567812345678123456781")
379 .expect("encrypt cc number"),
380 cc_number_last_4: "6781".to_string(),
381 cc_exp_month: 10,
382 cc_exp_year: 2025,
383 cc_type: "mastercard".to_string(),
384 })
385 .expect("add credit card to database");
386
387 store
388 .scrub_undecryptable_credit_card_data_for_remote_replacement(key)
389 .expect("scrub credit card record");
390 }
391}