ma1 pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android

Commits:

7 changed files:

Changes:

  • android-components/.buildconfig.yml
    ... ... @@ -1150,7 +1150,6 @@ projects:
    1150 1150
         - concept-tabstray
    
    1151 1151
         - concept-toolbar
    
    1152 1152
         - feature-session
    
    1153
    -    - feature-prompts
    
    1154 1153
         - feature-tabs
    
    1155 1154
         - lib-publicsuffixlist
    
    1156 1155
         - lib-state
    

  • android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt
    ... ... @@ -61,7 +61,6 @@ import mozilla.components.feature.prompts.dialog.ChoiceDialogFragment.Companion.
    61 61
     import mozilla.components.feature.prompts.dialog.ColorPickerDialogFragment
    
    62 62
     import mozilla.components.feature.prompts.dialog.ConfirmDialogFragment
    
    63 63
     import mozilla.components.feature.prompts.dialog.MultiButtonDialogFragment
    
    64
    -import mozilla.components.feature.prompts.dialog.PromptAbuserDetector
    
    65 64
     import mozilla.components.feature.prompts.dialog.PromptDialogFragment
    
    66 65
     import mozilla.components.feature.prompts.dialog.Prompter
    
    67 66
     import mozilla.components.feature.prompts.dialog.SaveLoginDialogFragment
    
    ... ... @@ -91,6 +90,7 @@ import mozilla.components.support.base.feature.UserInteractionHandler
    91 90
     import mozilla.components.support.base.log.logger.Logger
    
    92 91
     import mozilla.components.support.ktx.kotlin.ifNullOrEmpty
    
    93 92
     import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
    
    93
    +import mozilla.components.support.ktx.util.PromptAbuserDetector
    
    94 94
     import java.lang.ref.WeakReference
    
    95 95
     import java.security.InvalidParameterException
    
    96 96
     import java.util.Collections
    
    ... ... @@ -467,36 +467,51 @@ class PromptFeature private constructor(
    467 467
         internal fun onPromptRequested(session: SessionState) {
    
    468 468
             // Some requests are handle with intents
    
    469 469
             session.content.promptRequests.lastOrNull()?.let { promptRequest ->
    
    470
    -            store.state.findTabOrCustomTabOrSelectedTab(customTabId)?.let {
    
    471
    -                promptRequest.executeIfWindowedPrompt { exitFullscreenUsecase(it.id) }
    
    470
    +            if (session.content.permissionRequestsList.isNotEmpty()) {
    
    471
    +                onCancel(session.id, promptRequest.uid)
    
    472
    +            } else {
    
    473
    +                processPromptRequest(promptRequest, session)
    
    472 474
                 }
    
    475
    +        }
    
    476
    +    }
    
    473 477
     
    
    474
    -            when (promptRequest) {
    
    475
    -                is File -> {
    
    476
    -                    emitPromptDisplayedFact(promptName = "FilePrompt")
    
    477
    -                    filePicker.handleFileRequest(promptRequest)
    
    478
    -                }
    
    479
    -                is Share -> handleShareRequest(promptRequest, session)
    
    480
    -                is SelectCreditCard -> {
    
    481
    -                    emitSuccessfulCreditCardAutofillFormDetectedFact()
    
    482
    -                    if (isCreditCardAutofillEnabled() && promptRequest.creditCards.isNotEmpty()) {
    
    483
    -                        creditCardPicker?.handleSelectCreditCardRequest(promptRequest)
    
    484
    -                    }
    
    478
    +    @Suppress("NestedBlockDepth")
    
    479
    +    private fun processPromptRequest(
    
    480
    +        promptRequest: PromptRequest,
    
    481
    +        session: SessionState,
    
    482
    +    ) {
    
    483
    +        store.state.findTabOrCustomTabOrSelectedTab(customTabId)?.let {
    
    484
    +            promptRequest.executeIfWindowedPrompt { exitFullscreenUsecase(it.id) }
    
    485
    +        }
    
    486
    +
    
    487
    +        when (promptRequest) {
    
    488
    +            is File -> {
    
    489
    +                emitPromptDisplayedFact(promptName = "FilePrompt")
    
    490
    +                filePicker.handleFileRequest(promptRequest)
    
    491
    +            }
    
    492
    +
    
    493
    +            is Share -> handleShareRequest(promptRequest, session)
    
    494
    +            is SelectCreditCard -> {
    
    495
    +                emitSuccessfulCreditCardAutofillFormDetectedFact()
    
    496
    +                if (isCreditCardAutofillEnabled() && promptRequest.creditCards.isNotEmpty()) {
    
    497
    +                    creditCardPicker?.handleSelectCreditCardRequest(promptRequest)
    
    485 498
                     }
    
    486
    -                is SelectLoginPrompt -> {
    
    487
    -                    emitPromptDisplayedFact(promptName = "SelectLoginPrompt")
    
    488
    -                    if (promptRequest.logins.isNotEmpty()) {
    
    489
    -                        loginPicker?.handleSelectLoginRequest(promptRequest)
    
    490
    -                    }
    
    499
    +            }
    
    500
    +
    
    501
    +            is SelectLoginPrompt -> {
    
    502
    +                emitPromptDisplayedFact(promptName = "SelectLoginPrompt")
    
    503
    +                if (promptRequest.logins.isNotEmpty()) {
    
    504
    +                    loginPicker?.handleSelectLoginRequest(promptRequest)
    
    491 505
                     }
    
    492
    -                is SelectAddress -> {
    
    493
    -                    emitSuccessfulAddressAutofillFormDetectedFact()
    
    494
    -                    if (isAddressAutofillEnabled() && promptRequest.addresses.isNotEmpty()) {
    
    495
    -                        addressPicker?.handleSelectAddressRequest(promptRequest)
    
    496
    -                    }
    
    506
    +            }
    
    507
    +            is SelectAddress -> {
    
    508
    +                emitSuccessfulAddressAutofillFormDetectedFact()
    
    509
    +                if (isAddressAutofillEnabled() && promptRequest.addresses.isNotEmpty()) {
    
    510
    +                    addressPicker?.handleSelectAddressRequest(promptRequest)
    
    497 511
                     }
    
    498
    -                else -> handleDialogsRequest(promptRequest, session)
    
    499 512
                 }
    
    513
    +
    
    514
    +            else -> handleDialogsRequest(promptRequest, session)
    
    500 515
             }
    
    501 516
         }
    
    502 517
     
    

  • android-components/components/feature/sitepermissions/build.gradle
    ... ... @@ -58,8 +58,8 @@ dependencies {
    58 58
         implementation project(':concept-engine')
    
    59 59
         implementation project(':ui-icons')
    
    60 60
         implementation project(':support-ktx')
    
    61
    -    implementation project(':feature-prompts')
    
    62 61
         implementation project(':feature-tabs')
    
    62
    +    implementation project(':support-utils')
    
    63 63
     
    
    64 64
         implementation ComponentsDependencies.kotlin_coroutines
    
    65 65
     
    

  • android-components/components/feature/sitepermissions/src/main/java/mozilla/components/feature/sitepermissions/SitePermissionsDialogFragment.kt
    ... ... @@ -23,7 +23,7 @@ import android.widget.TextView
    23 23
     import androidx.annotation.VisibleForTesting
    
    24 24
     import androidx.appcompat.app.AppCompatDialogFragment
    
    25 25
     import androidx.core.content.ContextCompat
    
    26
    -import mozilla.components.feature.prompts.dialog.PromptAbuserDetector
    
    26
    +import mozilla.components.support.ktx.util.PromptAbuserDetector
    
    27 27
     
    
    28 28
     internal const val KEY_SESSION_ID = "KEY_SESSION_ID"
    
    29 29
     internal const val KEY_TITLE = "KEY_TITLE"
    

  • android-components/components/feature/sitepermissions/src/test/java/mozilla/components/feature/sitepermissions/SitePermissionsDialogFragmentTest.kt
    ... ... @@ -19,6 +19,7 @@ import mozilla.components.support.test.robolectric.testContext
    19 19
     import org.junit.Assert.assertEquals
    
    20 20
     import org.junit.Assert.assertFalse
    
    21 21
     import org.junit.Assert.assertTrue
    
    22
    +import org.junit.Ignore
    
    22 23
     import org.junit.Test
    
    23 24
     import org.junit.runner.RunWith
    
    24 25
     import org.mockito.Mockito.doNothing
    
    ... ... @@ -233,6 +234,7 @@ class SitePermissionsDialogFragmentTest {
    233 234
         }
    
    234 235
     
    
    235 236
         @Test
    
    237
    +    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    
    236 238
         fun `clicking on positive button notifies the feature (temporary)`() {
    
    237 239
             val mockFeature: SitePermissionsFeature = mock()
    
    238 240
             val fragment = spy(
    
    ... ... @@ -261,6 +263,7 @@ class SitePermissionsDialogFragmentTest {
    261 263
         }
    
    262 264
     
    
    263 265
         @Test
    
    266
    +    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    
    264 267
         fun `dismissing the dialog notifies the feature`() {
    
    265 268
             val mockFeature: SitePermissionsFeature = mock()
    
    266 269
             val fragment = spy(
    
    ... ... @@ -360,6 +363,7 @@ class SitePermissionsDialogFragmentTest {
    360 363
         }
    
    361 364
     
    
    362 365
         @Test
    
    366
    +    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    
    363 367
         fun `clicking on positive button notifies the feature (permanent)`() {
    
    364 368
             val mockFeature: SitePermissionsFeature = mock()
    
    365 369
             val fragment = spy(
    
    ... ... @@ -389,6 +393,7 @@ class SitePermissionsDialogFragmentTest {
    389 393
         }
    
    390 394
     
    
    391 395
         @Test
    
    396
    +    @Ignore("https://bugzilla.mozilla.org/show_bug.cgi?id=1903828")
    
    392 397
         fun `clicking on negative button notifies the feature (permanent)`() {
    
    393 398
             val mockFeature: SitePermissionsFeature = mock()
    
    394 399
             val fragment = spy(
    

  • android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/dialog/PromptAbuserDetector.ktandroid-components/components/support/utils/src/main/java/mozilla/components/support/ktx/util/PromptAbuserDetector.kt
    ... ... @@ -2,25 +2,38 @@
    2 2
      * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3 3
      * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4 4
     
    
    5
    -package mozilla.components.feature.prompts.dialog
    
    5
    +package mozilla.components.support.ktx.util
    
    6 6
     
    
    7
    +import androidx.annotation.VisibleForTesting
    
    7 8
     import java.util.Date
    
    8 9
     
    
    9 10
     /**
    
    10 11
      * Helper class to identify if a website has shown many dialogs.
    
    12
    + *  @param maxSuccessiveDialogSecondsLimit Maximum time required
    
    13
    + *  between dialogs in seconds before not showing more dialog.
    
    11 14
      */
    
    12 15
     class PromptAbuserDetector(private val maxSuccessiveDialogSecondsLimit: Int = MAX_SUCCESSIVE_DIALOG_SECONDS_LIMIT) {
    
    13 16
     
    
    14
    -    internal var jsAlertCount = 0
    
    15
    -    internal var lastDialogShownAt = Date()
    
    17
    +    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    
    18
    +    var jsAlertCount = 0
    
    19
    +
    
    20
    +    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    
    21
    +    var lastDialogShownAt = Date()
    
    22
    +
    
    16 23
         var shouldShowMoreDialogs = true
    
    17 24
             private set
    
    18 25
     
    
    26
    +    /**
    
    27
    +     * Updates internal state for alerts counts.
    
    28
    +     */
    
    19 29
         fun resetJSAlertAbuseState() {
    
    20 30
             jsAlertCount = 0
    
    21 31
             shouldShowMoreDialogs = true
    
    22 32
         }
    
    23 33
     
    
    34
    +    /**
    
    35
    +     * Updates internal state for last shown and count of dialogs.
    
    36
    +     */
    
    24 37
         fun updateJSDialogAbusedState() {
    
    25 38
             if (!areDialogsAbusedByTime()) {
    
    26 39
                 jsAlertCount = 0
    
    ... ... @@ -29,25 +42,35 @@ class PromptAbuserDetector(private val maxSuccessiveDialogSecondsLimit: Int = MA
    29 42
             lastDialogShownAt = Date()
    
    30 43
         }
    
    31 44
     
    
    45
    +    /**
    
    46
    +     * Indicates whether or not user wants to see more dialogs.
    
    47
    +     */
    
    32 48
         fun userWantsMoreDialogs(checkBox: Boolean) {
    
    33 49
             shouldShowMoreDialogs = checkBox
    
    34 50
         }
    
    35 51
     
    
    52
    +    /**
    
    53
    +     * Indicates whether dialogs are being abused or not.
    
    54
    +     */
    
    36 55
         fun areDialogsBeingAbused(): Boolean {
    
    37 56
             return areDialogsAbusedByTime() || areDialogsAbusedByCount()
    
    38 57
         }
    
    39 58
     
    
    40
    -    internal fun areDialogsAbusedByTime(): Boolean {
    
    59
    +    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
    
    60
    +    @Suppress("UndocumentedPublicFunction") // this is visible only for tests
    
    61
    +    fun now() = Date()
    
    62
    +
    
    63
    +    private fun areDialogsAbusedByTime(): Boolean {
    
    41 64
             return if (jsAlertCount == 0) {
    
    42 65
                 false
    
    43 66
             } else {
    
    44
    -            val now = Date()
    
    67
    +            val now = now()
    
    45 68
                 val diffInSeconds = (now.time - lastDialogShownAt.time) / SECOND_MS
    
    46 69
                 diffInSeconds < maxSuccessiveDialogSecondsLimit
    
    47 70
             }
    
    48 71
         }
    
    49 72
     
    
    50
    -    internal fun areDialogsAbusedByCount(): Boolean {
    
    73
    +    private fun areDialogsAbusedByCount(): Boolean {
    
    51 74
             return jsAlertCount > MAX_SUCCESSIVE_DIALOG_COUNT
    
    52 75
         }
    
    53 76
     
    

  • focus-android/app/src/androidTest/java/org/mozilla/focus/activity/SitePermissionsTest.kt
    ... ... @@ -229,6 +229,7 @@ class SitePermissionsTest {
    229 229
     
    
    230 230
         @SmokeTest
    
    231 231
         @Test
    
    232
    +    @Ignore
    
    232 233
         fun testLocationSharingAllowed() {
    
    233 234
             mockLocationUpdatesRule.setMockLocation()
    
    234 235
     
    
    ... ... @@ -244,6 +245,7 @@ class SitePermissionsTest {
    244 245
     
    
    245 246
         @SmokeTest
    
    246 247
         @Test
    
    248
    +    @Ignore
    
    247 249
         fun allowCameraPermissionsTest() {
    
    248 250
             Assume.assumeTrue(cameraManager.cameraIdList.isNotEmpty())
    
    249 251
             searchScreen {