From c607a17ea462e5a1a7e2cb42375b0f3b6bf3ca53 Mon Sep 17 00:00:00 2001 From: Joe Hansche Date: Tue, 28 Mar 2017 16:01:28 -0700 Subject: [PATCH 1/4] Fix #38 by sending a proper close() status code See https://tools.ietf.org/html/rfc6455#section-7.4 --- .../src/main/java/com/parse/OkHttp3SocketClientFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ParseLiveQuery/src/main/java/com/parse/OkHttp3SocketClientFactory.java b/ParseLiveQuery/src/main/java/com/parse/OkHttp3SocketClientFactory.java index 6268b3d..71c7c28 100644 --- a/ParseLiveQuery/src/main/java/com/parse/OkHttp3SocketClientFactory.java +++ b/ParseLiveQuery/src/main/java/com/parse/OkHttp3SocketClientFactory.java @@ -29,7 +29,7 @@ public WebSocketClient createInstance(WebSocketClient.WebSocketClientCallback we return new OkHttp3WebSocketClient(mClient, webSocketClientCallback, hostUrl); } - class OkHttp3WebSocketClient implements WebSocketClient { + static class OkHttp3WebSocketClient implements WebSocketClient { private static final String LOG_TAG = "OkHttpWebSocketClient"; @@ -38,7 +38,7 @@ class OkHttp3WebSocketClient implements WebSocketClient { private State state = State.NONE; private final OkHttpClient client; private final String url; - private final int STATUS_CODE = 200; + private final int STATUS_CODE = 1000; private final String CLOSING_MSG = "User invoked close"; private final WebSocketListener handler = new WebSocketListener() { From b6a5fd2dce06e57c3e3adb2b247eb90d630bec60 Mon Sep 17 00:00:00 2001 From: Joe Hansche Date: Tue, 28 Mar 2017 16:02:43 -0700 Subject: [PATCH 2/4] Add userInitiated boolean to the on-disconnected callback That lets us distinguish between an expected and unexpected disconnect. --- .../parse/ParseLiveQueryClientCallbacks.java | 2 +- .../com/parse/ParseLiveQueryClientImpl.java | 4 ++-- .../com/parse/TestParseLiveQueryClient.java | 23 ++++++++++++++++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientCallbacks.java b/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientCallbacks.java index 881e09c..c8275fa 100644 --- a/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientCallbacks.java +++ b/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientCallbacks.java @@ -3,7 +3,7 @@ public interface ParseLiveQueryClientCallbacks { void onLiveQueryClientConnected(ParseLiveQueryClient client); - void onLiveQueryClientDisconnected(ParseLiveQueryClient client); + void onLiveQueryClientDisconnected(ParseLiveQueryClient client, boolean userInitiated); void onLiveQueryError(ParseLiveQueryClient client, LiveQueryException reason); diff --git a/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java b/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java index 9f7f0a2..2c05867 100644 --- a/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java +++ b/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java @@ -138,8 +138,8 @@ public Void then(Task task) throws Exception { @Override public void disconnect() { if (webSocketClient != null) { - disconnectAsync(); userInitiatedDisconnect = true; + disconnectAsync(); } } @@ -254,7 +254,7 @@ private void dispatchConnected() { private void dispatchDisconnected() { for (ParseLiveQueryClientCallbacks callback : mCallbacks) { - callback.onLiveQueryClientDisconnected(this); + callback.onLiveQueryClientDisconnected(this, userInitiatedDisconnect); } } diff --git a/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java b/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java index 74dfdd1..b443733 100644 --- a/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java +++ b/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java @@ -405,8 +405,25 @@ public void testCallbackNotifiedOnDisconnect() throws Exception { parseLiveQueryClient.registerListener(callbacks); callbacks.transcript.assertNoEventsSoFar(); + // Unexpected close from the server: webSocketClientCallback.onClose(); - callbacks.transcript.assertEventsSoFar("onLiveQueryClientDisconnected"); + callbacks.transcript.assertEventsSoFar("onLiveQueryClientDisconnected: false"); + } + + + @Test + public void testCallbackNotifiedOnDisconnect_expected() throws Exception { + LoggingCallbacks callbacks = new LoggingCallbacks(); + parseLiveQueryClient.registerListener(callbacks); + callbacks.transcript.assertNoEventsSoFar(); + + parseLiveQueryClient.disconnect(); + verify(webSocketClient, times(1)).close(); + + callbacks.transcript.assertNoEventsSoFar(); + // the client is a mock, so it won't actually invoke the callback automatically + webSocketClientCallback.onClose(); + callbacks.transcript.assertEventsSoFar("onLiveQueryClientDisconnected: true"); } @Test @@ -548,8 +565,8 @@ public void onLiveQueryClientConnected(ParseLiveQueryClient client) { } @Override - public void onLiveQueryClientDisconnected(ParseLiveQueryClient client) { - transcript.add("onLiveQueryClientDisconnected"); + public void onLiveQueryClientDisconnected(ParseLiveQueryClient client, boolean userInitiated) { + transcript.add("onLiveQueryClientDisconnected: " + userInitiated); } @Override From acd04c10e0bf1ea6bf81eb70a5407e21ad6461b5 Mon Sep 17 00:00:00 2001 From: Joe Hansche Date: Tue, 28 Mar 2017 16:42:11 -0700 Subject: [PATCH 3/4] Dispatch onDisconnected after a socket error A socket failure implies that the socket also died, so it makes sense to also dispatch a disconnected event. --- .../src/main/java/com/parse/ParseLiveQueryClientImpl.java | 4 ++++ .../src/test/java/com/parse/TestParseLiveQueryClient.java | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java b/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java index 2c05867..b007ad6 100644 --- a/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java +++ b/ParseLiveQuery/src/main/java/com/parse/ParseLiveQueryClientImpl.java @@ -266,9 +266,13 @@ private void dispatchServerError(LiveQueryException exc) { } private void dispatchSocketError(Throwable reason) { + userInitiatedDisconnect = false; + for (ParseLiveQueryClientCallbacks callback : mCallbacks) { callback.onSocketError(this, reason); } + + dispatchDisconnected(); } private void handleSubscribedEvent(JSONObject jsonObject) throws JSONException { diff --git a/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java b/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java index b443733..4796fdc 100644 --- a/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java +++ b/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java @@ -443,7 +443,8 @@ public void testCallbackNotifiedOnSocketError() throws Exception { callbacks.transcript.assertNoEventsSoFar(); webSocketClientCallback.onError(new IOException("bad things happened")); - callbacks.transcript.assertEventsSoFar("onSocketError: java.io.IOException: bad things happened"); + callbacks.transcript.assertEventsSoFar("onSocketError: java.io.IOException: bad things happened", + "onLiveQueryClientDisconnected: false"); } @Test From 8481649018a59c6183e4aaeac4bdbd74e5ee6ed6 Mon Sep 17 00:00:00 2001 From: Joe Hansche Date: Tue, 28 Mar 2017 16:45:38 -0700 Subject: [PATCH 4/4] Fix CR comments --- .../src/test/java/com/parse/TestParseLiveQueryClient.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java b/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java index 4796fdc..cf73f3f 100644 --- a/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java +++ b/ParseLiveQuery/src/test/java/com/parse/TestParseLiveQueryClient.java @@ -400,7 +400,7 @@ public void testDisconnectOnBackgroundThread() throws Exception { } @Test - public void testCallbackNotifiedOnDisconnect() throws Exception { + public void testCallbackNotifiedOnUnexpectedDisconnect() throws Exception { LoggingCallbacks callbacks = new LoggingCallbacks(); parseLiveQueryClient.registerListener(callbacks); callbacks.transcript.assertNoEventsSoFar(); @@ -410,9 +410,8 @@ public void testCallbackNotifiedOnDisconnect() throws Exception { callbacks.transcript.assertEventsSoFar("onLiveQueryClientDisconnected: false"); } - @Test - public void testCallbackNotifiedOnDisconnect_expected() throws Exception { + public void testCallbackNotifiedOnExpectedDisconnect() throws Exception { LoggingCallbacks callbacks = new LoggingCallbacks(); parseLiveQueryClient.registerListener(callbacks); callbacks.transcript.assertNoEventsSoFar();