diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml
index 47d209f998..c76a534fcd 100644
--- a/app/lint-baseline.xml
+++ b/app/lint-baseline.xml
@@ -1031,72 +1031,6 @@
column="10"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
= Build.VERSION_CODES.S) {
+ PendingIntent.FLAG_MUTABLE
+ } else {
+ 0 // No flags. Default behavior.
+ }
val pendingIntent = PendingIntent.getActivity(
context,
0,
intent,
- 0
+ crashReportingIntentFlags
)
CrashReporter(
diff --git a/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt b/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt
index 24d3034f55..c4a68e2b73 100644
--- a/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt
+++ b/app/src/main/java/org/mozilla/fenix/components/NotificationManager.kt
@@ -21,6 +21,7 @@ import mozilla.components.concept.sync.Device
import mozilla.components.concept.sync.TabData
import mozilla.components.support.base.log.logger.Logger
import org.mozilla.fenix.R
+import org.mozilla.fenix.utils.IntentUtils
/**
* Manages notification channels and allows displaying different types of notifications.
@@ -54,11 +55,12 @@ class NotificationManager(private val context: Context) {
// For now, a single notification per tab received will suffice.
logger.debug("Showing ${tabs.size} tab(s) received from deviceID=${device?.id}")
tabs.forEach { tab ->
+ val showReceivedTabsIntentFlags = IntentUtils.defaultIntentPendingFlags or PendingIntent.FLAG_ONE_SHOT
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(tab.url))
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.putExtra(RECEIVE_TABS_TAG, true)
val pendingIntent: PendingIntent =
- PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT)
+ PendingIntent.getActivity(context, 0, intent, showReceivedTabsIntentFlags)
val builder = NotificationCompat.Builder(context, RECEIVE_TABS_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_status_logo)
diff --git a/app/src/main/java/org/mozilla/fenix/components/PrivateShortcutCreateManager.kt b/app/src/main/java/org/mozilla/fenix/components/PrivateShortcutCreateManager.kt
index 9aa3d6364d..6d37991e6f 100644
--- a/app/src/main/java/org/mozilla/fenix/components/PrivateShortcutCreateManager.kt
+++ b/app/src/main/java/org/mozilla/fenix/components/PrivateShortcutCreateManager.kt
@@ -13,6 +13,7 @@ import androidx.core.graphics.drawable.IconCompat
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.home.intent.StartSearchIntentProcessor
+import org.mozilla.fenix.utils.IntentUtils
import java.util.UUID
/**
@@ -50,11 +51,13 @@ object PrivateShortcutCreateManager {
}
)
.build()
+ val createPrivateShortcutIntentFlags = IntentUtils.defaultIntentPendingFlags or
+ PendingIntent.FLAG_UPDATE_CURRENT
val homeScreenIntent = Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val intentSender = PendingIntent
- .getActivity(context, 0, homeScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)
+ .getActivity(context, 0, homeScreenIntent, createPrivateShortcutIntentFlags)
.intentSender
ShortcutManagerCompat.requestPinShortcut(context, shortcut, intentSender)
}
diff --git a/app/src/main/java/org/mozilla/fenix/onboarding/DefaultBrowserNotificationWorker.kt b/app/src/main/java/org/mozilla/fenix/onboarding/DefaultBrowserNotificationWorker.kt
index 479fb090b4..de967d9a96 100644
--- a/app/src/main/java/org/mozilla/fenix/onboarding/DefaultBrowserNotificationWorker.kt
+++ b/app/src/main/java/org/mozilla/fenix/onboarding/DefaultBrowserNotificationWorker.kt
@@ -24,6 +24,7 @@ import mozilla.components.support.base.ids.SharedIdsHelper
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.settings
+import org.mozilla.fenix.utils.IntentUtils
import org.mozilla.fenix.utils.Settings
class DefaultBrowserNotificationWorker(
@@ -54,7 +55,7 @@ class DefaultBrowserNotificationWorker(
applicationContext,
SharedIdsHelper.getNextIdForTag(applicationContext, NOTIFICATION_PENDING_INTENT_TAG),
intent,
- 0
+ IntentUtils.defaultIntentPendingFlags
)
with(applicationContext) {
diff --git a/app/src/main/java/org/mozilla/fenix/utils/IntentUtils.kt b/app/src/main/java/org/mozilla/fenix/utils/IntentUtils.kt
new file mode 100644
index 0000000000..0715e3dca5
--- /dev/null
+++ b/app/src/main/java/org/mozilla/fenix/utils/IntentUtils.kt
@@ -0,0 +1,23 @@
+/* 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/. */
+
+package org.mozilla.fenix.utils
+
+import android.app.PendingIntent
+import android.os.Build
+
+object IntentUtils {
+
+ /**
+ * Since Android 12 we need to set PendingIntent mutability explicitly, but Android 6 can be the minimum version
+ * This additional requirement improves your app's security.
+ * FLAG_IMMUTABLE -> Flag indicating that the created PendingIntent should be immutable.
+ */
+ val defaultIntentPendingFlags
+ get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ PendingIntent.FLAG_IMMUTABLE
+ } else {
+ 0 // No flags. Default behavior.
+ }
+}
diff --git a/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt b/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt
index c657c80c79..2f35ea8a77 100644
--- a/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt
+++ b/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt
@@ -28,6 +28,7 @@ import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.home.intent.StartSearchIntentProcessor
+import org.mozilla.fenix.utils.IntentUtils
import org.mozilla.fenix.widget.VoiceSearchActivity
import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_PROCESSING
@@ -89,11 +90,13 @@ class SearchWidgetProvider : AppWidgetProvider() {
private fun createTextSearchIntent(context: Context): PendingIntent {
return Intent(context, IntentReceiverActivity::class.java)
.let { intent ->
+ val createTextSearchIntentFlags = IntentUtils.defaultIntentPendingFlags or
+ PendingIntent.FLAG_UPDATE_CURRENT
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
intent.putExtra(HomeActivity.OPEN_TO_SEARCH, StartSearchIntentProcessor.SEARCH_WIDGET)
PendingIntent.getActivity(
context,
- REQUEST_CODE_NEW_TAB, intent, PendingIntent.FLAG_UPDATE_CURRENT
+ REQUEST_CODE_NEW_TAB, intent, createTextSearchIntentFlags
)
}
}
@@ -117,7 +120,7 @@ class SearchWidgetProvider : AppWidgetProvider() {
return intentSpeech.resolveActivity(context.packageManager)?.let {
PendingIntent.getActivity(
context,
- REQUEST_CODE_VOICE, voiceIntent, 0
+ REQUEST_CODE_VOICE, voiceIntent, IntentUtils.defaultIntentPendingFlags
)
}
}
diff --git a/app/src/test/java/org/mozilla/fenix/components/PrivateShortcutCreateManagerTest.kt b/app/src/test/java/org/mozilla/fenix/components/PrivateShortcutCreateManagerTest.kt
index 5c55d5e401..c4772e7377 100644
--- a/app/src/test/java/org/mozilla/fenix/components/PrivateShortcutCreateManagerTest.kt
+++ b/app/src/test/java/org/mozilla/fenix/components/PrivateShortcutCreateManagerTest.kt
@@ -24,6 +24,7 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.home.intent.StartSearchIntentProcessor
+import org.mozilla.fenix.utils.IntentUtils
@RunWith(FenixRobolectricTestRunner::class)
class PrivateShortcutCreateManagerTest {
@@ -59,7 +60,7 @@ class PrivateShortcutCreateManagerTest {
PrivateShortcutCreateManager.createPrivateShortcut(testContext)
- verify { PendingIntent.getActivity(testContext, 0, capture(intent), PendingIntent.FLAG_UPDATE_CURRENT) }
+ verify { PendingIntent.getActivity(testContext, 0, capture(intent), IntentUtils.defaultIntentPendingFlags or PendingIntent.FLAG_UPDATE_CURRENT) }
verify { ShortcutManagerCompat.requestPinShortcut(testContext, capture(shortcut), capture(intentSender)) }
`assert shortcutInfoCompat is build correctly`(shortcut.captured)
`assert homeScreenIntent is built correctly`(intent.captured)