diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/ReactOkHttpNetworkFetcher.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/ReactOkHttpNetworkFetcher.java index 18a7ce9..9644a5b 100644 --- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/ReactOkHttpNetworkFetcher.java +++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/ReactOkHttpNetworkFetcher.java @@ -22,11 +22,25 @@ import okhttp3.Headers; import okhttp3.OkHttpClient; import okhttp3.Request; -class ReactOkHttpNetworkFetcher extends OkHttpNetworkFetcher { +import android.os.Looper; +import com.facebook.imagepipeline.common.BytesRange; +import com.facebook.imagepipeline.image.EncodedImage; +import com.facebook.imagepipeline.producers.BaseNetworkFetcher; +import com.facebook.imagepipeline.producers.BaseProducerContextCallbacks; +import com.facebook.imagepipeline.producers.Consumer; +import com.facebook.imagepipeline.producers.FetchState; +import com.facebook.imagepipeline.producers.ProducerContext; +import java.io.IOException; +import javax.annotation.Nullable; +import okhttp3.Call; +import okhttp3.Response; +import okhttp3.ResponseBody; + +public class ReactOkHttpNetworkFetcher extends OkHttpNetworkFetcher { private static final String TAG = "ReactOkHttpNetworkFetcher"; - private final OkHttpClient mOkHttpClient; + private static OkHttpClient mOkHttpClient; private final Executor mCancellationExecutor; /** @param okHttpClient client to use */ @@ -36,6 +50,10 @@ class ReactOkHttpNetworkFetcher extends OkHttpNetworkFetcher { mCancellationExecutor = okHttpClient.dispatcher().executorService(); } + public static void setOkHttpClient(OkHttpClient okHttpClient) { + mOkHttpClient = okHttpClient; + } + private Map getHeaders(ReadableMap readableMap) { if (readableMap == null) { return null; @@ -75,4 +93,88 @@ class ReactOkHttpNetworkFetcher extends OkHttpNetworkFetcher { fetchWithRequest(fetchState, callback, request); } + + @Override + protected void fetchWithRequest( + final OkHttpNetworkFetchState fetchState, + final NetworkFetcher.Callback callback, + final Request request) { + final Call call = mOkHttpClient.newCall(request); + + fetchState + .getContext() + .addCallbacks( + new BaseProducerContextCallbacks() { + @Override + public void onCancellationRequested() { + if (Looper.myLooper() != Looper.getMainLooper()) { + call.cancel(); + } else { + mCancellationExecutor.execute( + new Runnable() { + @Override + public void run() { + call.cancel(); + } + }); + } + } + }); + + call.enqueue( + new okhttp3.Callback() { + @Override + public void onResponse(Call call, Response response) throws IOException { + fetchState.responseTime = SystemClock.elapsedRealtime(); + final ResponseBody body = response.body(); + try { + if (!response.isSuccessful()) { + handleException( + call, new IOException("Unexpected HTTP code " + response), callback); + return; + } + + BytesRange responseRange = + BytesRange.fromContentRangeHeader(response.header("Content-Range")); + if (responseRange != null + && !(responseRange.from == 0 + && responseRange.to == BytesRange.TO_END_OF_CONTENT)) { + // Only treat as a partial image if the range is not all of the content + fetchState.setResponseBytesRange(responseRange); + fetchState.setOnNewResultStatusFlags(Consumer.IS_PARTIAL_RESULT); + } + + long contentLength = body.contentLength(); + if (contentLength < 0) { + contentLength = 0; + } + callback.onResponse(body.byteStream(), (int) contentLength); + } catch (Exception e) { + handleException(call, e, callback); + } finally { + body.close(); + } + } + + @Override + public void onFailure(Call call, IOException e) { + handleException(call, e, callback); + } + }); + } + + /** + * Handles exceptions. + * + *

OkHttp notifies callers of cancellations via an IOException. If IOException is caught after + * request cancellation, then the exception is interpreted as successful cancellation and + * onCancellation is called. Otherwise onFailure is called. + */ + private void handleException(final Call call, final Exception e, final Callback callback) { + if (call.isCanceled()) { + callback.onCancellation(); + } else { + callback.onFailure(e); + } + } } diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/CustomClientBuilder.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/CustomClientBuilder.java new file mode 100644 index 0000000..db81d65 --- /dev/null +++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/CustomClientBuilder.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) Facebook, Inc. and its 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 okhttp3.OkHttpClient; + +public interface CustomClientBuilder { + public void apply(OkHttpClient.Builder builder); +} diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 1c4b373..d723b59 100644 --- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -167,10 +167,6 @@ public final class NetworkingModule extends NativeNetworkingAndroidSpec { customClientBuilder = ccb; } - public static interface CustomClientBuilder { - public void apply(OkHttpClient.Builder builder); - } - private static void applyCustomBuilder(OkHttpClient.Builder builder) { if (customClientBuilder != null) { customClientBuilder.apply(builder); diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java index ee1b2c8..94bc974 100644 --- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java +++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java @@ -35,6 +35,9 @@ import okhttp3.WebSocket; import okhttp3.WebSocketListener; import okio.ByteString; +import com.facebook.react.modules.network.OkHttpClientProvider; +import com.facebook.react.modules.network.CustomClientBuilder; + @ReactModule(name = NativeWebSocketModuleSpec.NAME, hasConstants = false) public final class WebSocketModule extends NativeWebSocketModuleSpec { public interface ContentHandler { @@ -48,6 +51,18 @@ public final class WebSocketModule extends NativeWebSocketModuleSpec { private ForwardingCookieHandler mCookieHandler; + private static @Nullable CustomClientBuilder customClientBuilder = null; + + public static void setCustomClientBuilder(CustomClientBuilder ccb) { + customClientBuilder = ccb; + } + + private static void applyCustomBuilder(OkHttpClient.Builder builder) { + if (customClientBuilder != null) { + customClientBuilder.apply(builder); + } + } + public WebSocketModule(ReactApplicationContext context) { super(context); mCookieHandler = new ForwardingCookieHandler(context); @@ -88,8 +103,10 @@ public final class WebSocketModule extends NativeWebSocketModuleSpec { new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) - .readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read - .build(); + .readTimeout(0, TimeUnit.MINUTES); // Disable timeouts for read + + applyCustomBuilder(clientBuilder); + OkHttpClient client = clientBuilder.build(); Request.Builder builder = new Request.Builder().tag(id).url(url);