Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java

Issue 2397393002: Provide child/frame IDs for WebSocket handshake request (Closed)
Patch Set: fix Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.net.test.util; 5 package org.chromium.net.test.util;
6 6
7 import android.annotation.SuppressLint; 7 import android.annotation.SuppressLint;
8 import android.util.Base64; 8 import android.util.Base64;
9 import android.util.Log; 9 import android.util.Log;
10 import android.util.Pair; 10 import android.util.Pair;
11 11
12 import org.apache.http.Header;
12 import org.apache.http.HttpException; 13 import org.apache.http.HttpException;
13 import org.apache.http.HttpRequest; 14 import org.apache.http.HttpRequest;
14 import org.apache.http.HttpResponse; 15 import org.apache.http.HttpResponse;
15 import org.apache.http.HttpStatus; 16 import org.apache.http.HttpStatus;
16 import org.apache.http.HttpVersion; 17 import org.apache.http.HttpVersion;
17 import org.apache.http.RequestLine; 18 import org.apache.http.RequestLine;
18 import org.apache.http.StatusLine; 19 import org.apache.http.StatusLine;
19 import org.apache.http.entity.ByteArrayEntity; 20 import org.apache.http.entity.ByteArrayEntity;
20 import org.apache.http.impl.DefaultHttpServerConnection; 21 import org.apache.http.impl.DefaultHttpServerConnection;
21 import org.apache.http.impl.cookie.DateUtils; 22 import org.apache.http.impl.cookie.DateUtils;
22 import org.apache.http.message.BasicHttpResponse; 23 import org.apache.http.message.BasicHttpResponse;
23 import org.apache.http.params.BasicHttpParams; 24 import org.apache.http.params.BasicHttpParams;
24 import org.apache.http.params.CoreProtocolPNames; 25 import org.apache.http.params.CoreProtocolPNames;
25 import org.apache.http.params.HttpParams; 26 import org.apache.http.params.HttpParams;
26 27
27 import java.io.ByteArrayInputStream; 28 import java.io.ByteArrayInputStream;
28 import java.io.IOException; 29 import java.io.IOException;
29 import java.io.InputStream; 30 import java.io.InputStream;
30 import java.net.MalformedURLException; 31 import java.net.MalformedURLException;
31 import java.net.ServerSocket; 32 import java.net.ServerSocket;
32 import java.net.Socket; 33 import java.net.Socket;
33 import java.net.URI; 34 import java.net.URI;
34 import java.net.URL; 35 import java.net.URL;
35 import java.net.URLConnection; 36 import java.net.URLConnection;
37 import java.nio.charset.Charset;
36 import java.security.KeyManagementException; 38 import java.security.KeyManagementException;
37 import java.security.KeyStore; 39 import java.security.KeyStore;
40 import java.security.MessageDigest;
38 import java.security.NoSuchAlgorithmException; 41 import java.security.NoSuchAlgorithmException;
39 import java.security.cert.X509Certificate; 42 import java.security.cert.X509Certificate;
40 import java.util.ArrayList; 43 import java.util.ArrayList;
41 import java.util.Date; 44 import java.util.Date;
42 import java.util.HashMap; 45 import java.util.HashMap;
43 import java.util.Hashtable; 46 import java.util.Hashtable;
44 import java.util.List; 47 import java.util.List;
45 import java.util.Map; 48 import java.util.Map;
46 49
47 import javax.net.ssl.HostnameVerifier; 50 import javax.net.ssl.HostnameVerifier;
(...skipping 25 matching lines...) Expand all
73 private final boolean mSsl; 76 private final boolean mSsl;
74 private final int mPort; 77 private final int mPort;
75 78
76 private static class Response { 79 private static class Response {
77 final byte[] mResponseData; 80 final byte[] mResponseData;
78 final List<Pair<String, String>> mResponseHeaders; 81 final List<Pair<String, String>> mResponseHeaders;
79 final boolean mIsRedirect; 82 final boolean mIsRedirect;
80 final Runnable mResponseAction; 83 final Runnable mResponseAction;
81 final boolean mIsNotFound; 84 final boolean mIsNotFound;
82 final boolean mIsNoContent; 85 final boolean mIsNoContent;
86 final boolean mForWebSocket;
83 87
84 Response(byte[] responseData, List<Pair<String, String>> responseHeaders , 88 Response(byte[] responseData, List<Pair<String, String>> responseHeaders ,
85 boolean isRedirect, boolean isNotFound, boolean isNoContent, 89 boolean isRedirect, boolean isNotFound, boolean isNoContent, boo lean forWebSocket,
86 Runnable responseAction) { 90 Runnable responseAction) {
87 mIsRedirect = isRedirect; 91 mIsRedirect = isRedirect;
88 mIsNotFound = isNotFound; 92 mIsNotFound = isNotFound;
89 mIsNoContent = isNoContent; 93 mIsNoContent = isNoContent;
94 mForWebSocket = forWebSocket;
90 mResponseData = responseData; 95 mResponseData = responseData;
91 mResponseHeaders = responseHeaders == null 96 mResponseHeaders = responseHeaders == null
92 ? new ArrayList<Pair<String, String>>() : responseHeaders; 97 ? new ArrayList<Pair<String, String>>() : responseHeaders;
93 mResponseAction = responseAction; 98 mResponseAction = responseAction;
94 } 99 }
95 } 100 }
96 101
97 // The Maps below are modified on both the client thread and the internal se rver thread, so 102 // The Maps below are modified on both the client thread and the internal se rver thread, so
98 // need to use a lock when accessing them. 103 // need to use a lock when accessing them.
99 private final Object mLock = new Object(); 104 private final Object mLock = new Object();
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 193 }
189 194
190 private static void setSecureInstance(TestWebServer instance) { 195 private static void setSecureInstance(TestWebServer instance) {
191 sSecureInstance = instance; 196 sSecureInstance = instance;
192 } 197 }
193 198
194 private static final int RESPONSE_STATUS_NORMAL = 0; 199 private static final int RESPONSE_STATUS_NORMAL = 0;
195 private static final int RESPONSE_STATUS_MOVED_TEMPORARILY = 1; 200 private static final int RESPONSE_STATUS_MOVED_TEMPORARILY = 1;
196 private static final int RESPONSE_STATUS_NOT_FOUND = 2; 201 private static final int RESPONSE_STATUS_NOT_FOUND = 2;
197 private static final int RESPONSE_STATUS_NO_CONTENT = 3; 202 private static final int RESPONSE_STATUS_NO_CONTENT = 3;
203 private static final int RESPONSE_STATUS_FOR_WEBSOCKET = 4;
198 204
199 private String setResponseInternal( 205 private String setResponseInternal(
200 String requestPath, byte[] responseData, 206 String requestPath, byte[] responseData,
201 List<Pair<String, String>> responseHeaders, Runnable responseAction, 207 List<Pair<String, String>> responseHeaders, Runnable responseAction,
202 int status) { 208 int status) {
203 final boolean isRedirect = (status == RESPONSE_STATUS_MOVED_TEMPORARILY) ; 209 final boolean isRedirect = (status == RESPONSE_STATUS_MOVED_TEMPORARILY) ;
204 final boolean isNotFound = (status == RESPONSE_STATUS_NOT_FOUND); 210 final boolean isNotFound = (status == RESPONSE_STATUS_NOT_FOUND);
205 final boolean isNoContent = (status == RESPONSE_STATUS_NO_CONTENT); 211 final boolean isNoContent = (status == RESPONSE_STATUS_NO_CONTENT);
212 final boolean forWebSocket = (status == RESPONSE_STATUS_FOR_WEBSOCKET);
206 213
207 synchronized (mLock) { 214 synchronized (mLock) {
208 mResponseMap.put(requestPath, new Response( 215 mResponseMap.put(
209 responseData, responseHeaders, isRedirect, isNotFound, isNoC ontent, 216 requestPath, new Response(responseData, responseHeaders, isR edirect, isNotFound,
210 responseAction)); 217 isNoContent, forWebSocket, responseActi on));
211 mResponseCountMap.put(requestPath, Integer.valueOf(0)); 218 mResponseCountMap.put(requestPath, Integer.valueOf(0));
212 mLastRequestMap.put(requestPath, null); 219 mLastRequestMap.put(requestPath, null);
213 } 220 }
214 return getResponseUrl(requestPath); 221 return getResponseUrl(requestPath);
215 } 222 }
216 223
217 /** 224 /**
218 * Gets the URL on the server under which a particular request path will be accessible. 225 * Gets the URL on the server under which a particular request path will be accessible.
219 * 226 *
220 * This only gets the URL, you still need to set the response if you intend to access it. 227 * This only gets the URL, you still need to set the response if you intend to access it.
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 */ 344 */
338 public String setResponseBase64( 345 public String setResponseBase64(
339 String requestPath, String base64EncodedResponse, 346 String requestPath, String base64EncodedResponse,
340 List<Pair<String, String>> responseHeaders) { 347 List<Pair<String, String>> responseHeaders) {
341 return setResponseInternal( 348 return setResponseInternal(
342 requestPath, Base64.decode(base64EncodedResponse, Base64.DEFAULT ), 349 requestPath, Base64.decode(base64EncodedResponse, Base64.DEFAULT ),
343 responseHeaders, null, RESPONSE_STATUS_NORMAL); 350 responseHeaders, null, RESPONSE_STATUS_NORMAL);
344 } 351 }
345 352
346 /** 353 /**
354 * Sets a response to a WebSocket handshake request.
355 *
356 * @param requestPath The path to respond to.
357 * @param responseHeaders Any additional headers that should be returned alo ng with the
358 * response (null is acceptable).
359 * @return The full URL including the path that should be requested to get t he expected
360 * response.
361 */
362 public String setResponseForWebSocket(
363 String requestPath, List<Pair<String, String>> responseHeaders) {
364 if (responseHeaders == null) {
365 responseHeaders = new ArrayList<Pair<String, String>>();
366 }
367 responseHeaders.add(Pair.create("Connection", "Upgrade"));
mef 2016/10/19 17:41:24 If responseHeaders passed in are not null, then th
yhirano 2016/10/20 04:21:07 Done.
368 responseHeaders.add(Pair.create("Upgrade", "websocket"));
369 return setResponseInternal(
370 requestPath, "".getBytes(), responseHeaders, null, RESPONSE_STAT US_FOR_WEBSOCKET);
371 }
372
373 /**
347 * Get the number of requests was made at this path since it was last set. 374 * Get the number of requests was made at this path since it was last set.
348 */ 375 */
349 public int getRequestCount(String requestPath) { 376 public int getRequestCount(String requestPath) {
350 Integer count = null; 377 Integer count = null;
351 synchronized (mLock) { 378 synchronized (mLock) {
352 count = mResponseCountMap.get(requestPath); 379 count = mResponseCountMap.get(requestPath);
353 } 380 }
354 if (count == null) throw new IllegalArgumentException("Path not set: " + requestPath); 381 if (count == null) throw new IllegalArgumentException("Path not set: " + requestPath);
355 return count.intValue(); 382 return count.intValue();
356 } 383 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 } else if (response.mIsNoContent) { 501 } else if (response.mIsNoContent) {
475 httpResponse = createResponse(HttpStatus.SC_NO_CONTENT); 502 httpResponse = createResponse(HttpStatus.SC_NO_CONTENT);
476 httpResponse.setHeader("Content-Length", "0"); 503 httpResponse.setHeader("Content-Length", "0");
477 servedResponseFor(path, request); 504 servedResponseFor(path, request);
478 } else if (response.mIsRedirect) { 505 } else if (response.mIsRedirect) {
479 httpResponse = createResponse(HttpStatus.SC_MOVED_TEMPORARILY); 506 httpResponse = createResponse(HttpStatus.SC_MOVED_TEMPORARILY);
480 for (Pair<String, String> header : response.mResponseHeaders) { 507 for (Pair<String, String> header : response.mResponseHeaders) {
481 httpResponse.addHeader(header.first, header.second); 508 httpResponse.addHeader(header.first, header.second);
482 } 509 }
483 servedResponseFor(path, request); 510 servedResponseFor(path, request);
511 } else if (response.mForWebSocket) {
512 Header[] keys = request.getHeaders("Sec-WebSocket-Key");
513 try {
514 if (keys.length == 1) {
515 final String key = keys[0].getValue();
516 httpResponse = createResponse(HttpStatus.SC_SWITCHING_PROTOC OLS);
517 for (Pair<String, String> header : response.mResponseHeaders ) {
518 httpResponse.addHeader(header.first, header.second);
519 }
520 httpResponse.addHeader("Sec-WebSocket-Accept", computeWebSoc ketAccept(key));
521 servedResponseFor(path, request);
mef 2016/10/19 17:41:24 Should servedResponseFor(path, request); be also
yhirano 2016/10/20 04:21:07 Done.
522 } else {
523 httpResponse = createResponse(HttpStatus.SC_NOT_FOUND);
524 }
525 } catch (NoSuchAlgorithmException e) {
526 httpResponse = createResponse(HttpStatus.SC_NOT_FOUND);
527 }
484 } else { 528 } else {
485 if (response.mResponseAction != null) response.mResponseAction.run() ; 529 if (response.mResponseAction != null) response.mResponseAction.run() ;
486 530
487 httpResponse = createResponse(HttpStatus.SC_OK); 531 httpResponse = createResponse(HttpStatus.SC_OK);
488 ByteArrayEntity entity = createEntity(response.mResponseData); 532 ByteArrayEntity entity = createEntity(response.mResponseData);
489 httpResponse.setEntity(entity); 533 httpResponse.setEntity(entity);
490 httpResponse.setHeader("Content-Length", "" + entity.getContentLengt h()); 534 httpResponse.setHeader("Content-Length", "" + entity.getContentLengt h());
491 for (Pair<String, String> header : response.mResponseHeaders) { 535 for (Pair<String, String> header : response.mResponseHeaders) {
492 httpResponse.addHeader(header.first, header.second); 536 httpResponse.addHeader(header.first, header.second);
493 } 537 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 589
546 /** 590 /**
547 * Create a string entity for the given content. 591 * Create a string entity for the given content.
548 */ 592 */
549 private ByteArrayEntity createEntity(byte[] data) { 593 private ByteArrayEntity createEntity(byte[] data) {
550 ByteArrayEntity entity = new ByteArrayEntity(data); 594 ByteArrayEntity entity = new ByteArrayEntity(data);
551 entity.setContentType("text/html"); 595 entity.setContentType("text/html");
552 return entity; 596 return entity;
553 } 597 }
554 598
599 /**
600 * Return a response for WebSocket handshake challenge.
601 */
602 private static String computeWebSocketAccept(String keyString) throws NoSuch AlgorithmException {
603 byte[] key = keyString.getBytes(Charset.forName("US-ASCII"));
604 byte[] guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes(Charset.fo rName("US-ASCII"));
605
606 MessageDigest md = MessageDigest.getInstance("SHA");
607 md.update(key);
608 md.update(guid);
609 byte[] output = md.digest();
610 return Base64.encodeToString(output, Base64.DEFAULT);
611 }
612
555 private static class ServerThread extends Thread { 613 private static class ServerThread extends Thread {
556 private TestWebServer mServer; 614 private TestWebServer mServer;
557 private ServerSocket mSocket; 615 private ServerSocket mSocket;
558 private boolean mIsSsl; 616 private boolean mIsSsl;
559 private SSLContext mSslContext; 617 private SSLContext mSslContext;
560 618
561 private final Object mLock = new Object(); 619 private final Object mLock = new Object();
562 private boolean mIsCancelled; 620 private boolean mIsCancelled;
563 private Socket mCurrentRequestSocket; 621 private Socket mCurrentRequestSocket;
564 622
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 socket.close(); 767 socket.close();
710 } catch (IOException ignored) { 768 } catch (IOException ignored) {
711 // safe to ignore 769 // safe to ignore
712 } 770 }
713 } 771 }
714 } 772 }
715 } 773 }
716 } 774 }
717 } 775 }
718 } 776 }
OLDNEW
« no previous file with comments | « content/public/browser/websocket_handshake_request_info.h ('k') | net/websockets/websocket_channel.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698