diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt index d0e5ef7f8b14..cdb6ee0694fd 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt @@ -689,6 +689,7 @@ class BrowserTabFragment : override suspend fun onCredentialsAvailableToSave( currentUrl: String, credentials: LoginCredentials, + wasUsernameBackfilled: Boolean, ) { val username = credentials.username val password = credentials.password @@ -707,8 +708,8 @@ class BrowserTabFragment : withContext(dispatchers.main()) { when (matchType) { ExactMatch -> Timber.w("Credentials already exist for %s", currentUrl) - UsernameMatch -> showAutofillDialogUpdatePassword(currentUrl, credentials) - UsernameMissing -> showAutofillDialogUpdateUsername(currentUrl, credentials) + UsernameMatch -> showAutofillDialogUpdatePassword(currentUrl, credentials, wasUsernameBackfilled) + UsernameMissing -> showAutofillDialogUpdateUsername(currentUrl, credentials, wasUsernameBackfilled) NoMatch -> showAutofillDialogSaveCredentials(currentUrl, credentials) UrlOnlyMatch -> showAutofillDialogSaveCredentials(currentUrl, credentials) } @@ -2778,22 +2779,24 @@ class BrowserTabFragment : private fun showAutofillDialogUpdatePassword( currentUrl: String, credentials: LoginCredentials, + wasUsernameBackfilled: Boolean, ) { val url = webView?.url ?: return if (url != currentUrl) return - val dialog = credentialAutofillDialogFactory.autofillSavingUpdatePasswordDialog(url, credentials, tabId) + val dialog = credentialAutofillDialogFactory.autofillSavingUpdatePasswordDialog(url, credentials, tabId, wasUsernameBackfilled) showDialogHidingPrevious(dialog, CredentialUpdateExistingCredentialsDialog.TAG) } private fun showAutofillDialogUpdateUsername( currentUrl: String, credentials: LoginCredentials, + wasUsernameBackfilled: Boolean, ) { val url = webView?.url ?: return if (url != currentUrl) return - val dialog = credentialAutofillDialogFactory.autofillSavingUpdateUsernameDialog(url, credentials, tabId) + val dialog = credentialAutofillDialogFactory.autofillSavingUpdateUsernameDialog(url, credentials, tabId, wasUsernameBackfilled) showDialogHidingPrevious(dialog, CredentialUpdateExistingCredentialsDialog.TAG) } diff --git a/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/AutofillCredentialDialogs.kt b/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/AutofillCredentialDialogs.kt index 7e58d3eb9036..e4dcf46000bd 100644 --- a/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/AutofillCredentialDialogs.kt +++ b/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/AutofillCredentialDialogs.kt @@ -215,6 +215,7 @@ interface CredentialAutofillDialogFactory { url: String, credentials: LoginCredentials, tabId: String, + wasUsernameBackfilled: Boolean, ): DialogFragment /** @@ -224,6 +225,7 @@ interface CredentialAutofillDialogFactory { url: String, credentials: LoginCredentials, tabId: String, + wasUsernameBackfilled: Boolean, ): DialogFragment /** diff --git a/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/BrowserAutofill.kt b/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/BrowserAutofill.kt index 941a1ef02fe1..4caf121a44fa 100644 --- a/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/BrowserAutofill.kt +++ b/autofill/autofill-api/src/main/java/com/duckduckgo/autofill/api/BrowserAutofill.kt @@ -128,10 +128,15 @@ interface Callback { /** * Called when there are login credentials available to be saved. * When this is called, we'd typically want to prompt the user if they want to save the credentials. + * + * @param currentUrl The current URL of the webpage + * @param credentials The login credentials that can be saved + * @param wasUsernameBackfilled Whether the username was backfilled from a previous partial save */ suspend fun onCredentialsAvailableToSave( currentUrl: String, credentials: LoginCredentials, + wasUsernameBackfilled: Boolean, ) /** diff --git a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/AutofillJavascriptInterface.kt b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/AutofillJavascriptInterface.kt index 7dce0d01ef00..be55bad48fac 100644 --- a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/AutofillJavascriptInterface.kt +++ b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/AutofillJavascriptInterface.kt @@ -362,7 +362,7 @@ class AutofillStoredBackJavascriptInterface @Inject constructor( } is PromptToSave -> { - callback?.onCredentialsAvailableToSave(currentUrl, credentials) + callback?.onCredentialsAvailableToSave(currentUrl, credentials, wasUsernameBackfilled) } is UpdateSavedAutoLogin -> { diff --git a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/importing/gpm/webflow/autofill/AutofillNoOpCallbacks.kt b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/importing/gpm/webflow/autofill/AutofillNoOpCallbacks.kt index 8c9a35f141f7..4ea2c8739ce7 100644 --- a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/importing/gpm/webflow/autofill/AutofillNoOpCallbacks.kt +++ b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/importing/gpm/webflow/autofill/AutofillNoOpCallbacks.kt @@ -34,6 +34,7 @@ interface NoOpAutofillCallback : Callback { override suspend fun onCredentialsAvailableToSave( currentUrl: String, credentials: LoginCredentials, + wasUsernameBackfilled: Boolean, ) { } diff --git a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/CredentialAutofillDialogAndroidFactory.kt b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/CredentialAutofillDialogAndroidFactory.kt index badc6a00573c..175a760de35f 100644 --- a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/CredentialAutofillDialogAndroidFactory.kt +++ b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/CredentialAutofillDialogAndroidFactory.kt @@ -55,12 +55,14 @@ class CredentialAutofillDialogAndroidFactory @Inject constructor() : CredentialA url: String, credentials: LoginCredentials, tabId: String, + wasUsernameBackfilled: Boolean, ): DialogFragment { return AutofillUpdatingExistingCredentialsDialogFragment.instance( url, credentials, tabId, CredentialUpdateType.Password, + wasUsernameBackfilled = wasUsernameBackfilled, ) } @@ -68,12 +70,14 @@ class CredentialAutofillDialogAndroidFactory @Inject constructor() : CredentialA url: String, credentials: LoginCredentials, tabId: String, + wasUsernameBackfilled: Boolean, ): DialogFragment { return AutofillUpdatingExistingCredentialsDialogFragment.instance( url, credentials, tabId, CredentialUpdateType.Username, + wasUsernameBackfilled = wasUsernameBackfilled, ) } diff --git a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/credential/updating/AutofillUpdatingExistingCredentialsDialogFragment.kt b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/credential/updating/AutofillUpdatingExistingCredentialsDialogFragment.kt index ee6fd6d155df..26d65ccc055d 100644 --- a/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/credential/updating/AutofillUpdatingExistingCredentialsDialogFragment.kt +++ b/autofill/autofill-impl/src/main/java/com/duckduckgo/autofill/impl/ui/credential/updating/AutofillUpdatingExistingCredentialsDialogFragment.kt @@ -92,7 +92,7 @@ class AutofillUpdatingExistingCredentialsDialogFragment : BottomSheetDialogFragm container: ViewGroup?, savedInstanceState: Bundle?, ): View { - pixelNameDialogEvent(Shown)?.let { pixel.fire(it) } + pixelNameDialogEvent(Shown)?.let { pixel.fire(it, paramsForUpdateLoginPixel()) } autofillFireproofDialogSuppressor.autofillSaveOrUpdateDialogVisibilityChanged(visible = true) @@ -140,7 +140,7 @@ class AutofillUpdatingExistingCredentialsDialogFragment : BottomSheetDialogFragm } binding.updateCredentialsButton.setOnClickListener { - pixelNameDialogEvent(Updated)?.let { pixel.fire(it) } + pixelNameDialogEvent(Updated)?.let { pixel.fire(it, paramsForUpdateLoginPixel()) } val result = Bundle().also { it.putString(CredentialUpdateExistingCredentialsDialog.KEY_URL, originalUrl) @@ -182,7 +182,7 @@ class AutofillUpdatingExistingCredentialsDialogFragment : BottomSheetDialogFragm Timber.v("onCancel: AutofillUpdatingExistingCredentialsDialogFragment. User declined to update credentials") autofillFireproofDialogSuppressor.autofillSaveOrUpdateDialogVisibilityChanged(visible = false) - pixelNameDialogEvent(Dismissed)?.let { pixel.fire(it) } + pixelNameDialogEvent(Dismissed)?.let { pixel.fire(it, paramsForUpdateLoginPixel()) } } private fun pixelNameDialogEvent(dialogEvent: DialogEvent): AutofillPixelNames? { @@ -194,6 +194,10 @@ class AutofillUpdatingExistingCredentialsDialogFragment : BottomSheetDialogFragm } } + private fun paramsForUpdateLoginPixel(): Map { + return mapOf(PIXEL_PARAM_WAS_USERNAME_BACKFILLED to getWasUsernameBackfilled().toString()) + } + private interface DialogEvent { object Shown : DialogEvent object Dismissed : DialogEvent @@ -205,6 +209,7 @@ class AutofillUpdatingExistingCredentialsDialogFragment : BottomSheetDialogFragm private fun getOriginalUrl() = arguments?.getString(CredentialUpdateExistingCredentialsDialog.KEY_URL)!! private fun getUpdateType() = arguments?.getParcelable(CredentialUpdateExistingCredentialsDialog.KEY_CREDENTIAL_UPDATE_TYPE)!! + private fun getWasUsernameBackfilled() = arguments?.getBoolean(KEY_WAS_USERNAME_BACKFILLED)!! companion object { @@ -213,6 +218,7 @@ class AutofillUpdatingExistingCredentialsDialogFragment : BottomSheetDialogFragm credentials: LoginCredentials, tabId: String, credentialUpdateType: CredentialUpdateType, + wasUsernameBackfilled: Boolean, ): AutofillUpdatingExistingCredentialsDialogFragment { val fragment = AutofillUpdatingExistingCredentialsDialogFragment() fragment.arguments = @@ -221,8 +227,12 @@ class AutofillUpdatingExistingCredentialsDialogFragment : BottomSheetDialogFragm it.putParcelable(CredentialUpdateExistingCredentialsDialog.KEY_CREDENTIALS, credentials) it.putString(CredentialUpdateExistingCredentialsDialog.KEY_TAB_ID, tabId) it.putParcelable(CredentialUpdateExistingCredentialsDialog.KEY_CREDENTIAL_UPDATE_TYPE, credentialUpdateType) + it.putBoolean(KEY_WAS_USERNAME_BACKFILLED, wasUsernameBackfilled) } return fragment } + + private const val PIXEL_PARAM_WAS_USERNAME_BACKFILLED = "backfilled" + private const val KEY_WAS_USERNAME_BACKFILLED = "wasUsernameBackfilled" } } diff --git a/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/AutofillStoredBackJavascriptInterfaceTest.kt b/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/AutofillStoredBackJavascriptInterfaceTest.kt index e1cbd6d66d3c..998ae2571e91 100644 --- a/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/AutofillStoredBackJavascriptInterfaceTest.kt +++ b/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/AutofillStoredBackJavascriptInterfaceTest.kt @@ -417,6 +417,7 @@ class AutofillStoredBackJavascriptInterfaceTest { override suspend fun onCredentialsAvailableToSave( currentUrl: String, credentials: LoginCredentials, + wasUsernameBackfilled: Boolean, ) { credentialsToSave = credentials } diff --git a/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/InlineBrowserAutofillTest.kt b/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/InlineBrowserAutofillTest.kt index 0f28994e95a1..c0b0a91dfb1b 100644 --- a/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/InlineBrowserAutofillTest.kt +++ b/autofill/autofill-impl/src/test/java/com/duckduckgo/autofill/impl/InlineBrowserAutofillTest.kt @@ -56,6 +56,7 @@ class InlineBrowserAutofillTest { override suspend fun onCredentialsAvailableToSave( currentUrl: String, credentials: LoginCredentials, + wasUsernameBackfilled: Boolean, ) { }