diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 97c1d4495af8e2..e8695427c0616e 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -3495,12 +3495,12 @@ public abstract interface class com/facebook/react/modules/network/ProgressListe public abstract fun onProgress (JJZ)V } -public class com/facebook/react/modules/network/ProgressResponseBody : okhttp3/ResponseBody { +public final class com/facebook/react/modules/network/ProgressResponseBody : okhttp3/ResponseBody { public fun (Lokhttp3/ResponseBody;Lcom/facebook/react/modules/network/ProgressListener;)V public fun contentLength ()J public fun contentType ()Lokhttp3/MediaType; public fun source ()Lokio/BufferedSource; - public fun totalBytesRead ()J + public final fun totalBytesRead ()J } public final class com/facebook/react/modules/network/ReactCookieJarContainer : com/facebook/react/modules/network/CookieJarContainer { @@ -3523,7 +3523,7 @@ public class com/facebook/react/modules/network/ResponseUtil { public static fun onResponseReceived (Lcom/facebook/react/bridge/ReactApplicationContext;IILcom/facebook/react/bridge/WritableMap;Ljava/lang/String;)V } -public class com/facebook/react/modules/network/TLSSocketFactory : javax/net/ssl/SSLSocketFactory { +public final class com/facebook/react/modules/network/TLSSocketFactory : javax/net/ssl/SSLSocketFactory { public fun ()V public fun createSocket (Ljava/lang/String;I)Ljava/net/Socket; public fun createSocket (Ljava/lang/String;ILjava/net/InetAddress;I)Ljava/net/Socket; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressListener.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressListener.kt similarity index 54% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressListener.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressListener.kt index 714ea9f902ae88..80cb92f340a1de 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressListener.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressListener.kt @@ -5,8 +5,8 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.modules.network; +package com.facebook.react.modules.network -public interface ProgressListener { - void onProgress(long bytesWritten, long contentLength, boolean done); +public fun interface ProgressListener { + public fun onProgress(bytesWritten: Long, contentLength: Long, done: Boolean) } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressResponseBody.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressResponseBody.java deleted file mode 100644 index 7faf343c3a1a38..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressResponseBody.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.modules.network; - -import androidx.annotation.Nullable; -import java.io.IOException; -import okhttp3.MediaType; -import okhttp3.ResponseBody; -import okio.Buffer; -import okio.BufferedSource; -import okio.ForwardingSource; -import okio.Okio; -import okio.Source; - -public class ProgressResponseBody extends ResponseBody { - - private final ResponseBody mResponseBody; - private final ProgressListener mProgressListener; - private @Nullable BufferedSource mBufferedSource; - private long mTotalBytesRead; - - public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) { - mResponseBody = responseBody; - mProgressListener = progressListener; - mTotalBytesRead = 0L; - } - - @Override - public MediaType contentType() { - return mResponseBody.contentType(); - } - - @Override - public long contentLength() { - return mResponseBody.contentLength(); - } - - public long totalBytesRead() { - return mTotalBytesRead; - } - - @Override - public BufferedSource source() { - if (mBufferedSource == null) { - mBufferedSource = Okio.buffer(source(mResponseBody.source())); - } - return mBufferedSource; - } - - private Source source(Source source) { - return new ForwardingSource(source) { - @Override - public long read(Buffer sink, long byteCount) throws IOException { - long bytesRead = super.read(sink, byteCount); - // read() returns the number of bytes read, or -1 if this source is exhausted. - mTotalBytesRead += bytesRead != -1 ? bytesRead : 0; - mProgressListener.onProgress( - mTotalBytesRead, mResponseBody.contentLength(), bytesRead == -1); - return bytesRead; - } - }; - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressResponseBody.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressResponseBody.kt new file mode 100644 index 00000000000000..ceb4d44c588a8a --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/ProgressResponseBody.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.modules.network + +import java.io.IOException +import okhttp3.MediaType +import okhttp3.ResponseBody +import okio.Buffer +import okio.BufferedSource +import okio.ForwardingSource +import okio.Okio +import okio.Source + +public class ProgressResponseBody( + private val responseBody: ResponseBody, + private val progressListener: ProgressListener +) : ResponseBody() { + + private val _bufferedSource: BufferedSource by + lazy(LazyThreadSafetyMode.NONE) { Okio.buffer(source(responseBody.source())) } + private var _totalBytesRead = 0L + + override fun contentType(): MediaType? = responseBody.contentType() + + override fun contentLength(): Long = responseBody.contentLength() + + public fun totalBytesRead(): Long = _totalBytesRead + + override fun source(): BufferedSource = _bufferedSource + + private fun source(source: Source): Source { + return object : ForwardingSource(source) { + @Throws(IOException::class) + override fun read(sink: Buffer, byteCount: Long): Long { + val bytesRead = super.read(sink, byteCount) + // read() returns the number of bytes read, or -1 if this source is exhausted. + if (bytesRead != -1L) { + _totalBytesRead += bytesRead + } + progressListener.onProgress(_totalBytesRead, responseBody.contentLength(), bytesRead == -1L) + return bytesRead + } + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/TLSSocketFactory.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/TLSSocketFactory.java deleted file mode 100644 index 77798a81fc82ed..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/TLSSocketFactory.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.modules.network; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; - -/** - * This class is needed for TLS 1.2 support on Android 4.x - * - *

Source: http://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/ - */ -public class TLSSocketFactory extends SSLSocketFactory { - private SSLSocketFactory delegate; - - public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, null, null); - delegate = context.getSocketFactory(); - } - - @Override - public String[] getDefaultCipherSuites() { - return delegate.getDefaultCipherSuites(); - } - - @Override - public String[] getSupportedCipherSuites() { - return delegate.getSupportedCipherSuites(); - } - - @Override - public Socket createSocket(Socket s, String host, int port, boolean autoClose) - throws IOException { - return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose)); - } - - @Override - public Socket createSocket(String host, int port) throws IOException, UnknownHostException { - return enableTLSOnSocket(delegate.createSocket(host, port)); - } - - @Override - public Socket createSocket(String host, int port, InetAddress localHost, int localPort) - throws IOException, UnknownHostException { - return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort)); - } - - @Override - public Socket createSocket(InetAddress host, int port) throws IOException { - return enableTLSOnSocket(delegate.createSocket(host, port)); - } - - @Override - public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) - throws IOException { - return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort)); - } - - private Socket enableTLSOnSocket(Socket socket) { - if (socket != null && (socket instanceof SSLSocket)) { - ((SSLSocket) socket).setEnabledProtocols(new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"}); - } - return socket; - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/TLSSocketFactory.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/TLSSocketFactory.kt new file mode 100644 index 00000000000000..fb06b7ce77835d --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/TLSSocketFactory.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.modules.network + +import java.io.IOException +import java.net.InetAddress +import java.net.Socket +import java.net.UnknownHostException +import javax.net.ssl.SSLContext +import javax.net.ssl.SSLSocket +import javax.net.ssl.SSLSocketFactory + +/** + * This class is needed for TLS 1.2 support on Android 4.x + * + * Source: http://blog.dev-area.net/2015/08/13/android-4-1-enable-tls-1-1-and-tls-1-2/ + */ +public class TLSSocketFactory : SSLSocketFactory() { + + private val delegate: SSLSocketFactory + + init { + val context = SSLContext.getInstance("TLS") + context.init(null, null, null) + delegate = context.socketFactory + } + + override fun getDefaultCipherSuites(): Array = delegate.defaultCipherSuites + + override fun getSupportedCipherSuites(): Array = delegate.supportedCipherSuites + + @Throws(IOException::class) + override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket = + enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose)) + + @Throws(IOException::class, UnknownHostException::class) + override fun createSocket(host: String?, port: Int): Socket = + enableTLSOnSocket(delegate.createSocket(host, port)) + + @Throws(IOException::class, UnknownHostException::class) + override fun createSocket( + host: String?, + port: Int, + localHost: InetAddress, + localPort: Int + ): Socket = enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort)) + + @Throws(IOException::class) + override fun createSocket(host: InetAddress, port: Int): Socket = + enableTLSOnSocket(delegate.createSocket(host, port)) + + @Throws(IOException::class) + override fun createSocket( + address: InetAddress, + port: Int, + localAddress: InetAddress, + localPort: Int + ): Socket? = enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort)) + + private fun enableTLSOnSocket(socket: Socket): Socket { + (socket as? SSLSocket)?.enabledProtocols = arrayOf("TLSv1", "TLSv1.1", "TLSv1.2") + return socket + } +}