diff --git a/mobile/android/android-components/.buildconfig.yml b/mobile/android/android-components/.buildconfig.yml index 3d95247a97d86..474e227b9e912 100644 --- a/mobile/android/android-components/.buildconfig.yml +++ b/mobile/android/android-components/.buildconfig.yml @@ -533,6 +533,13 @@ projects: - components:support-test - components:support-utils - components:tooling-lint + components:concept-passwords-file: + description: An abstract definition of a component for importing passwords from + a file. + path: components/concept/passwords-file + publish: true + upstream_dependencies: + - components:tooling-lint components:concept-push: description: An abstract definition of a push service component. path: components/concept/push @@ -2033,6 +2040,14 @@ projects: - components:support-utils - components:tooling-lint - components:ui-icons + components:lib-passwords-file: + description: A concrete implementation of concept-passwords-file that imports + passwords from CSV files. + path: components/lib/passwords-file + publish: true + upstream_dependencies: + - components:concept-passwords-file + - components:tooling-lint components:lib-publicsuffixlist: description: A library for reading and using the public suffix list. path: components/lib/publicsuffixlist diff --git a/mobile/android/android-components/components/concept/passwords-file/build.gradle b/mobile/android/android-components/components/concept/passwords-file/build.gradle new file mode 100644 index 0000000000000..f908ada70391e --- /dev/null +++ b/mobile/android/android-components/components/concept/passwords-file/build.gradle @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +plugins { + alias(libs.plugins.dependency.analysis) +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + namespace = 'mozilla.components.concept.passwords.file' +} + +dependencies { + testImplementation libs.androidx.test.junit + testImplementation libs.kotlinx.coroutines.test + testImplementation libs.robolectric +} + +apply from: '../../../common-config.gradle' +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, project.name, project.ext.description) diff --git a/mobile/android/android-components/components/concept/passwords-file/lint-baseline.xml b/mobile/android/android-components/components/concept/passwords-file/lint-baseline.xml new file mode 100644 index 0000000000000..dc0eec78f4b10 --- /dev/null +++ b/mobile/android/android-components/components/concept/passwords-file/lint-baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/mobile/android/android-components/components/concept/passwords-file/src/main/AndroidManifest.xml b/mobile/android/android-components/components/concept/passwords-file/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000..e16cda1d34462 --- /dev/null +++ b/mobile/android/android-components/components/concept/passwords-file/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + diff --git a/mobile/android/android-components/components/concept/passwords-file/src/main/java/mozilla/components/concept/passwords/file/PasswordsFileImporter.kt b/mobile/android/android-components/components/concept/passwords-file/src/main/java/mozilla/components/concept/passwords/file/PasswordsFileImporter.kt new file mode 100644 index 0000000000000..54951f3997914 --- /dev/null +++ b/mobile/android/android-components/components/concept/passwords-file/src/main/java/mozilla/components/concept/passwords/file/PasswordsFileImporter.kt @@ -0,0 +1,47 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +package mozilla.components.concept.passwords.file + +import android.net.Uri + +/** + * An interface for importing passwords from a file. + */ +fun interface PasswordsFileImporter { + /** + * The result of a passwords file import. + * + * @property count The number of passwords imported. + */ + data class ImportResult(val count: Int) + + /** + * Imports passwords from the file at the given [uri]. + * + * @param uri The URI of the file to import passwords from. + * @return A [Result] containing [ImportResult] on success or an exception on failure. + */ + suspend fun importPasswordsFromUri(uri: Uri): Result + + companion object { + /** + * Creates a [PasswordsFileImporter] that always returns a successful [Result]. + * + * @param result The [ImportResult] to return on every import. + */ + fun alwaysSuccess( + result: ImportResult = ImportResult(count = 0), + ): PasswordsFileImporter = PasswordsFileImporter { Result.success(result) } + + /** + * Creates a [PasswordsFileImporter] that always returns a failed [Result]. + * + * @param exception The [Exception] to return on every import. + */ + fun alwaysFailure( + exception: Exception = IllegalStateException("Import failed"), + ): PasswordsFileImporter = PasswordsFileImporter { Result.failure(exception) } + } +} diff --git a/mobile/android/android-components/components/lib/passwords-file/build.gradle b/mobile/android/android-components/components/lib/passwords-file/build.gradle new file mode 100644 index 0000000000000..a182c18241b8b --- /dev/null +++ b/mobile/android/android-components/components/lib/passwords-file/build.gradle @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + namespace = 'mozilla.components.lib.passwords.file' +} + +dependencies { + api project(':components:concept-passwords-file') + implementation libs.kotlinx.coroutines + + testImplementation platform(libs.junit.bom) + testImplementation libs.junit4 + testImplementation libs.kotlinx.coroutines.test + testImplementation libs.robolectric +} + +apply from: '../../../common-config.gradle' +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, project.name, project.ext.description) diff --git a/mobile/android/android-components/components/lib/passwords-file/lint-baseline.xml b/mobile/android/android-components/components/lib/passwords-file/lint-baseline.xml new file mode 100644 index 0000000000000..dc0eec78f4b10 --- /dev/null +++ b/mobile/android/android-components/components/lib/passwords-file/lint-baseline.xml @@ -0,0 +1,4 @@ + + + + diff --git a/mobile/android/android-components/components/lib/passwords-file/src/main/AndroidManifest.xml b/mobile/android/android-components/components/lib/passwords-file/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000..e16cda1d34462 --- /dev/null +++ b/mobile/android/android-components/components/lib/passwords-file/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + diff --git a/mobile/android/android-components/components/lib/passwords-file/src/main/java/mozilla/components/lib/passwords/file/CsvPasswordsFileImporter.kt b/mobile/android/android-components/components/lib/passwords-file/src/main/java/mozilla/components/lib/passwords/file/CsvPasswordsFileImporter.kt new file mode 100644 index 0000000000000..9e9f62de2d03b --- /dev/null +++ b/mobile/android/android-components/components/lib/passwords-file/src/main/java/mozilla/components/lib/passwords/file/CsvPasswordsFileImporter.kt @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +package mozilla.components.lib.passwords.file + +import android.net.Uri +import mozilla.components.concept.passwords.file.PasswordsFileImporter +import mozilla.components.concept.passwords.file.PasswordsFileImporter.ImportResult + +/** + * A [PasswordsFileImporter] for CSV password files. + * + * This is a stub implementation. CSV parsing and storage insertion will be added in a follow-up. + */ +class CsvPasswordsFileImporter : PasswordsFileImporter { + override suspend fun importPasswordsFromUri(uri: Uri): Result = + Result.success(ImportResult(count = 0)) +} diff --git a/mobile/android/android-components/components/lib/passwords-file/src/test/java/mozilla/components/lib/passwords/file/CsvPasswordsFileImporterTest.kt b/mobile/android/android-components/components/lib/passwords-file/src/test/java/mozilla/components/lib/passwords/file/CsvPasswordsFileImporterTest.kt new file mode 100644 index 0000000000000..0dc383d018bb5 --- /dev/null +++ b/mobile/android/android-components/components/lib/passwords-file/src/test/java/mozilla/components/lib/passwords/file/CsvPasswordsFileImporterTest.kt @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +package mozilla.components.lib.passwords.file + +import android.net.Uri +import kotlinx.coroutines.test.runTest +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class CsvPasswordsFileImporterTest { + + @Test + fun `importPasswordsFromUri returns success with zero count`() = runTest { + val importer = CsvPasswordsFileImporter() + + val result = importer.importPasswordsFromUri(Uri.EMPTY) + + assertTrue(result.isSuccess) + assertEquals(0, result.getOrThrow().count) + } +} diff --git a/mobile/android/android-components/components/lib/passwords-file/src/test/resources/robolectric.properties b/mobile/android/android-components/components/lib/passwords-file/src/test/resources/robolectric.properties new file mode 100644 index 0000000000000..3f67ea5ac1bf1 --- /dev/null +++ b/mobile/android/android-components/components/lib/passwords-file/src/test/resources/robolectric.properties @@ -0,0 +1 @@ +sdk=35 diff --git a/taskcluster/config.yml b/taskcluster/config.yml index df334cdfa2889..0d41192924370 100644 --- a/taskcluster/config.yml +++ b/taskcluster/config.yml @@ -251,6 +251,7 @@ treeherder: 'concept-fetch': 'concept-fetch' 'concept-llm': 'concept-llm' 'concept-menu': 'concept-menu' + 'concept-passwords-file': 'concept-passwords-file' 'concept-push': 'concept-push' 'concept-storage': 'concept-storage' 'concept-storage-bookmarks': 'concept-storage-bookmarks' @@ -310,6 +311,7 @@ treeherder: 'lib-llm-gemininano': 'lib-llm-gemininano' 'lib-llm-mlpa': 'lib-llm-mlpa' 'lib-integrity-googleplay': 'lib-integrity-googleplay' + 'lib-passwords-file': 'lib-passwords-file' 'lib-shake': 'lib-shake' 'lib-publicsuffixlist': 'lib-publicsuffixlist' 'lib-push-firebase': 'lib-push-firebase'