mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-13 09:21:46 +08:00
Move JSPackagerWebSocketClient and JSDebuggerWebSocketClient to react/devsupport module
Summary: This move lets us remove the dependency on okhttp3 from react/bridge. The classes I moved are all strictly related to dev support features and don't need to go into the core bridge module that gets shipped to production. Reviewed By: AaaChiuuu Differential Revision: D3698977 fbshipit-source-id: 6ba1517377061690cef289a544ec1622122cef85
This commit is contained in:
committed by
Facebook Github Bot 9
parent
6e60b1763c
commit
031fe4d797
@@ -7,6 +7,7 @@ android_library(
|
||||
deps = [
|
||||
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/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'),
|
||||
|
||||
@@ -15,7 +15,6 @@ import android.text.TextUtils;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.JSPackagerWebSocketClient;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.network.OkHttpCallUtil;
|
||||
|
||||
@@ -45,7 +45,6 @@ import com.facebook.react.bridge.JavaJSExecutor;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.bridge.WebsocketJavaScriptExecutor;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.ShakeDetector;
|
||||
import com.facebook.react.common.futures.SimpleSettableFuture;
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* 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.devsupport;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
|
||||
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 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;
|
||||
|
||||
/**
|
||||
* A wrapper around WebSocketClient that recognizes RN debugging message format.
|
||||
*/
|
||||
public class JSDebuggerWebSocketClient implements WebSocketListener {
|
||||
|
||||
private static final String TAG = "JSDebuggerWebSocketClient";
|
||||
private static final JsonFactory mJsonFactory = new JsonFactory();
|
||||
|
||||
public interface JSDebuggerCallback {
|
||||
void onSuccess(@Nullable String response);
|
||||
void onFailure(Throwable cause);
|
||||
}
|
||||
|
||||
private @Nullable WebSocket mWebSocket;
|
||||
private @Nullable OkHttpClient mHttpClient;
|
||||
private @Nullable JSDebuggerCallback mConnectCallback;
|
||||
private final AtomicInteger mRequestID = new AtomicInteger();
|
||||
private final ConcurrentHashMap<Integer, JSDebuggerCallback> mCallbacks =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
public void connect(String url, JSDebuggerCallback callback) {
|
||||
if (mHttpClient != null) {
|
||||
throw new IllegalStateException("JSDebuggerWebSocketClient is already initialized.");
|
||||
}
|
||||
mConnectCallback = callback;
|
||||
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);
|
||||
call.enqueue(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the next JSON message to send to remote JS executor, with request ID pre-filled in.
|
||||
*/
|
||||
private JsonGenerator startMessageObject(int requestID) throws IOException {
|
||||
JsonGenerator jg = mJsonFactory.createGenerator(new StringWriter());
|
||||
jg.writeStartObject();
|
||||
jg.writeNumberField("id", requestID);
|
||||
return jg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a JsonGenerator created by {@link #startMessageObject} and returns the stringified
|
||||
* JSON
|
||||
*/
|
||||
private String endMessageObject(JsonGenerator jg) throws IOException {
|
||||
jg.writeEndObject();
|
||||
jg.flush();
|
||||
return ((StringWriter) jg.getOutputTarget()).getBuffer().toString();
|
||||
}
|
||||
|
||||
public void prepareJSRuntime(JSDebuggerCallback callback) {
|
||||
int requestID = mRequestID.getAndIncrement();
|
||||
mCallbacks.put(requestID, callback);
|
||||
|
||||
try {
|
||||
JsonGenerator jg = startMessageObject(requestID);
|
||||
jg.writeStringField("method", "prepareJSRuntime");
|
||||
sendMessage(requestID, endMessageObject(jg));
|
||||
} catch (IOException e) {
|
||||
triggerRequestFailure(requestID, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadApplicationScript(
|
||||
String sourceURL,
|
||||
HashMap<String, String> injectedObjects,
|
||||
JSDebuggerCallback callback) {
|
||||
int requestID = mRequestID.getAndIncrement();
|
||||
mCallbacks.put(requestID, callback);
|
||||
|
||||
try {
|
||||
JsonGenerator jg = startMessageObject(requestID);
|
||||
jg.writeStringField("method", "executeApplicationScript");
|
||||
jg.writeStringField("url", sourceURL);
|
||||
jg.writeObjectFieldStart("inject");
|
||||
for (String key : injectedObjects.keySet()) {
|
||||
jg.writeObjectField(key, injectedObjects.get(key));
|
||||
}
|
||||
jg.writeEndObject();
|
||||
sendMessage(requestID, endMessageObject(jg));
|
||||
} catch (IOException e) {
|
||||
triggerRequestFailure(requestID, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void executeJSCall(
|
||||
String methodName,
|
||||
String jsonArgsArray,
|
||||
JSDebuggerCallback callback) {
|
||||
|
||||
int requestID = mRequestID.getAndIncrement();
|
||||
mCallbacks.put(requestID, callback);
|
||||
|
||||
try {
|
||||
JsonGenerator jg = startMessageObject(requestID);
|
||||
jg.writeStringField("method", methodName);
|
||||
jg.writeFieldName("arguments");
|
||||
jg.writeRawValue(jsonArgsArray);
|
||||
sendMessage(requestID, endMessageObject(jg));
|
||||
} catch (IOException e) {
|
||||
triggerRequestFailure(requestID, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeQuietly() {
|
||||
if (mWebSocket != null) {
|
||||
try {
|
||||
mWebSocket.close(1000, "End of session");
|
||||
} catch (IOException e) {
|
||||
// swallow, no need to handle it here
|
||||
}
|
||||
mWebSocket = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(int requestID, String message) {
|
||||
if (mWebSocket == null) {
|
||||
triggerRequestFailure(
|
||||
requestID,
|
||||
new IllegalStateException("WebSocket connection no longer valid"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mWebSocket.sendMessage(RequestBody.create(WebSocket.TEXT, message));
|
||||
} catch (IOException e) {
|
||||
triggerRequestFailure(requestID, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerRequestFailure(int requestID, Throwable cause) {
|
||||
JSDebuggerCallback callback = mCallbacks.get(requestID);
|
||||
if (callback != null) {
|
||||
mCallbacks.remove(requestID);
|
||||
callback.onFailure(cause);
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerRequestSuccess(int requestID, @Nullable String response) {
|
||||
JSDebuggerCallback callback = mCallbacks.get(requestID);
|
||||
if (callback != null) {
|
||||
mCallbacks.remove(requestID);
|
||||
callback.onSuccess(response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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 = response.source().readUtf8();
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
Integer replyID = null;
|
||||
|
||||
try {
|
||||
JsonParser parser = new JsonFactory().createParser(message);
|
||||
String result = null;
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
String field = parser.getCurrentName();
|
||||
if ("replyID".equals(field)) {
|
||||
parser.nextToken();
|
||||
replyID = parser.getIntValue();
|
||||
} else if ("result".equals(field)) {
|
||||
parser.nextToken();
|
||||
result = parser.getText();
|
||||
}
|
||||
}
|
||||
if (replyID != null) {
|
||||
triggerRequestSuccess(replyID, result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (replyID != null) {
|
||||
triggerRequestFailure(replyID, e);
|
||||
} else {
|
||||
abort("Parsing response message from websocket failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IOException e, Response response) {
|
||||
abort("Websocket exception", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, Response response) {
|
||||
mWebSocket = webSocket;
|
||||
Assertions.assertNotNull(mConnectCallback).onSuccess(null);
|
||||
mConnectCallback = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason) {
|
||||
mWebSocket = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPong(Buffer payload) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
private void abort(String message, Throwable cause) {
|
||||
FLog.e(TAG, "Error occurred, shutting down websocket connection: " + message, cause);
|
||||
closeQuietly();
|
||||
|
||||
// Trigger failure callbacks
|
||||
if (mConnectCallback != null) {
|
||||
mConnectCallback.onFailure(cause);
|
||||
mConnectCallback = null;
|
||||
}
|
||||
for (JSDebuggerCallback callback : mCallbacks.values()) {
|
||||
callback.onFailure(cause);
|
||||
}
|
||||
mCallbacks.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* 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.devsupport;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.ws.WebSocket;
|
||||
import okhttp3.ws.WebSocketCall;
|
||||
import okhttp3.ws.WebSocketListener;
|
||||
import okio.Buffer;
|
||||
|
||||
/**
|
||||
* A wrapper around WebSocketClient that recognizes packager's message format.
|
||||
*/
|
||||
public class JSPackagerWebSocketClient implements WebSocketListener {
|
||||
private static final String TAG = "JSPackagerWebSocketClient";
|
||||
|
||||
private static final int RECONNECT_DELAY_MS = 2000;
|
||||
|
||||
private final String mUrl;
|
||||
private final Handler mHandler;
|
||||
private boolean mSuppressConnectionErrors;
|
||||
|
||||
public interface JSPackagerCallback {
|
||||
void onMessage(String target, String action);
|
||||
}
|
||||
|
||||
private @Nullable WebSocket mWebSocket;
|
||||
private @Nullable JSPackagerCallback mCallback;
|
||||
|
||||
public JSPackagerWebSocketClient(String url, JSPackagerCallback callback) {
|
||||
super();
|
||||
mUrl = url;
|
||||
mCallback = callback;
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
OkHttpClient httpClient = 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(mUrl).build();
|
||||
WebSocketCall call = WebSocketCall.create(httpClient, request);
|
||||
call.enqueue(this);
|
||||
}
|
||||
|
||||
private void reconnect() {
|
||||
if (!mSuppressConnectionErrors) {
|
||||
FLog.w(TAG, "Couldn't connect to packager, will silently retry");
|
||||
mSuppressConnectionErrors = true;
|
||||
}
|
||||
mHandler.postDelayed(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
connect();
|
||||
}
|
||||
}, RECONNECT_DELAY_MS);
|
||||
}
|
||||
|
||||
public void closeQuietly() {
|
||||
if (mWebSocket != null) {
|
||||
try {
|
||||
mWebSocket.close(1000, "End of session");
|
||||
} catch (IOException e) {
|
||||
// swallow, no need to handle it here
|
||||
}
|
||||
mWebSocket = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerMessageCallback(String target, String action) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onMessage(target, action);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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 = response.source().readUtf8();
|
||||
} finally {
|
||||
response.close();
|
||||
}
|
||||
|
||||
try {
|
||||
JsonParser parser = new JsonFactory().createParser(message);
|
||||
|
||||
Integer version = null;
|
||||
String target = null;
|
||||
String action = null;
|
||||
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
String field = parser.getCurrentName();
|
||||
if ("version".equals(field)) {
|
||||
parser.nextToken();
|
||||
version = parser.getIntValue();
|
||||
} else if ("target".equals(field)) {
|
||||
parser.nextToken();
|
||||
target = parser.getText();
|
||||
} else if ("action".equals(field)) {
|
||||
parser.nextToken();
|
||||
action = parser.getText();
|
||||
}
|
||||
}
|
||||
if (version != 1) {
|
||||
return;
|
||||
}
|
||||
if (target == null || action == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerMessageCallback(target, action);
|
||||
} catch (IOException e) {
|
||||
abort("Parsing response message from websocket failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(IOException e, Response response) {
|
||||
if (mWebSocket != null) {
|
||||
abort("Websocket exception", e);
|
||||
}
|
||||
reconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, Response response) {
|
||||
mWebSocket = webSocket;
|
||||
mSuppressConnectionErrors = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason) {
|
||||
mWebSocket = null;
|
||||
reconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPong(Buffer payload) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
private void abort(String message, Throwable cause) {
|
||||
FLog.e(TAG, "Error occurred, shutting down websocket connection: " + message, cause);
|
||||
closeQuietly();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* 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.devsupport;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.JavaJSExecutor;
|
||||
|
||||
/**
|
||||
* Executes JS remotely via the react nodejs server as a proxy to a browser on the host machine.
|
||||
*/
|
||||
public class WebsocketJavaScriptExecutor implements JavaJSExecutor {
|
||||
|
||||
private static final long CONNECT_TIMEOUT_MS = 5000;
|
||||
private static final int CONNECT_RETRY_COUNT = 3;
|
||||
|
||||
public interface JSExecutorConnectCallback {
|
||||
void onSuccess();
|
||||
void onFailure(Throwable cause);
|
||||
}
|
||||
|
||||
public static class WebsocketExecutorTimeoutException extends Exception {
|
||||
public WebsocketExecutorTimeoutException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private static class JSExecutorCallbackFuture implements
|
||||
JSDebuggerWebSocketClient.JSDebuggerCallback {
|
||||
|
||||
private final Semaphore mSemaphore = new Semaphore(0);
|
||||
private @Nullable Throwable mCause;
|
||||
private @Nullable String mResponse;
|
||||
|
||||
@Override
|
||||
public void onSuccess(@Nullable String response) {
|
||||
mResponse = response;
|
||||
mSemaphore.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable cause) {
|
||||
mCause = cause;
|
||||
mSemaphore.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call only once per object instance!
|
||||
*/
|
||||
public @Nullable String get() throws Throwable {
|
||||
mSemaphore.acquire();
|
||||
if (mCause != null) {
|
||||
throw mCause;
|
||||
}
|
||||
return mResponse;
|
||||
}
|
||||
}
|
||||
|
||||
final private HashMap<String, String> mInjectedObjects = new HashMap<>();
|
||||
private @Nullable JSDebuggerWebSocketClient mWebSocketClient;
|
||||
|
||||
public void connect(final String webSocketServerUrl, final JSExecutorConnectCallback callback) {
|
||||
final AtomicInteger retryCount = new AtomicInteger(CONNECT_RETRY_COUNT);
|
||||
final JSExecutorConnectCallback retryProxyCallback = new JSExecutorConnectCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
callback.onSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable cause) {
|
||||
if (retryCount.decrementAndGet() <= 0) {
|
||||
callback.onFailure(cause);
|
||||
} else {
|
||||
connectInternal(webSocketServerUrl, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
connectInternal(webSocketServerUrl, retryProxyCallback);
|
||||
}
|
||||
|
||||
private void connectInternal(
|
||||
String webSocketServerUrl,
|
||||
final JSExecutorConnectCallback callback) {
|
||||
final JSDebuggerWebSocketClient client = new JSDebuggerWebSocketClient();
|
||||
final Handler timeoutHandler = new Handler(Looper.getMainLooper());
|
||||
client.connect(
|
||||
webSocketServerUrl, new JSDebuggerWebSocketClient.JSDebuggerCallback() {
|
||||
// It's possible that both callbacks can fire on an error so make sure we only
|
||||
// dispatch results once to our callback.
|
||||
private boolean didSendResult = false;
|
||||
|
||||
@Override
|
||||
public void onSuccess(@Nullable String response) {
|
||||
client.prepareJSRuntime(
|
||||
new JSDebuggerWebSocketClient.JSDebuggerCallback() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable String response) {
|
||||
timeoutHandler.removeCallbacksAndMessages(null);
|
||||
mWebSocketClient = client;
|
||||
if (!didSendResult) {
|
||||
callback.onSuccess();
|
||||
didSendResult = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable cause) {
|
||||
timeoutHandler.removeCallbacksAndMessages(null);
|
||||
if (!didSendResult) {
|
||||
callback.onFailure(cause);
|
||||
didSendResult = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable cause) {
|
||||
timeoutHandler.removeCallbacksAndMessages(null);
|
||||
if (!didSendResult) {
|
||||
callback.onFailure(cause);
|
||||
didSendResult = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
timeoutHandler.postDelayed(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
client.closeQuietly();
|
||||
callback.onFailure(
|
||||
new WebsocketExecutorTimeoutException(
|
||||
"Timeout while connecting to remote debugger"));
|
||||
}
|
||||
},
|
||||
CONNECT_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (mWebSocketClient != null) {
|
||||
mWebSocketClient.closeQuietly();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadApplicationScript(String sourceURL)
|
||||
throws ProxyExecutorException {
|
||||
JSExecutorCallbackFuture callback = new JSExecutorCallbackFuture();
|
||||
Assertions.assertNotNull(mWebSocketClient).loadApplicationScript(
|
||||
sourceURL,
|
||||
mInjectedObjects,
|
||||
callback);
|
||||
try {
|
||||
callback.get();
|
||||
} catch (Throwable cause) {
|
||||
throw new ProxyExecutorException(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String executeJSCall(String methodName, String jsonArgsArray)
|
||||
throws ProxyExecutorException {
|
||||
JSExecutorCallbackFuture callback = new JSExecutorCallbackFuture();
|
||||
Assertions.assertNotNull(mWebSocketClient).executeJSCall(
|
||||
methodName,
|
||||
jsonArgsArray,
|
||||
callback);
|
||||
try {
|
||||
return callback.get();
|
||||
} catch (Throwable cause) {
|
||||
throw new ProxyExecutorException(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGlobalVariable(String propertyName, String jsonEncodedValue) {
|
||||
// Store and use in the next loadApplicationScript() call.
|
||||
mInjectedObjects.put(propertyName, jsonEncodedValue);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user