Firefox · Core
CVE-2026-74980
Logic Error in Core
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
Transitionmobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt |
modified | |
RenameAndChangeLocationDialogFragmentmobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/RenameAndChangeLocationDialogFragment.kt |
modified |
Files Changed
mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.ktmobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/RenameAndChangeLocationDialogFragment.kt
Patch
diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt
index e3dc093d419..bde1643a9a4 100644
--- a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt
+++ b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt
@@ -29,6 +29,7 @@ import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiSelector
import androidx.test.uiautomator.Until
+import mozilla.components.support.ktx.util.PromptAbuserDetector
import org.hamcrest.CoreMatchers.allOf
import org.mozilla.fenix.R
import org.mozilla.fenix.compose.snackbar.SNACKBAR_TEST_TAG
@@ -257,7 +258,9 @@ class DownloadRobot(private val composeTestRule: ComposeTestRule) {
class Transition(private val composeTestRule: ComposeTestRule) {
fun clickDownload(composeTestRule: ComposeTestRule, interact: DownloadRobot.() -> Unit): Transition {
Log.i(TAG, "clickDownload: Trying to click the \"Download\" download prompt button")
+ PromptAbuserDetector.validationsEnabled = false
composeTestRule.downloadButton().performClick()
+ PromptAbuserDetector.validationsEnabled = true
Log.i(TAG, "clickDownload: Clicked the \"Download\" download prompt button")
DownloadRobot(composeTestRule).interact()
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/RenameAndChangeLocationDialogFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/RenameAndChangeLocationDialogFragment.kt
index 61af9284515..0f7a30b76e5 100644
--- a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/RenameAndChangeLocationDialogFragment.kt
+++ b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/downloads/RenameAndChangeLocationDialogFragment.kt
@@ -20,6 +20,8 @@ import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import mozilla.components.concept.base.crash.Breadcrumb
import mozilla.components.support.base.log.logger.Logger
+import mozilla.components.support.ktx.util.PromptAbuserDetector
+import mozilla.components.support.utils.OnEnterAnimationCompleteListener
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents
@@ -38,10 +40,12 @@ import org.mozilla.fenix.theme.FirefoxTheme
*
* The callback [onConfirmSave] is invoked with the final file name and directory path.
*/
-class RenameAndChangeLocationDialogFragment : DialogFragment() {
+class RenameAndChangeLocationDialogFragment : DialogFragment(), OnEnterAnimationCompleteListener {
private val logger = Logger("RenameAndChangeLocationDialogFragment")
private val safeArguments get() = requireNotNull(arguments)
+ private val promptAbuserDetector = PromptAbuserDetector(TIME_SHOWN_OFFSET_MILLIS)
+
internal val fileName: String
get() = safeArguments.getString(KEY_FILE_NAME, "")
@@ -75,6 +79,15 @@ class RenameAndChangeLocationDialogFragment : DialogFragment() {
}
}
+ override fun onResume() {
+ super.onResume()
+ promptAbuserDetector.start()
+ }
+
+ override fun onEnterAnimationComplete() {
+ promptAbuserDetector.start()
+ }
+
override fun onCancel(dialog: DialogInterface) {
super.onCancel(dialog)
onCancel()
@@ -99,6 +112,8 @@ class RenameAndChangeLocationDialogFragment : DialogFragment() {
val composeView = createComposeView()
+ promptAbuserDetector.start()
+
return MaterialAlertDialogBuilder(requireContext())
.setView(composeView)
.create()
@@ -144,11 +159,15 @@ class RenameAndChangeLocationDialogFragment : DialogFragment() {
directoryLauncher.launch(null)
},
onConfirm = {
- onConfirmSave(
- dialogState.fileName,
- dialogState.directoryPath,
- )
- dismiss()
+ if (promptAbuserDetector.areDialogsBeingAbused()) {
+ promptAbuserDetector.updateJSDialogAbusedState()
+ } else {
+ onConfirmSave(
+ dialogState.fileName,
+ dialogState.directoryPath,
+ )
+ dismiss()
+ }
},
onCancel = {
onCancel()
@@ -182,6 +201,7 @@ class RenameAndChangeLocationDialogFragment : DialogFragment() {
private const val KEY_DIRECTORY_PATH = "directory_path"
private const val KEY_CONTENT_SIZE = "content_size"
const val RENAME_AND_CHANGE_LOCATION_DIALOG_TAG = "RENAME_AND_CHANGE_LOCATION_DIALOG_TAG"
+ private const val TIME_SHOWN_OFFSET_MILLIS = 500
/**
* Creates a new instance of [RenameAndChangeLocationDialogFragment].
@@ -203,3 +223,14 @@ class RenameAndChangeLocationDialogFragment : DialogFragment() {
}
}
}
+
+/**
+ * Starts (or restarts) the time-based check without increasing the "click count".
+ *
+ * Makes it safe to call from multiple/successive lifecycle methods, without running into the risk
+ * of triggering the more restrictive count-based protection on the 1st click (or even before it).
+ */
+private fun PromptAbuserDetector.start() {
+ resetJSAlertAbuseState()
+ updateJSDialogAbusedState()
+}
Loading diff…
References
On This Page