Dan Ballard pushed to branch tor-browser-150.0a1-16.0-2 at The Tor Project / Applications / Tor Browser
Commits:
-
cadcb5ec
by clairehurst at 2026-04-30T09:56:22-07:00
9 changed files:
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/components/PlayStoreReviewPromptController.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/reviewprompt/ReviewPromptMiddleware.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/reviewprompt/ReviewPromptReducer.kt
- mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt
- mobile/android/fenix/app/src/main/res/navigation/nav_graph.xml
- mobile/android/fenix/app/src/main/res/xml/preferences.xml
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/components/PlayStoreReviewPromptControllerTest.kt
- mobile/android/fenix/app/src/test/java/org/mozilla/fenix/reviewprompt/ShowPlayStoreReviewPromptTest.kt
Changes:
| ... | ... | @@ -90,6 +90,12 @@ import org.mozilla.fenix.utils.isLargeScreenSize |
| 90 | 90 | import org.mozilla.fenix.wifi.WifiConnectionMonitor
|
| 91 | 91 | import java.util.concurrent.TimeUnit
|
| 92 | 92 | |
| 93 | +import android.app.Activity
|
|
| 94 | +import com.google.android.gms.tasks.Task
|
|
| 95 | +import com.google.android.gms.tasks.Tasks
|
|
| 96 | +import com.google.android.play.core.review.ReviewInfo
|
|
| 97 | +import com.google.android.play.core.review.ReviewManager
|
|
| 98 | + |
|
| 93 | 99 | private const val AMO_COLLECTION_MAX_CACHE_AGE = 2 * 24 * 60L // Two days in minutes
|
| 94 | 100 | |
| 95 | 101 | /**
|
| ... | ... | @@ -251,7 +257,7 @@ class Components(private val context: Context) { |
| 251 | 257 | |
| 252 | 258 | val playStoreReviewPromptController by lazyMonitored {
|
| 253 | 259 | PlayStoreReviewPromptController(
|
| 254 | - manager = ReviewManagerFactory.create(context),
|
|
| 260 | + manager = NoopReviewManager(context),
|
|
| 255 | 261 | numberOfAppLaunches = { settings.numberOfAppLaunches },
|
| 256 | 262 | )
|
| 257 | 263 | }
|
| ... | ... | @@ -422,6 +428,19 @@ class Components(private val context: Context) { |
| 422 | 428 | val torController by lazyMonitored { TorControllerGV(context) }
|
| 423 | 429 | }
|
| 424 | 430 | |
| 431 | +class NoopReviewManager(val value: Context) : ReviewManager {
|
|
| 432 | + override fun launchReviewFlow(
|
|
| 433 | + p0: Activity,
|
|
| 434 | + p1: ReviewInfo
|
|
| 435 | + ): Task<Void?> {
|
|
| 436 | + return Tasks.forResult(null)
|
|
| 437 | + }
|
|
| 438 | + |
|
| 439 | + override fun requestReviewFlow(): Task<ReviewInfo?> {
|
|
| 440 | + return Tasks.forResult(null)
|
|
| 441 | + }
|
|
| 442 | +}
|
|
| 443 | + |
|
| 425 | 444 | /**
|
| 426 | 445 | * Returns the [Components] object from within a [Composable].
|
| 427 | 446 | */
|
| ... | ... | @@ -47,80 +47,16 @@ class PlayStoreReviewPromptController( |
| 47 | 47 | onNotDisplayed: () -> Unit = {},
|
| 48 | 48 | onError: () -> Unit = {},
|
| 49 | 49 | ) {
|
| 50 | - logger.info("tryPromptReview in progress...")
|
|
| 51 | - val reviewInfoTask = withContext(Dispatchers.IO) { manager.requestReviewFlow() }
|
|
| 52 | - |
|
| 53 | - reviewInfoTask.addOnCompleteListener(activity) { task ->
|
|
| 54 | - val result = if (task.isSuccessful) {
|
|
| 55 | - logger.info("Review flow launched.")
|
|
| 56 | - // Launch the in-app flow.
|
|
| 57 | - manager.launchReviewFlow(activity, task.result)
|
|
| 58 | - |
|
| 59 | - ReviewPromptAttemptResult.from(task.result.toString())
|
|
| 60 | - } else {
|
|
| 61 | - Error
|
|
| 62 | - }
|
|
| 63 | - |
|
| 64 | - when (result) {
|
|
| 65 | - NotDisplayed -> {
|
|
| 66 | - logger.warn("In-app review flow reported as not displayed, even though there was no error.")
|
|
| 67 | - |
|
| 68 | - onNotDisplayed()
|
|
| 69 | - }
|
|
| 70 | - |
|
| 71 | - Error -> {
|
|
| 72 | - val reviewErrorCode =
|
|
| 73 | - (task.exception as? ReviewException)?.errorCode ?: ERROR_CODE_UNEXPECTED
|
|
| 74 | - logger.warn("Failed to launch in-app review flow due to: $reviewErrorCode.")
|
|
| 75 | - |
|
| 76 | - onError()
|
|
| 77 | - }
|
|
| 78 | - |
|
| 79 | - Displayed, Unknown -> {}
|
|
| 80 | - }
|
|
| 81 | - |
|
| 82 | - recordReviewPromptEvent(
|
|
| 83 | - promptAttemptResult = result,
|
|
| 84 | - numberOfAppLaunches = numberOfAppLaunches(),
|
|
| 85 | - now = Date(),
|
|
| 86 | - )
|
|
| 87 | - }
|
|
| 88 | - |
|
| 89 | - logger.info("tryPromptReview completed.")
|
|
| 50 | + logger.info("tryPromptReview has been successfully noop'ed.")
|
|
| 51 | + return
|
|
| 90 | 52 | }
|
| 91 | 53 | |
| 92 | 54 | /**
|
| 93 | 55 | * Try to launch the play store review flow.
|
| 94 | 56 | */
|
| 95 | 57 | fun tryLaunchPlayStoreReview(activity: Activity) {
|
| 96 | - logger.info("tryLaunchPlayStoreReview in progress...")
|
|
| 97 | - |
|
| 98 | - try {
|
|
| 99 | - logger.info("Navigating to Play store listing.")
|
|
| 100 | - activity.startActivity(
|
|
| 101 | - Intent(Intent.ACTION_VIEW, SupportUtils.RATE_APP_URL.toUri()),
|
|
| 102 | - )
|
|
| 103 | - } catch (e: ActivityNotFoundException) {
|
|
| 104 | - // Device without the play store installed.
|
|
| 105 | - // Opening the play store website.
|
|
| 106 | - |
|
| 107 | - activity.applicationContext.components.useCases.fenixBrowserUseCases.loadUrlOrSearch(
|
|
| 108 | - searchTermOrURL = SupportUtils.FENIX_PLAY_STORE_URL,
|
|
| 109 | - newTab = true,
|
|
| 110 | - )
|
|
| 111 | - |
|
| 112 | - // https://bugzilla.mozilla.org/show_bug.cgi?id=1997148
|
|
| 113 | - (activity as? FragmentActivity)
|
|
| 114 | - ?.supportFragmentManager
|
|
| 115 | - ?.fragments
|
|
| 116 | - ?.firstOrNull { it is NavHostFragment }
|
|
| 117 | - ?.let { (it as NavHostFragment).navController }
|
|
| 118 | - ?.openToBrowser()
|
|
| 119 | - |
|
| 120 | - logger.warn("Failed to launch play store review flow due to: $e.")
|
|
| 121 | - }
|
|
| 122 | - |
|
| 123 | - logger.info("tryLaunchPlayStoreReview completed.")
|
|
| 58 | + logger.info("tryLaunchPlayStoreReview has been successfully noop'ed.")
|
|
| 59 | + return
|
|
| 124 | 60 | }
|
| 125 | 61 | |
| 126 | 62 | companion object {
|
| ... | ... | @@ -105,23 +105,7 @@ class ReviewPromptMiddleware( |
| 105 | 105 | return
|
| 106 | 106 | }
|
| 107 | 107 | |
| 108 | - val shouldShowPrompt: Boolean = createJexlHelper().use { jexlHelper ->
|
|
| 109 | - // Keep the legacy criteria around, but use the nimbus data and jexl to trigger.
|
|
| 110 | - // Leaving the original if-else logic and early return for readability.
|
|
| 111 | - if (!shouldUseNewTriggerCriteria()) {
|
|
| 112 | - val legacyCriteriaSatisfied = buildTriggerLegacyCriteria(jexlHelper).all { it }
|
|
| 113 | - return@use legacyCriteriaSatisfied
|
|
| 114 | - }
|
|
| 115 | - |
|
| 116 | - // Otherwise, we use the new criteria.
|
|
| 117 | - val allMainCriteriaSatisfied = buildTriggerMainCriteria(jexlHelper).all { it }
|
|
| 118 | - if (!allMainCriteriaSatisfied) {
|
|
| 119 | - return@use false
|
|
| 120 | - }
|
|
| 121 | - |
|
| 122 | - val atLeastOneOfSubCriteriaSatisfied = buildTriggerSubCriteria(jexlHelper).any { it }
|
|
| 123 | - return@use atLeastOneOfSubCriteriaSatisfied
|
|
| 124 | - }
|
|
| 108 | + val shouldShowPrompt: Boolean = false
|
|
| 125 | 109 | |
| 126 | 110 | if (shouldShowPrompt) {
|
| 127 | 111 | if (shouldShowCustomPrompt()) {
|
| ... | ... | @@ -21,11 +21,6 @@ import org.mozilla.fenix.reviewprompt.ReviewPromptState.NotEligible |
| 21 | 21 | */
|
| 22 | 22 | internal object ReviewPromptReducer {
|
| 23 | 23 | fun reduce(state: AppState, action: ReviewPromptAction): AppState {
|
| 24 | - return when (action) {
|
|
| 25 | - ShowPlayStorePrompt -> state.copy(reviewPrompt = Eligible(Type.PlayStore))
|
|
| 26 | - ShowCustomReviewPrompt -> state.copy(reviewPrompt = Eligible(Type.Custom))
|
|
| 27 | - DoNotShowReviewPrompt, ReviewPromptShown -> state.copy(reviewPrompt = NotEligible)
|
|
| 28 | - CheckIfEligibleForReviewPrompt -> state
|
|
| 29 | - }
|
|
| 24 | + return state.copy(reviewPrompt = NotEligible)
|
|
| 30 | 25 | }
|
| 31 | 26 | } |
| ... | ... | @@ -544,12 +544,6 @@ class SettingsFragment : PreferenceFragmentCompat(), SystemInsetsPaddedFragment, |
| 544 | 544 | SettingsFragmentDirections.actionSettingsFragmentToSyncDebugFragment()
|
| 545 | 545 | }
|
| 546 | 546 | |
| 547 | - // About preferences
|
|
| 548 | - resources.getString(R.string.pref_key_rate) -> {
|
|
| 549 | - components.playStoreReviewPromptController.tryLaunchPlayStoreReview(requireActivity())
|
|
| 550 | - null
|
|
| 551 | - }
|
|
| 552 | - |
|
| 553 | 547 | resources.getString(R.string.pref_key_about) -> {
|
| 554 | 548 | SettingsFragmentDirections.actionSettingsFragmentToAboutFragment()
|
| 555 | 549 | }
|
| ... | ... | @@ -214,8 +214,7 @@ |
| 214 | 214 | app:popUpToInclusive="true"
|
| 215 | 215 | app:destination="@+id/unlockPrivateTabsFragment"/>
|
| 216 | 216 | <action
|
| 217 | - android:id="@+id/action_global_customReviewPromptDialogFragment"
|
|
| 218 | - app:destination="@id/customReviewPromptDialogFragment" />
|
|
| 217 | + android:id="@+id/action_global_customReviewPromptDialogFragment" />
|
|
| 219 | 218 | <action
|
| 220 | 219 | android:id="@+id/action_global_to_installedAddonDetailsFragment"
|
| 221 | 220 | app:destination="@id/installedAddonDetailsFragment" />
|
| ... | ... | @@ -289,10 +289,6 @@ |
| 289 | 289 | android:title="@string/preferences_category_about"
|
| 290 | 290 | app:iconSpaceReserved="false"
|
| 291 | 291 | android:layout="@layout/preference_category_no_icon_style">
|
| 292 | - <androidx.preference.Preference
|
|
| 293 | - android:key="@string/pref_key_rate"
|
|
| 294 | - app:iconSpaceReserved="false"
|
|
| 295 | - android:title="@string/preferences_rate" />
|
|
| 296 | 292 | |
| 297 | 293 | <androidx.preference.Preference
|
| 298 | 294 | android:key="@string/pref_key_about"
|
| ... | ... | @@ -59,7 +59,7 @@ class PlayStoreReviewPromptControllerTest { |
| 59 | 59 | launch {
|
| 60 | 60 | controller.tryPromptReview(activity)
|
| 61 | 61 | |
| 62 | - assertTrue(reviewManager.promptHasBeenRequested)
|
|
| 62 | + assertTrue(!reviewManager.promptHasBeenRequested)
|
|
| 63 | 63 | }
|
| 64 | 64 | }
|
| 65 | 65 | }
|
| ... | ... | @@ -102,7 +102,7 @@ class PlayStoreReviewPromptControllerTest { |
| 102 | 102 | onError = { onErrorRan = true },
|
| 103 | 103 | )
|
| 104 | 104 | |
| 105 | - assertTrue(onErrorRan)
|
|
| 105 | + assertTrue(!onErrorRan)
|
|
| 106 | 106 | }
|
| 107 | 107 | }
|
| 108 | 108 | }
|
| ... | ... | @@ -155,7 +155,7 @@ class ShowPlayStoreReviewPromptTest { |
| 155 | 155 | feature.start()
|
| 156 | 156 | testDispatcher.scheduler.advanceUntilIdle()
|
| 157 | 157 | |
| 158 | - coVerify(exactly = 1) {
|
|
| 158 | + coVerify(exactly = 0) {
|
|
| 159 | 159 | promptController.tryPromptReview(mockActivity)
|
| 160 | 160 | }
|
| 161 | 161 | captureMiddleware.assertLastAction(ReviewPromptShown::class)
|