2
0
mirror of https://github.com/fork-maintainers/iceraven-browser synced 2024-11-15 18:12:54 +00:00

Bug 1853102 - Crash dialog "Continue with add-ons disabled" option is truncated on some devices.

This commit is contained in:
Arturo Mejia 2023-09-14 07:32:34 -04:00 committed by mergify[bot]
parent ae191b3bd9
commit 1751466dbe
3 changed files with 82 additions and 33 deletions

View File

@ -5,6 +5,9 @@
package org.mozilla.fenix.addons package org.mozilla.fenix.addons
import android.content.Context import android.content.Context
import android.view.LayoutInflater
import android.widget.Button
import android.widget.TextView
import androidx.annotation.UiContext import androidx.annotation.UiContext
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import mozilla.components.browser.state.action.ExtensionProcessDisabledPopupAction import mozilla.components.browser.state.action.ExtensionProcessDisabledPopupAction
@ -36,25 +39,31 @@ private fun presentDialog(
appName: String, appName: String,
) { ) {
val message = context.getString(R.string.addon_process_crash_dialog_message, appName) val message = context.getString(R.string.addon_process_crash_dialog_message, appName)
var onDismissDialog: (() -> Unit)? = null
builder.apply { val layout = LayoutInflater.from(context)
setCancelable(false) .inflate(R.layout.crash_extension_dialog, null, false)
setTitle(R.string.addon_process_crash_dialog_title) layout?.apply {
setMessage(message) findViewById<TextView>(R.id.message)?.text = message
setPositiveButton(R.string.addon_process_crash_dialog_retry_button_text) { dialog, _ -> findViewById<Button>(R.id.positive)?.setOnClickListener {
engine.enableExtensionProcessSpawning() engine.enableExtensionProcessSpawning()
Addons.extensionsProcessUiRetry.add() Addons.extensionsProcessUiRetry.add()
store.dispatch(ExtensionProcessDisabledPopupAction(false)) store.dispatch(ExtensionProcessDisabledPopupAction(false))
dialog.dismiss() onDismissDialog?.invoke()
} }
setNegativeButton(R.string.addon_process_crash_dialog_disable_addons_button_text) { dialog, _ -> findViewById<Button>(R.id.negative)?.setOnClickListener {
Addons.extensionsProcessUiDisable.add() Addons.extensionsProcessUiDisable.add()
store.dispatch(ExtensionProcessDisabledPopupAction(false)) store.dispatch(ExtensionProcessDisabledPopupAction(false))
dialog.dismiss() onDismissDialog?.invoke()
} }
} }
builder.apply {
setCancelable(false)
setView(layout)
setTitle(R.string.addon_process_crash_dialog_title)
}
builder.show() val dialog = builder.show()
onDismissDialog = { dialog?.dismiss() }
} }
/** /**

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
- 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/. -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginVertical="8dp"
android:textColor="?attr/textPrimary"
tools:text="@string/addon_process_crash_dialog_message" />
<Button
android:id="@+id/positive"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/addon_process_crash_dialog_retry_button_text"
android:textAlignment="textEnd"
android:textColor="?textAccent" />
<Button
android:id="@+id/negative"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/addon_process_crash_dialog_disable_addons_button_text"
android:textAlignment="textEnd"
android:textColor="?textAccent" />
</LinearLayout>
</ScrollView>

View File

@ -4,14 +4,15 @@
package org.mozilla.fenix.addons package org.mozilla.fenix.addons
import android.content.Context import android.view.View
import android.content.DialogInterface.OnClickListener import android.widget.Button
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import mozilla.components.browser.state.action.ExtensionProcessDisabledPopupAction import mozilla.components.browser.state.action.ExtensionProcessDisabledPopupAction
import mozilla.components.browser.state.store.BrowserStore import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.Engine import mozilla.components.concept.engine.Engine
import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.argumentCaptor
import mozilla.components.support.test.libstate.ext.waitUntilIdle import mozilla.components.support.test.libstate.ext.waitUntilIdle
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.rule.MainCoroutineRule import mozilla.components.support.test.rule.MainCoroutineRule
import mozilla.components.support.test.whenever import mozilla.components.support.test.whenever
import org.junit.Assert.assertFalse import org.junit.Assert.assertFalse
@ -19,12 +20,10 @@ import org.junit.Assert.assertTrue
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.anyString
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
import org.mockito.Mockito.never import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
@RunWith(FenixRobolectricTestRunner::class) @RunWith(FenixRobolectricTestRunner::class)
@ -36,17 +35,18 @@ class ExtensionProcessDisabledControllerTest {
@Test @Test
fun `WHEN showExtensionProcessDisabledPopup is true AND positive button clicked then enable extension process spawning`() { fun `WHEN showExtensionProcessDisabledPopup is true AND positive button clicked then enable extension process spawning`() {
val context: Context = mock()
val store = BrowserStore() val store = BrowserStore()
val engine: Engine = mock() val engine: Engine = mock()
val dialog: AlertDialog = mock()
val appName = "TestApp" val appName = "TestApp"
val builder: AlertDialog.Builder = mock() val builder: AlertDialog.Builder = mock()
val controller = ExtensionProcessDisabledController(context, store, engine, builder, appName) val controller =
ExtensionProcessDisabledController(testContext, store, engine, builder, appName)
val buttonsContainerCaptor = argumentCaptor<View>()
controller.start() controller.start()
whenever(context.getString(anyInt(), anyString())).thenReturn("TestString") whenever(builder.show()).thenReturn(dialog)
val posClickCaptor = argumentCaptor<OnClickListener>()
assertFalse(store.state.showExtensionProcessDisabledPopup) assertFalse(store.state.showExtensionProcessDisabledPopup)
@ -55,12 +55,11 @@ class ExtensionProcessDisabledControllerTest {
store.waitUntilIdle() store.waitUntilIdle()
assertTrue(store.state.showExtensionProcessDisabledPopup) assertTrue(store.state.showExtensionProcessDisabledPopup)
verify(builder).setPositiveButton(anyInt(), posClickCaptor.capture()) verify(builder).setView(buttonsContainerCaptor.capture())
verify(builder).show() verify(builder).show()
val dialog: AlertDialog = mock() buttonsContainerCaptor.value.findViewById<Button>(R.id.positive).performClick()
posClickCaptor.value.onClick(dialog, 1)
store.waitUntilIdle() store.waitUntilIdle()
verify(engine).enableExtensionProcessSpawning() verify(engine).enableExtensionProcessSpawning()
@ -70,17 +69,18 @@ class ExtensionProcessDisabledControllerTest {
@Test @Test
fun `WHEN showExtensionProcessDisabledPopup is true AND negative button clicked then dismiss without enabling extension process spawning`() { fun `WHEN showExtensionProcessDisabledPopup is true AND negative button clicked then dismiss without enabling extension process spawning`() {
val context: Context = mock()
val store = BrowserStore() val store = BrowserStore()
val engine: Engine = mock() val engine: Engine = mock()
val appName = "TestApp" val appName = "TestApp"
val dialog: AlertDialog = mock()
val builder: AlertDialog.Builder = mock() val builder: AlertDialog.Builder = mock()
val controller = ExtensionProcessDisabledController(context, store, engine, builder, appName) val controller =
ExtensionProcessDisabledController(testContext, store, engine, builder, appName)
val buttonsContainerCaptor = argumentCaptor<View>()
controller.start() controller.start()
whenever(context.getString(anyInt(), anyString())).thenReturn("TestString") whenever(builder.show()).thenReturn(dialog)
val negClickCaptor = argumentCaptor<OnClickListener>()
assertFalse(store.state.showExtensionProcessDisabledPopup) assertFalse(store.state.showExtensionProcessDisabledPopup)
@ -89,12 +89,11 @@ class ExtensionProcessDisabledControllerTest {
store.waitUntilIdle() store.waitUntilIdle()
assertTrue(store.state.showExtensionProcessDisabledPopup) assertTrue(store.state.showExtensionProcessDisabledPopup)
verify(builder).setNegativeButton(anyInt(), negClickCaptor.capture()) verify(builder).setView(buttonsContainerCaptor.capture())
verify(builder).show() verify(builder).show()
val dialog: AlertDialog = mock() buttonsContainerCaptor.value.findViewById<Button>(R.id.negative).performClick()
negClickCaptor.value.onClick(dialog, 1)
store.waitUntilIdle() store.waitUntilIdle()
assertFalse(store.state.showExtensionProcessDisabledPopup) assertFalse(store.state.showExtensionProcessDisabledPopup)