Skip to content

Commit

Permalink
Extract blob download in iframes logic to make it reusable
Browse files Browse the repository at this point in the history
  • Loading branch information
CDRussell committed Nov 14, 2024
1 parent 3116b24 commit 14e9701
Show file tree
Hide file tree
Showing 27 changed files with 850 additions and 597 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import com.duckduckgo.app.browser.api.WebViewCapabilityChecker.WebViewCapability
import com.duckduckgo.browser.api.WebViewVersionProvider
import com.duckduckgo.common.utils.DispatcherProvider
import com.duckduckgo.common.utils.extensions.compareSemanticVersion
import com.duckduckgo.di.scopes.FragmentScope
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesBinding
import javax.inject.Inject
import kotlinx.coroutines.withContext

@ContributesBinding(FragmentScope::class)
@ContributesBinding(AppScope::class)
class RealWebViewCapabilityChecker @Inject constructor(
private val dispatchers: DispatcherProvider,
private val webViewVersionProvider: WebViewVersionProvider,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@

package com.duckduckgo.autofill.api

import android.os.Parcelable
import com.duckduckgo.autofill.api.domain.app.LoginCredentials
import com.duckduckgo.navigation.api.GlobalActivityStarter.ActivityParams
import kotlinx.parcelize.Parcelize

sealed interface AutofillScreens {

Expand Down Expand Up @@ -50,29 +48,6 @@ sealed interface AutofillScreens {
val loginCredentials: LoginCredentials,
val source: AutofillSettingsLaunchSource,
) : ActivityParams

object ImportGooglePassword {
data object AutofillImportViaGooglePasswordManagerScreen : ActivityParams {
private fun readResolve(): Any = AutofillImportViaGooglePasswordManagerScreen
}

sealed interface Result : Parcelable {

companion object {
const val RESULT_KEY = "importResult"
const val RESULT_KEY_DETAILS = "importResultDetails"
}

@Parcelize
data class Success(val importedCount: Int) : Result

@Parcelize
data class UserCancelled(val stage: String) : Result

@Parcelize
data object Error : Result
}
}
}

enum class AutofillSettingsLaunchSource {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ interface CsvCredentialConverter {
sealed interface CsvCredentialImportResult : Parcelable {

@Parcelize
data class Success(val numberCredentialsInSource: Int, val loginCredentialsToImport: List<LoginCredentials>) : CsvCredentialImportResult
data class Success(
val numberCredentialsInSource: Int,
val loginCredentialsToImport: List<LoginCredentials>,
) : CsvCredentialImportResult

@Parcelize
data object Error : CsvCredentialImportResult
Expand Down Expand Up @@ -80,15 +83,27 @@ class GooglePasswordManagerCsvCredentialConverter @Inject constructor(
}
}

private suspend fun deduplicateAndCleanup(allCredentials: List<LoginCredentials>): List<LoginCredentials> {
val dedupedCredentials = allCredentials.distinct()
val validCredentials = dedupedCredentials.filter { credentialValidator.isValid(it) }
val normalizedDomains = domainNameNormalizer.normalizeDomains(validCredentials)
val entriesNotAlreadySaved = filterNewCredentials(normalizedDomains)
return entriesNotAlreadySaved
private suspend fun deduplicateAndCleanup(allCredentials: List<GoogleCsvLoginCredential>): List<LoginCredentials> {
return allCredentials
.distinct()
.filter { credentialValidator.isValid(it) }
.toLoginCredentials()
.filterNewCredentials()
}

private suspend fun filterNewCredentials(credentials: List<LoginCredentials>): List<LoginCredentials> {
return existingCredentialMatchDetector.filterExistingCredentials(credentials)
private suspend fun List<GoogleCsvLoginCredential>.toLoginCredentials(): List<LoginCredentials> {
return this.map {
LoginCredentials(
domainTitle = it.title,
username = it.username,
password = it.password,
domain = domainNameNormalizer.normalize(it.url),
notes = it.notes,
)
}
}

private suspend fun List<LoginCredentials>.filterNewCredentials(): List<LoginCredentials> {
return existingCredentialMatchDetector.filterExistingCredentials(this)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.duckduckgo.autofill.impl.importing

import com.duckduckgo.autofill.api.domain.app.LoginCredentials
import com.duckduckgo.autofill.impl.importing.CsvCredentialParser.ParseResult
import com.duckduckgo.autofill.impl.importing.CsvCredentialParser.ParseResult.Error
import com.duckduckgo.autofill.impl.importing.CsvCredentialParser.ParseResult.Success
Expand All @@ -33,7 +32,7 @@ interface CsvCredentialParser {
suspend fun parseCsv(csv: String): ParseResult

sealed interface ParseResult {
data class Success(val credentials: List<LoginCredentials>) : ParseResult
data class Success(val credentials: List<GoogleCsvLoginCredential>) : ParseResult
data object Error : ParseResult
}
}
Expand Down Expand Up @@ -61,7 +60,7 @@ class GooglePasswordManagerCsvCredentialParser @Inject constructor(
* Format of the Google Password Manager CSV is:
* name | url | username | password | note
*/
private suspend fun convertToCredentials(csv: String): List<LoginCredentials> {
private suspend fun convertToCredentials(csv: String): List<GoogleCsvLoginCredential> {
return withContext(dispatchers.io()) {
val lines = mutableListOf<CsvRow>()
val iter = CsvReader.builder().build(csv).spliterator()
Expand All @@ -81,8 +80,8 @@ class GooglePasswordManagerCsvCredentialParser @Inject constructor(
}

parseToCredential(
domainTitle = it.getField(0).blanksToNull(),
domain = it.getField(1).blanksToNull(),
title = it.getField(0).blanksToNull(),
url = it.getField(1).blanksToNull(),
username = it.getField(2).blanksToNull(),
password = it.getField(3).blanksToNull(),
notes = it.getField(4).blanksToNull(),
Expand All @@ -92,15 +91,15 @@ class GooglePasswordManagerCsvCredentialParser @Inject constructor(
}

private fun parseToCredential(
domainTitle: String?,
domain: String?,
title: String?,
url: String?,
username: String?,
password: String?,
notes: String?,
): LoginCredentials {
return LoginCredentials(
domainTitle = domainTitle,
domain = domain,
): GoogleCsvLoginCredential {
return GoogleCsvLoginCredential(
title = title,
url = url,
username = username,
password = password,
notes = notes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,24 @@

package com.duckduckgo.autofill.impl.importing

import com.duckduckgo.autofill.api.domain.app.LoginCredentials
import com.duckduckgo.autofill.impl.urlmatcher.AutofillUrlMatcher
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesBinding
import javax.inject.Inject

interface DomainNameNormalizer {
suspend fun normalizeDomains(unnormalized: List<LoginCredentials>): List<LoginCredentials>
suspend fun normalize(unnormalizedUrl: String?): String?
}

@ContributesBinding(AppScope::class)
class DefaultDomainNameNormalizer @Inject constructor(
private val urlMatcher: AutofillUrlMatcher,
) : DomainNameNormalizer {
override suspend fun normalizeDomains(unnormalized: List<LoginCredentials>): List<LoginCredentials> {
return unnormalized.map {
val currentDomain = it.domain ?: return@map it
val normalizedDomain = urlMatcher.cleanRawUrl(currentDomain)
it.copy(domain = normalizedDomain)
override suspend fun normalize(unnormalizedUrl: String?): String? {
return if (unnormalizedUrl == null) {
null
} else {
urlMatcher.cleanRawUrl(unnormalizedUrl)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@
* limitations under the License.
*/

package com.duckduckgo.browser.api
package com.duckduckgo.autofill.impl.importing

interface WebViewMessageListening {

suspend fun isWebMessageListenerSupported(): Boolean
}
/**
* Data class representing the login credentials imported from a Google CSV file.
*/
data class GoogleCsvLoginCredential(
val url: String? = null,
val username: String? = null,
val password: String? = null,
val title: String? = null,
val notes: String? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@

package com.duckduckgo.autofill.impl.importing

import com.duckduckgo.autofill.api.domain.app.LoginCredentials
import com.duckduckgo.di.scopes.AppScope
import com.squareup.anvil.annotations.ContributesBinding
import javax.inject.Inject

interface ImportedCredentialValidator {
fun isValid(loginCredentials: LoginCredentials): Boolean
fun isValid(loginCredentials: GoogleCsvLoginCredential): Boolean
}

@ContributesBinding(AppScope::class)
class DefaultImportedCredentialValidator @Inject constructor() : ImportedCredentialValidator {

override fun isValid(loginCredentials: LoginCredentials): Boolean {
override fun isValid(loginCredentials: GoogleCsvLoginCredential): Boolean {
with(loginCredentials) {
if (domain?.startsWith(APP_PASSWORD_PREFIX) == true) return false
if (url?.startsWith(APP_PASSWORD_PREFIX) == true) {
return false
}

if (allFieldsEmpty()) {
return false
Expand All @@ -40,11 +41,11 @@ class DefaultImportedCredentialValidator @Inject constructor() : ImportedCredent
}
}

private fun LoginCredentials.allFieldsEmpty(): Boolean {
return domain.isNullOrBlank() &&
private fun GoogleCsvLoginCredential.allFieldsEmpty(): Boolean {
return url.isNullOrBlank() &&
username.isNullOrBlank() &&
password.isNullOrBlank() &&
domainTitle.isNullOrBlank() &&
title.isNullOrBlank() &&
notes.isNullOrBlank()
}

Expand Down
Loading

0 comments on commit 14e9701

Please sign in to comment.