1use crate::db::models::address::{
6 Address, AddressBulkResultEntry, AddressBulkTombstoneResultEntry, AddressTombstone,
7 UpdatableAddressFields, UpdatableAddressFieldsWithMeta,
8};
9use crate::db::models::credit_card::{CreditCard, UpdatableCreditCardFields};
10use crate::db::models::passport::{Passport, UpdatablePassportFields};
11use crate::db::{
12 addresses, credit_cards, credit_cards::CreditCardsDeletionMetrics, passports, AutofillDb,
13};
14use crate::error::*;
15use error_support::handle_error;
16use parking_lot::{MappedMutexGuard, Mutex, MutexGuard};
17use rusqlite::{
18 types::{FromSql, ToSql},
19 Connection,
20};
21use sql_support::{self, run_maintenance, ConnExt};
22use std::path::Path;
23use std::sync::{Arc, Weak};
24use sync15::engine::{SyncEngine, SyncEngineId};
25use sync_guid::Guid;
26
27lazy_static::lazy_static! {
29 static ref STORE_FOR_MANAGER: std::sync::Mutex<Weak<Store>> =
33 std::sync::Mutex::new(Weak::new());
34}
35
36pub fn get_registered_sync_engine(engine_id: &SyncEngineId) -> Option<Box<dyn SyncEngine>> {
39 let weak = STORE_FOR_MANAGER.lock().unwrap();
40 match weak.upgrade() {
41 None => None,
42 Some(store) => match engine_id {
43 SyncEngineId::Addresses => Some(Box::new(crate::sync::address::create_engine(store))),
44 SyncEngineId::CreditCards => {
45 Some(Box::new(crate::sync::credit_card::create_engine(store)))
46 }
47 _ => unreachable!("can't provide unknown engine: {}", engine_id),
50 },
51 }
52}
53
54pub struct Store {
56 pub(crate) db: Mutex<Option<AutofillDb>>,
57}
58
59impl Store {
60 #[handle_error(Error)]
61 pub fn new(db_path: impl AsRef<Path>) -> ApiResult<Self> {
62 Ok(Self {
63 db: Mutex::new(Some(AutofillDb::new(db_path)?)),
64 })
65 }
66
67 #[cfg(test)]
69 pub fn new_memory() -> Self {
70 Self {
71 db: Mutex::new(Some(crate::db::test::new_mem_db())),
72 }
73 }
74
75 #[handle_error(Error)]
77 pub fn new_shared_memory(db_name: &str) -> ApiResult<Self> {
78 Ok(Self {
79 db: Mutex::new(Some(AutofillDb::new_memory(db_name)?)),
80 })
81 }
82
83 pub(crate) fn lock_db(&self) -> Result<MappedMutexGuard<'_, AutofillDb>> {
84 MutexGuard::try_map(self.db.lock(), |db| db.as_mut()).map_err(|_| Error::DatabaseClosed)
85 }
86
87 #[handle_error(Error)]
88 pub fn add_credit_card(&self, fields: UpdatableCreditCardFields) -> ApiResult<CreditCard> {
89 let credit_card = credit_cards::add_credit_card(&self.lock_db()?.writer, fields)?;
90 Ok(credit_card.into())
91 }
92
93 #[handle_error(Error)]
94 pub fn get_credit_card(&self, guid: String) -> ApiResult<CreditCard> {
95 let credit_card =
96 credit_cards::get_credit_card(&self.lock_db()?.writer, &Guid::new(&guid))?;
97 Ok(credit_card.into())
98 }
99
100 #[handle_error(Error)]
101 pub fn get_all_credit_cards(&self) -> ApiResult<Vec<CreditCard>> {
102 let credit_cards = credit_cards::get_all_credit_cards(&self.lock_db()?.writer)?
103 .into_iter()
104 .map(|x| x.into())
105 .collect();
106 Ok(credit_cards)
107 }
108
109 #[handle_error(Error)]
110 pub fn count_all_credit_cards(&self) -> ApiResult<i64> {
111 let count = credit_cards::count_all_credit_cards(&self.lock_db()?.writer)?;
112 Ok(count)
113 }
114
115 #[handle_error(Error)]
116 pub fn update_credit_card(
117 &self,
118 guid: String,
119 credit_card: UpdatableCreditCardFields,
120 ) -> ApiResult<()> {
121 credit_cards::update_credit_card(&self.lock_db()?.writer, &Guid::new(&guid), &credit_card)
122 }
123
124 #[handle_error(Error)]
125 pub fn delete_credit_card(&self, guid: String) -> ApiResult<bool> {
126 credit_cards::delete_credit_card(&self.lock_db()?.writer, &Guid::new(&guid))
127 }
128
129 #[handle_error(Error)]
130 pub fn touch_credit_card(&self, guid: String) -> ApiResult<()> {
131 credit_cards::touch(&self.lock_db()?.writer, &Guid::new(&guid))
132 }
133
134 #[handle_error(Error)]
135 pub fn add_address(&self, new_address: UpdatableAddressFields) -> ApiResult<Address> {
136 Ok(addresses::add_address(&self.lock_db()?.writer, new_address)?.into())
137 }
138
139 #[handle_error(Error)]
145 pub fn add_address_with_meta(
146 &self,
147 entry_with_meta: UpdatableAddressFieldsWithMeta,
148 ) -> ApiResult<Address> {
149 Ok(addresses::add_address_with_meta(
150 &self.lock_db()?.writer,
151 entry_with_meta.fields,
152 entry_with_meta.meta,
153 )?
154 .into())
155 }
156
157 #[handle_error(Error)]
159 pub fn add_many_addresses_with_meta(
160 &self,
161 entries_with_meta: Vec<UpdatableAddressFieldsWithMeta>,
162 ) -> ApiResult<Vec<AddressBulkResultEntry>> {
163 let results =
164 addresses::add_many_addresses_with_meta(&self.lock_db()?.writer, entries_with_meta)?;
165 Ok(results
166 .into_iter()
167 .map(|result| match result {
168 Ok(address) => AddressBulkResultEntry::Success {
169 address: address.into(),
170 },
171 Err(message) => AddressBulkResultEntry::Error { message },
172 })
173 .collect())
174 }
175
176 #[handle_error(Error)]
179 pub fn add_many_address_tombstones(
180 &self,
181 tombstones: Vec<AddressTombstone>,
182 ) -> ApiResult<Vec<AddressBulkTombstoneResultEntry>> {
183 let results = addresses::add_many_address_tombstones(
184 &self.lock_db()?.writer,
185 tombstones
186 .into_iter()
187 .map(|t| (t.guid, t.time_deleted))
188 .collect(),
189 )?;
190 Ok(results
191 .into_iter()
192 .map(|result| match result {
193 Ok(guid) => AddressBulkTombstoneResultEntry::Success { guid },
194 Err(message) => AddressBulkTombstoneResultEntry::Error { message },
195 })
196 .collect())
197 }
198
199 #[handle_error(Error)]
201 pub fn delete_all_addresses(&self) -> ApiResult<()> {
202 addresses::delete_all_addresses(&self.lock_db()?.writer)?;
203 Ok(())
204 }
205
206 #[handle_error(Error)]
207 pub fn get_address(&self, guid: String) -> ApiResult<Address> {
208 Ok(addresses::get_address(&self.lock_db()?.writer, &Guid::new(&guid))?.into())
209 }
210
211 #[handle_error(Error)]
212 pub fn get_all_addresses(&self) -> ApiResult<Vec<Address>> {
213 let addresses = addresses::get_all_addresses(&self.lock_db()?.writer)?
214 .into_iter()
215 .map(|x| x.into())
216 .collect();
217 Ok(addresses)
218 }
219
220 #[handle_error(Error)]
221 pub fn count_all_addresses(&self) -> ApiResult<i64> {
222 let count = addresses::count_all_addresses(&self.lock_db()?.writer)?;
223 Ok(count)
224 }
225
226 #[handle_error(Error)]
227 pub fn update_address(&self, guid: String, address: UpdatableAddressFields) -> ApiResult<()> {
228 addresses::update_address(&self.lock_db()?.writer, &Guid::new(&guid), &address)
229 }
230
231 #[handle_error(Error)]
237 pub fn update_address_with_meta(
238 &self,
239 entry_with_meta: UpdatableAddressFieldsWithMeta,
240 ) -> ApiResult<()> {
241 addresses::update_address_with_meta(
242 &self.lock_db()?.writer,
243 entry_with_meta.fields,
244 entry_with_meta.meta,
245 )
246 }
247
248 #[handle_error(Error)]
249 pub fn delete_address(&self, guid: String) -> ApiResult<bool> {
250 addresses::delete_address(&self.lock_db()?.writer, &Guid::new(&guid))
251 }
252
253 #[handle_error(Error)]
254 pub fn touch_address(&self, guid: String) -> ApiResult<()> {
255 addresses::touch(&self.lock_db()?.writer, &Guid::new(&guid))
256 }
257
258 #[handle_error(Error)]
259 pub fn add_passport(&self, fields: UpdatablePassportFields) -> ApiResult<Passport> {
260 Ok(passports::add_passport(&self.lock_db()?.writer, fields)?.into())
261 }
262
263 #[handle_error(Error)]
264 pub fn get_passport(&self, guid: String) -> ApiResult<Passport> {
265 Ok(passports::get_passport(&self.lock_db()?.writer, &Guid::new(&guid))?.into())
266 }
267
268 #[handle_error(Error)]
269 pub fn get_all_passports(&self) -> ApiResult<Vec<Passport>> {
270 let passports = passports::get_all_passports(&self.lock_db()?.writer)?
271 .into_iter()
272 .map(|x| x.into())
273 .collect();
274 Ok(passports)
275 }
276
277 #[handle_error(Error)]
278 pub fn count_all_passports(&self) -> ApiResult<i64> {
279 passports::count_all_passports(&self.lock_db()?.writer)
280 }
281
282 #[handle_error(Error)]
283 pub fn update_passport(
284 &self,
285 guid: String,
286 passport: UpdatablePassportFields,
287 ) -> ApiResult<()> {
288 passports::update_passport(&self.lock_db()?.writer, &Guid::new(&guid), &passport)
289 }
290
291 #[handle_error(Error)]
292 pub fn delete_passport(&self, guid: String) -> ApiResult<bool> {
293 passports::delete_passport(&self.lock_db()?.writer, &Guid::new(&guid))
294 }
295
296 #[handle_error(Error)]
297 pub fn touch_passport(&self, guid: String) -> ApiResult<()> {
298 passports::touch(&self.lock_db()?.writer, &Guid::new(&guid))
299 }
300
301 #[handle_error(Error)]
302 pub fn scrub_encrypted_data(self: Arc<Self>) -> ApiResult<()> {
303 credit_cards::scrub_encrypted_credit_card_data(&self.lock_db()?.writer)?;
306 crate::sync::credit_card::create_engine(self).reset_local_sync_data()?;
309 Ok(())
310 }
311
312 #[handle_error(Error)]
313 pub fn scrub_undecryptable_credit_card_data_for_remote_replacement(
314 self: Arc<Self>,
315 local_encryption_key: String,
316 ) -> ApiResult<CreditCardsDeletionMetrics> {
317 let db = self.lock_db()?;
318 let deletion_stats =
319 credit_cards::scrub_undecryptable_credit_card_data_for_remote_replacement(
320 &db.writer,
321 local_encryption_key,
322 )?;
323
324 crate::sync::credit_card::create_engine(self.clone())
329 .reset_local_sync_data_for_verification(&db.writer)?;
330 Ok(deletion_stats)
331 }
332
333 #[handle_error(Error)]
334 pub fn run_maintenance(&self) -> ApiResult<()> {
335 let conn = self.lock_db()?;
336 run_maintenance(&conn)?;
337 Ok(())
338 }
339
340 pub fn shutdown(&self) {
341 if let Some(db) = self.db.lock().take() {
342 db.close();
343 }
344 }
345
346 pub fn register_with_sync_manager(self: Arc<Self>) {
352 let mut state = STORE_FOR_MANAGER.lock().unwrap();
353 *state = Arc::downgrade(&self);
354 }
355
356 pub fn create_credit_cards_sync_engine(self: Arc<Self>) -> Box<dyn SyncEngine> {
363 Box::new(crate::sync::credit_card::create_engine(self))
364 }
365
366 pub fn create_addresses_sync_engine(self: Arc<Self>) -> Box<dyn SyncEngine> {
367 Box::new(crate::sync::address::create_engine(self))
368 }
369}
370
371pub(crate) fn put_meta(conn: &Connection, key: &str, value: &dyn ToSql) -> Result<()> {
372 conn.execute_cached(
373 "REPLACE INTO moz_meta (key, value) VALUES (:key, :value)",
374 &[(":key", &key as &dyn ToSql), (":value", value)],
375 )?;
376 Ok(())
377}
378
379pub(crate) fn get_meta<T: FromSql>(conn: &Connection, key: &str) -> Result<Option<T>> {
380 let res = conn.try_query_one(
381 "SELECT value FROM moz_meta WHERE key = :key",
382 &[(":key", &key)],
383 true,
384 )?;
385 Ok(res)
386}
387
388pub(crate) fn delete_meta(conn: &Connection, key: &str) -> Result<()> {
389 conn.execute_cached("DELETE FROM moz_meta WHERE key = :key", &[(":key", &key)])?;
390 Ok(())
391}
392
393#[cfg(test)]
394mod tests {
395 use super::*;
396 use crate::db::test::new_mem_db;
397 use crate::encryption::EncryptorDecryptor;
398 use nss_as::ensure_initialized;
399
400 #[test]
401 fn test_autofill_meta() -> Result<()> {
402 let db = new_mem_db();
403 let test_key = "TEST KEY A";
404 let test_value = "TEST VALUE A";
405 let test_key2 = "TEST KEY B";
406 let test_value2 = "TEST VALUE B";
407
408 put_meta(&db, test_key, &test_value)?;
409 put_meta(&db, test_key2, &test_value2)?;
410
411 let retrieved_value: String = get_meta(&db, test_key)?.expect("test value");
412 let retrieved_value2: String = get_meta(&db, test_key2)?.expect("test value 2");
413
414 assert_eq!(retrieved_value, test_value);
415 assert_eq!(retrieved_value2, test_value2);
416
417 let test_value3 = "TEST VALUE C";
419 put_meta(&db, test_key, &test_value3)?;
420
421 let retrieved_value3: String = get_meta(&db, test_key)?.expect("test value 3");
422
423 assert_eq!(retrieved_value3, test_value3);
424
425 delete_meta(&db, test_key)?;
427 let retrieved_value4: Option<String> = get_meta(&db, test_key)?;
428 assert!(retrieved_value4.is_none());
429
430 db.writer.execute("DELETE FROM moz_meta", [])?;
431
432 Ok(())
433 }
434
435 #[test]
436 fn test_sync_manager_registration() {
437 let store = Arc::new(Store::new_shared_memory("sync-mgr-test").unwrap());
438 assert_eq!(Arc::strong_count(&store), 1);
439 assert_eq!(Arc::weak_count(&store), 0);
440 Arc::clone(&store).register_with_sync_manager();
441 assert_eq!(Arc::strong_count(&store), 1);
442 assert_eq!(Arc::weak_count(&store), 1);
443 let registered = STORE_FOR_MANAGER
444 .lock()
445 .unwrap()
446 .upgrade()
447 .expect("should upgrade");
448 assert!(Arc::ptr_eq(&store, ®istered));
449 drop(registered);
450 assert_eq!(Arc::strong_count(&store), 1);
452 assert_eq!(Arc::weak_count(&store), 1);
453 drop(store);
455 assert!(STORE_FOR_MANAGER.lock().unwrap().upgrade().is_none());
456 }
457
458 #[test]
459 fn test_shutdown_closes_the_store() {
460 let store = Store::new_shared_memory("shutdown-test").expect("create store");
461 assert_eq!(store.count_all_passports().expect("count"), 0);
463
464 store.shutdown();
465
466 assert!(store.count_all_passports().is_err());
469
470 store.shutdown();
472 }
473
474 #[test]
475 fn test_scrub_undecryptable_credit_card_data_for_remote_replacement() {
476 ensure_initialized();
477 let store = Arc::new(Store::new_shared_memory("sync-mgr-test").expect("create store"));
478 let key = EncryptorDecryptor::create_key().expect("create key");
479 let encdec = EncryptorDecryptor::new(&key).expect("create EncryptorDecryptor");
480
481 store
482 .add_credit_card(UpdatableCreditCardFields {
483 cc_name: "john deer".to_string(),
484 cc_number_enc: encdec
485 .encrypt("567812345678123456781")
486 .expect("encrypt cc number"),
487 cc_number_last_4: "6781".to_string(),
488 cc_exp_month: 10,
489 cc_exp_year: 2025,
490 cc_type: "mastercard".to_string(),
491 })
492 .expect("add credit card to database");
493
494 store
495 .scrub_undecryptable_credit_card_data_for_remote_replacement(key)
496 .expect("scrub credit card record");
497 }
498}