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