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 963aacfeac4781..ee51e20d245488 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 2ae9344c3b8557..d527714819e598 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 0bad88bdeb83e5..c27596ee462c3e 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 38b2a0f961294d..c9cd347831f99f 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 @@ 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 static OkHttpClient.Builder createClientBuilder() { .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 static OkHttpClient.Builder createClientBuilder(Context context, int cach 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 90b3f3f9f84c07..4a825c007434cb 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_prebuilt_jar( +rn_android_library( name = "okhttp3", - binary_jar = ":okhttp3-binary.jar", + 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-binary", + binary_jar = ":okhttp3-binary.jar", ) 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 e62ba43e228b15..c8b65998b22a5d 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_prebuilt_jar( +rn_android_library( name = "okio", - binary_jar = ":okio-binary.jar", + 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-binary", + binary_jar = ":okio-binary.jar", ) 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 00000000000000..caad9d63e62805 --- /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 f155eebbddd312..53a1340330911a 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 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 void test_executeJSCall_ShouldSendCorrectMessage() throws Exception { 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 321a9d87c8b314..eb09e6dee01f9a 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 Object answer(InvocationOnMock invocation) throws Throwable { 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 void testMultipartPostRequestBody() throws Exception { .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);