Skip to content

Commit 0cd877d

Browse files
authored
Merge branch 'main' into markushi/feat/anr-profiling
2 parents e67c713 + 0eaac1e commit 0cd877d

File tree

18 files changed

+267
-20
lines changed

18 files changed

+267
-20
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66

77
- Add `installGroupsOverride` parameter and `installGroups` property to Build Distribution SDK ([#5062](https://github.com/getsentry/sentry-java/pull/5062))
88
- Update Android targetSdk to API 36 (Android 16) ([#5016](https://github.com/getsentry/sentry-java/pull/5016))
9+
- Add AndroidManifest support for Spotlight configuration via `io.sentry.spotlight.enable` and `io.sentry.spotlight.url` ([#5064](https://github.com/getsentry/sentry-java/pull/5064))
10+
11+
### Fixes
12+
13+
- Extract `SpotlightIntegration` to separate `sentry-spotlight` module to prevent insecure HTTP URLs from appearing in release APKs ([#5064](https://github.com/getsentry/sentry-java/pull/5064))
14+
- **Breaking:** Users who enable Spotlight must now add the `io.sentry:sentry-spotlight` dependency:
15+
```kotlin
16+
dependencies {
17+
debugImplementation("io.sentry:sentry-spotlight:<version>")
18+
}
19+
```
920

1021
### Fixes
1122

sentry-android-core/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ dependencies {
102102
testImplementation(libs.mockito.kotlin)
103103
testImplementation(libs.mockito.inline)
104104
testImplementation(projects.sentryTestSupport)
105+
testImplementation(projects.sentrySpotlight)
105106
testImplementation(projects.sentryAndroidFragment)
106107
testImplementation(projects.sentryAndroidTimber)
107108
testImplementation(projects.sentryAndroidReplay)

sentry-android-core/proguard-rules.pro

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,8 @@
8383
-dontwarn io.sentry.android.distribution.DistributionIntegration
8484
-keepnames class io.sentry.android.distribution.DistributionIntegration
8585
##---------------End: proguard configuration for sentry-android-distribution ----------
86+
87+
##---------------Begin: proguard configuration for sentry-spotlight ----------
88+
-dontwarn io.sentry.spotlight.SpotlightIntegration
89+
-keepnames class io.sentry.spotlight.SpotlightIntegration
90+
##---------------End: proguard configuration for sentry-spotlight ----------

sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ final class ManifestMetadataReader {
164164

165165
static final String FEEDBACK_SHOW_BRANDING = "io.sentry.feedback.show-branding";
166166

167+
static final String SPOTLIGHT_ENABLE = "io.sentry.spotlight.enable";
168+
169+
static final String SPOTLIGHT_CONNECTION_URL = "io.sentry.spotlight.url";
170+
167171
static final String ENABLE_ANR_PROFILING = "io.sentry.anr.enable-profiling";
168172

169173
/** ManifestMetadataReader ctor */
@@ -645,6 +649,15 @@ static void applyMetadata(
645649
feedbackOptions.setShowBranding(
646650
readBool(metadata, logger, FEEDBACK_SHOW_BRANDING, feedbackOptions.isShowBranding()));
647651

652+
options.setEnableSpotlight(
653+
readBool(metadata, logger, SPOTLIGHT_ENABLE, options.isEnableSpotlight()));
654+
655+
final @Nullable String spotlightUrl =
656+
readString(metadata, logger, SPOTLIGHT_CONNECTION_URL, null);
657+
if (spotlightUrl != null) {
658+
options.setSpotlightConnectionUrl(spotlightUrl);
659+
}
660+
648661
options.setEnableAnrProfiling(
649662
readBool(metadata, logger, ENABLE_ANR_PROFILING, options.isEnableAnrProfiling()));
650663
}

sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,4 +2242,76 @@ class ManifestMetadataReaderTest {
22422242
assertTrue(headers.contains("Authorization"))
22432243
assertTrue(headers.contains("X-Custom-Header"))
22442244
}
2245+
2246+
// Spotlight Configuration Tests
2247+
2248+
@Test
2249+
fun `applyMetadata reads spotlight enabled and keeps default value if not found`() {
2250+
// Arrange
2251+
val context = fixture.getContext()
2252+
2253+
// Act
2254+
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)
2255+
2256+
// Assert
2257+
assertFalse(fixture.options.isEnableSpotlight)
2258+
}
2259+
2260+
@Test
2261+
fun `applyMetadata reads spotlight enabled to options`() {
2262+
// Arrange
2263+
val bundle = bundleOf(ManifestMetadataReader.SPOTLIGHT_ENABLE to true)
2264+
val context = fixture.getContext(metaData = bundle)
2265+
2266+
// Act
2267+
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)
2268+
2269+
// Assert
2270+
assertTrue(fixture.options.isEnableSpotlight)
2271+
}
2272+
2273+
@Test
2274+
fun `applyMetadata reads spotlight url and keeps null if not found`() {
2275+
// Arrange
2276+
val context = fixture.getContext()
2277+
2278+
// Act
2279+
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)
2280+
2281+
// Assert
2282+
assertNull(fixture.options.spotlightConnectionUrl)
2283+
}
2284+
2285+
@Test
2286+
fun `applyMetadata reads spotlight url to options`() {
2287+
// Arrange
2288+
val expectedUrl = "http://10.0.2.2:8969/stream"
2289+
val bundle = bundleOf(ManifestMetadataReader.SPOTLIGHT_CONNECTION_URL to expectedUrl)
2290+
val context = fixture.getContext(metaData = bundle)
2291+
2292+
// Act
2293+
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)
2294+
2295+
// Assert
2296+
assertEquals(expectedUrl, fixture.options.spotlightConnectionUrl)
2297+
}
2298+
2299+
@Test
2300+
fun `applyMetadata reads both spotlight enabled and url to options`() {
2301+
// Arrange
2302+
val expectedUrl = "http://localhost:8969/stream"
2303+
val bundle =
2304+
bundleOf(
2305+
ManifestMetadataReader.SPOTLIGHT_ENABLE to true,
2306+
ManifestMetadataReader.SPOTLIGHT_CONNECTION_URL to expectedUrl,
2307+
)
2308+
val context = fixture.getContext(metaData = bundle)
2309+
2310+
// Act
2311+
ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider)
2312+
2313+
// Assert
2314+
assertTrue(fixture.options.isEnableSpotlight)
2315+
assertEquals(expectedUrl, fixture.options.spotlightConnectionUrl)
2316+
}
22452317
}

sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import io.sentry.SentryOptions
2626
import io.sentry.SentryOptions.BeforeSendCallback
2727
import io.sentry.Session
2828
import io.sentry.ShutdownHookIntegration
29-
import io.sentry.SpotlightIntegration
3029
import io.sentry.SystemOutLogger
3130
import io.sentry.UncaughtExceptionHandlerIntegration
3231
import io.sentry.android.core.anr.AnrProfilingIntegration
@@ -47,6 +46,7 @@ import io.sentry.cache.PersistingScopeObserver.TRANSACTION_FILENAME
4746
import io.sentry.cache.tape.QueueFile
4847
import io.sentry.protocol.Contexts
4948
import io.sentry.protocol.SentryId
49+
import io.sentry.spotlight.SpotlightIntegration
5050
import io.sentry.test.applyTestOptions
5151
import io.sentry.transport.NoOpEnvelopeCache
5252
import io.sentry.util.StringUtils

sentry-samples/sentry-samples-android/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ dependencies {
127127
implementation(projects.sentryCompose)
128128
implementation(projects.sentryKotlinExtensions)
129129
implementation(projects.sentryOkhttp)
130+
implementation(projects.sentrySpotlight)
130131

131132
// how to exclude androidx if release health feature is disabled
132133
// implementation(projects.sentryAndroid) {

sentry-samples/sentry-samples-android/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,5 +257,8 @@
257257
<meta-data
258258
android:name="io.sentry.session-replay.network-response-headers"
259259
android:value="X-Response-Time,X-Cache-Status,X-Test-Response" />
260+
<meta-data
261+
android:name="io.sentry.spotlight.enable"
262+
android:value="true" />
260263
</application>
261264
</manifest>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public final class io/sentry/spotlight/BuildConfig {
2+
public static final field VERSION_NAME Ljava/lang/String;
3+
}
4+
5+
public final class io/sentry/spotlight/SpotlightIntegration : io/sentry/Integration, io/sentry/SentryOptions$BeforeEnvelopeCallback, java/io/Closeable {
6+
public fun <init> ()V
7+
public fun close ()V
8+
public fun execute (Lio/sentry/SentryEnvelope;Lio/sentry/Hint;)V
9+
public fun register (Lio/sentry/IScopes;Lio/sentry/SentryOptions;)V
10+
}
11+

sentry-spotlight/build.gradle.kts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import net.ltgt.gradle.errorprone.errorprone
2+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
3+
4+
plugins {
5+
`java-library`
6+
id("io.sentry.javadoc")
7+
alias(libs.plugins.kotlin.jvm)
8+
jacoco
9+
alias(libs.plugins.errorprone)
10+
alias(libs.plugins.gradle.versions)
11+
alias(libs.plugins.animalsniffer)
12+
alias(libs.plugins.buildconfig)
13+
}
14+
15+
tasks.withType<KotlinCompile>().configureEach {
16+
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
17+
}
18+
19+
dependencies {
20+
api(projects.sentry)
21+
22+
errorprone(libs.errorprone.core)
23+
errorprone(libs.nopen.checker)
24+
errorprone(libs.nullaway)
25+
compileOnly(libs.jetbrains.annotations)
26+
compileOnly(libs.nopen.annotations)
27+
28+
// tests
29+
testImplementation(kotlin(Config.kotlinStdLib))
30+
testImplementation(libs.kotlin.test.junit)
31+
testImplementation(libs.mockito.kotlin)
32+
testImplementation(libs.mockito.inline)
33+
testImplementation(projects.sentryTestSupport)
34+
35+
val gummyBearsModule = libs.gummy.bears.api21.get().module
36+
signature("${gummyBearsModule}:${libs.versions.gummyBears.get()}@signature")
37+
}
38+
39+
configure<SourceSetContainer> { test { java.srcDir("src/test/java") } }
40+
41+
jacoco { toolVersion = libs.versions.jacoco.get() }
42+
43+
tasks.jacocoTestReport {
44+
reports {
45+
xml.required.set(true)
46+
html.required.set(false)
47+
}
48+
}
49+
50+
tasks {
51+
jacocoTestCoverageVerification {
52+
violationRules { rule { limit { minimum = Config.QualityPlugins.Jacoco.minimumCoverage } } }
53+
}
54+
check {
55+
dependsOn(jacocoTestCoverageVerification)
56+
dependsOn(jacocoTestReport)
57+
dependsOn(animalsnifferMain)
58+
}
59+
}
60+
61+
buildConfig {
62+
useJavaOutput()
63+
packageName("io.sentry.spotlight")
64+
buildConfigField("String", "VERSION_NAME", "\"${project.version}\"")
65+
}
66+
67+
tasks.withType<JavaCompile>().configureEach {
68+
dependsOn(tasks.generateBuildConfig)
69+
options.errorprone {
70+
check("NullAway", net.ltgt.gradle.errorprone.CheckSeverity.ERROR)
71+
option("NullAway:AnnotatedPackages", "io.sentry")
72+
}
73+
}
74+
75+
tasks.jar {
76+
manifest {
77+
attributes(
78+
"Sentry-Version-Name" to project.version,
79+
"Sentry-SDK-Name" to Config.Sentry.SENTRY_JAVA_SDK_NAME,
80+
"Sentry-SDK-Package-Name" to "maven:io.sentry:sentry-spotlight",
81+
"Implementation-Vendor" to "Sentry",
82+
"Implementation-Title" to project.name,
83+
"Implementation-Version" to project.version,
84+
)
85+
}
86+
}

0 commit comments

Comments
 (0)