Skip to content

Commit 9c653c7

Browse files
authored
Add a StrictMode noteSlowCall for SSL init (#8339)
Add strict mode checks on slow calls
1 parent fed29a2 commit 9c653c7

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package okhttp.android.test
2+
3+
import android.os.StrictMode
4+
import android.os.StrictMode.ThreadPolicy
5+
import android.os.strictmode.Violation
6+
import androidx.test.filters.SdkSuppress
7+
import assertk.assertThat
8+
import assertk.assertions.hasSize
9+
import assertk.assertions.isEmpty
10+
import assertk.assertions.isEqualTo
11+
import okhttp3.HttpUrl.Companion.toHttpUrl
12+
import okhttp3.OkHttpClient
13+
import okhttp3.Request
14+
import okhttp3.internal.platform.Platform
15+
import org.junit.After
16+
import org.junit.Test
17+
import org.junit.jupiter.api.parallel.Isolated
18+
19+
@Isolated
20+
@SdkSuppress(minSdkVersion = 28)
21+
class StrictModeTest {
22+
private val violations = mutableListOf<Violation>()
23+
24+
@After
25+
fun cleanup() {
26+
StrictMode.setThreadPolicy(
27+
ThreadPolicy.Builder()
28+
.permitAll()
29+
.build(),
30+
)
31+
}
32+
33+
@Test
34+
fun testInit() {
35+
Platform.resetForTests()
36+
37+
applyStrictMode()
38+
39+
// Not currently safe
40+
// See https://github.com/square/okhttp/pull/8248
41+
OkHttpClient()
42+
43+
assertThat(violations).hasSize(1)
44+
assertThat(violations[0].message).isEqualTo("newSSLContext")
45+
}
46+
47+
@Test
48+
fun testNewCall() {
49+
Platform.resetForTests()
50+
51+
val client = OkHttpClient()
52+
53+
applyStrictMode()
54+
55+
// Safe on main
56+
client.newCall(Request("https://google.com/robots.txt".toHttpUrl()))
57+
58+
assertThat(violations).isEmpty()
59+
}
60+
61+
private fun applyStrictMode() {
62+
StrictMode.setThreadPolicy(
63+
ThreadPolicy.Builder()
64+
.detectCustomSlowCalls()
65+
.penaltyListener({ it.run() }) {
66+
violations.add(it)
67+
}
68+
.build(),
69+
)
70+
}
71+
}

okhttp/src/androidMain/kotlin/okhttp3/internal/platform/Android10Platform.kt

+15
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ package okhttp3.internal.platform
1818
import android.annotation.SuppressLint
1919
import android.content.Context
2020
import android.os.Build
21+
import android.os.StrictMode
2122
import android.security.NetworkSecurityPolicy
2223
import android.util.CloseGuard
24+
import javax.net.ssl.SSLContext
2325
import javax.net.ssl.SSLSocket
2426
import javax.net.ssl.SSLSocketFactory
2527
import javax.net.ssl.X509TrustManager
@@ -32,6 +34,7 @@ import okhttp3.internal.platform.android.BouncyCastleSocketAdapter
3234
import okhttp3.internal.platform.android.ConscryptSocketAdapter
3335
import okhttp3.internal.platform.android.DeferredSocketAdapter
3436
import okhttp3.internal.tls.CertificateChainCleaner
37+
import okhttp3.internal.tls.TrustRootIndex
3538

3639
/** Android 10+ (API 29+). */
3740
@SuppressSignatureCheck
@@ -51,6 +54,18 @@ class Android10Platform : Platform(), ContextAwarePlatform {
5154
socketAdapters.find { it.matchesSocketFactory(sslSocketFactory) }
5255
?.trustManager(sslSocketFactory)
5356

57+
override fun newSSLContext(): SSLContext {
58+
StrictMode.noteSlowCall("newSSLContext")
59+
60+
return super.newSSLContext()
61+
}
62+
63+
override fun buildTrustRootIndex(trustManager: X509TrustManager): TrustRootIndex {
64+
StrictMode.noteSlowCall("buildTrustRootIndex")
65+
66+
return super.buildTrustRootIndex(trustManager)
67+
}
68+
5469
override fun configureTlsExtensions(
5570
sslSocket: SSLSocket,
5671
hostname: String?,

okhttp/src/androidMain/kotlin/okhttp3/internal/platform/AndroidPlatform.kt

+10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package okhttp3.internal.platform
1717

1818
import android.content.Context
1919
import android.os.Build
20+
import android.os.StrictMode
2021
import android.security.NetworkSecurityPolicy
2122
import android.util.Log
2223
import java.io.IOException
@@ -26,6 +27,7 @@ import java.net.InetSocketAddress
2627
import java.net.Socket
2728
import java.security.cert.TrustAnchor
2829
import java.security.cert.X509Certificate
30+
import javax.net.ssl.SSLContext
2931
import javax.net.ssl.SSLSocket
3032
import javax.net.ssl.SSLSocketFactory
3133
import javax.net.ssl.X509TrustManager
@@ -74,6 +76,12 @@ class AndroidPlatform : Platform(), ContextAwarePlatform {
7476
}
7577
}
7678

79+
override fun newSSLContext(): SSLContext {
80+
StrictMode.noteSlowCall("newSSLContext")
81+
82+
return super.newSSLContext()
83+
}
84+
7785
override fun trustManager(sslSocketFactory: SSLSocketFactory): X509TrustManager? =
7886
socketAdapters.find { it.matchesSocketFactory(sslSocketFactory) }
7987
?.trustManager(sslSocketFactory)
@@ -104,6 +112,8 @@ class AndroidPlatform : Platform(), ContextAwarePlatform {
104112

105113
override fun buildTrustRootIndex(trustManager: X509TrustManager): TrustRootIndex =
106114
try {
115+
StrictMode.noteSlowCall("buildTrustRootIndex")
116+
107117
// From org.conscrypt.TrustManagerImpl, we want the method with this signature:
108118
// private TrustAnchor findTrustAnchorByIssuerAndSignature(X509Certificate lastCert);
109119
val method =

0 commit comments

Comments
 (0)