diff --git a/app/src/geckoBeta/java/org/mozilla/fenix/engine/GeckoProvider.kt b/app/src/geckoBeta/java/org/mozilla/fenix/engine/GeckoProvider.kt index d9efeadee..b784e185f 100644 --- a/app/src/geckoBeta/java/org/mozilla/fenix/engine/GeckoProvider.kt +++ b/app/src/geckoBeta/java/org/mozilla/fenix/engine/GeckoProvider.kt @@ -6,10 +6,9 @@ import android.content.Context import android.os.Bundle import mozilla.components.browser.engine.gecko.autofill.GeckoLoginDelegateWrapper import mozilla.components.browser.engine.gecko.glean.GeckoAdapter +import mozilla.components.concept.storage.LoginsStorage import mozilla.components.lib.crash.handler.CrashHandlerService -import mozilla.components.lib.dataprotect.SecureAbove22Preferences import mozilla.components.service.experiments.Experiments -import mozilla.components.service.sync.logins.AsyncLoginsStorage import mozilla.components.service.sync.logins.GeckoLoginStorageDelegate import org.mozilla.fenix.Config import org.mozilla.fenix.ext.settings @@ -24,11 +23,10 @@ object GeckoProvider { @Synchronized fun getOrCreateRuntime( context: Context, - storage: AsyncLoginsStorage, - securePreferences: SecureAbove22Preferences + storage: LoginsStorage ): GeckoRuntime { if (runtime == null) { - runtime = createRuntime(context, storage, securePreferences) + runtime = createRuntime(context, storage) } return runtime!! @@ -36,8 +34,7 @@ object GeckoProvider { private fun createRuntime( context: Context, - storage: AsyncLoginsStorage, - securePreferences: SecureAbove22Preferences + storage: LoginsStorage ): GeckoRuntime { val builder = GeckoRuntimeSettings.Builder() @@ -69,7 +66,6 @@ object GeckoProvider { val geckoRuntime = GeckoRuntime.create(context, runtimeSettings) val loginStorageDelegate = GeckoLoginStorageDelegate( storage, - securePreferences, { context.settings().shouldAutofillLogins && context.settings().shouldPromptToSaveLogins } ) geckoRuntime.loginStorageDelegate = GeckoLoginDelegateWrapper(loginStorageDelegate) diff --git a/app/src/geckoNightly/java/org/mozilla/fenix/engine/GeckoProvider.kt b/app/src/geckoNightly/java/org/mozilla/fenix/engine/GeckoProvider.kt index 359262381..ba446ce13 100644 --- a/app/src/geckoNightly/java/org/mozilla/fenix/engine/GeckoProvider.kt +++ b/app/src/geckoNightly/java/org/mozilla/fenix/engine/GeckoProvider.kt @@ -6,9 +6,8 @@ import android.content.Context import android.os.Bundle import mozilla.components.browser.engine.gecko.autofill.GeckoLoginDelegateWrapper import mozilla.components.browser.engine.gecko.glean.GeckoAdapter +import mozilla.components.concept.storage.LoginsStorage import mozilla.components.lib.crash.handler.CrashHandlerService -import mozilla.components.lib.dataprotect.SecureAbove22Preferences -import mozilla.components.service.sync.logins.AsyncLoginsStorage import mozilla.components.service.sync.logins.GeckoLoginStorageDelegate import org.mozilla.fenix.Config import org.mozilla.fenix.ext.settings @@ -23,11 +22,10 @@ object GeckoProvider { @Synchronized fun getOrCreateRuntime( context: Context, - storage: AsyncLoginsStorage, - securePreferences: SecureAbove22Preferences + storage: LoginsStorage ): GeckoRuntime { if (runtime == null) { - runtime = createRuntime(context, storage, securePreferences) + runtime = createRuntime(context, storage) } return runtime!! @@ -35,8 +33,7 @@ object GeckoProvider { private fun createRuntime( context: Context, - storage: AsyncLoginsStorage, - securePreferences: SecureAbove22Preferences + storage: LoginsStorage ): GeckoRuntime { val builder = GeckoRuntimeSettings.Builder() @@ -61,7 +58,6 @@ object GeckoProvider { val geckoRuntime = GeckoRuntime.create(context, runtimeSettings) val loginStorageDelegate = GeckoLoginStorageDelegate( storage, - securePreferences, { context.settings().shouldAutofillLogins && context.settings().shouldPromptToSaveLogins } ) geckoRuntime.loginStorageDelegate = GeckoLoginDelegateWrapper(loginStorageDelegate) diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 4c5f01cd4..6bc91f3fc 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -328,8 +328,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session customTabId = customTabSessionId, fragmentManager = parentFragmentManager, loginValidationDelegate = DefaultLoginValidationDelegate( - context.components.core.asyncPasswordsStorage, - context.components.core.getSecureAbove22Preferences() + context.components.core.passwordsStorage ), isSaveLoginEnabled = { context.settings().shouldPromptToSaveLogins diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index 8e9398314..0e9b8a2a9 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -20,7 +20,6 @@ import mozilla.components.feature.accounts.push.SendTabFeature import mozilla.components.feature.push.AutoPushFeature import mozilla.components.feature.push.PushConfig import mozilla.components.lib.crash.CrashReporter -import mozilla.components.lib.dataprotect.SecureAbove22Preferences import mozilla.components.service.fxa.DeviceConfig import mozilla.components.service.fxa.ServerConfig import mozilla.components.service.fxa.SyncConfig @@ -30,7 +29,7 @@ import mozilla.components.service.fxa.manager.SCOPE_SESSION import mozilla.components.service.fxa.manager.SCOPE_SYNC import mozilla.components.service.fxa.manager.SyncEnginesStorage import mozilla.components.service.fxa.sync.GlobalSyncableStoreProvider -import mozilla.components.service.sync.logins.SyncableLoginsStore +import mozilla.components.service.sync.logins.SyncableLoginsStorage import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.Config import org.mozilla.fenix.FeatureFlags @@ -51,8 +50,7 @@ class BackgroundServices( crashReporter: CrashReporter, historyStorage: PlacesHistoryStorage, bookmarkStorage: PlacesBookmarksStorage, - passwordsStorage: SyncableLoginsStore, - secureAbove22Preferences: SecureAbove22Preferences + passwordsStorage: SyncableLoginsStorage ) { fun defaultDeviceName(context: Context): String = context.getString( @@ -88,7 +86,7 @@ class BackgroundServices( syncPeriodInMinutes = 240L) // four hours } - val pushService by lazy { FirebasePushService() } + private val pushService by lazy { FirebasePushService() } val push by lazy { makePushConfig()?.let { makePush(it) } } @@ -97,7 +95,6 @@ class BackgroundServices( GlobalSyncableStoreProvider.configureStore(SyncEngine.History to historyStorage) GlobalSyncableStoreProvider.configureStore(SyncEngine.Bookmarks to bookmarkStorage) GlobalSyncableStoreProvider.configureStore(SyncEngine.Passwords to passwordsStorage) - GlobalSyncableStoreProvider.configureKeyStorage(secureAbove22Preferences) } private val telemetryAccountObserver = TelemetryAccountObserver( diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index cc56661d0..3115d556f 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -29,8 +29,7 @@ class Components(private val context: Context) { analytics.crashReporter, core.historyStorage, core.bookmarksStorage, - core.syncablePasswordsStorage, - core.getSecureAbove22Preferences() + core.passwordsStorage ) } val services by lazy { Services(context, backgroundServices.accountManager) } diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index c67d35ef9..2d03bf4c8 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -9,7 +9,6 @@ import android.app.Application import android.content.Context import android.content.res.Configuration import io.sentry.Sentry -import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -38,8 +37,7 @@ import mozilla.components.feature.webcompat.WebCompatFeature import mozilla.components.feature.webnotifications.WebNotificationFeature import mozilla.components.lib.dataprotect.SecureAbove22Preferences import mozilla.components.lib.dataprotect.generateEncryptionKey -import mozilla.components.service.sync.logins.AsyncLoginsStorageAdapter -import mozilla.components.service.sync.logins.SyncableLoginsStore +import mozilla.components.service.sync.logins.SyncableLoginsStorage import org.mozilla.fenix.AppRequestInterceptor import org.mozilla.fenix.Config import org.mozilla.fenix.FeatureFlags @@ -47,7 +45,6 @@ import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.ext.settings import org.mozilla.fenix.test.Mockable -import java.io.File import java.util.concurrent.TimeUnit /** @@ -76,9 +73,7 @@ class Core(private val context: Context) { GeckoEngine( context, defaultSettings, - GeckoProvider.getOrCreateRuntime( - context, asyncPasswordsStorage, getSecureAbove22Preferences() - ) + GeckoProvider.getOrCreateRuntime(context, passwordsStorage) ).also { WebCompatFeature.install(it) } @@ -90,11 +85,7 @@ class Core(private val context: Context) { val client: Client by lazy { GeckoViewFetchClient( context, - GeckoProvider.getOrCreateRuntime( - context, - asyncPasswordsStorage, - getSecureAbove22Preferences() - ) + GeckoProvider.getOrCreateRuntime(context, passwordsStorage) ) } @@ -201,6 +192,8 @@ class Core(private val context: Context) { val bookmarksStorage by lazy { PlacesBookmarksStorage(context) } + val passwordsStorage by lazy { SyncableLoginsStorage(context, passwordsEncryptionKey) } + val tabCollectionStorage by lazy { TabCollectionStorage(context, sessionManager) } val topSiteStorage by lazy { TopSiteStorage(context) } @@ -209,36 +202,19 @@ class Core(private val context: Context) { val webAppManifestStorage by lazy { ManifestStorage(context) } - val asyncPasswordsStorage by lazy { - AsyncLoginsStorageAdapter.forDatabase( - File( - context.filesDir, - "logins.sqlite" - ).canonicalPath - ) - } - - val syncablePasswordsStorage by lazy { - SyncableLoginsStore( - asyncPasswordsStorage - ) { - CompletableDeferred(passwordsEncryptionKey) - } - } - /** * Shared Preferences that encrypt/decrypt using Android KeyStore and lib-dataprotect for 23+ * only on Nightly/Debug for now, otherwise simply stored. * See https://github.com/mozilla-mobile/fenix/issues/8324 */ - fun getSecureAbove22Preferences() = + private fun getSecureAbove22Preferences() = SecureAbove22Preferences( context = context, name = KEY_STORAGE_NAME, forceInsecure = !Config.channel.isNightlyOrDebug ) - val passwordsEncryptionKey: String = + private val passwordsEncryptionKey by lazy { getSecureAbove22Preferences().getString(PASSWORDS_KEY) ?: generateEncryptionKey(KEY_STRENGTH).also { if (context.settings().passwordsEncryptionKeyGenerated) { @@ -248,6 +224,7 @@ class Core(private val context: Context) { context.settings().recordPasswordsEncryptionKeyGenerated() getSecureAbove22Preferences().putString(PASSWORDS_KEY, it) } + } val trackingProtectionPolicyFactory = TrackingProtectionPolicyFactory(context.settings()) diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginSiteInfoFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginSiteInfoFragment.kt index 7a37cbd64..1e4e529d4 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginSiteInfoFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginSiteInfoFragment.kt @@ -94,9 +94,7 @@ class SavedLoginSiteInfoFragment : Fragment(R.layout.fragment_saved_login_site_i var deleteLoginJob: Deferred? = null val deleteJob = lifecycleScope.launch(IO) { deleteLoginJob = async { - requireContext().components.core.syncablePasswordsStorage.withUnlocked { - it.delete(args.savedLoginItem.id).await() - } + requireContext().components.core.passwordsStorage.delete(args.savedLoginItem.id) } deleteLoginJob?.await() withContext(Main) { diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt index e99015400..05082a6d3 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt @@ -22,7 +22,7 @@ import kotlinx.coroutines.ObsoleteCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import mozilla.appservices.logins.ServerPassword +import mozilla.components.concept.storage.Login import mozilla.components.lib.state.ext.consumeFrom import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity @@ -103,18 +103,16 @@ class SavedLoginsFragment : Fragment() { } private fun loadAndMapLogins() { - var deferredLogins: Deferred>? = null + var deferredLogins: Deferred>? = null val fetchLoginsJob = lifecycleScope.launch(IO) { deferredLogins = async { - requireContext().components.core.syncablePasswordsStorage.withUnlocked { - it.list().await() - } + requireContext().components.core.passwordsStorage.list() } val logins = deferredLogins?.await() logins?.let { withContext(Main) { savedLoginsStore.dispatch(SavedLoginsFragmentAction.UpdateLogins(logins.map { item -> - SavedLoginsItem(item.hostname, item.username, item.password, item.id) + SavedLoginsItem(item.origin, item.username, item.password, item.guid!!) })) } } diff --git a/app/src/test/java/org/mozilla/fenix/components/BackgroundServicesTest.kt b/app/src/test/java/org/mozilla/fenix/components/BackgroundServicesTest.kt index 8ba2698d7..500c68a3c 100644 --- a/app/src/test/java/org/mozilla/fenix/components/BackgroundServicesTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/BackgroundServicesTest.kt @@ -27,7 +27,7 @@ import org.mozilla.fenix.components.metrics.MetricController class BackgroundServicesTest { class TestableBackgroundServices( val context: Context - ) : BackgroundServices(context, mockk(), mockk(), mockk(), mockk(), mockk()) { + ) : BackgroundServices(context, mockk(), mockk(), mockk(), mockk()) { override fun makeAccountManager( context: Context, serverConfig: ServerConfig, diff --git a/app/src/test/java/org/mozilla/fenix/components/TestCore.kt b/app/src/test/java/org/mozilla/fenix/components/TestCore.kt index cb75c508a..000a3c0ba 100644 --- a/app/src/test/java/org/mozilla/fenix/components/TestCore.kt +++ b/app/src/test/java/org/mozilla/fenix/components/TestCore.kt @@ -11,7 +11,6 @@ import mozilla.components.browser.session.SessionManager import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.fetch.Client import mozilla.components.feature.pwa.WebAppShortcutManager -import mozilla.components.lib.dataprotect.SecureAbove22Preferences class TestCore(context: Context) : Core(context) { @@ -20,5 +19,4 @@ class TestCore(context: Context) : Core(context) { override val store = mockk() override val client = mockk() override val webAppShortcutManager = mockk() - override fun getSecureAbove22Preferences() = mockk(relaxed = true) }