From 8207e97f9174a04e319431193c0f63d47a093c44 Mon Sep 17 00:00:00 2001 From: Araz Abishov Date: Thu, 8 Apr 2021 10:44:10 -0700 Subject: [PATCH] Android: upgrading to OkHttp from v3 to v4 (#31084) Summary: Extends https://github.com/facebook/react-native/pull/30694 to fix tests. OkHttp v4 was released almost a year ago. Even though v3 is still receiving security and bug fixes, most of the new improvements and features are landing in v4. This PR bumps OkHttp from v3 to v4 and addresses backward-incompatible changes. Side effects of this upgrade: - OkHttp v4 depends on Kotlin's standard library, so react-native will have a transitive dependency on it. - The dex method count of test apk has exceeded the maximum, so multidexing had to be enabled for android tests. ## Changelog [Android] [Changed] - Bumping OkHttp from v3 to v4. Pull Request resolved: https://github.com/facebook/react-native/pull/31084 Test Plan: Automated (relying on the test suite) and manual testing. Reviewed By: fkgozali Differential Revision: D27597430 Pulled By: ShikaSD fbshipit-source-id: 967379b41c2bcd7cfd4083f65059f5da467b8a91 --- ReactAndroid/build.gradle | 2 +- ReactAndroid/gradle.properties | 2 +- ReactAndroid/src/androidTest/buck-runner/BUCK | 1 + .../modules/network/OkHttpClientProvider.java | 19 +--- .../src/main/third-party/java/okhttp/BUCK | 38 ++++++-- .../src/main/third-party/java/okio/BUCK | 20 +++- ReactAndroid/src/main/third-party/kotlin/BUCK | 91 +++++++++++++++++++ .../JSDebuggerWebSocketClientTest.java | 4 +- .../modules/network/NetworkingModuleTest.java | 10 +- 9 files changed, 147 insertions(+), 40 deletions(-) create mode 100644 ReactAndroid/src/main/third-party/kotlin/BUCK diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 963aacfeac4..ee51e20d245 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -451,7 +451,7 @@ dependencies { api("com.google.code.findbugs:jsr305:3.0.2") api("com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}") api("com.squareup.okhttp3:okhttp-urlconnection:${OKHTTP_VERSION}") - api("com.squareup.okio:okio:1.17.5") + api("com.squareup.okio:okio:2.9.0") api("com.facebook.fbjni:fbjni-java-only:0.2.2") extractHeaders("com.facebook.fbjni:fbjni:0.2.2:headers") extractJNI("com.facebook.fbjni:fbjni:0.2.2") diff --git a/ReactAndroid/gradle.properties b/ReactAndroid/gradle.properties index 2ae9344c3b8..d527714819e 100644 --- a/ReactAndroid/gradle.properties +++ b/ReactAndroid/gradle.properties @@ -12,7 +12,7 @@ JUNIT_VERSION=4.12 ANDROIDX_TEST_VERSION=1.1.0 FRESCO_VERSION=2.3.0 -OKHTTP_VERSION=3.14.9 +OKHTTP_VERSION=4.9.0 SO_LOADER_VERSION=0.9.0 BOOST_VERSION=1_63_0 diff --git a/ReactAndroid/src/androidTest/buck-runner/BUCK b/ReactAndroid/src/androidTest/buck-runner/BUCK index 0bad88bdeb8..c27596ee462 100644 --- a/ReactAndroid/src/androidTest/buck-runner/BUCK +++ b/ReactAndroid/src/androidTest/buck-runner/BUCK @@ -11,6 +11,7 @@ rn_android_binary( name = "instrumentation-tests", keystore = KEYSTORE_TARGET, manifest = "AndroidManifest.xml", + use_split_dex = True, deps = [ react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"), react_native_dep("third-party/java/testing-support-lib:exposed-instrumentation-api"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java index 38b2a0f9612..c9cd347831f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/OkHttpClientProvider.java @@ -10,8 +10,6 @@ package com.facebook.react.modules.network; import android.content.Context; import androidx.annotation.Nullable; import java.io.File; -import java.security.Provider; -import java.security.Security; import java.util.concurrent.TimeUnit; import okhttp3.Cache; import okhttp3.OkHttpClient; @@ -62,13 +60,7 @@ public class OkHttpClientProvider { .writeTimeout(0, TimeUnit.MILLISECONDS) .cookieJar(new ReactCookieJarContainer()); - try { - Class ConscryptProvider = Class.forName("org.conscrypt.OpenSSLProvider"); - Security.insertProviderAt((Provider) ConscryptProvider.newInstance(), 1); - return client; - } catch (Exception e) { - return enableTls12OnPreLollipop(client); - } + return client; } public static OkHttpClient.Builder createClientBuilder(Context context) { @@ -88,13 +80,4 @@ public class OkHttpClientProvider { return client.cache(cache); } - - /* - On Android 4.1-4.4 (API level 16 to 19) TLS 1.1 and 1.2 are - available but not enabled by default. The following method - enables it. - */ - public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) { - return client; - } } diff --git a/ReactAndroid/src/main/third-party/java/okhttp/BUCK b/ReactAndroid/src/main/third-party/java/okhttp/BUCK index 90b3f3f9f84..4a825c00743 100644 --- a/ReactAndroid/src/main/third-party/java/okhttp/BUCK +++ b/ReactAndroid/src/main/third-party/java/okhttp/BUCK @@ -1,26 +1,46 @@ load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -load("//tools/build_defs/oss:rn_defs.bzl", "rn_prebuilt_jar") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library", "rn_prebuilt_jar") + +rn_android_library( + name = "okhttp3", + autoglob = False, + visibility = ["//ReactAndroid/..."], + exported_deps = [ + ":okhttp3-binary", + react_native_dep("third-party/java/okio:okio"), + # Forces resolver to use OSS Kotlin version + react_native_target("third-party/kotlin:kotlin-stdlib-jdk8"), + ], +) + +rn_android_library( + name = "okhttp3-urlconnection", + autoglob = False, + visibility = ["//ReactAndroid/..."], + exported_deps = [ + ":okhttp3", + ":okhttp3-urlconnection-binary", + ], +) rn_prebuilt_jar( - name = "okhttp3", + name = "okhttp3-binary", binary_jar = ":okhttp3-binary.jar", - visibility = ["//ReactAndroid/..."], ) fb_native.remote_file( name = "okhttp3-binary.jar", - sha1 = "3e6d101343c7ea687cd593e4990f73b25c878383", - url = "mvn:com.squareup.okhttp3:okhttp:jar:3.14.9", + sha1 = "08e17601d3bdc8cf57902c154de021931d2c27c1", + url = "mvn:com.squareup.okhttp3:okhttp:jar:4.9.0", ) rn_prebuilt_jar( - name = "okhttp3-urlconnection", + name = "okhttp3-urlconnection-binary", binary_jar = ":okhttp3-urlconnection-binary.jar", - visibility = ["//ReactAndroid/..."], ) fb_native.remote_file( name = "okhttp3-urlconnection-binary.jar", - sha1 = "c9a3b45b815cf2982415ec8145339f5af58989c3", - url = "mvn:com.squareup.okhttp3:okhttp-urlconnection:jar:3.14.9", + sha1 = "94f82aaabdf53e48d7a1c515bf89ce60dcebfbeb", + url = "mvn:com.squareup.okhttp3:okhttp-urlconnection:jar:4.9.0", ) diff --git a/ReactAndroid/src/main/third-party/java/okio/BUCK b/ReactAndroid/src/main/third-party/java/okio/BUCK index e62ba43e228..c8b65998b22 100644 --- a/ReactAndroid/src/main/third-party/java/okio/BUCK +++ b/ReactAndroid/src/main/third-party/java/okio/BUCK @@ -1,14 +1,24 @@ load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") -load("//tools/build_defs/oss:rn_defs.bzl", "rn_prebuilt_jar") +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_target", "rn_android_library", "rn_prebuilt_jar") + +rn_android_library( + name = "okio", + autoglob = False, + visibility = ["//ReactAndroid/..."], + exported_deps = [ + ":okio-binary", + # Forces resolver to use OSS Kotlin version + react_native_target("third-party/kotlin:kotlin-stdlib"), + ], +) rn_prebuilt_jar( - name = "okio", + name = "okio-binary", binary_jar = ":okio-binary.jar", - visibility = ["//ReactAndroid/..."], ) fb_native.remote_file( name = "okio-binary.jar", - sha1 = "34336f82f14dde1c0752fd5f0546dbf3c3225aba", - url = "mvn:com.squareup.okio:okio:jar:1.17.5", + sha1 = "0dcc813b08ce5933f8bdfd1dfbab4ad4bd170e7a", + url = "mvn:com.squareup.okio:okio:jar:2.9.0", ) diff --git a/ReactAndroid/src/main/third-party/kotlin/BUCK b/ReactAndroid/src/main/third-party/kotlin/BUCK new file mode 100644 index 00000000000..caad9d63e62 --- /dev/null +++ b/ReactAndroid/src/main/third-party/kotlin/BUCK @@ -0,0 +1,91 @@ +load("//tools/build_defs:fb_native_wrapper.bzl", "fb_native") +load("//tools/build_defs/oss:rn_defs.bzl", "rn_android_library", "rn_prebuilt_jar") + +rn_android_library( + name = "kotlin-stdlib", + visibility = ["PUBLIC"], + exported_deps = [ + ":jetbrains-annotations", + ":kotlin-stdlib-binary", + ":kotlin-stdlib-common", + ], +) + +rn_android_library( + name = "kotlin-stdlib-jdk7", + visibility = ["PUBLIC"], + exported_deps = [ + ":kotlin-stdlib", + ":kotlin-stdlib-jdk7-binary", + ], +) + +rn_android_library( + name = "kotlin-stdlib-jdk8", + visibility = ["PUBLIC"], + exported_deps = [ + ":kotlin-stdlib", + ":kotlin-stdlib-jdk7", + ":kotlin-stdlib-jdk8-binary", + ], +) + +rn_prebuilt_jar( + name = "jetbrains-annotations", + binary_jar = ":jetbrains-annotations.jar", + visibility = ["//ReactAndroid/..."], +) + +fb_native.remote_file( + name = "jetbrains-annotations.jar", + sha1 = "919f0dfe192fb4e063e7dacadee7f8bb9a2672a9", + url = "mvn:org.jetbrains:annotations:jar:13.0", +) + +rn_prebuilt_jar( + name = "kotlin-stdlib-binary", + binary_jar = ":kotlin-stdlib-binary.jar", + visibility = ["//ReactAndroid/..."], +) + +fb_native.remote_file( + name = "kotlin-stdlib-binary.jar", + sha1 = "ea29e063d2bbe695be13e9d044dcfb0c7add398e", + url = "mvn:org.jetbrains.kotlin:kotlin-stdlib:jar:1.4.10", +) + +rn_prebuilt_jar( + name = "kotlin-stdlib-common", + binary_jar = ":kotlin-stdlib-common.jar", + visibility = ["//ReactAndroid/..."], +) + +fb_native.remote_file( + name = "kotlin-stdlib-common.jar", + sha1 = "6229be3465805c99db1142ad75e6c6ddeac0b04c", + url = "mvn:org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.4.10", +) + +rn_prebuilt_jar( + name = "kotlin-stdlib-jdk7-binary", + binary_jar = ":kotlin-stdlib-jdk7-binary.jar", + visibility = ["//ReactAndroid/..."], +) + +fb_native.remote_file( + name = "kotlin-stdlib-jdk7-binary.jar", + sha1 = "30e46450b0bb3dbf43898d2f461be4a942784780", + url = "mvn:org.jetbrains.kotlin:kotlin-stdlib-jdk7:jar:1.4.10", +) + +rn_prebuilt_jar( + name = "kotlin-stdlib-jdk8-binary", + binary_jar = ":kotlin-stdlib-jdk8-binary.jar", + visibility = ["//ReactAndroid/..."], +) + +fb_native.remote_file( + name = "kotlin-stdlib-jdk8-binary.jar", + sha1 = "998caa30623f73223194a8b657abd2baec4880ea", + url = "mvn:org.jetbrains.kotlin:kotlin-stdlib-jdk8:jar:1.4.10", +) diff --git a/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java b/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java index f155eebbddd..53a13403309 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/devsupport/JSDebuggerWebSocketClientTest.java @@ -11,6 +11,7 @@ import static org.mockito.Mockito.*; import com.facebook.react.common.JavascriptException; import java.util.HashMap; +import okhttp3.WebSocket; import okio.ByteString; import org.junit.Rule; import org.junit.Test; @@ -74,7 +75,8 @@ public class JSDebuggerWebSocketClientTest { public void test_onMessage_WithInvalidContentType_ShouldNotTriggerCallbacks() throws Exception { JSDebuggerWebSocketClient client = PowerMockito.spy(new JSDebuggerWebSocketClient()); - client.onMessage(null, ByteString.encodeUtf8("{\"replyID\":0, \"result\":\"OK\"}")); + client.onMessage( + mock(WebSocket.class), ByteString.encodeUtf8("{\"replyID\":0, \"result\":\"OK\"}")); PowerMockito.verifyPrivate(client, never()) .invoke("triggerRequestSuccess", anyInt(), nullable(String.class)); PowerMockito.verifyPrivate(client, never()).invoke("triggerRequestFailure", anyInt(), any()); diff --git a/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java b/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java index 321a9d87c8b..eb09e6dee01 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/modules/network/NetworkingModuleTest.java @@ -76,8 +76,8 @@ public class NetworkingModuleTest { @Before public void prepareModules() { - mHttpClient = mock(OkHttpClient.class); - when(mHttpClient.cookieJar()).thenReturn(mock(CookieJarContainer.class)); + mHttpClient = PowerMockito.mock(OkHttpClient.class); + PowerMockito.when(mHttpClient.cookieJar()).thenReturn(mock(CookieJarContainer.class)); when(mHttpClient.newCall(any(Request.class))) .thenAnswer( new Answer() { @@ -87,8 +87,8 @@ public class NetworkingModuleTest { return callMock; } }); - OkHttpClient.Builder clientBuilder = mock(OkHttpClient.Builder.class); - when(clientBuilder.build()).thenReturn(mHttpClient); + OkHttpClient.Builder clientBuilder = PowerMockito.mock(OkHttpClient.Builder.class); + PowerMockito.when(clientBuilder.build()).thenReturn(mHttpClient); when(mHttpClient.newBuilder()).thenReturn(clientBuilder); mEmitter = mock(RCTDeviceEventEmitter.class); @@ -453,7 +453,7 @@ public class NetworkingModuleTest { .thenCallRealMethod(); when(inputStream.available()).thenReturn("imageUri".length()); - final MultipartBody.Builder multipartBuilder = mock(MultipartBody.Builder.class); + final MultipartBody.Builder multipartBuilder = PowerMockito.mock(MultipartBody.Builder.class); PowerMockito.whenNew(MultipartBody.Builder.class) .withNoArguments() .thenReturn(multipartBuilder);