Index: net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java |
diff --git a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java |
index 9023991843d3266afbc4fbb199936d95edecfdda..4d84dd1ef4b096d89bb048789acc3a3564d44974 100644 |
--- a/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java |
+++ b/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java |
@@ -9,6 +9,7 @@ import android.util.Base64; |
import android.util.Log; |
import android.util.Pair; |
+import org.apache.http.Header; |
mef
2016/10/14 16:52:26
According to https://bugs.chromium.org/p/chromium/
jbudorick
2016/10/18 17:27:30
Agreed. We're still working to replace existing us
|
import org.apache.http.HttpException; |
import org.apache.http.HttpRequest; |
import org.apache.http.HttpResponse; |
@@ -33,8 +34,10 @@ import java.net.Socket; |
import java.net.URI; |
import java.net.URL; |
import java.net.URLConnection; |
+import java.nio.charset.Charset; |
import java.security.KeyManagementException; |
import java.security.KeyStore; |
+import java.security.MessageDigest; |
import java.security.NoSuchAlgorithmException; |
import java.security.cert.X509Certificate; |
import java.util.ArrayList; |
@@ -80,13 +83,15 @@ public class TestWebServer { |
final Runnable mResponseAction; |
final boolean mIsNotFound; |
final boolean mIsNoContent; |
+ final boolean mForWebSocket; |
Response(byte[] responseData, List<Pair<String, String>> responseHeaders, |
- boolean isRedirect, boolean isNotFound, boolean isNoContent, |
+ boolean isRedirect, boolean isNotFound, boolean isNoContent, boolean forWebSocket, |
Runnable responseAction) { |
mIsRedirect = isRedirect; |
mIsNotFound = isNotFound; |
mIsNoContent = isNoContent; |
+ mForWebSocket = forWebSocket; |
mResponseData = responseData; |
mResponseHeaders = responseHeaders == null |
? new ArrayList<Pair<String, String>>() : responseHeaders; |
@@ -195,6 +200,7 @@ public class TestWebServer { |
private static final int RESPONSE_STATUS_MOVED_TEMPORARILY = 1; |
private static final int RESPONSE_STATUS_NOT_FOUND = 2; |
private static final int RESPONSE_STATUS_NO_CONTENT = 3; |
+ private static final int RESPONSE_STATUS_FOR_WEBSOCKET = 4; |
private String setResponseInternal( |
String requestPath, byte[] responseData, |
@@ -203,11 +209,12 @@ public class TestWebServer { |
final boolean isRedirect = (status == RESPONSE_STATUS_MOVED_TEMPORARILY); |
final boolean isNotFound = (status == RESPONSE_STATUS_NOT_FOUND); |
final boolean isNoContent = (status == RESPONSE_STATUS_NO_CONTENT); |
+ final boolean forWebSocket = (status == RESPONSE_STATUS_FOR_WEBSOCKET); |
synchronized (mLock) { |
- mResponseMap.put(requestPath, new Response( |
- responseData, responseHeaders, isRedirect, isNotFound, isNoContent, |
- responseAction)); |
+ mResponseMap.put( |
+ requestPath, new Response(responseData, responseHeaders, isRedirect, isNotFound, |
+ isNoContent, forWebSocket, responseAction)); |
mResponseCountMap.put(requestPath, Integer.valueOf(0)); |
mLastRequestMap.put(requestPath, null); |
} |
@@ -344,6 +351,26 @@ public class TestWebServer { |
} |
/** |
+ * Sets a response to a WebSocket handshake request. |
+ * |
+ * @param requestPath The path to respond to. |
+ * @param responseHeaders Any additional headers that should be returned along with the |
+ * response (null is acceptable). |
+ * @return The full URL including the path that should be requested to get the expected |
+ * response. |
+ */ |
+ public String setResponseForWebSocket( |
+ String requestPath, List<Pair<String, String>> responseHeaders) { |
+ if (responseHeaders == null) { |
+ responseHeaders = new ArrayList<Pair<String, String>>(); |
+ } |
+ responseHeaders.add(Pair.create("Connection", "Upgrade")); |
+ responseHeaders.add(Pair.create("Upgrade", "websocket")); |
+ return setResponseInternal( |
+ requestPath, "".getBytes(), responseHeaders, null, RESPONSE_STATUS_FOR_WEBSOCKET); |
+ } |
+ |
+ /** |
* Get the number of requests was made at this path since it was last set. |
*/ |
public int getRequestCount(String requestPath) { |
@@ -481,6 +508,23 @@ public class TestWebServer { |
httpResponse.addHeader(header.first, header.second); |
} |
servedResponseFor(path, request); |
+ } else if (response.mForWebSocket) { |
+ Header[] keys = request.getHeaders("Sec-WebSocket-Key"); |
+ try { |
+ if (keys.length == 1) { |
+ final String key = keys[0].getValue(); |
+ httpResponse = createResponse(HttpStatus.SC_SWITCHING_PROTOCOLS); |
+ for (Pair<String, String> header : response.mResponseHeaders) { |
+ httpResponse.addHeader(header.first, header.second); |
+ } |
+ httpResponse.addHeader("Sec-WebSocket-Accept", computeWebSocketAccept(key)); |
+ servedResponseFor(path, request); |
+ } else { |
+ httpResponse = createResponse(HttpStatus.SC_NOT_FOUND); |
+ } |
+ } catch (NoSuchAlgorithmException e) { |
+ httpResponse = createResponse(HttpStatus.SC_NOT_FOUND); |
+ } |
} else { |
if (response.mResponseAction != null) response.mResponseAction.run(); |
@@ -552,6 +596,20 @@ public class TestWebServer { |
return entity; |
} |
+ /** |
+ * Return a response for WebSocket handshake challenge. |
+ */ |
+ private static String computeWebSocketAccept(String keyString) throws NoSuchAlgorithmException { |
+ byte[] key = keyString.getBytes(Charset.forName("US-ASCII")); |
+ byte[] guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes(Charset.forName("US-ASCII")); |
+ |
+ MessageDigest md = MessageDigest.getInstance("SHA"); |
+ md.update(key); |
+ md.update(guid); |
+ byte[] output = md.digest(); |
+ return Base64.encodeToString(output, Base64.DEFAULT); |
+ } |
+ |
private static class ServerThread extends Thread { |
private TestWebServer mServer; |
private ServerSocket mSocket; |