diff --git a/components/browser/session-storage/src/main/java/mozilla/components/browser/session/storage/SessionStorage.kt b/components/browser/session-storage/src/main/java/mozilla/components/browser/session/storage/SessionStorage.kt
index 1649e0084cf..38e765e0e7a 100644
--- a/components/browser/session-storage/src/main/java/mozilla/components/browser/session/storage/SessionStorage.kt
+++ b/components/browser/session-storage/src/main/java/mozilla/components/browser/session/storage/SessionStorage.kt
@@ -70,13 +70,18 @@ class SessionStorage(
return true
}
- val stateToPersist = if (state.selectedTabId != null && state.selectedTab == null) {
+ // "about:crashparent" is meant for testing purposes only. If saved/restored then it will
+ // continue to crash the app until data is cleared. Therefore, we are filtering it out.
+ val updatedTabList = state.tabs.filterNot { it.content.url == "about:crashparent" }
+ val updatedState = state.copy(tabs = updatedTabList)
+
+ val stateToPersist = if (updatedState.selectedTabId != null && updatedState.selectedTab == null) {
// Needs investigation to figure out and prevent cause:
// https://github.com/mozilla-mobile/android-components/issues/8417
logger.error("Selected tab ID set, but tab with matching ID not found. Clearing selection.")
- state.copy(selectedTabId = null)
+ updatedState.copy(selectedTabId = null)
} else {
- state
+ updatedState
}
return synchronized(sessionFileLock) {
diff --git a/components/browser/session-storage/src/test/java/mozilla/components/browser/session/storage/SessionStorageTest.kt b/components/browser/session-storage/src/test/java/mozilla/components/browser/session/storage/SessionStorageTest.kt
index e4eddabf574..9fbf9d9c5f9 100644
--- a/components/browser/session-storage/src/test/java/mozilla/components/browser/session/storage/SessionStorageTest.kt
+++ b/components/browser/session-storage/src/test/java/mozilla/components/browser/session/storage/SessionStorageTest.kt
@@ -357,6 +357,34 @@ class SessionStorageTest {
// the first one if all tabs have the same last access value.
assertEquals("mozilla", browsingSession.selectedTabId)
}
+
+ @Test
+ fun `WHEN saving state with crash parent tab THEN don't save tab`() {
+ val state = BrowserState(
+ tabs = listOf(
+ createTab(url = "about:crashparent", id = "crash"),
+ createTab(url = "https://getpocket.com", id = "pocket")
+ ),
+ selectedTabId = "crash"
+ )
+
+ val engine = FakeEngine()
+
+ val storage = SessionStorage(testContext, engine)
+ val persisted = storage.save(state)
+ assertTrue(persisted)
+
+ // Read it back
+ val browsingSession = storage.restore()
+ assertNotNull(browsingSession!!)
+
+ assertEquals(1, browsingSession.tabs.size)
+ assertEquals("https://getpocket.com", browsingSession.tabs[0].state.url)
+
+ // Selected tab doesn't exist so we take to most recently accessed one, or
+ // the first one if all tabs have the same last access value.
+ assertEquals("pocket", browsingSession.selectedTabId)
+ }
}
internal fun TabSessionState.assertSameAs(tab: RecoverableTab) {
diff --git a/components/feature/search/src/main/AndroidManifest.xml b/components/feature/search/src/main/AndroidManifest.xml
index eac0d4df6cf..e2ccfb4ee0a 100644
--- a/components/feature/search/src/main/AndroidManifest.xml
+++ b/components/feature/search/src/main/AndroidManifest.xml
@@ -1,11 +1,4 @@
-
-
-
-
+
diff --git a/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt b/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt
index 0e518df259a..82d296bdb13 100644
--- a/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt
+++ b/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt
@@ -13,7 +13,6 @@ import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
-import android.speech.RecognizerIntent
import android.view.View
import android.widget.RemoteViews
import androidx.annotation.Dimension
@@ -26,8 +25,8 @@ import mozilla.components.feature.search.widget.BaseVoiceSearchActivity.Companio
import mozilla.components.support.utils.PendingIntentUtils
/**
- * It contains all the Gui and behaviour for AppWidgetProvider.
- * Needs to be extended in client app.
+ * An abstract [AppWidgetProvider] that implements core behaviour needed to support a Search Widget
+ * on the launcher.
*/
abstract class AppSearchWidgetProvider : AppWidgetProvider() {
@@ -102,14 +101,10 @@ abstract class AppSearchWidgetProvider : AppWidgetProvider() {
putExtra(SPEECH_PROCESSING, true)
}
- val intentSpeech = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
-
- return intentSpeech.resolveActivity(context.packageManager)?.let {
- PendingIntent.getActivity(
- context,
- REQUEST_CODE_VOICE, voiceIntent, PendingIntentUtils.defaultFlags
- )
- }
+ return PendingIntent.getActivity(
+ context,
+ REQUEST_CODE_VOICE, voiceIntent, PendingIntentUtils.defaultFlags
+ )
}
private fun updateWidgetLayout(
diff --git a/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt b/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt
index 5701180243d..077b38e49ea 100644
--- a/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt
+++ b/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt
@@ -5,9 +5,11 @@
package mozilla.components.feature.search.widget
import android.app.Activity
+import android.content.ActivityNotFoundException
import android.content.Intent
import android.os.Bundle
import android.speech.RecognizerIntent
+import android.util.Log
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
@@ -26,8 +28,7 @@ abstract class BaseVoiceSearchActivity : AppCompatActivity() {
*/
private var previousIntent: Intent? = null
- @VisibleForTesting
- private var activityResultLauncher: ActivityResultLauncher? = null
+ private var activityResultLauncher: ActivityResultLauncher = getActivityResultLauncher()
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
@@ -36,12 +37,6 @@ abstract class BaseVoiceSearchActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- activityResultLauncher = getActivityResultLauncher()
- if (Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).resolveActivity(packageManager) == null) {
- finish()
- return
- }
-
// Retrieve the previous intent from the saved state
previousIntent = savedInstanceState?.get(PREVIOUS_INTENT) as Intent?
if (previousIntent.isForSpeechProcessing()) {
@@ -111,7 +106,12 @@ abstract class BaseVoiceSearchActivity : AppCompatActivity() {
)
}
onSpeechRecognitionStarted()
- activityResultLauncher?.launch(intentSpeech)
+ try {
+ activityResultLauncher.launch(intentSpeech)
+ } catch (e: ActivityNotFoundException) {
+ Log.e(TAG, "ActivityNotFoundException " + e.message.toString())
+ finish()
+ }
}
/**
@@ -128,5 +128,6 @@ abstract class BaseVoiceSearchActivity : AppCompatActivity() {
* In [BaseVoiceSearchActivity] activity, used to store if the speech processing should start.
*/
const val SPEECH_PROCESSING = "speech_processing"
+ const val TAG = "BaseVoiceSearchActivity"
}
}
diff --git a/components/feature/search/src/test/java/mozilla/components/feature/search/widget/VoiceSearchActivityExtendedForTests.kt b/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityExtendedForTests.kt
similarity index 86%
rename from components/feature/search/src/test/java/mozilla/components/feature/search/widget/VoiceSearchActivityExtendedForTests.kt
rename to components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityExtendedForTests.kt
index 05fb73ebd17..a3ea6070338 100644
--- a/components/feature/search/src/test/java/mozilla/components/feature/search/widget/VoiceSearchActivityExtendedForTests.kt
+++ b/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityExtendedForTests.kt
@@ -6,7 +6,7 @@ package mozilla.components.feature.search.widget
import java.util.Locale
-class VoiceSearchActivityExtendedForTests : BaseVoiceSearchActivity() {
+class BaseVoiceSearchActivityExtendedForTests : BaseVoiceSearchActivity() {
override fun getCurrentLocale(): Locale {
return Locale.getDefault()
diff --git a/components/feature/search/src/test/java/mozilla/components/feature/search/widget/VoiceSearchActivityTest.kt b/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityTest.kt
similarity index 87%
rename from components/feature/search/src/test/java/mozilla/components/feature/search/widget/VoiceSearchActivityTest.kt
rename to components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityTest.kt
index f5cf91f5a92..9f74c3da5f4 100644
--- a/components/feature/search/src/test/java/mozilla/components/feature/search/widget/VoiceSearchActivityTest.kt
+++ b/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityTest.kt
@@ -30,10 +30,10 @@ import org.robolectric.android.controller.ActivityController
import org.robolectric.shadows.ShadowActivity
@RunWith(RobolectricTestRunner::class)
-class VoiceSearchActivityTest {
+class BaseVoiceSearchActivityTest {
- private lateinit var controller: ActivityController
- private lateinit var activity: VoiceSearchActivityExtendedForTests
+ private lateinit var controller: ActivityController
+ private lateinit var activity: BaseVoiceSearchActivityExtendedForTests
private lateinit var shadow: ShadowActivity
@Before
@@ -41,7 +41,7 @@ class VoiceSearchActivityTest {
val intent = Intent()
intent.putExtra(SPEECH_PROCESSING, true)
- controller = Robolectric.buildActivity(VoiceSearchActivityExtendedForTests::class.java, intent)
+ controller = Robolectric.buildActivity(BaseVoiceSearchActivityExtendedForTests::class.java, intent)
activity = controller.get()
shadow = shadowOf(activity)
}
@@ -72,7 +72,7 @@ class VoiceSearchActivityTest {
val intent = Intent()
intent.putExtra(SPEECH_PROCESSING, false)
- val controller = Robolectric.buildActivity(VoiceSearchActivityExtendedForTests::class.java, intent)
+ val controller = Robolectric.buildActivity(BaseVoiceSearchActivityExtendedForTests::class.java, intent)
val activity = controller.get()
controller.create()
@@ -83,7 +83,7 @@ class VoiceSearchActivityTest {
@Test
fun `process null intent`() {
allowVoiceIntentToResolveActivity()
- val controller = Robolectric.buildActivity(VoiceSearchActivityExtendedForTests::class.java, null)
+ val controller = Robolectric.buildActivity(BaseVoiceSearchActivityExtendedForTests::class.java, null)
val activity = controller.get()
controller.create()
@@ -130,10 +130,4 @@ class VoiceSearchActivityTest {
assertTrue(activity.isFinishing)
}
-
- @Test
- fun `handle no activity able to resolve voice intent`() {
- controller.create()
- assertTrue(activity.isFinishing)
- }
}
diff --git a/components/lib/crash/src/main/res/values-fr/strings.xml b/components/lib/crash/src/main/res/values-fr/strings.xml
index 99b5534cf2b..87ebf25320a 100644
--- a/components/lib/crash/src/main/res/values-fr/strings.xml
+++ b/components/lib/crash/src/main/res/values-fr/strings.xml
@@ -25,6 +25,9 @@
Envoi du rapport de plantage à %1$s
+
+ Collecte des données de plantage
+
Collecte des données de télémétrie du plantage
diff --git a/components/lib/crash/src/main/res/values-sl/strings.xml b/components/lib/crash/src/main/res/values-sl/strings.xml
index abc8a5fc324..a0a020d1c41 100644
--- a/components/lib/crash/src/main/res/values-sl/strings.xml
+++ b/components/lib/crash/src/main/res/values-sl/strings.xml
@@ -24,6 +24,9 @@
Pošiljanje poročila o sesutju organizaciji %1$s
+
+ Zbiranje podatkov o sesutju
+
Zbiranje telemetričnih podatkov o sesutju
diff --git a/components/tooling/nimbus-gradle-plugin/src/main/groovy/mozilla/components/tooling/nimbus/NimbusGradlePlugin.groovy b/components/tooling/nimbus-gradle-plugin/src/main/groovy/mozilla/components/tooling/nimbus/NimbusGradlePlugin.groovy
index dbe0d81e300..d43002e7ad3 100644
--- a/components/tooling/nimbus-gradle-plugin/src/main/groovy/mozilla/components/tooling/nimbus/NimbusGradlePlugin.groovy
+++ b/components/tooling/nimbus-gradle-plugin/src/main/groovy/mozilla/components/tooling/nimbus/NimbusGradlePlugin.groovy
@@ -171,7 +171,7 @@ class NimbusPlugin implements Plugin {
// a) this plugin is going to live in the AS repo (eventually)
// See https://github.com/mozilla-mobile/android-components/issues/11422 for tying this
// to a version that is specified in buildSrc/src/main/java/Dependencies.kt
- return "93.5.0"
+ return "93.6.0"
}
// Try one or more hosts to download the given file.