From 78f318b7fc9a89614456e3c425f4d27bea68b440 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Thu, 29 Aug 2019 16:05:41 -0700 Subject: [PATCH] Clean up commits for sync manager work, a few things still not finished before this is actually ready for review --- Cargo.lock | 3 + components/logins/src/db.rs | 2 +- components/logins/src/engine.rs | 1 + components/logins/src/lib.rs | 2 + components/places/src/api/places_api.rs | 26 ++- components/places/src/history_sync/store.rs | 2 +- components/sync15/src/lib.rs | 2 +- components/sync15/src/state.rs | 18 ++ components/sync15/src/status.rs | 3 + components/sync15/src/sync_multiple.rs | 7 +- components/sync_manager/Cargo.toml | 11 +- components/sync_manager/README.md | 13 ++ components/sync_manager/ffi/Cargo.toml | 8 +- components/sync_manager/ffi/src/lib.rs | 24 +-- components/sync_manager/src/error.rs | 8 + components/sync_manager/src/lib.rs | 7 - components/sync_manager/src/manager.rs | 180 ++++++++++++++++---- megazords/fenix/Cargo.toml | 2 +- megazords/full/Cargo.toml | 2 +- megazords/lockbox/Cargo.toml | 2 +- 20 files changed, 257 insertions(+), 66 deletions(-) create mode 100644 components/sync_manager/README.md diff --git a/Cargo.lock b/Cargo.lock index cd0c4c596a..456d35fbf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2402,7 +2402,10 @@ dependencies = [ "prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "prost-build 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "prost-derive 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "sql-support 0.1.0", "sync15 0.1.0", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/components/logins/src/db.rs b/components/logins/src/db.rs index 83b85a5f67..74b1121332 100644 --- a/components/logins/src/db.rs +++ b/components/logins/src/db.rs @@ -922,7 +922,7 @@ impl LoginDb { } } -pub(crate) struct LoginStore<'a> { +pub struct LoginStore<'a> { pub db: &'a LoginDb, pub scope: sql_support::SqlInterruptScope, } diff --git a/components/logins/src/engine.rs b/components/logins/src/engine.rs index 227d71ce5c..641e1c12c9 100644 --- a/components/logins/src/engine.rs +++ b/components/logins/src/engine.rs @@ -115,6 +115,7 @@ impl PasswordEngine { storage_init, root_sync_key, &store.scope, + None, ); // We always update the state - sync_multiple does the right thing // if it needs to be dropped (ie, they will be None or contain Nones etc) diff --git a/components/logins/src/lib.rs b/components/logins/src/lib.rs index fca4848208..22f33fedf4 100644 --- a/components/logins/src/lib.rs +++ b/components/logins/src/lib.rs @@ -17,6 +17,8 @@ mod util; mod ffi; +// Mostly exposed for the sync manager. +pub use crate::db::LoginStore; pub use crate::engine::*; pub use crate::error::*; pub use crate::login::*; diff --git a/components/places/src/api/places_api.rs b/components/places/src/api/places_api.rs index 2a978d124f..de51086533 100644 --- a/components/places/src/api/places_api.rs +++ b/components/places/src/api/places_api.rs @@ -68,9 +68,9 @@ lazy_static! { static ID_COUNTER: AtomicUsize = AtomicUsize::new(0); -struct SyncState { - mem_cached_state: Cell, - disk_cached_state: Cell>, +pub struct SyncState { + pub mem_cached_state: Cell, + pub disk_cached_state: Cell>, } /// The entry-point to the places API. This object gives access to database @@ -242,6 +242,7 @@ impl PlacesApi { client_init, key_bundle, &interruptee, + None, ) }, ) @@ -264,6 +265,7 @@ impl PlacesApi { client_init, key_bundle, &interruptee, + None, ) }, ) @@ -351,6 +353,7 @@ impl PlacesApi { client_init, key_bundle, &interruptee, + None, ); // even on failure we set the persisted state - sync itself takes care // to ensure this has been None'd out if necessary. @@ -382,6 +385,23 @@ impl PlacesApi { Ok(()) } + pub fn reset_history(&self) -> Result<()> { + // Take the lock to prevent syncing while we're doing this. + let _guard = self.sync_state.lock().unwrap(); + let conn = self.open_sync_connection()?; + + // Somewhat ironically, we start by migrating from the legacy storage + // format. We *are* just going to delete it anyway, but the code is + // simpler if we can just reuse the existing path. + HistoryStore::migrate_v1_global_state(&conn)?; + + // We'd rather you didn't interrupt this, but it's a required arg for + // HistoryStore + let scope = conn.begin_interrupt_scope(); + let store = HistoryStore::new(&conn, &scope); + store.do_reset(&sync15::StoreSyncAssociation::Disconnected) + } + /// Get a new interrupt handle for the sync connection. pub fn new_sync_conn_interrupt_handle(&self) -> Result { // Probably not necessary to lock here, since this should only get diff --git a/components/places/src/history_sync/store.rs b/components/places/src/history_sync/store.rs index cf53d81d88..823e2ffca3 100644 --- a/components/places/src/history_sync/store.rs +++ b/components/places/src/history_sync/store.rs @@ -89,7 +89,7 @@ impl<'a> HistoryStore<'a> { Ok(()) } - fn do_reset(&self, assoc: &StoreSyncAssociation) -> Result<()> { + pub(crate) fn do_reset(&self, assoc: &StoreSyncAssociation) -> Result<()> { let tx = self.db.begin_transaction()?; reset_storage(self.db)?; self.put_meta(LAST_SYNC_META_KEY, &0)?; diff --git a/components/sync15/src/lib.rs b/components/sync15/src/lib.rs index 265f99c332..3a1d499d99 100644 --- a/components/sync15/src/lib.rs +++ b/components/sync15/src/lib.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#![allow(unknown_lints)] +#![allow(unknown_lints, clippy::implicit_hasher)] #![warn(rust_2018_idioms)] mod bso_record; diff --git a/components/sync15/src/state.rs b/components/sync15/src/state.rs index 236a3556f7..0e345a35fc 100644 --- a/components/sync15/src/state.rs +++ b/components/sync15/src/state.rs @@ -87,6 +87,24 @@ pub struct GlobalState { pub keys: EncryptedBso, } +impl GlobalState { + // TODO: this function needs to change once we understand 'accepted'. + pub fn update_declined_engines(&mut self, changes: &HashMap) { + let mut current_state: HashMap = self.global.declined.iter().map(|e| (e.to_string(), false)).collect(); + for (e, v) in changes { + current_state.insert(e.to_string(), *v); + } + let new_declined = current_state.into_iter().filter_map(|(e, allow)| { + if allow { + None + } else { + Some(e) + } + }).collect::>(); + self.global.declined = new_declined; + } +} + /// Creates a fresh `meta/global` record, using the default engine selections, /// and declined engines from our PersistedGlobalState. fn new_global(pgs: &PersistedGlobalState) -> error::Result { diff --git a/components/sync15/src/status.rs b/components/sync15/src/status.rs index 5f80334b4a..e2293c55e7 100644 --- a/components/sync15/src/status.rs +++ b/components/sync15/src/status.rs @@ -66,6 +66,9 @@ pub struct SyncResult { /// The general health. pub service_status: ServiceStatus, + /// The set of declined engines, if we know them. + pub declined: Option>, + /// The result of the sync. pub result: Result<(), Error>, diff --git a/components/sync15/src/sync_multiple.rs b/components/sync15/src/sync_multiple.rs index 74a9adb161..43a4718a7b 100644 --- a/components/sync15/src/sync_multiple.rs +++ b/components/sync15/src/sync_multiple.rs @@ -70,10 +70,12 @@ pub fn sync_multiple( storage_init: &Sync15StorageClientInit, root_sync_key: &KeyBundle, interruptee: &impl Interruptee, + engines_to_state_change: Option<&HashMap>, ) -> SyncResult { let mut sync_result = SyncResult { service_status: ServiceStatus::OtherError, result: Ok(()), + declined: None, engine_results: HashMap::with_capacity(stores.len()), telemetry: telemetry::SyncTelemetryPing::new(), }; @@ -85,6 +87,7 @@ pub fn sync_multiple( root_sync_key, interruptee, &mut sync_result, + engines_to_state_change, ) { Ok(()) => { log::debug!( @@ -114,6 +117,7 @@ fn do_sync_multiple( root_sync_key: &KeyBundle, interruptee: &impl Interruptee, sync_result: &mut SyncResult, + engines_to_state_change: Option<&HashMap>, ) -> result::Result<(), Error> { if interruptee.was_interrupted() { sync_result.service_status = ServiceStatus::Interrupted; @@ -160,7 +164,8 @@ fn do_sync_multiple( } } None => { - log::info!("The application didn't give us persisted state - this is only expected on the very first run for a given user."); + log::info!("The application didn't give us persisted state - \ + this is only expected on the very first run for a given user."); PersistedGlobalState::default() } }; diff --git a/components/sync_manager/Cargo.toml b/components/sync_manager/Cargo.toml index 49cbcfbd8a..135311329c 100644 --- a/components/sync_manager/Cargo.toml +++ b/components/sync_manager/Cargo.toml @@ -7,16 +7,19 @@ license = "MPL-2.0" [dependencies] sync15 = { path = "../sync15" } -places = { path = "../places", optional = true } -logins = { path = "../logins", optional = true } +places = { path = "../places" } +logins = { path = "../logins" } ffi-support = { path = "../support/ffi" } failure = "0.1.5" error-support = { path = "../support/error" } prost = "0.5.0" prost-derive = "0.5.0" bytes = "0.4.12" -lazy_static = "1.3.0" -log = "0.4.7" +lazy_static = "1.4.0" +log = "0.4.8" +sql-support = { path = "../support/sql" } +url = "1.7.2" +serde_json = "1.0.40" [build-dependencies] prost-build = "0.5.0" diff --git a/components/sync_manager/README.md b/components/sync_manager/README.md new file mode 100644 index 0000000000..036f3a082e --- /dev/null +++ b/components/sync_manager/README.md @@ -0,0 +1,13 @@ +# Sync Manager + +It's a bit unfortunate this component can't just be part of `sync15`. +Conceptually and functionally, it shares most in common with with the `sync15` +crate, and in some cases stretches (or arguably breaks) the abstraction barrier +that `sync15` puts up. + +Unfortunately, places/logins/etc depend on sync15 directly, and so to prevent a +dependency cycle (which is disallowed by cargo), doing so would require +implementing the manager in a fully generic manner, with no specific handling of +underlying crates. This seems extremely difficult to me, so this is split out +into it's own crate, which might happen to reach into the guts of `sync15` in +some cases. \ No newline at end of file diff --git a/components/sync_manager/ffi/Cargo.toml b/components/sync_manager/ffi/Cargo.toml index 8b3bf8f9b5..30d9f4a149 100644 --- a/components/sync_manager/ffi/Cargo.toml +++ b/components/sync_manager/ffi/Cargo.toml @@ -6,14 +6,14 @@ edition = "2018" license = "MPL-2.0" [features] -logins = ["sync_manager/logins", "logins_ffi"] -places = ["sync_manager/places", "places-ffi"] +# logins = ["sync_manager/logins", "logins_ffi"] +# places = ["sync_manager/places", "places-ffi"] [dependencies] sync_manager = { path = ".." } sync15 = { path = "../../sync15" } ffi-support = { path = "../../support/ffi" } -places-ffi = { path = "../../places/ffi", optional = true } -logins_ffi = { path = "../../logins/ffi", optional = true } +places-ffi = { path = "../../places/ffi" }#, optional = true } +logins_ffi = { path = "../../logins/ffi" }#, optional = true } prost = "0.5.0" log = "0.4.7" diff --git a/components/sync_manager/ffi/src/lib.rs b/components/sync_manager/ffi/src/lib.rs index c38537b8d0..2c53196a2d 100644 --- a/components/sync_manager/ffi/src/lib.rs +++ b/components/sync_manager/ffi/src/lib.rs @@ -14,7 +14,7 @@ use sync_manager::Result as MgrResult; #[no_mangle] pub extern "C" fn sync_manager_set_places(_places_api_handle: u64, error: &mut ExternError) { ffi_support::call_with_result(error, || -> MgrResult<()> { - #[cfg(feature = "places")] + // #[cfg(feature = "places")] { let api = places_ffi::APIS .get_u64(_places_api_handle, |api| -> Result<_, HandleError> { @@ -23,18 +23,18 @@ pub extern "C" fn sync_manager_set_places(_places_api_handle: u64, error: &mut E sync_manager::set_places(api); Ok(()) } - #[cfg(not(feature = "places"))] - { - log::error!("Sync manager not compiled with places support"); - Err(sync_manager::ErrorKind::UnsupportedFeature("places".to_string()).into()) - } + // #[cfg(not(feature = "places"))] + // { + // log::error!("Sync manager not compiled with places support"); + // Err(sync_manager::ErrorKind::UnsupportedFeature("places".to_string()).into()) + // } }) } #[no_mangle] pub extern "C" fn sync_manager_set_logins(_logins_handle: u64, error: &mut ExternError) { ffi_support::call_with_result(error, || -> MgrResult<()> { - #[cfg(feature = "logins")] + // #[cfg(feature = "logins")] { let api = logins_ffi::ENGINES .get_u64(_logins_handle, |api| -> Result<_, HandleError> { @@ -43,11 +43,11 @@ pub extern "C" fn sync_manager_set_logins(_logins_handle: u64, error: &mut Exter sync_manager::set_logins(api); Ok(()) } - #[cfg(not(feature = "logins"))] - { - log::error!("Sync manager not compiled with logins support"); - Err(sync_manager::ErrorKind::UnsupportedFeature("logins".to_string()).into()) - } + // #[cfg(not(feature = "logins"))] + // { + // log::error!("Sync manager not compiled with logins support"); + // Err(sync_manager::ErrorKind::UnsupportedFeature("logins".to_string()).into()) + // } }) } diff --git a/components/sync_manager/src/error.rs b/components/sync_manager/src/error.rs index 9326b398f0..ab24d9435c 100644 --- a/components/sync_manager/src/error.rs +++ b/components/sync_manager/src/error.rs @@ -15,11 +15,19 @@ pub enum ErrorKind { InvalidHandle(#[fail(cause)] ffi_support::HandleError), #[fail(display = "Protobuf decode error: {}", _0)] ProtobufDecodeError(#[fail(cause)] prost::DecodeError), + // Used for things like 'failed to decode the provided sync key because it's + // completely the wrong format', etc. + #[fail(display = "Sync error: {}", _0)] + Sync15Error(#[fail(cause)] sync15::Error), + #[fail(display = "URL parse error: {}", _0)] + UrlParseError(#[fail(cause)] url::ParseError), } error_support::define_error! { ErrorKind { (InvalidHandle, ffi_support::HandleError), (ProtobufDecodeError, prost::DecodeError), + (Sync15Error, sync15::Error), + (UrlParseError, url::ParseError), } } diff --git a/components/sync_manager/src/lib.rs b/components/sync_manager/src/lib.rs index 1ef5381eef..81dbe9bd43 100644 --- a/components/sync_manager/src/lib.rs +++ b/components/sync_manager/src/lib.rs @@ -15,12 +15,9 @@ pub mod msg_types { include!(concat!(env!("OUT_DIR"), "/msg_types.rs")); } -#[cfg(feature = "logins")] use logins::PasswordEngine; use manager::SyncManager; -#[cfg(feature = "places")] use places::PlacesApi; -#[cfg(any(feature = "places", feature = "logins"))] use std::sync::Arc; use std::sync::Mutex; @@ -28,13 +25,11 @@ lazy_static::lazy_static! { static ref MANAGER: Mutex = Mutex::new(SyncManager::new()); } -#[cfg(feature = "places")] pub fn set_places(places: Arc) { let mut manager = MANAGER.lock().unwrap(); manager.set_places(places); } -#[cfg(feature = "logins")] pub fn set_logins(places: Arc>) { let mut manager = MANAGER.lock().unwrap(); manager.set_logins(places); @@ -47,7 +42,5 @@ pub fn disconnect() { pub fn sync(params: msg_types::SyncParams) -> Result { let mut manager = MANAGER.lock().unwrap(); - // TODO: translate the protobuf message into something nicer to work with in - // Rust. manager.sync(params) } diff --git a/components/sync_manager/src/manager.rs b/components/sync_manager/src/manager.rs index 75a8cf6016..df214a7d11 100644 --- a/components/sync_manager/src/manager.rs +++ b/components/sync_manager/src/manager.rs @@ -2,70 +2,192 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#[cfg(feature = "places")] -use places::PlacesApi; -// use sql_support::SqlInterruptHandle; use crate::error::*; -use crate::msg_types::{SyncParams, SyncResult}; -#[cfg(feature = "logins")] +use crate::msg_types::{ServiceStatus, SyncParams, SyncResult}; use logins::PasswordEngine; -#[cfg(feature = "logins")] +use places::{bookmark_sync::store::BookmarksStore, history_sync::store::HistoryStore, PlacesApi}; +use std::collections::HashMap; use std::sync::Mutex; -#[cfg(any(feature = "places", feature = "logins"))] -use std::sync::{Arc, Weak}; +use std::sync::{atomic::AtomicUsize, Arc, Weak}; +use sync15::MemoryCachedState; + +const LOGINS_ENGINE: &str = "passwords"; +const HISTORY_ENGINE: &str = "history"; +const BOOKMARKS_ENGINE: &str = "bookmarks"; pub struct SyncManager { - #[cfg(feature = "places")] + mem_cached_state: Option, places: Weak, - #[cfg(feature = "logins")] logins: Weak>, } impl SyncManager { pub fn new() -> Self { Self { - #[cfg(feature = "places")] + mem_cached_state: None, places: Weak::new(), - #[cfg(feature = "logins")] logins: Weak::new(), } } - #[cfg(feature = "places")] pub fn set_places(&mut self, places: Arc) { self.places = Arc::downgrade(&places); } - #[cfg(feature = "logins")] pub fn set_logins(&mut self, logins: Arc>) { self.logins = Arc::downgrade(&logins); } pub fn disconnect(&mut self) { - unimplemented!(); + if let Some(logins) = self + .logins + .upgrade() + .as_ref() + .map(|l| l.lock().expect("poisoned logins mutex")) + { + if let Err(e) = logins.reset() { + log::error!("Failed to reset logins: {}", e); + } + } else { + log::warn!("Unable to wipe logins, be sure to call set_logins before disconnect if this is surprising"); + } + + if let Some(places) = self.places.upgrade() { + if let Err(e) = places.reset_bookmarks() { + log::error!("Failed to reset bookmarks: {}", e); + } + if let Err(e) = places.reset_history() { + log::error!("Failed to reset history: {}", e); + } + } else { + log::warn!("Unable to wipe places, be sure to call set_places before disconnect if this is surprising"); + } + } + + pub fn sync(&mut self, mut params: SyncParams) -> Result { + let mut places = self.places.upgrade(); + let logins = self.logins.upgrade(); + let mut have_engines = vec![]; + if places.is_some() { + have_engines.push(HISTORY_ENGINE); + have_engines.push(BOOKMARKS_ENGINE); + } + if logins.is_some() { + have_engines.push(LOGINS_ENGINE); + } + check_engine_list(¶ms.engines_to_sync, &have_engines)?; + + let key_bundle = sync15::KeyBundle::from_ksync_base64(¶ms.acct_sync_key)?; + let tokenserver_url = url::Url::parse(¶ms.acct_tokenserver_url)?; + + let logins_sync = should_sync(¶ms, LOGINS_ENGINE); + let bookmarks_sync = should_sync(¶ms, BOOKMARKS_ENGINE); + let history_sync = should_sync(¶ms, HISTORY_ENGINE); + + let places_conn = if bookmarks_sync || history_sync { + places + .as_mut() + .expect("already checked") + .open_sync_connection() + .ok() + } else { + None + }; + let l = logins.as_ref().map(|l| l.lock().expect("poisoned mutex")); + // XXX this isn't ideal, we should have real support for interruption. + let p = Arc::new(AtomicUsize::new(0)); + let interruptee = sql_support::SqlInterruptScope::new(p); + + let mut mem_cached_state = self.mem_cached_state.take().unwrap_or_default(); + let mut disk_cached_state = params.persisted_state.take(); + // `sync_multiple` takes a &[&dyn Store], but we need something to hold + // ownership of our stores. + let mut stores: Vec> = vec![]; + + if let Some(pc) = places_conn.as_ref() { + if history_sync { + stores.push(Box::new(HistoryStore::new(pc, &interruptee))) + } + if bookmarks_sync { + stores.push(Box::new(BookmarksStore::new(pc, &interruptee))) + } + } + + if let Some(le) = l.as_ref() { + assert!(logins_sync, "Should have already checked"); + stores.push(Box::new(logins::LoginStore::new(&le.db))); + } + + let store_refs: Vec<&dyn sync15::Store> = stores.iter().map(|s| &**s).collect(); + + let client_init = sync15::Sync15StorageClientInit { + key_id: params.acct_key_id.clone(), + access_token: params.acct_access_token.clone(), + tokenserver_url, + }; + + let result = sync15::sync_multiple( + &store_refs, + &mut disk_cached_state, + &mut mem_cached_state, + &client_init, + &key_bundle, + &interruptee, + Some(¶ms.engines_to_change_state), + ); + + let status = ServiceStatus::from(result.service_status) as i32; + let results: HashMap = result + .engine_results + .into_iter() + .filter_map(|(e, r)| r.err().map(|r| (e, r.to_string()))) + .collect(); + + // Unwrap here can never fail -- it indicates trying to serialize an + // unserializable type. + let telemetry_json = serde_json::to_string(&result.telemetry).unwrap(); + + Ok(SyncResult { + status, + results, + // XXX FIXME/FINISH ME + have_declined: false, + declined: vec![], + next_sync_allowed_at: None, + persisted_state: disk_cached_state.unwrap_or_default(), + telemetry_json: Some(telemetry_json), + }) } +} - pub fn sync(&mut self, params: SyncParams) -> Result { - check_engine_list(¶ms.engines_to_sync)?; - unimplemented!(); +impl From for ServiceStatus { + fn from(s15s: sync15::ServiceStatus) -> Self { + use sync15::ServiceStatus::*; + match s15s { + Ok => ServiceStatus::Ok, + NetworkError => ServiceStatus::NetworkError, + ServiceError => ServiceStatus::ServiceError, + AuthenticationError => ServiceStatus::AuthError, + BackedOff => ServiceStatus::BackedOff, + Interrupted => ServiceStatus::OtherError, // Eh... + OtherError => ServiceStatus::OtherError, + } } } -fn check_engine_list(list: &[String]) -> Result<()> { +fn should_sync(p: &SyncParams, engine: &str) -> bool { + p.sync_all_engines || p.engines_to_sync.iter().any(|e| e == engine) +} + +fn check_engine_list(list: &[String], have_engines: &[&str]) -> Result<()> { for e in list { - if e == "bookmarks" || e == "history" { - if cfg!(not(feature = "places")) { - return Err(ErrorKind::UnsupportedFeature(e.to_string()).into()); - } - continue; - } - if e == "passwords" { - if cfg!(not(feature = "logins")) { + if e == "bookmarks" || e == "history" || e == "passwords" { + if !have_engines.iter().any(|engine| e == engine) { return Err(ErrorKind::UnsupportedFeature(e.to_string()).into()); } - continue; + } else { + return Err(ErrorKind::UnknownEngine(e.to_string()).into()); } - return Err(ErrorKind::UnknownEngine(e.to_string()).into()); } Ok(()) } diff --git a/megazords/fenix/Cargo.toml b/megazords/fenix/Cargo.toml index 56c2c6c29e..2b9f973733 100644 --- a/megazords/fenix/Cargo.toml +++ b/megazords/fenix/Cargo.toml @@ -15,4 +15,4 @@ places-ffi = { path = "../../components/places/ffi" } push-ffi = { path = "../../components/push/ffi" } rc_log_ffi = { path = "../../components/rc_log" } viaduct = { path = "../../components/viaduct", default-features = false } -sync_manager_ffi = { path = "../../components/sync_manager/ffi", features = ["places"] } +sync_manager_ffi = { path = "../../components/sync_manager/ffi" }#, features = ["places"] } diff --git a/megazords/full/Cargo.toml b/megazords/full/Cargo.toml index b037fe6349..7f2bb9c0b0 100644 --- a/megazords/full/Cargo.toml +++ b/megazords/full/Cargo.toml @@ -15,5 +15,5 @@ places-ffi = { path = "../../components/places/ffi" } push-ffi = { path = "../../components/push/ffi" } rc_log_ffi = { path = "../../components/rc_log" } viaduct = { path = "../../components/viaduct", default_features = false } -sync_manager_ffi = { path = "../../components/sync_manager/ffi", features = ["logins", "places"] } +sync_manager_ffi = { path = "../../components/sync_manager/ffi" } lazy_static = "1.4.0" diff --git a/megazords/lockbox/Cargo.toml b/megazords/lockbox/Cargo.toml index 7e6f910109..b0df62bbc2 100644 --- a/megazords/lockbox/Cargo.toml +++ b/megazords/lockbox/Cargo.toml @@ -13,4 +13,4 @@ fxaclient_ffi = { path = "../../components/fxa-client/ffi" } logins_ffi = { path = "../../components/logins/ffi" } rc_log_ffi = { path = "../../components/rc_log" } viaduct = { path = "../../components/viaduct", default-features = false } -sync_manager_ffi = { path = "../../components/sync_manager/ffi", features = ["logins"] } +sync_manager_ffi = { path = "../../components/sync_manager/ffi" }