From 6bbaff2944dafd6fa7e5b77ef46dece0ec2c9983 Mon Sep 17 00:00:00 2001 From: Andrew Jack Date: Tue, 17 May 2016 12:37:50 -0700 Subject: [PATCH] Upgrade to OkHttp3 Summary: Update to [OkHttp](https://github.com/square/okhttp) to [OkHttp3](https://publicobject.com/2015/12/12/com-squareup-okhttp3/) We must also update: - Fresco to 0.10.0 - okio to 1.8.0 **Motivation** Reasons for upgrading: * Issue #4021 * "We discovered that RN Android sometimes fails to connect to the latest stable version of NGINX when HTTP/2 is enabled. We aren't seeing errors with other HTTP clients so we think it's specific to RN and OkHttp. Square has fixed several HTTP/2 bugs over the past eight months." - ide * OkHttp3 will be maintained & improved, but OkHttp2 will only receive [security fixes](https://publicobject.com/2016/02/11/okhttp-certificate-pinning-vulnerability/) * Cleaner APIs - "Get and Set prefixes are avoided" * Deprecated/Removed - HttpURLConnection & Apache HTTP * React Native apps are currently being forced to bundle two versions of OkHttp (v2 & v3), if another library uses v3 * Improved WebSocket performance - [CHANGELOG.md](https://github.com/square/okhttp/blob/master Closes https://github.com/facebook/react-native/pull/6113 Reviewed By: andreicoman11, lexs Differential Revision: D3292375 Pulled By: bestander fbshipit-source-id: 7c7043eaa2ea63f95854108b401c4066098d67f7 --- ReactAndroid/build.gradle | 11 +-- .../main/java/com/facebook/react/bridge/BUCK | 6 +- .../bridge/JSDebuggerWebSocketClient.java | 39 +++++---- .../react/bridge/webworkers/WebWorkers.java | 6 +- .../main/java/com/facebook/react/common/BUCK | 1 + .../react/common/network/OkHttpCallUtil.java | 35 ++++++++ .../java/com/facebook/react/devsupport/BUCK | 13 ++- .../react/devsupport/DevServerHelper.java | 55 ++++++------- .../react/devsupport/RedBoxDialog.java | 8 +- .../com/facebook/react/modules/fresco/BUCK | 16 ++-- .../react/modules/fresco/FrescoModule.java | 8 +- .../com/facebook/react/modules/network/BUCK | 9 ++- .../modules/network/CookieJarContainer.java | 11 +++ .../network/NetworkInterceptorCreator.java | 2 +- .../modules/network/NetworkingModule.java | 80 +++++++++---------- .../modules/network/OkHttpClientProvider.java | 25 +++--- .../network/ReactCookieJarContainer.java | 44 ++++++++++ .../modules/network/RequestBodyUtil.java | 6 +- .../com/facebook/react/modules/websocket/BUCK | 12 +-- .../modules/websocket/WebSocketModule.java | 48 +++++------ .../libraries/fresco/fresco-react-native/BUCK | 38 ++++++--- .../src/main/third-party/java/okhttp/BUCK | 32 +++++--- .../src/main/third-party/java/okio/BUCK | 4 +- .../src/test/java/com/facebook/react/BUCK | 20 +++-- .../test/java/com/facebook/react/modules/BUCK | 19 +++-- .../modules/network/NetworkingModuleTest.java | 48 +++++------ .../java/com/facebook/react/uimanager/BUCK | 21 +++-- .../test/java/com/facebook/react/views/BUCK | 28 +++---- .../templates/src/app/proguard-rules.pro | 6 +- 29 files changed, 378 insertions(+), 273 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/common/network/OkHttpCallUtil.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/network/CookieJarContainer.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.java diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index abd0fec39..5f5ba755c 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -259,13 +259,14 @@ dependencies { compile fileTree(dir: 'src/main/third-party/java/infer-annotations/', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:recyclerview-v7:23.0.1' - compile 'com.facebook.fresco:fresco:0.8.1' - compile 'com.facebook.fresco:imagepipeline-okhttp:0.8.1' + compile 'com.facebook.fresco:fresco:0.10.0' + compile 'com.facebook.fresco:imagepipeline-okhttp3:0.10.0' compile 'com.fasterxml.jackson.core:jackson-core:2.2.3' compile 'com.google.code.findbugs:jsr305:3.0.0' - compile 'com.squareup.okhttp:okhttp:2.5.0' - compile 'com.squareup.okhttp:okhttp-ws:2.5.0' - compile 'com.squareup.okio:okio:1.6.0' + compile 'com.squareup.okhttp3:okhttp:3.2.0' + compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0' + compile 'com.squareup.okhttp3:okhttp-ws:3.2.0' + compile 'com.squareup.okio:okio:1.8.0' compile 'org.webkit:android-jsc:r174650' testCompile "junit:junit:${JUNIT_VERSION}" diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK index 43aaf9c5d..6164c32a8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK @@ -21,16 +21,16 @@ android_library( react_native_dep('java/com/facebook/proguard/annotations:annotations'), ], deps = [ - react_native_target('java/com/facebook/react/common:common'), react_native_dep('java/com/facebook/systrace:systrace'), react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'), react_native_dep('libraries/soloader/java/com/facebook/soloader:soloader'), react_native_dep('third-party/java/infer-annotations:infer-annotations'), react_native_dep('third-party/java/jackson:core'), react_native_dep('third-party/java/jsr-305:jsr-305'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okhttp:okhttp3-ws'), react_native_dep('third-party/java/okio:okio'), - react_native_dep('third-party/java/okhttp:okhttp'), - react_native_dep('third-party/java/okhttp:okhttp-ws'), + react_native_target('java/com/facebook/react/common:common'), ], visibility = [ 'PUBLIC', diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSDebuggerWebSocketClient.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSDebuggerWebSocketClient.java index 849a0ea79..9370f46b4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSDebuggerWebSocketClient.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSDebuggerWebSocketClient.java @@ -25,14 +25,15 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ws.WebSocket; -import com.squareup.okhttp.ws.WebSocketCall; -import com.squareup.okhttp.ws.WebSocketListener; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okhttp3.ws.WebSocket; +import okhttp3.ws.WebSocketCall; +import okhttp3.ws.WebSocketListener; import okio.Buffer; -import okio.BufferedSource; /** * A wrapper around WebSocketClient that recognizes RN debugging message format. @@ -59,11 +60,11 @@ public class JSDebuggerWebSocketClient implements WebSocketListener { throw new IllegalStateException("JSDebuggerWebSocketClient is already initialized."); } mConnectCallback = callback; - mHttpClient = new OkHttpClient(); - mHttpClient.setConnectTimeout(10, TimeUnit.SECONDS); - mHttpClient.setWriteTimeout(10, TimeUnit.SECONDS); - // Disable timeouts for read - mHttpClient.setReadTimeout(0, TimeUnit.MINUTES); + mHttpClient = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read + .build(); Request request = new Request.Builder().url(url).build(); WebSocketCall call = WebSocketCall.create(mHttpClient, request); @@ -162,10 +163,8 @@ public class JSDebuggerWebSocketClient implements WebSocketListener { new IllegalStateException("WebSocket connection no longer valid")); return; } - Buffer messageBuffer = new Buffer(); - messageBuffer.writeUtf8(message); try { - mWebSocket.sendMessage(WebSocket.PayloadType.TEXT, messageBuffer); + mWebSocket.sendMessage(RequestBody.create(WebSocket.TEXT, message)); } catch (IOException e) { triggerRequestFailure(requestID, e); } @@ -188,17 +187,17 @@ public class JSDebuggerWebSocketClient implements WebSocketListener { } @Override - public void onMessage(BufferedSource payload, WebSocket.PayloadType type) throws IOException { - if (type != WebSocket.PayloadType.TEXT) { - FLog.w(TAG, "Websocket received unexpected message with payload of type " + type); + public void onMessage(ResponseBody response) throws IOException { + if (response.contentType() != WebSocket.TEXT) { + FLog.w(TAG, "Websocket received unexpected message with payload of type " + response.contentType()); return; } String message = null; try { - message = payload.readUtf8(); + message = response.source().readUtf8(); } finally { - payload.close(); + response.close(); } Integer replyID = null; diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/webworkers/WebWorkers.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/webworkers/WebWorkers.java index c2b897b24..e0e3a20ee 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/webworkers/WebWorkers.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/webworkers/WebWorkers.java @@ -18,9 +18,9 @@ import com.facebook.react.bridge.queue.MessageQueueThreadImpl; import com.facebook.react.bridge.queue.ProxyQueueThreadExceptionHandler; import com.facebook.react.common.build.ReactBuildConfig; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import okio.Okio; import okio.Sink; diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK index e98c528e8..289daab3d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/common/BUCK @@ -7,6 +7,7 @@ android_library( ':build_config', react_native_dep('third-party/java/infer-annotations:infer-annotations'), react_native_dep('third-party/java/jsr-305:jsr-305'), + react_native_dep('third-party/java/okhttp:okhttp3'), ], exported_deps = [ react_native_dep('java/com/facebook/proguard/annotations:annotations'), diff --git a/ReactAndroid/src/main/java/com/facebook/react/common/network/OkHttpCallUtil.java b/ReactAndroid/src/main/java/com/facebook/react/common/network/OkHttpCallUtil.java new file mode 100644 index 000000000..4da3a5e9b --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/common/network/OkHttpCallUtil.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + *

+ * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package com.facebook.react.common.network; + +import okhttp3.Call; +import okhttp3.OkHttpClient; + +/** + * Helper class that provides the necessary methods for canceling queued and running OkHttp calls + */ +public class OkHttpCallUtil { + + private OkHttpCallUtil() { + } + + public static void cancelTag(OkHttpClient client, Object tag) { + for (Call call : client.dispatcher().queuedCalls()) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + for (Call call : client.dispatcher().runningCalls()) { + if (tag.equals(call.request().tag())) { + call.cancel(); + } + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK index 8bd558248..0757fe379 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK @@ -5,17 +5,16 @@ android_library( manifest = 'AndroidManifest.xml', srcs = glob(['**/*.java']), deps = [ - react_native_target('res:devsupport'), + react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'), + react_native_dep('third-party/java/infer-annotations:infer-annotations'), + react_native_dep('third-party/java/jsr-305:jsr-305'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okio:okio'), react_native_target('java/com/facebook/react/bridge:bridge'), react_native_target('java/com/facebook/react/common:common'), react_native_target('java/com/facebook/react/modules/debug:debug'), react_native_target('java/com/facebook/react/modules/systeminfo:systeminfo'), - react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'), - react_native_dep('third-party/java/infer-annotations:infer-annotations'), - react_native_dep('third-party/java/jsr-305:jsr-305'), - react_native_dep('third-party/java/okhttp:okhttp'), - react_native_dep('third-party/java/okio:okio'), - + react_native_target('res:devsupport'), ], visibility = [ 'PUBLIC', diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java index ffd53e5bd..95d347852 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java @@ -17,14 +17,8 @@ import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.common.ReactConstants; +import com.facebook.react.common.network.OkHttpCallUtil; import com.facebook.react.modules.systeminfo.AndroidInfoHelpers; -import com.squareup.okhttp.Call; -import com.squareup.okhttp.Callback; -import com.squareup.okhttp.ConnectionPool; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; import java.io.File; import java.io.IOException; @@ -33,6 +27,13 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; import okio.Okio; import okio.Sink; @@ -91,12 +92,12 @@ public class DevServerHelper { public DevServerHelper(DevInternalSettings settings) { mSettings = settings; - mClient = new OkHttpClient(); - mClient.setConnectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + mClient = new OkHttpClient.Builder() + .connectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS) + .readTimeout(0, TimeUnit.MILLISECONDS) + .writeTimeout(0, TimeUnit.MILLISECONDS) + .build(); - // No read or write timeouts by default - mClient.setReadTimeout(0, TimeUnit.MILLISECONDS); - mClient.setWriteTimeout(0, TimeUnit.MILLISECONDS); mRestartOnChangePollingHandler = new Handler(); } @@ -176,7 +177,7 @@ public class DevServerHelper { mDownloadBundleFromURLCall = Assertions.assertNotNull(mClient.newCall(request)); mDownloadBundleFromURLCall.enqueue(new Callback() { @Override - public void onFailure(Request request, IOException e) { + public void onFailure(Call call, IOException e) { // ignore callback if call was cancelled if (mDownloadBundleFromURLCall == null || mDownloadBundleFromURLCall.isCanceled()) { mDownloadBundleFromURLCall = null; @@ -191,12 +192,12 @@ public class DevServerHelper { .append("\u2022 Ensure that your device/emulator is connected to your machine and has USB debugging enabled - run 'adb devices' to see a list of connected devices\n") .append("\u2022 If you're on a physical device connected to the same machine, run 'adb reverse tcp:8081 tcp:8081' to forward requests from your device\n") .append("\u2022 If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:8081\n\n") - .append("URL: ").append(request.urlString()); + .append("URL: ").append(call.request().url().toString()); callback.onFailure(new DebugServerException(sb.toString())); } @Override - public void onResponse(Response response) throws IOException { + public void onResponse(Call call, Response response) throws IOException { // ignore callback if call was cancelled if (mDownloadBundleFromURLCall == null || mDownloadBundleFromURLCall.isCanceled()) { mDownloadBundleFromURLCall = null; @@ -213,7 +214,7 @@ public class DevServerHelper { } else { StringBuilder sb = new StringBuilder(); sb.append("The development server returned response error code: ").append(response.code()).append("\n\n") - .append("URL: ").append(request.urlString()).append("\n\n") + .append("URL: ").append(call.request().url().toString()).append("\n\n") .append("Body:\n") .append(body); callback.onFailure(new DebugServerException(sb.toString())); @@ -251,7 +252,7 @@ public class DevServerHelper { mClient.newCall(request).enqueue( new Callback() { @Override - public void onFailure(Request request, IOException e) { + public void onFailure(Call call, IOException e) { FLog.w( ReactConstants.TAG, "The packager does not seem to be running as we got an IOException requesting " + @@ -260,7 +261,7 @@ public class DevServerHelper { } @Override - public void onResponse(Response response) throws IOException { + public void onResponse(Call call, Response response) throws IOException { if (!response.isSuccessful()) { FLog.e( ReactConstants.TAG, @@ -297,7 +298,7 @@ public class DevServerHelper { mOnChangePollingEnabled = false; mRestartOnChangePollingHandler.removeCallbacksAndMessages(null); if (mOnChangePollingClient != null) { - mOnChangePollingClient.cancel(this); + OkHttpCallUtil.cancelTag(mOnChangePollingClient, this); mOnChangePollingClient = null; } mOnServerContentChangeListener = null; @@ -311,10 +312,10 @@ public class DevServerHelper { } mOnChangePollingEnabled = true; mOnServerContentChangeListener = onServerContentChangeListener; - mOnChangePollingClient = new OkHttpClient(); - mOnChangePollingClient - .setConnectionPool(new ConnectionPool(1, LONG_POLL_KEEP_ALIVE_DURATION_MS)) - .setConnectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS); + mOnChangePollingClient = new OkHttpClient.Builder() + .connectionPool(new ConnectionPool(1, LONG_POLL_KEEP_ALIVE_DURATION_MS, TimeUnit.MINUTES)) + .connectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS) + .build(); enqueueOnChangeEndpointLongPolling(); } @@ -338,7 +339,7 @@ public class DevServerHelper { Request request = new Request.Builder().url(createOnChangeEndpointUrl()).tag(this).build(); Assertions.assertNotNull(mOnChangePollingClient).newCall(request).enqueue(new Callback() { @Override - public void onFailure(Request request, IOException e) { + public void onFailure(Call call, IOException e) { if (mOnChangePollingEnabled) { // this runnable is used by onchange endpoint poller to delay subsequent requests in case // of a failure, so that we don't flood network queue with frequent requests in case when @@ -356,7 +357,7 @@ public class DevServerHelper { } @Override - public void onResponse(Response response) throws IOException { + public void onResponse(Call call, Response response) throws IOException { handleOnChangePollingResponse(response.code() == 205); } }); @@ -376,13 +377,13 @@ public class DevServerHelper { .build(); mClient.newCall(request).enqueue(new Callback() { @Override - public void onFailure(Request request, IOException e) { + public void onFailure(Call call, IOException e) { // ignore HTTP call response, this is just to open a debugger page and there is no reason // to report failures from here } @Override - public void onResponse(Response response) throws IOException { + public void onResponse(Call call, Response response) throws IOException { // ignore HTTP call response - see above } }); diff --git a/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java b/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java index e6b777e1b..eefb1d735 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java +++ b/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java @@ -30,10 +30,10 @@ import com.facebook.react.common.MapBuilder; import com.facebook.react.common.ReactConstants; import com.facebook.react.devsupport.StackTraceHelper.StackFrame; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.RequestBody; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; import org.json.JSONObject; /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK index 18cae1994..0f462adbc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK @@ -4,21 +4,21 @@ android_library( name = 'fresco', srcs = glob(['**/*.java']), deps = [ - react_native_target('java/com/facebook/react/bridge:bridge'), - react_native_target('java/com/facebook/react/modules/common:common'), - react_native_target('java/com/facebook/react/modules/network:network'), react_native_dep('java/com/facebook/systrace:systrace'), + react_native_dep('libraries/fresco/fresco-react-native:fbcore'), + react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'), react_native_dep('libraries/fresco/fresco-react-native:fresco-react-native'), react_native_dep('libraries/fresco/fresco-react-native:imagepipeline'), - react_native_dep('libraries/fresco/fresco-react-native:imagepipeline-okhttp'), + react_native_dep('libraries/fresco/fresco-react-native:imagepipeline-okhttp3'), react_native_dep('libraries/soloader/java/com/facebook/soloader:soloader'), react_native_dep('third-party/android/support-annotations:android-support-annotations'), react_native_dep('third-party/android/support/v4:lib-support-v4'), react_native_dep('third-party/java/jsr-305:jsr-305'), - react_native_dep('third-party/java/okhttp:okhttp'), - react_native_dep('libraries/fresco/fresco-react-native:fbcore'), - react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'), -], + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_target('java/com/facebook/react/bridge:bridge'), + react_native_target('java/com/facebook/react/modules/common:common'), + react_native_target('java/com/facebook/react/modules/network:network'), + ], visibility = [ 'PUBLIC', ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java index 3f2302ab9..210f89e35 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java @@ -19,7 +19,7 @@ import com.facebook.cache.disk.DiskCacheConfig; import com.facebook.common.internal.AndroidPredicates; import com.facebook.common.soloader.SoLoaderShim; import com.facebook.drawee.backends.pipeline.Fresco; -import com.facebook.imagepipeline.backends.okhttp.OkHttpImagePipelineConfigFactory; +import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory; import com.facebook.imagepipeline.core.ImagePipelineConfig; import com.facebook.imagepipeline.core.ImagePipelineFactory; import com.facebook.imagepipeline.listener.RequestListener; @@ -29,7 +29,7 @@ import com.facebook.react.modules.common.ModuleDataCleaner; import com.facebook.react.modules.network.OkHttpClientProvider; import com.facebook.soloader.SoLoader; -import com.squareup.okhttp.OkHttpClient; +import okhttp3.OkHttpClient; /** * Module to initialize the Fresco library. @@ -84,8 +84,8 @@ public class FrescoModule extends ReactContextBaseJavaModule implements ImagePipelineFactory imagePipelineFactory = Fresco.getImagePipelineFactory(); imagePipelineFactory.getBitmapMemoryCache().removeAll(AndroidPredicates.True()); imagePipelineFactory.getEncodedMemoryCache().removeAll(AndroidPredicates.True()); - imagePipelineFactory.getMainDiskStorageCache().clearAll(); - imagePipelineFactory.getSmallImageDiskStorageCache().clearAll(); + imagePipelineFactory.getMainFileCache().clearAll(); + imagePipelineFactory.getSmallImageFileCache().clearAll(); } private static ImagePipelineConfig getDefaultConfig( diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK index 42f9d30b0..aa6b475a0 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/BUCK @@ -4,15 +4,16 @@ android_library( name = 'network', srcs = glob(['**/*.java']), deps = [ - react_native_target('java/com/facebook/react/bridge:bridge'), - react_native_target('java/com/facebook/react/modules/core:core'), - react_native_target('java/com/facebook/react/common:common'), react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'), react_native_dep('third-party/android/support/v4:lib-support-v4'), react_native_dep('third-party/java/infer-annotations:infer-annotations'), react_native_dep('third-party/java/jsr-305:jsr-305'), - react_native_dep('third-party/java/okhttp:okhttp'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okhttp:okhttp3-urlconnection'), react_native_dep('third-party/java/okio:okio'), + react_native_target('java/com/facebook/react/bridge:bridge'), + react_native_target('java/com/facebook/react/common:common'), + react_native_target('java/com/facebook/react/modules/core:core'), ], visibility = [ 'PUBLIC', diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/CookieJarContainer.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/CookieJarContainer.java new file mode 100644 index 000000000..fcf375f08 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/CookieJarContainer.java @@ -0,0 +1,11 @@ +package com.facebook.react.modules.network; + +import okhttp3.CookieJar; + +public interface CookieJarContainer extends CookieJar { + + void setCookieJar(CookieJar cookieJar); + + void removeCookieJar(); + +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkInterceptorCreator.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkInterceptorCreator.java index b2b7ac250..15f136753 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkInterceptorCreator.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkInterceptorCreator.java @@ -9,7 +9,7 @@ package com.facebook.react.modules.network; -import com.squareup.okhttp.Interceptor; +import okhttp3.Interceptor; /** * Classes implementing this interface return a new {@link Interceptor} when the {@link #create} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 5db80193b..8a67aa104 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -9,17 +9,6 @@ package com.facebook.react.modules.network; -import javax.annotation.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; - -import java.net.SocketTimeoutException; - -import java.util.List; -import java.util.concurrent.TimeUnit; - import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ExecutorToken; import com.facebook.react.bridge.GuardedAsyncTask; @@ -30,19 +19,29 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import com.facebook.react.common.network.OkHttpCallUtil; import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.squareup.okhttp.Callback; -import com.squareup.okhttp.Headers; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.MultipartBuilder; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.SocketTimeoutException; +import java.util.List; +import java.util.concurrent.TimeUnit; -import static java.lang.Math.min; +import javax.annotation.Nullable; + +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.Headers; +import okhttp3.JavaNetCookieJar; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; /** * Implements the XMLHttpRequest JavaScript interface. @@ -61,6 +60,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { private final OkHttpClient mClient; private final ForwardingCookieHandler mCookieHandler; private final @Nullable String mDefaultUserAgent; + private final CookieJarContainer mCookieJarContainer; private boolean mShuttingDown; /* package */ NetworkingModule( @@ -76,6 +76,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { } } mCookieHandler = new ForwardingCookieHandler(reactContext); + mCookieJarContainer = (CookieJarContainer) mClient.cookieJar(); mShuttingDown = false; mDefaultUserAgent = defaultUserAgent; } @@ -126,7 +127,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { @Override public void initialize() { - mClient.setCookieHandler(mCookieHandler); + mCookieJarContainer.setCookieJar(new JavaNetCookieJar(mCookieHandler)); } @Override @@ -137,10 +138,10 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { @Override public void onCatalystInstanceDestroy() { mShuttingDown = true; - mClient.cancel(null); + OkHttpCallUtil.cancelTag(mClient, null); mCookieHandler.destroy(); - mClient.setCookieHandler(null); + mCookieJarContainer.removeCookieJar(); } @ReactMethod @@ -167,9 +168,10 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { // client and set the timeout explicitly on the clone. This is cheap as everything else is // shared under the hood. // See https://github.com/square/okhttp/wiki/Recipes#per-call-configuration for more information - if (timeout != mClient.getConnectTimeout()) { - client = mClient.clone(); - client.setReadTimeout(timeout, TimeUnit.MILLISECONDS); + if (timeout != mClient.connectTimeoutMillis()) { + client = mClient.newBuilder() + .readTimeout(timeout, TimeUnit.MILLISECONDS) + .build(); } Headers requestHeaders = extractHeaders(headers, data); @@ -228,7 +230,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { contentType = "multipart/form-data"; } ReadableArray parts = data.getArray(REQUEST_BODY_KEY_FORMDATA); - MultipartBuilder multipartBuilder = + MultipartBody.Builder multipartBuilder = constructMultipartBody(executorToken, parts, contentType, requestId); if (multipartBuilder == null) { return; @@ -242,7 +244,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { client.newCall(requestBuilder.build()).enqueue( new Callback() { @Override - public void onFailure(Request request, IOException e) { + public void onFailure(Call call, IOException e) { if (mShuttingDown) { return; } @@ -250,7 +252,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { } @Override - public void onResponse(Response response) throws IOException { + public void onResponse(Call call, Response response) throws IOException { if (mShuttingDown) { return; } @@ -328,7 +330,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { args.pushInt(requestId); args.pushInt(response.code()); args.pushMap(headers); - args.pushString(response.request().urlString()); + args.pushString(response.request().url().toString()); getEventEmitter(ExecutorToken).emit("didReceiveNetworkResponse", args); } @@ -356,7 +358,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { new GuardedAsyncTask(getReactApplicationContext()) { @Override protected void doInBackgroundGuarded(Void... params) { - mClient.cancel(requestId); + OkHttpCallUtil.cancelTag(mClient, requestId); } }.execute(); } @@ -373,15 +375,13 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { return true; } - private - @Nullable - MultipartBuilder constructMultipartBody( + private @Nullable MultipartBody.Builder constructMultipartBody( ExecutorToken ExecutorToken, ReadableArray body, String contentType, int requestId) { - MultipartBuilder multipartBuilder = new MultipartBuilder(); - multipartBuilder.type(MediaType.parse(contentType)); + MultipartBody.Builder multipartBuilder = new MultipartBody.Builder(); + multipartBuilder.setType(MediaType.parse(contentType)); for (int i = 0, size = body.size(); i < size; i++) { ReadableMap bodyPart = body.getMap(i); @@ -440,9 +440,7 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { /** * Extracts the headers from the Array. If the format is invalid, this method will return null. */ - private - @Nullable - Headers extractHeaders( + private @Nullable Headers extractHeaders( @Nullable ReadableArray headersArray, @Nullable ReadableMap requestData) { if (headersArray == null) { @@ -475,4 +473,4 @@ public final class NetworkingModule extends ReactContextBaseJavaModule { return getReactApplicationContext() .getJSModule(ExecutorToken, DeviceEventManagerModule.RCTDeviceEventEmitter.class); } -} \ No newline at end of file +} 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 956b5fbae..dcd8972cf 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 @@ -9,11 +9,11 @@ package com.facebook.react.modules.network; -import javax.annotation.Nullable; - import java.util.concurrent.TimeUnit; -import com.squareup.okhttp.OkHttpClient; +import javax.annotation.Nullable; + +import okhttp3.OkHttpClient; /** * Helper class that provides the same OkHttpClient instance that will be used for all networking @@ -30,15 +30,20 @@ public class OkHttpClientProvider { } return sClient; } + + // okhttp3 OkHttpClient is immutable + // This allows app to init an OkHttpClient with custom settings. + public static void replaceOkHttpClient(OkHttpClient client) { + sClient = client; + } private static OkHttpClient createClient() { - OkHttpClient client = new OkHttpClient(); - // No timeouts by default - client.setConnectTimeout(0, TimeUnit.MILLISECONDS); - client.setReadTimeout(0, TimeUnit.MILLISECONDS); - client.setWriteTimeout(0, TimeUnit.MILLISECONDS); - - return client; + return new OkHttpClient.Builder() + .connectTimeout(0, TimeUnit.MILLISECONDS) + .readTimeout(0, TimeUnit.MILLISECONDS) + .writeTimeout(0, TimeUnit.MILLISECONDS) + .cookieJar(new ReactCookieJarContainer()) + .build(); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.java new file mode 100644 index 000000000..a8436c218 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/ReactCookieJarContainer.java @@ -0,0 +1,44 @@ +package com.facebook.react.modules.network; + +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nullable; + +import okhttp3.Cookie; +import okhttp3.CookieJar; +import okhttp3.HttpUrl; + +/** + * Basic okhttp3 CookieJar container + */ +public class ReactCookieJarContainer implements CookieJarContainer { + + @Nullable + private CookieJar cookieJar = null; + + @Override + public void setCookieJar(CookieJar cookieJar) { + this.cookieJar = cookieJar; + } + + @Override + public void removeCookieJar() { + this.cookieJar = null; + } + + @Override + public void saveFromResponse(HttpUrl url, List cookies) { + if (cookieJar != null) { + cookieJar.saveFromResponse(url, cookies); + } + } + + @Override + public List loadForRequest(HttpUrl url) { + if (cookieJar != null) { + return cookieJar.loadForRequest(url); + } + return Collections.emptyList(); + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java index f834120ac..0290a23fd 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/RequestBodyUtil.java @@ -23,9 +23,9 @@ import android.net.Uri; import com.facebook.common.logging.FLog; import com.facebook.react.common.ReactConstants; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.RequestBody; -import com.squareup.okhttp.internal.Util; +import okhttp3.MediaType; +import okhttp3.RequestBody; +import okhttp3.internal.Util; import okio.BufferedSink; import okio.ByteString; import okio.Okio; diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK index 6289e0598..7c8af9cca 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/BUCK @@ -4,16 +4,16 @@ android_library( name = 'websocket', srcs = glob(['**/*.java']), deps = [ - react_native_target('java/com/facebook/react/bridge:bridge'), - react_native_target('java/com/facebook/react/common:common'), - react_native_target('java/com/facebook/react/modules/core:core'), react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'), react_native_dep('third-party/java/infer-annotations:infer-annotations'), react_native_dep('third-party/java/jsr-305:jsr-305'), - react_native_dep('third-party/java/okhttp:okhttp-ws'), - react_native_dep('third-party/java/okhttp:okhttp'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okhttp:okhttp3-ws'), react_native_dep('third-party/java/okio:okio'), -], + react_native_target('java/com/facebook/react/bridge:bridge'), + react_native_target('java/com/facebook/react/common:common'), + react_native_target('java/com/facebook/react/modules/core:core'), + ], visibility = [ 'PUBLIC', ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java index 938136f36..e7eae279b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java @@ -29,12 +29,14 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.ReactConstants; import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ws.WebSocket; -import com.squareup.okhttp.ws.WebSocketCall; -import com.squareup.okhttp.ws.WebSocketListener; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okhttp3.ws.WebSocket; +import okhttp3.ws.WebSocketCall; +import okhttp3.ws.WebSocketListener; import java.net.URISyntaxException; import java.net.URI; @@ -43,7 +45,6 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import okio.Buffer; -import okio.BufferedSource; import okio.ByteString; public class WebSocketModule extends ReactContextBaseJavaModule { @@ -69,12 +70,11 @@ public class WebSocketModule extends ReactContextBaseJavaModule { @ReactMethod public void connect(final String url, @Nullable final ReadableArray protocols, @Nullable final ReadableMap headers, final int id) { - OkHttpClient client = new OkHttpClient(); - - client.setConnectTimeout(10, TimeUnit.SECONDS); - client.setWriteTimeout(10, TimeUnit.SECONDS); - // Disable timeouts for read - client.setReadTimeout(0, TimeUnit.MINUTES); + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read + .build(); Request.Builder builder = new Request.Builder() .tag(id) @@ -145,20 +145,20 @@ public class WebSocketModule extends ReactContextBaseJavaModule { } @Override - public void onMessage(BufferedSource bufferedSource, WebSocket.PayloadType payloadType) { + public void onMessage(ResponseBody response) throws IOException { String message; try { - if (payloadType == WebSocket.PayloadType.BINARY) { - message = Base64.encodeToString(bufferedSource.readByteArray(), Base64.NO_WRAP); + if (response.contentType() == WebSocket.BINARY) { + message = Base64.encodeToString(response.source().readByteArray(), Base64.NO_WRAP); } else { - message = bufferedSource.readUtf8(); + message = response.source().readUtf8(); } } catch (IOException e) { notifyWebSocketFailed(id, e.getMessage()); return; } try { - bufferedSource.close(); + response.source().close(); } catch (IOException e) { FLog.e( ReactConstants.TAG, @@ -169,13 +169,13 @@ public class WebSocketModule extends ReactContextBaseJavaModule { WritableMap params = Arguments.createMap(); params.putInt("id", id); params.putString("data", message); - params.putString("type", payloadType == WebSocket.PayloadType.BINARY ? "binary" : "text"); + params.putString("type", response.contentType() == WebSocket.BINARY ? "binary" : "text"); sendEvent("websocketMessage", params); } }); // Trigger shutdown of the dispatcher's executor so this process can exit cleanly - client.getDispatcher().getExecutorService().shutdown(); + client.dispatcher().executorService().shutdown(); } @ReactMethod @@ -209,9 +209,7 @@ public class WebSocketModule extends ReactContextBaseJavaModule { throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id); } try { - client.sendMessage( - WebSocket.PayloadType.TEXT, - new Buffer().writeUtf8(message)); + client.sendMessage(RequestBody.create(WebSocket.TEXT, message)); } catch (IOException | IllegalStateException e) { notifyWebSocketFailed(id, e.getMessage()); } @@ -225,9 +223,7 @@ public class WebSocketModule extends ReactContextBaseJavaModule { throw new RuntimeException("Cannot send a message. Unknown WebSocket id " + id); } try { - client.sendMessage( - WebSocket.PayloadType.BINARY, - new Buffer().write(ByteString.decodeBase64(base64String))); + client.sendMessage(RequestBody.create(WebSocket.TEXT, ByteString.decodeBase64(base64String))); } catch (IOException | IllegalStateException e) { notifyWebSocketFailed(id, e.getMessage()); } diff --git a/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK b/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK index 7b410d076..ee04bc4f0 100644 --- a/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK +++ b/ReactAndroid/src/main/libraries/fresco/fresco-react-native/BUCK @@ -6,8 +6,8 @@ android_prebuilt_aar( remote_file( name = 'fresco-binary-aar', - url = 'mvn:com.facebook.fresco:fresco:aar:0.8.1', - sha1 = 'f0a4f04318123e1597514b2abf56b7e66581f3f8', + url = 'mvn:com.facebook.fresco:fresco:aar:0.10.0', + sha1 = '8576630feea3d08eb681dec389a472623179f84d', ) android_prebuilt_aar( @@ -18,19 +18,31 @@ android_prebuilt_aar( remote_file( name = 'drawee-binary-aar', - url = 'mvn:com.facebook.fresco:drawee:aar:0.8.1', - sha1 = 'a944015ddf50fdad79302e42a85a351633c24472', + url = 'mvn:com.facebook.fresco:drawee:aar:0.10.0', + sha1 = 'c594f9c23f844d08ecd4c0e42df40d80767d4b18', ) android_library( name = 'imagepipeline', exported_deps = [ + ':imagepipeline-base', ':imagepipeline-core', ':bolts', ], visibility = ['//ReactAndroid/...',], ) +android_prebuilt_aar( + name = 'imagepipeline-base', + aar = ':imagepipeline-base-aar', + visibility = ['//ReactAndroid/...',], +) + +remote_file( + name = 'imagepipeline-base-aar', + url = 'mvn:com.facebook.fresco:imagepipeline-base:aar:0.10.0', + sha1 = '1390f28d0e4f16b0008fed481eb1b107d93f35b8', +) android_prebuilt_aar( name = 'imagepipeline-core', @@ -40,8 +52,8 @@ android_prebuilt_aar( remote_file( name = 'imagepipeline-aar', - url = 'mvn:com.facebook.fresco:imagepipeline:aar:0.8.1', - sha1 = '93fe3e629c03aea8f63dabd80a0e616b0caef65b', + url = 'mvn:com.facebook.fresco:imagepipeline:aar:0.10.0', + sha1 = 'ecec308b714039dd9e0cf4b7595a427765f43a01', ) prebuilt_jar( @@ -64,18 +76,18 @@ android_prebuilt_aar( remote_file( name = 'fbcore-aar', - url = 'mvn:com.facebook.fresco:fbcore:aar:0.8.1', - sha1 = 'cc46b3d564139bf63bb41534c7a723ee8119ae5f', + url = 'mvn:com.facebook.fresco:fbcore:aar:0.10.0', + sha1 = '4650dd9a46064c254e0468bba23804e8f32e6144', ) android_prebuilt_aar( - name = 'imagepipeline-okhttp', - aar = ':imagepipeline-okhttp-binary-aar', + name = 'imagepipeline-okhttp3', + aar = ':imagepipeline-okhttp3-binary-aar', visibility = ['//ReactAndroid/...',], ) remote_file( - name = 'imagepipeline-okhttp-binary-aar', - url = 'mvn:com.facebook.fresco:imagepipeline-okhttp:aar:0.8.1', - sha1 = 'd6b16dbaab8b810620347355a425fb2982e33ef8', + name = 'imagepipeline-okhttp3-binary-aar', + url = 'mvn:com.facebook.fresco:imagepipeline-okhttp3:aar:0.10.0', + sha1 = 'a3e95483f116b528bdf2d06f7ff2212cb9b372e2', ) diff --git a/ReactAndroid/src/main/third-party/java/okhttp/BUCK b/ReactAndroid/src/main/third-party/java/okhttp/BUCK index f4da3fa0b..07d870bdb 100644 --- a/ReactAndroid/src/main/third-party/java/okhttp/BUCK +++ b/ReactAndroid/src/main/third-party/java/okhttp/BUCK @@ -1,23 +1,35 @@ prebuilt_jar( - name = 'okhttp', - binary_jar = ':okhttp-binary-jar', + name = 'okhttp3', + binary_jar = ':okhttp3-binary-jar', visibility = ['//ReactAndroid/...',], ) remote_file( - name = 'okhttp-binary-jar', - url = 'mvn:com.squareup.okhttp:okhttp:jar:2.5.0', - sha1 = '4de2b4ed3445c37ec1720a7d214712e845a24636' + name = 'okhttp3-binary-jar', + url = 'mvn:com.squareup.okhttp3:okhttp:jar:3.2.0', + sha1 = 'f7873a2ebde246a45c2a8d6f3247108b4c88a879' ) prebuilt_jar( - name = 'okhttp-ws', - binary_jar = ':okhttp-ws-binary-jar', + name = 'okhttp3-urlconnection', + binary_jar = ':okhttp3-urlconnection-binary-jar', + visibility = ['//ReactAndroid/...',], +) + +remote_file( + name = 'okhttp3-urlconnection-binary-jar', + url = 'mvn:com.squareup.okhttp3:okhttp-urlconnection:jar:3.2.0', + sha1 = '6f8a4b1435c9e0a6f9c5fe4a1be46627b848fd0c' +) + +prebuilt_jar( + name = 'okhttp3-ws', + binary_jar = ':okhttp3-ws-binary-jar', visibility = ['//ReactAndroid/...',], ) remote_file( - name = 'okhttp-ws-binary-jar', - url = 'mvn:com.squareup.okhttp:okhttp-ws:jar:2.5.0', - sha1 = '0e9753b7dcae5deca92e871c5c759067070b07bc', + name = 'okhttp3-ws-binary-jar', + url = 'mvn:com.squareup.okhttp3:okhttp-ws:jar:3.2.0', + sha1 = '1ea229d6984444c8c58b8e97ba4c8429d9d135b3', ) diff --git a/ReactAndroid/src/main/third-party/java/okio/BUCK b/ReactAndroid/src/main/third-party/java/okio/BUCK index 61ad012c2..3f3339840 100644 --- a/ReactAndroid/src/main/third-party/java/okio/BUCK +++ b/ReactAndroid/src/main/third-party/java/okio/BUCK @@ -6,6 +6,6 @@ prebuilt_jar( remote_file( name = 'okio-binary-jar', - url = 'mvn:com.squareup.okio:okio:jar:1.6.0', - sha1 = '98476622f10715998eacf9240d6b479f12c66143', + url = 'mvn:com.squareup.okio:okio:jar:1.8.0', + sha1 = '05ea7af56cc7c567ed9856d99efb30740e9b17ff', ) diff --git a/ReactAndroid/src/test/java/com/facebook/react/BUCK b/ReactAndroid/src/test/java/com/facebook/react/BUCK index 0396f42ae..9d3626d23 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/BUCK @@ -6,8 +6,15 @@ robolectric3_test( contacts = ['oncall+fbandroid_sheriff@xmail.facebook.com'], srcs = glob(['*.java']), deps = [ + react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), + react_native_dep('third-party/java/fest:fest'), + react_native_dep('third-party/java/jsr-305:jsr-305'), + react_native_dep('third-party/java/junit:junit'), + react_native_dep('third-party/java/mockito:mockito'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okio:okio'), + react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), react_native_target('java/com/facebook/csslayout:csslayout'), - react_native_target('java/com/facebook/react:react'), react_native_target('java/com/facebook/react/animation:animation'), react_native_target('java/com/facebook/react/bridge:bridge'), react_native_target('java/com/facebook/react/common:common'), @@ -15,20 +22,11 @@ robolectric3_test( react_native_target('java/com/facebook/react/uimanager:uimanager'), react_native_target('java/com/facebook/react/views/text:text'), react_native_target('java/com/facebook/react/views/view:view'), + react_native_target('java/com/facebook/react:react'), react_native_tests_target('java/com/facebook/react/bridge:testhelpers'), - - react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), - react_native_dep('third-party/java/fest:fest'), - react_native_dep('third-party/java/junit:junit'), - react_native_dep('third-party/java/okio:okio'), - react_native_dep('third-party/java/mockito:mockito'), - react_native_dep('third-party/java/okhttp:okhttp'), - react_native_dep('third-party/java/jsr-305:jsr-305'), - react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), ], ) project_config( test_target = ':react', ) - diff --git a/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK b/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK index 5e9df2b0b..19787b131 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/modules/BUCK @@ -6,8 +6,14 @@ robolectric3_test( name = 'modules', srcs = glob(['**/*.java']), deps = [ + react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), + react_native_dep('third-party/java/fest:fest'), + react_native_dep('third-party/java/junit:junit'), + react_native_dep('third-party/java/mockito:mockito'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okio:okio'), + react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), react_native_target('java/com/facebook/csslayout:csslayout'), - react_native_target('java/com/facebook/react:react'), react_native_target('java/com/facebook/react/animation:animation'), react_native_target('java/com/facebook/react/bridge:bridge'), react_native_target('java/com/facebook/react/common:common'), @@ -19,17 +25,10 @@ robolectric3_test( react_native_target('java/com/facebook/react/modules/network:network'), react_native_target('java/com/facebook/react/modules/storage:storage'), react_native_target('java/com/facebook/react/modules/systeminfo:systeminfo'), - react_native_target('java/com/facebook/react/uimanager:uimanager'), react_native_target('java/com/facebook/react/touch:touch'), - + react_native_target('java/com/facebook/react/uimanager:uimanager'), + react_native_target('java/com/facebook/react:react'), react_native_tests_target('java/com/facebook/react/bridge:testhelpers'), - react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), - react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), - react_native_dep('third-party/java/fest:fest'), - react_native_dep('third-party/java/junit:junit'), - react_native_dep('third-party/java/okio:okio'), - react_native_dep('third-party/java/mockito:mockito'), - react_native_dep('third-party/java/okhttp:okhttp'), ], visibility = [ 'PUBLIC' 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 ce3896123..b80561183 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 @@ -23,22 +23,19 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; -import com.squareup.okhttp.Call; -import com.squareup.okhttp.Headers; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.MultipartBuilder; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.RequestBody; +import okhttp3.Call; +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; import okio.Buffer; -import org.junit.After; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -46,9 +43,7 @@ import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.modules.junit4.rule.PowerMockRule; -import org.robolectric.RuntimeEnvironment; import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; import static org.fest.assertions.api.Assertions.assertThat; import static org.mockito.Mockito.any; @@ -65,7 +60,8 @@ import static org.mockito.Mockito.when; Arguments.class, Call.class, RequestBodyUtil.class, - MultipartBuilder.class, + MultipartBody.class, + MultipartBody.Builder.class, NetworkingModule.class, OkHttpClient.class}) @RunWith(RobolectricTestRunner.class) @@ -100,7 +96,7 @@ public class NetworkingModuleTest { ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Request.class); verify(httpClient).newCall(argumentCaptor.capture()); - assertThat(argumentCaptor.getValue().urlString()).isEqualTo("http://somedomain/foo"); + assertThat(argumentCaptor.getValue().url().toString()).isEqualTo("http://somedomain/foo"); // We set the User-Agent header by default assertThat(argumentCaptor.getValue().headers().size()).isEqualTo(1); assertThat(argumentCaptor.getValue().method()).isEqualTo("GET"); @@ -215,7 +211,7 @@ public class NetworkingModuleTest { ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Request.class); verify(httpClient).newCall(argumentCaptor.capture()); - assertThat(argumentCaptor.getValue().urlString()).isEqualTo("http://somedomain/bar"); + assertThat(argumentCaptor.getValue().url().toString()).isEqualTo("http://somedomain/bar"); assertThat(argumentCaptor.getValue().headers().size()).isEqualTo(2); assertThat(argumentCaptor.getValue().method()).isEqualTo("POST"); assertThat(argumentCaptor.getValue().body().contentType().type()).isEqualTo("text"); @@ -302,12 +298,12 @@ public class NetworkingModuleTest { // verify url, method, headers ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Request.class); verify(httpClient).newCall(argumentCaptor.capture()); - assertThat(argumentCaptor.getValue().urlString()).isEqualTo("http://someurl/uploadFoo"); + assertThat(argumentCaptor.getValue().url().toString()).isEqualTo("http://someurl/uploadFoo"); assertThat(argumentCaptor.getValue().method()).isEqualTo("POST"); assertThat(argumentCaptor.getValue().body().contentType().type()). - isEqualTo(MultipartBuilder.FORM.type()); + isEqualTo(MultipartBody.FORM.type()); assertThat(argumentCaptor.getValue().body().contentType().subtype()). - isEqualTo(MultipartBuilder.FORM.subtype()); + isEqualTo(MultipartBody.FORM.subtype()); Headers requestHeaders = argumentCaptor.getValue().headers(); assertThat(requestHeaders.size()).isEqualTo(1); } @@ -361,12 +357,12 @@ public class NetworkingModuleTest { // verify url, method, headers ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Request.class); verify(httpClient).newCall(argumentCaptor.capture()); - assertThat(argumentCaptor.getValue().urlString()).isEqualTo("http://someurl/uploadFoo"); + assertThat(argumentCaptor.getValue().url().toString()).isEqualTo("http://someurl/uploadFoo"); assertThat(argumentCaptor.getValue().method()).isEqualTo("POST"); assertThat(argumentCaptor.getValue().body().contentType().type()). - isEqualTo(MultipartBuilder.FORM.type()); + isEqualTo(MultipartBody.FORM.type()); assertThat(argumentCaptor.getValue().body().contentType().subtype()). - isEqualTo(MultipartBuilder.FORM.subtype()); + isEqualTo(MultipartBody.FORM.subtype()); Headers requestHeaders = argumentCaptor.getValue().headers(); assertThat(requestHeaders.size()).isEqualTo(3); assertThat(requestHeaders.get("Accept")).isEqualTo("text/plain"); @@ -383,9 +379,9 @@ public class NetworkingModuleTest { when(RequestBodyUtil.create(any(MediaType.class), any(InputStream.class))).thenCallRealMethod(); when(inputStream.available()).thenReturn("imageUri".length()); - final MultipartBuilder multipartBuilder = mock(MultipartBuilder.class); - PowerMockito.whenNew(MultipartBuilder.class).withNoArguments().thenReturn(multipartBuilder); - when(multipartBuilder.type(any(MediaType.class))).thenAnswer( + final MultipartBody.Builder multipartBuilder = mock(MultipartBody.Builder.class); + PowerMockito.whenNew(MultipartBody.Builder.class).withNoArguments().thenReturn(multipartBuilder); + when(multipartBuilder.setType(any(MediaType.class))).thenAnswer( new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { @@ -403,7 +399,7 @@ public class NetworkingModuleTest { new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { - return mock(RequestBody.class); + return mock(MultipartBody.class); } }); @@ -462,7 +458,7 @@ public class NetworkingModuleTest { // verify body verify(multipartBuilder).build(); - verify(multipartBuilder).type(MultipartBuilder.FORM); + verify(multipartBuilder).setType(MultipartBody.FORM); ArgumentCaptor headersArgumentCaptor = ArgumentCaptor.forClass(Headers.class); ArgumentCaptor bodyArgumentCaptor = ArgumentCaptor.forClass(RequestBody.class); verify(multipartBuilder, times(2)). diff --git a/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK b/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK index 9fe1b6977..ccfb2bc70 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/uimanager/BUCK @@ -6,26 +6,25 @@ robolectric3_test( contacts = ['oncall+fbandroid_sheriff@xmail.facebook.com'], srcs = glob(['**/*.java']), deps = [ + react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), + react_native_dep('third-party/java/fest:fest'), + react_native_dep('third-party/java/jsr-305:jsr-305'), + react_native_dep('third-party/java/junit:junit'), + react_native_dep('third-party/java/mockito:mockito'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okio:okio'), + react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), react_native_target('java/com/facebook/csslayout:csslayout'), - react_native_target('java/com/facebook/react:react'), react_native_target('java/com/facebook/react/animation:animation'), react_native_target('java/com/facebook/react/bridge:bridge'), react_native_target('java/com/facebook/react/common:common'), react_native_target('java/com/facebook/react/touch:touch'), - react_native_target('java/com/facebook/react/uimanager:uimanager'), react_native_target('java/com/facebook/react/uimanager/annotations:annotations'), + react_native_target('java/com/facebook/react/uimanager:uimanager'), react_native_target('java/com/facebook/react/views/text:text'), react_native_target('java/com/facebook/react/views/view:view'), - + react_native_target('java/com/facebook/react:react'), react_native_tests_target('java/com/facebook/react/bridge:testhelpers'), - react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), - react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), - react_native_dep('third-party/java/fest:fest'), - react_native_dep('third-party/java/junit:junit'), - react_native_dep('third-party/java/okio:okio'), - react_native_dep('third-party/java/mockito:mockito'), - react_native_dep('third-party/java/okhttp:okhttp'), - react_native_dep('third-party/java/jsr-305:jsr-305'), ], visibility = [ 'PUBLIC' diff --git a/ReactAndroid/src/test/java/com/facebook/react/views/BUCK b/ReactAndroid/src/test/java/com/facebook/react/views/BUCK index 5834b9374..673085e03 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/views/BUCK +++ b/ReactAndroid/src/test/java/com/facebook/react/views/BUCK @@ -6,31 +6,29 @@ robolectric3_test( contacts = ['oncall+fbandroid_sheriff@xmail.facebook.com'], srcs = glob(['**/*.java']), deps = [ + react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), + react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'), + react_native_dep('libraries/fresco/fresco-react-native:fresco-react-native'), + react_native_dep('libraries/fresco/fresco-react-native:imagepipeline'), + react_native_dep('third-party/java/fest:fest'), + react_native_dep('third-party/java/jsr-305:jsr-305'), + react_native_dep('third-party/java/junit:junit'), + react_native_dep('third-party/java/mockito:mockito'), + react_native_dep('third-party/java/okhttp:okhttp3'), + react_native_dep('third-party/java/okio:okio'), + react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), react_native_target('java/com/facebook/csslayout:csslayout'), - react_native_target('java/com/facebook/react:react'), react_native_target('java/com/facebook/react/bridge:bridge'), react_native_target('java/com/facebook/react/common:common'), react_native_target('java/com/facebook/react/touch:touch'), - react_native_target('java/com/facebook/react/uimanager:uimanager'), react_native_target('java/com/facebook/react/uimanager/annotations:annotations'), + react_native_target('java/com/facebook/react/uimanager:uimanager'), react_native_target('java/com/facebook/react/views/image:image'), react_native_target('java/com/facebook/react/views/text:text'), react_native_target('java/com/facebook/react/views/textinput:textinput'), react_native_target('java/com/facebook/react/views/view:view'), - + react_native_target('java/com/facebook/react:react'), react_native_tests_target('java/com/facebook/react/bridge:testhelpers'), - react_native_dep('third-party/java/robolectric3/robolectric:robolectric'), - react_native_dep('third-party/java/fest:fest'), - react_native_dep('third-party/java/junit:junit'), - react_native_dep('third-party/java/okio:okio'), - react_native_dep('third-party/java/mockito:mockito'), - react_native_dep('third-party/java/okhttp:okhttp'), - react_native_dep('third-party/java/jsr-305:jsr-305'), - - react_native_dep('libraries/fbcore/src/test/java/com/facebook/powermock:powermock'), - react_native_dep('libraries/fresco/fresco-react-native:fresco-react-native'), - react_native_dep('libraries/fresco/fresco-react-native:imagepipeline'), - react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'), ], ) diff --git a/local-cli/generator-android/templates/src/app/proguard-rules.pro b/local-cli/generator-android/templates/src/app/proguard-rules.pro index 347a13ce1..9852871bd 100644 --- a/local-cli/generator-android/templates/src/app/proguard-rules.pro +++ b/local-cli/generator-android/templates/src/app/proguard-rules.pro @@ -51,9 +51,9 @@ -keepattributes Signature -keepattributes *Annotation* --keep class com.squareup.okhttp.** { *; } --keep interface com.squareup.okhttp.** { *; } --dontwarn com.squareup.okhttp.** +-keep class okhttp3.** { *; } +-keep interface okhttp3.** { *; } +-dontwarn okhttp3.** # okio