From 0e9843ccba9fefabcb33e81ea13756bbbf74506e Mon Sep 17 00:00:00 2001 From: Fabian Henneke Date: Tue, 3 Nov 2020 09:06:17 +0100 Subject: Make autofill-parser API explicit and refactor (#1182) (cherry picked from commit 73648b39d02086d1b964a89e049fe2c4ae3c33fc) --- .../autofillparser/AutofillFormParser.kt | 51 ++++++------ .../autofillparser/AutofillHelper.kt | 12 +-- .../autofillparser/AutofillScenario.kt | 95 ++++++++++++---------- .../autofillparser/AutofillStrategy.kt | 4 +- .../autofillparser/AutofillStrategyDsl.kt | 12 +-- .../autofillparser/FeatureAndTrustDetection.kt | 10 +-- .../autofillparser/FormField.kt | 4 +- .../autofillparser/PublicSuffixListCache.kt | 9 +- .../lib/publicsuffixlist/PublicSuffixList.kt | 73 +---------------- 9 files changed, 103 insertions(+), 167 deletions(-) (limited to 'autofill-parser/src') diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt index c9aa2f2e..d7dc1287 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt @@ -17,17 +17,17 @@ import com.github.ajalt.timberkt.d /** * A unique identifier for either an Android app (package name) or a website (origin minus port). */ -sealed class FormOrigin(open val identifier: String) { +public sealed class FormOrigin(public open val identifier: String) { - data class Web(override val identifier: String) : FormOrigin(identifier) - data class App(override val identifier: String) : FormOrigin(identifier) + public data class Web(override val identifier: String) : FormOrigin(identifier) + public data class App(override val identifier: String) : FormOrigin(identifier) - companion object { + public companion object { private const val BUNDLE_KEY_WEB_IDENTIFIER = "webIdentifier" private const val BUNDLE_KEY_APP_IDENTIFIER = "appIdentifier" - fun fromBundle(bundle: Bundle): FormOrigin? { + public fun fromBundle(bundle: Bundle): FormOrigin? { val webIdentifier = bundle.getString(BUNDLE_KEY_WEB_IDENTIFIER) if (webIdentifier != null) { return Web(webIdentifier) @@ -37,18 +37,19 @@ sealed class FormOrigin(open val identifier: String) { } } - fun getPrettyIdentifier(context: Context, untrusted: Boolean = true) = when (this) { - is Web -> identifier - is App -> { - val info = context.packageManager.getApplicationInfo( - identifier, PackageManager.GET_META_DATA - ) - val label = context.packageManager.getApplicationLabel(info) - if (untrusted) "“$label”" else "$label" + public fun getPrettyIdentifier(context: Context, untrusted: Boolean = true): String = + when (this) { + is Web -> identifier + is App -> { + val info = context.packageManager.getApplicationInfo( + identifier, PackageManager.GET_META_DATA + ) + val label = context.packageManager.getApplicationLabel(info) + if (untrusted) "“$label”" else "$label" + } } - } - fun toBundle() = Bundle().apply { + public fun toBundle(): Bundle = Bundle().apply { when (this@FormOrigin) { is Web -> putString(BUNDLE_KEY_WEB_IDENTIFIER, identifier) is App -> putString(BUNDLE_KEY_APP_IDENTIFIER, identifier) @@ -183,24 +184,24 @@ private class AutofillFormParser( } } -data class Credentials(val username: String?, val password: String?, val otp: String?) +public data class Credentials(val username: String?, val password: String?, val otp: String?) /** * Represents a collection of fields in a specific app that can be filled or saved. This is the * entry point to all fill and save features. */ @RequiresApi(Build.VERSION_CODES.O) -class FillableForm private constructor( - val formOrigin: FormOrigin, - val scenario: AutofillScenario, - val ignoredIds: List, - val saveFlags: Int? +public class FillableForm private constructor( + public val formOrigin: FormOrigin, + public val scenario: AutofillScenario, + public val ignoredIds: List, + public val saveFlags: Int? ) { - companion object { + public companion object { /** * Returns a [FillableForm] if a login form could be detected in [structure]. */ - fun parseAssistStructure( + public fun parseAssistStructure( context: Context, structure: AssistStructure, isManualRequest: Boolean, @@ -208,11 +209,11 @@ class FillableForm private constructor( ): FillableForm? { val form = AutofillFormParser(context, structure, isManualRequest, customSuffixes) if (form.formOrigin == null || form.scenario == null) return null - return FillableForm(form.formOrigin, form.scenario, form.ignoredIds, form.saveFlags) + return FillableForm(form.formOrigin, form.scenario.map { it.autofillId }, form.ignoredIds, form.saveFlags) } } - fun toClientState() = scenario.toBundle().apply { + public fun toClientState(): Bundle = scenario.toBundle().apply { putAll(formOrigin.toBundle()) } } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt index 9273f432..4c55783b 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillHelper.kt @@ -42,7 +42,7 @@ private fun stableHash(array: Collection): String { * In most cases apps will only have a single certificate. If there are multiple, this functions * returns all of them in sorted order and separated with `;`. */ -fun computeCertificatesHash(context: Context, appPackage: String): String { +public fun computeCertificatesHash(context: Context, appPackage: String): String { // The warning does not apply since 1) we are specifically hashing **all** signatures and 2) it // no longer applies to Android 4.4+. // Even though there is a new way to get the certificates as of Android Pie, we need to keep @@ -68,18 +68,18 @@ fun computeCertificatesHash(context: Context, appPackage: String): String { * Returns the "origin" (without port information) of the [AssistStructure.ViewNode] derived from * its `webDomain` and `webScheme`, if available. */ -val AssistStructure.ViewNode.webOrigin: String? +internal val AssistStructure.ViewNode.webOrigin: String? @RequiresApi(Build.VERSION_CODES.O) get() = webDomain?.let { domain -> val scheme = (if (Build.VERSION.SDK_INT >= 28) webScheme else null) ?: "https" "$scheme://$domain" } @RequiresApi(Build.VERSION_CODES.O) -class FixedSaveCallback(context: Context, private val callback: SaveCallback) { +public class FixedSaveCallback(context: Context, private val callback: SaveCallback) { private val applicationContext = context.applicationContext - fun onFailure(message: CharSequence) { + public fun onFailure(message: CharSequence) { callback.onFailure(message) // When targeting SDK 29, the message is no longer shown as a toast. // See https://developer.android.com/reference/android/service/autofill/SaveCallback#onFailure(java.lang.CharSequence) @@ -88,7 +88,7 @@ class FixedSaveCallback(context: Context, private val callback: SaveCallback) { } } - fun onSuccess(intentSender: IntentSender) { + public fun onSuccess(intentSender: IntentSender) { if (Build.VERSION.SDK_INT >= 28) { callback.onSuccess(intentSender) } else { @@ -117,7 +117,7 @@ private fun visitViewNode( } @RequiresApi(Build.VERSION_CODES.O) -fun AssistStructure.findNodeByAutofillId(autofillId: AutofillId): AssistStructure.ViewNode? { +internal fun AssistStructure.findNodeByAutofillId(autofillId: AutofillId): AssistStructure.ViewNode? { var node: AssistStructure.ViewNode? = null visitViewNodes(this) { if (it.autofillId == autofillId) diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt index a374bc37..f8ba4679 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt @@ -13,7 +13,7 @@ import android.view.autofill.AutofillValue import androidx.annotation.RequiresApi import com.github.ajalt.timberkt.e -enum class AutofillAction { +public enum class AutofillAction { Match, Search, Generate, FillOtpFromSms } @@ -24,18 +24,23 @@ enum class AutofillAction { * field is needed and available in the particular situation. */ @RequiresApi(Build.VERSION_CODES.O) -sealed class AutofillScenario { +public sealed class AutofillScenario { - companion object { + public companion object { - const val BUNDLE_KEY_USERNAME_ID = "usernameId" - const val BUNDLE_KEY_FILL_USERNAME = "fillUsername" - const val BUNDLE_KEY_OTP_ID = "otpId" - const val BUNDLE_KEY_CURRENT_PASSWORD_IDS = "currentPasswordIds" - const val BUNDLE_KEY_NEW_PASSWORD_IDS = "newPasswordIds" - const val BUNDLE_KEY_GENERIC_PASSWORD_IDS = "genericPasswordIds" + internal const val BUNDLE_KEY_USERNAME_ID = "usernameId" + internal const val BUNDLE_KEY_FILL_USERNAME = "fillUsername" + internal const val BUNDLE_KEY_OTP_ID = "otpId" + internal const val BUNDLE_KEY_CURRENT_PASSWORD_IDS = "currentPasswordIds" + internal const val BUNDLE_KEY_NEW_PASSWORD_IDS = "newPasswordIds" + internal const val BUNDLE_KEY_GENERIC_PASSWORD_IDS = "genericPasswordIds" - fun fromBundle(clientState: Bundle): AutofillScenario? { + @Deprecated("Use `fromClientState` instead.", ReplaceWith("fromClientState(clientState)", "com.github.androidpasswordstore.autofillparser.AutofillScenario.Companion.fromClientState")) + public fun fromBundle(clientState: Bundle): AutofillScenario? { + return fromClientState(clientState) + } + + public fun fromClientState(clientState: Bundle): AutofillScenario? { return try { Builder().apply { username = clientState.getParcelable(BUNDLE_KEY_USERNAME_ID) @@ -64,7 +69,7 @@ sealed class AutofillScenario { } } - class Builder { + internal class Builder { var username: T? = null var fillUsername = false @@ -94,22 +99,23 @@ sealed class AutofillScenario { } } - abstract val username: T? - abstract val fillUsername: Boolean - abstract val otp: T? - abstract val allPasswordFields: List - abstract val passwordFieldsToFillOnMatch: List - abstract val passwordFieldsToFillOnSearch: List - abstract val passwordFieldsToFillOnGenerate: List - abstract val passwordFieldsToSave: List + public abstract val username: T? + public abstract val passwordFieldsToSave: List - val fieldsToSave + internal abstract val otp: T? + internal abstract val allPasswordFields: List + internal abstract val fillUsername: Boolean + internal abstract val passwordFieldsToFillOnMatch: List + internal abstract val passwordFieldsToFillOnSearch: List + internal abstract val passwordFieldsToFillOnGenerate: List + + public val fieldsToSave: List get() = listOfNotNull(username) + passwordFieldsToSave - val allFields + internal val allFields: List get() = listOfNotNull(username, otp) + allPasswordFields - fun fieldsToFillOn(action: AutofillAction): List { + internal fun fieldsToFillOn(action: AutofillAction): List { val credentialFieldsToFill = when (action) { AutofillAction.Match -> passwordFieldsToFillOnMatch + listOfNotNull(otp) AutofillAction.Search -> passwordFieldsToFillOnSearch + listOfNotNull(otp) @@ -134,10 +140,23 @@ sealed class AutofillScenario { else -> emptyList() } } + + public fun hasFieldsToFillOn(action: AutofillAction): Boolean { + return fieldsToFillOn(action).isNotEmpty() + } + + public val hasFieldsToSave: Boolean + get() = fieldsToSave.isNotEmpty() + + public val hasPasswordFieldsToSave: Boolean + get() = fieldsToSave.minus(listOfNotNull(username)).isNotEmpty() + + public val hasUsername: Boolean + get() = username != null } @RequiresApi(Build.VERSION_CODES.O) -data class ClassifiedAutofillScenario( +internal data class ClassifiedAutofillScenario( override val username: T?, override val fillUsername: Boolean, override val otp: T?, @@ -158,7 +177,7 @@ data class ClassifiedAutofillScenario( } @RequiresApi(Build.VERSION_CODES.O) -data class GenericAutofillScenario( +internal data class GenericAutofillScenario( override val username: T?, override val fillUsername: Boolean, override val otp: T?, @@ -177,7 +196,7 @@ data class GenericAutofillScenario( get() = genericPassword } -fun AutofillScenario.passesOriginCheck(singleOriginMode: Boolean): Boolean { +internal fun AutofillScenario.passesOriginCheck(singleOriginMode: Boolean): Boolean { return if (singleOriginMode) { // In single origin mode, only the browsers URL bar (which is never filled) should have // a webOrigin. @@ -191,7 +210,7 @@ fun AutofillScenario.passesOriginCheck(singleOriginMode: Boolean): Bo @RequiresApi(Build.VERSION_CODES.O) @JvmName("fillWithAutofillId") -fun Dataset.Builder.fillWith( +public fun Dataset.Builder.fillWith( scenario: AutofillScenario, action: AutofillAction, credentials: Credentials? @@ -211,17 +230,7 @@ fun Dataset.Builder.fillWith( } } -@RequiresApi(Build.VERSION_CODES.O) -@JvmName("fillWithFormField") -fun Dataset.Builder.fillWith( - scenario: AutofillScenario, - action: AutofillAction, - credentials: Credentials? -) { - fillWith(scenario.map { it.autofillId }, action, credentials) -} - -inline fun AutofillScenario.map(transform: (T) -> S): AutofillScenario { +internal inline fun AutofillScenario.map(transform: (T) -> S): AutofillScenario { val builder = AutofillScenario.Builder() builder.username = username?.let(transform) builder.fillUsername = fillUsername @@ -240,7 +249,7 @@ inline fun AutofillScenario.map(transform: (T) -> S): Auto @RequiresApi(Build.VERSION_CODES.O) @JvmName("toBundleAutofillId") -private fun AutofillScenario.toBundle(): Bundle = when (this) { +internal fun AutofillScenario.toBundle(): Bundle = when (this) { is ClassifiedAutofillScenario -> { Bundle(5).apply { putParcelable(AutofillScenario.BUNDLE_KEY_USERNAME_ID, username) @@ -267,22 +276,18 @@ private fun AutofillScenario.toBundle(): Bundle = when (this) { } @RequiresApi(Build.VERSION_CODES.O) -@JvmName("toBundleFormField") -fun AutofillScenario.toBundle(): Bundle = map { it.autofillId }.toBundle() - -@RequiresApi(Build.VERSION_CODES.O) -fun AutofillScenario.recoverNodes(structure: AssistStructure): AutofillScenario? { +public fun AutofillScenario.recoverNodes(structure: AssistStructure): AutofillScenario? { return map { autofillId -> structure.findNodeByAutofillId(autofillId) ?: return null } } -val AutofillScenario.usernameValue: String? +public val AutofillScenario.usernameValue: String? @RequiresApi(Build.VERSION_CODES.O) get() { val value = username?.autofillValue ?: return null return if (value.isText) value.textValue.toString() else null } -val AutofillScenario.passwordValue: String? +public val AutofillScenario.passwordValue: String? @RequiresApi(Build.VERSION_CODES.O) get() { val distinctValues = passwordFieldsToSave.map { if (it.autofillValue?.isText == true) { diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategy.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategy.kt index b8356783..a98d6e81 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategy.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategy.kt @@ -23,7 +23,7 @@ private inline fun Pair.none(predicate: T.() -> Boolean) = * [AutofillDsl]. */ @RequiresApi(Build.VERSION_CODES.O) -val autofillStrategy = strategy { +internal val autofillStrategy = strategy { // Match two new password fields, an optional current password field right below or above, and // an optional username field with autocomplete hint. @@ -65,7 +65,7 @@ val autofillStrategy = strategy { } } currentPassword { - takeSingle { _ -> + takeSingle { hasAutocompleteHintCurrentPassword && isFocused } } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt index f3f6d97d..b29d34a7 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillStrategyDsl.kt @@ -10,10 +10,10 @@ import com.github.ajalt.timberkt.d import com.github.ajalt.timberkt.w @DslMarker -annotation class AutofillDsl +internal annotation class AutofillDsl @RequiresApi(Build.VERSION_CODES.O) -interface FieldMatcher { +internal interface FieldMatcher { fun match(fields: List, alreadyMatched: List): List? @@ -63,7 +63,7 @@ interface FieldMatcher { } @RequiresApi(Build.VERSION_CODES.O) -class SingleFieldMatcher( +internal class SingleFieldMatcher( private val take: (FormField, List) -> Boolean, private val tieBreakers: List<(FormField, List) -> Boolean> ) : FieldMatcher { @@ -157,7 +157,7 @@ private class PairOfFieldsMatcher( } @RequiresApi(Build.VERSION_CODES.O) -class AutofillRule private constructor( +internal class AutofillRule private constructor( private val matchers: List, private val applyInSingleOriginMode: Boolean, private val applyOnManualRequestOnly: Boolean, @@ -332,7 +332,7 @@ class AutofillRule private constructor( } @RequiresApi(Build.VERSION_CODES.O) -class AutofillStrategy private constructor(private val rules: List) { +internal class AutofillStrategy private constructor(private val rules: List) { @AutofillDsl class Builder { @@ -385,5 +385,5 @@ class AutofillStrategy private constructor(private val rules: List } } -fun strategy(block: AutofillStrategy.Builder.() -> Unit) = +internal fun strategy(block: AutofillStrategy.Builder.() -> Unit) = AutofillStrategy.Builder().apply(block).build() diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt index 4df13213..e244e2c5 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FeatureAndTrustDetection.kt @@ -89,7 +89,7 @@ private fun isTrustedBrowser(context: Context, appPackage: String): Boolean { return certificateHash in expectedCertificateHashes } -enum class BrowserMultiOriginMethod { +internal enum class BrowserMultiOriginMethod { None, WebView, Field } @@ -164,13 +164,13 @@ private fun getBrowserSaveFlag(context: Context, appPackage: String): Int? = isNoAccessibilityServiceEnabled(context) } -data class BrowserAutofillSupportInfo( +internal data class BrowserAutofillSupportInfo( val multiOriginMethod: BrowserMultiOriginMethod, val saveFlags: Int? ) @RequiresApi(Build.VERSION_CODES.O) -fun getBrowserAutofillSupportInfoIfTrusted( +internal fun getBrowserAutofillSupportInfoIfTrusted( context: Context, appPackage: String ): BrowserAutofillSupportInfo? { @@ -187,7 +187,7 @@ private val FLAKY_BROWSERS = listOf( "com.kiwibrowser.browser", ) -enum class BrowserAutofillSupportLevel { +public enum class BrowserAutofillSupportLevel { None, FlakyFill, PasswordFill, @@ -213,7 +213,7 @@ private fun getBrowserAutofillSupportLevel( } @RequiresApi(Build.VERSION_CODES.O) -fun getInstalledBrowsersWithAutofillSupportLevel(context: Context): List> { +public fun getInstalledBrowsersWithAutofillSupportLevel(context: Context): List> { val testWebIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("http://example.org") } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt index 91e51f5c..2ebfa47e 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt @@ -13,7 +13,7 @@ import androidx.annotation.RequiresApi import androidx.autofill.HintConstants import java.util.Locale -enum class CertaintyLevel { +internal enum class CertaintyLevel { Impossible, Possible, Likely, Certain } @@ -22,7 +22,7 @@ enum class CertaintyLevel { * extracted from its [AssistStructure.ViewNode]. */ @RequiresApi(Build.VERSION_CODES.O) -class FormField( +internal class FormField( node: AssistStructure.ViewNode, private val index: Int, passDownWebViewOrigins: Boolean, diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/PublicSuffixListCache.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/PublicSuffixListCache.kt index 316d102b..ef53565c 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/PublicSuffixListCache.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/PublicSuffixListCache.kt @@ -24,7 +24,7 @@ private object PublicSuffixListCache { } } -fun cachePublicSuffixList(context: Context) { +public fun cachePublicSuffixList(context: Context) { PublicSuffixListCache.getOrCachePublicSuffixList(context) } @@ -35,7 +35,7 @@ fun cachePublicSuffixList(context: Context) { * Note: Invalid domains, such as IP addresses, are returned unchanged and thus never collide with * the return value for valid domains. */ -fun getPublicSuffixPlusOne(context: Context, domain: String, customSuffixes: Sequence) = runBlocking { +internal fun getPublicSuffixPlusOne(context: Context, domain: String, customSuffixes: Sequence) = runBlocking { // We only feed valid domain names which are not IP addresses into getPublicSuffixPlusOne. // We do not check whether the domain actually exists (actually, not even whether its TLD // exists). As long as we restrict ourselves to syntactically valid domain names, @@ -55,7 +55,7 @@ fun getPublicSuffixPlusOne(context: Context, domain: String, customSuffixes: Seq * - null, if [domain] does not have [suffix] as a domain suffix or only with an empty prefix; * - the direct subdomain of [suffix] of which [domain] is a subdomain. */ -fun getSuffixPlusUpToOne(domain: String, suffix: String): String? { +private fun getSuffixPlusUpToOne(domain: String, suffix: String): String? { if (domain == suffix) return domain val prefix = domain.removeSuffix(".$suffix") @@ -65,7 +65,8 @@ fun getSuffixPlusUpToOne(domain: String, suffix: String): String? { return "$lastPrefixPart.$suffix" } -suspend fun getCanonicalSuffix(context: Context, domain: String, customSuffixes: Sequence): String { +private suspend fun getCanonicalSuffix( + context: Context, domain: String, customSuffixes: Sequence): String { val publicSuffixList = PublicSuffixListCache.getOrCachePublicSuffixList(context) val publicSuffixPlusOne = publicSuffixList.getPublicSuffixPlusOne(domain).await() ?: return domain diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt index f1cdb12a..3d1cb8d8 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixList.kt @@ -26,7 +26,7 @@ import kotlinx.coroutines.async * https://publicsuffix.org/ * https://github.com/publicsuffix/list */ -class PublicSuffixList( +internal class PublicSuffixList( context: Context, dispatcher: CoroutineDispatcher = Dispatchers.IO, private val scope: CoroutineScope = CoroutineScope(dispatcher) @@ -41,30 +41,6 @@ class PublicSuffixList( data.run { Unit } } - /** - * Returns true if the given [domain] is a public suffix; false otherwise. - * - * E.g.: - * ``` - * co.uk -> true - * com -> true - * mozilla.org -> false - * org -> true - * ``` - * - * Note that this method ignores the default "prevailing rule" described in the formal public suffix list algorithm: - * If no rule matches then the passed [domain] is assumed to *not* be a public suffix. - * - * @param [domain] _must_ be a valid domain. [PublicSuffixList] performs no validation, and if any unexpected values - * are passed (e.g., a full URL, a domain with a trailing '/', etc) this may return an incorrect result. - */ - fun isPublicSuffix(domain: String): Deferred = scope.async { - when (data.getPublicSuffixOffset(domain)) { - is PublicSuffixOffset.PublicSuffix -> true - else -> false - } - } - /** * Returns the public suffix and one more level; known as the registrable domain. Returns `null` if * [domain] is a public suffix itself. @@ -89,51 +65,4 @@ class PublicSuffixList( } } - /** - * Returns the public suffix of the given [domain]; known as the effective top-level domain (eTLD). Returns `null` - * if the [domain] is a public suffix itself. - * - * E.g.: - * ``` - * wwww.mozilla.org -> org - * www.bcc.co.uk -> co.uk - * a.b.ide.kyoto.jp -> ide.kyoto.jp - * ``` - * - * @param [domain] _must_ be a valid domain. [PublicSuffixList] performs no validation, and if any unexpected values - * are passed (e.g., a full URL, a domain with a trailing '/', etc) this may return an incorrect result. - */ - fun getPublicSuffix(domain: String) = scope.async { - when (val offset = data.getPublicSuffixOffset(domain)) { - is PublicSuffixOffset.Offset -> domain - .split('.') - .drop(offset.value + 1) - .joinToString(separator = ".") - else -> null - } - } - - /** - * Strips the public suffix from the given [domain]. Returns the original domain if no public suffix could be - * stripped. - * - * E.g.: - * ``` - * wwww.mozilla.org -> www.mozilla - * www.bcc.co.uk -> www.bbc - * a.b.ide.kyoto.jp -> a.b - * ``` - * - * @param [domain] _must_ be a valid domain. [PublicSuffixList] performs no validation, and if any unexpected values - * are passed (e.g., a full URL, a domain with a trailing '/', etc) this may return an incorrect result. - */ - fun stripPublicSuffix(domain: String) = scope.async { - when (val offset = data.getPublicSuffixOffset(domain)) { - is PublicSuffixOffset.Offset -> domain - .split('.') - .joinToString(separator = ".", limit = offset.value + 1, truncated = "") - .dropLast(1) - else -> domain - } - } } -- cgit v1.2.3