1use crate::db::models::address::{
6 Address, AddressBulkResultEntry, AddressBulkTombstoneResultEntry, AddressTombstone,
7 UpdatableAddressFields, UpdatableAddressFieldsWithMeta,
8};
9use crate::db::models::credit_card::{
10 CreditCard, CreditCardBulkResultEntry, CreditCardBulkTombstoneResultEntry, CreditCardTombstone,
11 UpdatableCreditCardFields, UpdatableCreditCardFieldsWithMeta,
12};
13use crate::db::models::passport::{Passport, UpdatablePassportFields};
14use crate::db::{
15 addresses, credit_cards, credit_cards::CreditCardsDeletionMetrics, passports, AutofillDb,
16};
17use crate::error::*;
18use error_support::handle_error;
19use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
20use rusqlite::{
21 types::{FromSql, ToSql},
22 Connection,
23};
24use sql_support::{self, run_maintenance, ConnExt};
25use std::path::Path;
26use std::sync::{Arc, Weak};
27use sync15::engine::{SyncEngine, SyncEngineId};
28use sync_guid::Guid;
29
30lazy_static::lazy_static! {
32 static ref STORE_FOR_MANAGER: std::sync::Mutex<Weak<Store>> =
36 std::sync::Mutex::new(Weak::new());
37}
38
39pub fn get_registered_sync_engine(engine_id: &SyncEngineId) -> Option<Box<dyn SyncEngine>> {
42 let weak = STORE_FOR_MANAGER.lock().unwrap();
43 match weak.upgrade() {
44 None => None,
45 Some(store) => match engine_id {
46 SyncEngineId::Addresses => Some(Box::new(crate::sync::address::create_engine(store))),
47 SyncEngineId::CreditCards => {
48 Some(Box::new(crate::sync::credit_card::create_engine(store)))
49 }
50 _ => unreachable!("can't provide unknown engine: {}", engine_id),
53 },
54 }
55}
56
57pub struct Store {
59 pub(crate) db: Mutex<Option<AutofillDb>>,
60}
61
62impl Store {
63 #[handle_error(Error)]
64 pub fn new(db_path: impl AsRef<Path>) -> ApiResult<Self> {
65 Ok(Self {
66 db: Mutex::new(Some(AutofillDb::new(db_path)?)),
67 })
68 }
69
70 #[cfg(test)]
72 pub fn new_memory() -> Self {
73 Self {
74 db: Mutex::new(Some(crate::db::test::new_mem_db())),
75 }
76 }
77
78 #[handle_error(Error)]
80 pub fn new_shared_memory(db_name: &str) -> ApiResult<Self> {
81 Ok(Self {
82 db: Mutex::new(Some(AutofillDb::new_memory(db_name)?)),
83 })
84 }
85
86 pub(crate) fn lock_db(&self) -> Result<MappedMutexGuard<'_, AutofillDb>> {
87 MutexGuard::try_map(self.db.lock(), |db| db.as_mut()).map_err(|_| Error::DatabaseClosed)
88 }
89
90 #[handle_error(Error)]
91 pub fn add_credit_card(&self, fields: UpdatableCreditCardFields) -> ApiResult<CreditCard> {
92 let credit_card = credit_cards::add_credit_card(&self.lock_db()?.writer, fields)?;
93 Ok(credit_card.into())
94 }
95
96 #[handle_error(Error)]
101 pub fn add_credit_card_with_meta(
102 &self,
103 entry_with_meta: UpdatableCreditCardFieldsWithMeta,
104 ) -> ApiResult<CreditCard> {
105 Ok(credit_cards::add_credit_card_with_meta(
106 &self.lock_db()?.writer,
107 entry_with_meta.fields,
108 entry_with_meta.meta,
109 )?
110 .into())
111 }
112
113 #[handle_error(Error)]
116 pub fn add_many_credit_cards_with_meta(
117 &self,
118 entries_with_meta: Vec<UpdatableCreditCardFieldsWithMeta>,
119 ) -> ApiResult<Vec<CreditCardBulkResultEntry>> {
120 let results = credit_cards::add_many_credit_cards_with_meta(
121 &self.lock_db()?.writer,
122 entries_with_meta,
123 )?;
124 Ok(results
125 .into_iter()
126 .map(|result| match result {
127 Ok(credit_card) => CreditCardBulkResultEntry::Success {
128 credit_card: credit_card.into(),
129 },
130 Err(message) => CreditCardBulkResultEntry::Error { message },
131 })
132 .collect())
133 }
134
135 #[handle_error(Error)]
138 pub fn add_many_credit_card_tombstones(
139 &self,
140 tombstones: Vec<CreditCardTombstone>,
141 ) -> ApiResult<Vec<CreditCardBulkTombstoneResultEntry>> {
142 let results = credit_cards::add_many_credit_card_tombstones(
143 &self.lock_db()?.writer,
144 tombstones
145 .into_iter()
146 .map(|t| (t.guid, t.time_deleted))
147 .collect(),
148 )?;
149 Ok(results
150 .into_iter()
151 .map(|result| match result {
152 Ok(guid) => CreditCardBulkTombstoneResultEntry::Success { guid },
153 Err(message) => CreditCardBulkTombstoneResultEntry::Error { message },
154 })
155 .collect())
156 }
157
158 #[handle_error(Error)]
165 pub fn delete_all_credit_cards(&self) -> ApiResult<()> {
166 credit_cards::delete_all_credit_cards(&self.lock_db()?.writer)?;
167 Ok(())
168 }
169
170 #[handle_error(Error)]
176 pub fn update_credit_card_with_meta(
177 &self,
178 entry_with_meta: UpdatableCreditCardFieldsWithMeta,
179 ) -> ApiResult<()> {
180 credit_cards::update_credit_card_with_meta(
181 &self.lock_db()?.writer,
182 entry_with_meta.fields,
183 entry_with_meta.meta,
184 )
185 }
186
187 #[handle_error(Error)]
188 pub fn get_credit_card(&self, guid: String) -> ApiResult<CreditCard> {
189 let credit_card =
190 credit_cards::get_credit_card(&self.lock_db()?.writer, &Guid::new(&guid))?;
191 Ok(credit_card.into())
192 }
193
194 #[handle_error(Error)]
195 pub fn get_all_credit_cards(&self) -> ApiResult<Vec<CreditCard>> {
196 let credit_cards = credit_cards::get_all_credit_cards(&self.lock_db()?.writer)?
197 .into_iter()
198 .map(|x| x.into())
199 .collect();
200 Ok(credit_cards)
201 }
202
203 #[handle_error(Error)]
204 pub fn count_all_credit_cards(&self) -> ApiResult<i64> {
205 let count = credit_cards::count_all_credit_cards(&self.lock_db()?.writer)?;
206 Ok(count)
207 }
208
209 #[handle_error(Error)]
210 pub fn update_credit_card(
211 &self,
212 guid: String,
213 credit_card: UpdatableCreditCardFields,
214 ) -> ApiResult<()> {
215 credit_cards::update_credit_card(&self.lock_db()?.writer, &Guid::new(&guid), &credit_card)
216 }
217
218 #[handle_error(Error)]
219 pub fn delete_credit_card(&self, guid: String) -> ApiResult<bool> {
220 credit_cards::delete_credit_card(&self.lock_db()?.writer, &Guid::new(&guid))
221 }
222
223 #[handle_error(Error)]
224 pub fn touch_credit_card(&self, guid: String) -> ApiResult<()> {
225 credit_cards::touch(&self.lock_db()?.writer, &Guid::new(&guid))
226 }
227
228 #[handle_error(Error)]
229 pub fn add_address(&self, new_address: UpdatableAddressFields) -> ApiResult<Address> {
230 Ok(addresses::add_address(&self.lock_db()?.writer, new_address)?.into())
231 }
232
233 #[handle_error(Error)]
239 pub fn add_address_with_meta(
240 &self,
241 entry_with_meta: UpdatableAddressFieldsWithMeta,
242 ) -> ApiResult<Address> {
243 Ok(addresses::add_address_with_meta(
244 &self.lock_db()?.writer,
245 entry_with_meta.fields,
246 entry_with_meta.meta,
247 )?
248 .into())
249 }
250
251 #[handle_error(Error)]
253 pub fn add_many_addresses_with_meta(
254 &self,
255 entries_with_meta: Vec<UpdatableAddressFieldsWithMeta>,
256 ) -> ApiResult<Vec<AddressBulkResultEntry>> {
257 let results =
258 addresses::add_many_addresses_with_meta(&self.lock_db()?.writer, entries_with_meta)?;
259 Ok(results
260 .into_iter()
261 .map(|result| match result {
262 Ok(address) => AddressBulkResultEntry::Success {
263 address: address.into(),
264 },
265 Err(message) => AddressBulkResultEntry::Error { message },
266 })
267 .collect())
268 }
269
270 #[handle_error(Error)]
273 pub fn add_many_address_tombstones(
274 &self,
275 tombstones: Vec<AddressTombstone>,
276 ) -> ApiResult<Vec<AddressBulkTombstoneResultEntry>> {
277 let results = addresses::add_many_address_tombstones(
278 &self.lock_db()?.writer,
279 tombstones
280 .into_iter()
281 .map(|t| (t.guid, t.time_deleted))
282 .collect(),
283 )?;
284 Ok(results
285 .into_iter()
286 .map(|result| match result {
287 Ok(guid) => AddressBulkTombstoneResultEntry::Success { guid },
288 Err(message) => AddressBulkTombstoneResultEntry::Error { message },
289 })
290 .collect())
291 }
292
293 #[handle_error(Error)]
300 pub fn delete_all_addresses(&self) -> ApiResult<()> {
301 addresses::delete_all_addresses(&self.lock_db()?.writer)?;
302 Ok(())
303 }
304
305 #[handle_error(Error)]
306 pub fn get_address(&self, guid: String) -> ApiResult<Address> {
307 Ok(addresses::get_address(&self.lock_db()?.writer, &Guid::new(&guid))?.into())
308 }
309
310 #[handle_error(Error)]
311 pub fn get_all_addresses(&self) -> ApiResult<Vec<Address>> {
312 let addresses = addresses::get_all_addresses(&self.lock_db()?.writer)?
313 .into_iter()
314 .map(|x| x.into())
315 .collect();
316 Ok(addresses)
317 }
318
319 #[handle_error(Error)]
320 pub fn count_all_addresses(&self) -> ApiResult<i64> {
321 let count = addresses::count_all_addresses(&self.lock_db()?.writer)?;
322 Ok(count)
323 }
324
325 #[handle_error(Error)]
326 pub fn update_address(&self, guid: String, address: UpdatableAddressFields) -> ApiResult<()> {
327 addresses::update_address(&self.lock_db()?.writer, &Guid::new(&guid), &address)
328 }
329
330 #[handle_error(Error)]
336 pub fn update_address_with_meta(
337 &self,
338 entry_with_meta: UpdatableAddressFieldsWithMeta,
339 ) -> ApiResult<()> {
340 addresses::update_address_with_meta(
341 &self.lock_db()?.writer,
342 entry_with_meta.fields,
343 entry_with_meta.meta,
344 )
345 }
346
347 #[handle_error(Error)]
348 pub fn delete_address(&self, guid: String) -> ApiResult<bool> {
349 addresses::delete_address(&self.lock_db()?.writer, &Guid::new(&guid))
350 }
351
352 #[handle_error(Error)]
353 pub fn touch_address(&self, guid: String) -> ApiResult<()> {
354 addresses::touch(&self.lock_db()?.writer, &Guid::new(&guid))
355 }
356
357 #[handle_error(Error)]
358 pub fn add_passport(&self, fields: UpdatablePassportFields) -> ApiResult<Passport> {
359 Ok(passports::add_passport(&self.lock_db()?.writer, fields)?.into())
360 }
361
362 #[handle_error(Error)]
363 pub fn get_passport(&self, guid: String) -> ApiResult<Passport> {
364 Ok(passports::get_passport(&self.lock_db()?.writer, &Guid::new(&guid))?.into())
365 }
366
367 #[handle_error(Error)]
368 pub fn get_all_passports(&self) -> ApiResult<Vec<Passport>> {
369 let passports = passports::get_all_passports(&self.lock_db()?.writer)?
370 .into_iter()
371 .map(|x| x.into())
372 .collect();
373 Ok(passports)
374 }
375
376 #[handle_error(Error)]
377 pub fn count_all_passports(&self) -> ApiResult<i64> {
378 passports::count_all_passports(&self.lock_db()?.writer)
379 }
380
381 #[handle_error(Error)]
382 pub fn update_passport(
383 &self,
384 guid: String,
385 passport: UpdatablePassportFields,
386 ) -> ApiResult<()> {
387 passports::update_passport(&self.lock_db()?.writer, &Guid::new(&guid), &passport)
388 }
389
390 #[handle_error(Error)]
391 pub fn delete_passport(&self, guid: String) -> ApiResult<bool> {
392 passports::delete_passport(&self.lock_db()?.writer, &Guid::new(&guid))
393 }
394
395 #[handle_error(Error)]
396 pub fn touch_passport(&self, guid: String) -> ApiResult<()> {
397 passports::touch(&self.lock_db()?.writer, &Guid::new(&guid))
398 }
399
400 #[handle_error(Error)]
401 pub fn scrub_encrypted_data(self: Arc<Self>) -> ApiResult<()> {
402 credit_cards::scrub_encrypted_credit_card_data(&self.lock_db()?.writer)?;
405 crate::sync::credit_card::create_engine(self).reset_local_sync_data()?;
408 Ok(())
409 }
410
411 #[handle_error(Error)]
412 pub fn scrub_undecryptable_credit_card_data_for_remote_replacement(
413 self: Arc<Self>,
414 local_encryption_key: String,
415 ) -> ApiResult<CreditCardsDeletionMetrics> {
416 let db = self.lock_db()?;
417 let deletion_stats =
418 credit_cards::scrub_undecryptable_credit_card_data_for_remote_replacement(
419 &db.writer,
420 local_encryption_key,
421 )?;
422
423 crate::sync::credit_card::create_engine(self.clone())
428 .reset_local_sync_data_for_verification(&db.writer)?;
429 Ok(deletion_stats)
430 }
431
432 #[handle_error(Error)]
433 pub fn run_maintenance(&self) -> ApiResult<()> {
434 let conn = self.lock_db()?;
435 run_maintenance(&conn)?;
436 Ok(())
437 }
438
439 pub fn shutdown(&self) {
440 if let Some(db) = self.db.lock().take() {
441 db.close();
442 }
443 }
444
445 pub fn register_with_sync_manager(self: Arc<Self>) {
451 let mut state = STORE_FOR_MANAGER.lock().unwrap();
452 *state = Arc::downgrade(&self);
453 }
454
455 pub fn create_credit_cards_sync_engine(self: Arc<Self>) -> Box<dyn SyncEngine> {
462 Box::new(crate::sync::credit_card::create_engine(self))
463 }
464
465 pub fn create_addresses_sync_engine(self: Arc<Self>) -> Box<dyn SyncEngine> {
466 Box::new(crate::sync::address::create_engine(self))
467 }
468}
469
470pub(crate) fn put_meta(conn: &Connection, key: &str, value: &dyn ToSql) -> Result<()> {
471 conn.execute_cached(
472 "REPLACE INTO moz_meta (key, value) VALUES (:key, :value)",
473 &[(":key", &key as &dyn ToSql), (":value", value)],
474 )?;
475 Ok(())
476}
477
478pub(crate) fn get_meta<T: FromSql>(conn: &Connection, key: &str) -> Result<Option<T>> {
479 let res = conn.try_query_one(
480 "SELECT value FROM moz_meta WHERE key = :key",
481 &[(":key", &key)],
482 true,
483 )?;
484 Ok(res)
485}
486
487pub(crate) fn delete_meta(conn: &Connection, key: &str) -> Result<()> {
488 conn.execute_cached("DELETE FROM moz_meta WHERE key = :key", &[(":key", &key)])?;
489 Ok(())
490}
491
492#[cfg(test)]
493mod tests {
494 use super::*;
495 use crate::db::test::new_mem_db;
496 use crate::encryption::EncryptorDecryptor;
497 use nss_as::ensure_initialized;
498
499 #[test]
500 fn test_autofill_meta() -> Result<()> {
501 let db = new_mem_db();
502 let test_key = "TEST KEY A";
503 let test_value = "TEST VALUE A";
504 let test_key2 = "TEST KEY B";
505 let test_value2 = "TEST VALUE B";
506
507 put_meta(&db, test_key, &test_value)?;
508 put_meta(&db, test_key2, &test_value2)?;
509
510 let retrieved_value: String = get_meta(&db, test_key)?.expect("test value");
511 let retrieved_value2: String = get_meta(&db, test_key2)?.expect("test value 2");
512
513 assert_eq!(retrieved_value, test_value);
514 assert_eq!(retrieved_value2, test_value2);
515
516 let test_value3 = "TEST VALUE C";
518 put_meta(&db, test_key, &test_value3)?;
519
520 let retrieved_value3: String = get_meta(&db, test_key)?.expect("test value 3");
521
522 assert_eq!(retrieved_value3, test_value3);
523
524 delete_meta(&db, test_key)?;
526 let retrieved_value4: Option<String> = get_meta(&db, test_key)?;
527 assert!(retrieved_value4.is_none());
528
529 db.writer.execute("DELETE FROM moz_meta", [])?;
530
531 Ok(())
532 }
533
534 #[test]
535 fn test_sync_manager_registration() {
536 let store = Arc::new(Store::new_shared_memory("sync-mgr-test").unwrap());
537 assert_eq!(Arc::strong_count(&store), 1);
538 assert_eq!(Arc::weak_count(&store), 0);
539 Arc::clone(&store).register_with_sync_manager();
540 assert_eq!(Arc::strong_count(&store), 1);
541 assert_eq!(Arc::weak_count(&store), 1);
542 let registered = STORE_FOR_MANAGER
543 .lock()
544 .unwrap()
545 .upgrade()
546 .expect("should upgrade");
547 assert!(Arc::ptr_eq(&store, ®istered));
548 drop(registered);
549 assert_eq!(Arc::strong_count(&store), 1);
551 assert_eq!(Arc::weak_count(&store), 1);
552 drop(store);
554 assert!(STORE_FOR_MANAGER.lock().unwrap().upgrade().is_none());
555 }
556
557 #[test]
558 fn test_shutdown_closes_the_store() {
559 let store = Store::new_shared_memory("shutdown-test").expect("create store");
560 assert_eq!(store.count_all_passports().expect("count"), 0);
562
563 store.shutdown();
564
565 assert!(store.count_all_passports().is_err());
568
569 store.shutdown();
571 }
572
573 #[test]
574 fn test_scrub_undecryptable_credit_card_data_for_remote_replacement() {
575 ensure_initialized();
576 let store = Arc::new(Store::new_shared_memory("sync-mgr-test").expect("create store"));
577 let key = EncryptorDecryptor::create_key().expect("create key");
578 let encdec = EncryptorDecryptor::new(&key).expect("create EncryptorDecryptor");
579
580 store
581 .add_credit_card(UpdatableCreditCardFields {
582 cc_name: "john deer".to_string(),
583 cc_number_enc: encdec
584 .encrypt("567812345678123456781")
585 .expect("encrypt cc number"),
586 cc_number_last_4: "6781".to_string(),
587 cc_exp_month: 10,
588 cc_exp_year: 2025,
589 cc_type: "mastercard".to_string(),
590 })
591 .expect("add credit card to database");
592
593 store
594 .scrub_undecryptable_credit_card_data_for_remote_replacement(key)
595 .expect("scrub credit card record");
596 }
597}