Firefox · Core
CVE-2026-8951
Logic Error in Core
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrl.ktmobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt
Patch
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrl.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrl.kt
index 7ceb0b6d3ea..5e7c5fefad1 100644
--- a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrl.kt
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrl.kt
@@ -27,6 +27,7 @@ import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
@@ -171,7 +172,12 @@ private fun Modifier.focusTextIndexRange(
.drawWithContent {
drawContent()
- val brush = createDomainHighlightBrush(text, highlightRange, scrollState.value, fadeFraction)
+ val brush = createUrlFadeBrush(
+ scrolledPixels = scrollState.value,
+ maxScrollPixels = scrollState.maxValue,
+ viewportSize = scrollState.viewportSize,
+ fadeFraction = fadeFraction
+ )
drawRect(
brush = brush,
@@ -223,21 +229,26 @@ internal fun computeDomainEndScrollValue(
}
@VisibleForTesting
-internal fun createDomainHighlightBrush(
- text: String,
- highlightRange: Pair<Int, Int>?,
+internal fun createUrlFadeBrush(
scrolledPixels: Int,
+ maxScrollPixels: Int,
+ viewportSize: Int,
fadeFraction: Float,
): Brush {
- val brush = when {
- // Don't fade the start if the text is not scrolled to fit the highlighted domain.
- scrolledPixels == 0 -> Brush.horizontalGradient(
+ val fadeWidthPixels = viewportSize * fadeFraction
+ val needsLeftFade = scrolledPixels > 0
+ val remainingScroll = maxScrollPixels - scrolledPixels
+ val needsRightFade = remainingScroll > fadeWidthPixels
+
+ return when {
+ !needsLeftFade && !needsRightFade -> SolidColor(Color.Black)
+
+ !needsLeftFade && needsRightFade -> Brush.horizontalGradient(
(1f - fadeFraction) to Color.Black,
1f to Color.Transparent,
)
- // Don't fade the end if the highlight is also at the end of the text.
- (highlightRange?.second ?: Int.MIN_VALUE) >= text.lastIndex -> Brush.horizontalGradient(
+ needsLeftFade && !needsRightFade -> Brush.horizontalGradient(
0f to Color.Transparent,
fadeFraction to Color.Black,
)
@@ -251,7 +262,6 @@ internal fun createDomainHighlightBrush(
),
)
}
- return brush
}
@Composable
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt
index 2919b133319..e48b327aaa3 100644
--- a/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt
@@ -9,6 +9,7 @@ import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.TextLayoutResult
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.support.test.mock
@@ -91,43 +92,55 @@ class HighlightedDomainUrlTest {
}
@Test
- fun `GIVEN the start of the URL should be highlighted THEN get an appropriate highlight brush`() {
- val url = "pagedomain.com/testing"
- scrollState.stubScrollInfo(url)
- val highlightRange = computeHighlightRange(url, "pagedomain.com")
- val scrolledPixels = computeDomainEndScrollValue(url, highlightRange)
+ fun `GIVEN the displayed URL does not overflow the available space WHEN creating the fading brush THEN set no fading`() {
+ val expected = SolidColor(Color.Black)
+
+ val result = createUrlFadeBrush(
+ scrolledPixels = 0,
+ maxScrollPixels = 0,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
+
+ assertEquals(expected, result)
+ }
+
+ @Test
+ fun `GIVEN the displayed URL only overflows to the right WHEN creating the fading brush THEN fade the right edge`() {
val expected = Brush.horizontalGradient(
0.5f to Color.Black,
1f to Color.Transparent,
)
- val result = createDomainHighlightBrush(url, highlightRange, scrolledPixels, 0.5f)
+ val result = createUrlFadeBrush(
+ scrolledPixels = 0,
+ maxScrollPixels = 600,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
assertEquals(expected, result)
}
@Test
- fun `GIVEN the end of the URL should be highlighted THEN get an appropriate highlight brush`() {
- val url = "subdomain.pagedomain.com"
- scrollState.stubScrollInfo(url)
- val highlightRange = computeHighlightRange(url, "pagedomain.com")
- val scrolledPixels = computeDomainEndScrollValue(url, highlightRange)
+ fun `GIVEN the displayed URL only overflows to the left WHEN creating the fading brush THEN fade the left edge`() {
val expected = Brush.horizontalGradient(
0f to Color.Transparent,
0.5f to Color.Black,
)
- val result = createDomainHighlightBrush(url, highlightRange, scrolledPixels, 0.5f)
+ val result = createUrlFadeBrush(
+ scrolledPixels = 600,
+ maxScrollPixels = 600,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
assertEquals(expected, result)
}
@Test
- fun `GIVEN the middle of the URL should be highlighted THEN get an appropriate highlight brush`() {
- val url = "subdomain.pagedomain.com/testing"
- scrollState.stubScrollInfo(url)
- val highlightRange = computeHighlightRange(url, "pagedomain.com")
- val scrolledPixels = computeDomainEndScrollValue(url, highlightRange)
+ fun `GIVEN the displayed URL overflows on both sides WHEN creating the fading brush THEN fade both edges`() {
val expected = Brush.horizontalGradient(
colorStops = arrayOf(
0f to Color.Transparent,
@@ -137,7 +150,12 @@ class HighlightedDomainUrlTest {
),
)
- val result = createDomainHighlightBrush(url, highlightRange, scrolledPixels, 0.5f)
+ val result = createUrlFadeBrush(
+ scrolledPixels = 100,
+ maxScrollPixels = 1200,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
assertEquals(expected, result)
}
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt
index 2919b133319..e48b327aaa3 100644
--- a/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/test/java/mozilla/components/compose/browser/toolbar/ui/HighlightedDomainUrlTest.kt
@@ -9,6 +9,7 @@ import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.TextLayoutResult
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.support.test.mock
@@ -91,43 +92,55 @@ class HighlightedDomainUrlTest {
}
@Test
- fun `GIVEN the start of the URL should be highlighted THEN get an appropriate highlight brush`() {
- val url = "pagedomain.com/testing"
- scrollState.stubScrollInfo(url)
- val highlightRange = computeHighlightRange(url, "pagedomain.com")
- val scrolledPixels = computeDomainEndScrollValue(url, highlightRange)
+ fun `GIVEN the displayed URL does not overflow the available space WHEN creating the fading brush THEN set no fading`() {
+ val expected = SolidColor(Color.Black)
+
+ val result = createUrlFadeBrush(
+ scrolledPixels = 0,
+ maxScrollPixels = 0,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
+
+ assertEquals(expected, result)
+ }
+
+ @Test
+ fun `GIVEN the displayed URL only overflows to the right WHEN creating the fading brush THEN fade the right edge`() {
val expected = Brush.horizontalGradient(
0.5f to Color.Black,
1f to Color.Transparent,
)
- val result = createDomainHighlightBrush(url, highlightRange, scrolledPixels, 0.5f)
+ val result = createUrlFadeBrush(
+ scrolledPixels = 0,
+ maxScrollPixels = 600,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
assertEquals(expected, result)
}
@Test
- fun `GIVEN the end of the URL should be highlighted THEN get an appropriate highlight brush`() {
- val url = "subdomain.pagedomain.com"
- scrollState.stubScrollInfo(url)
- val highlightRange = computeHighlightRange(url, "pagedomain.com")
- val scrolledPixels = computeDomainEndScrollValue(url, highlightRange)
+ fun `GIVEN the displayed URL only overflows to the left WHEN creating the fading brush THEN fade the left edge`() {
val expected = Brush.horizontalGradient(
0f to Color.Transparent,
0.5f to Color.Black,
)
- val result = createDomainHighlightBrush(url, highlightRange, scrolledPixels, 0.5f)
+ val result = createUrlFadeBrush(
+ scrolledPixels = 600,
+ maxScrollPixels = 600,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
assertEquals(expected, result)
}
@Test
- fun `GIVEN the middle of the URL should be highlighted THEN get an appropriate highlight brush`() {
- val url = "subdomain.pagedomain.com/testing"
- scrollState.stubScrollInfo(url)
- val highlightRange = computeHighlightRange(url, "pagedomain.com")
- val scrolledPixels = computeDomainEndScrollValue(url, highlightRange)
+ fun `GIVEN the displayed URL overflows on both sides WHEN creating the fading brush THEN fade both edges`() {
val expected = Brush.horizontalGradient(
colorStops = arrayOf(
0f to Color.Transparent,
@@ -137,7 +150,12 @@ class HighlightedDomainUrlTest {
),
)
- val result = createDomainHighlightBrush(url, highlightRange, scrolledPixels, 0.5f)
+ val result = createUrlFadeBrush(
+ scrolledPixels = 100,
+ maxScrollPixels = 1200,
+ viewportSize = viewPortWidth.toInt(),
+ fadeFraction = 0.5f,
+ )
assertEquals(expected, result)
}
Loading diff…
References
On This Page