summaryrefslogtreecommitdiff
path: root/chromium/net/test
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:19:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:01:50 +0000
commit51f6c2793adab2d864b3d2b360000ef8db1d3e92 (patch)
tree835b3b4446b012c75e80177cef9fbe6972cc7dbe /chromium/net/test
parent6036726eb981b6c4b42047513b9d3f4ac865daac (diff)
downloadqtwebengine-chromium-51f6c2793adab2d864b3d2b360000ef8db1d3e92.tar.gz
BASELINE: Update Chromium to 71.0.3578.93
Change-Id: I6a32086c33670e1b033f8b10e6bf1fd4da1d105d Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/net/test')
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java186
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticatorService.java22
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java553
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java333
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java47
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerService.java19
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl3
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/util/CertTestUtil.java77
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/util/NetworkChangeNotifierTestUtil.java26
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java437
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/util/WebServer.java506
-rw-r--r--chromium/net/test/android/net_test_jni_onload.cc20
-rw-r--r--chromium/net/test/android/net_test_jni_onload.h18
-rw-r--r--chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc5
-rw-r--r--chromium/net/test/embedded_test_server/android/embedded_test_server_android.h4
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.cc9
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.h4
-rw-r--r--chromium/net/test/embedded_test_server/request_handler_util.cc2
-rw-r--r--chromium/net/test/run_all_unittests.cc5
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.cc42
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.h3
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server.cc15
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server_posix.cc6
-rw-r--r--chromium/net/test/spawned_test_server/remote_test_server_config.cc2
-rw-r--r--chromium/net/test/url_request/url_request_slow_download_job.cc6
25 files changed, 2293 insertions, 57 deletions
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java
new file mode 100644
index 00000000000..f5c82ad6670
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticator.java
@@ -0,0 +1,186 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorException;
+import android.accounts.NetworkErrorException;
+import android.accounts.OperationCanceledException;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeClassQualifiedName;
+import org.chromium.net.HttpNegotiateConstants;
+
+import java.io.IOException;
+
+/**
+ * Dummy Android authenticator, to test SPNEGO/Keberos support on Android. This is deliberately
+ * minimal, and is not intended as an example of how to write a real SPNEGO Authenticator.
+ */
+@JNINamespace("net::android")
+public class DummySpnegoAuthenticator extends AbstractAccountAuthenticator {
+ private static final String ACCOUNT_TYPE = "org.chromium.test.DummySpnegoAuthenticator";
+ private static final String ACCOUNT_NAME = "DummySpnegoAccount";
+ private static int sResult;
+ private static String sToken;
+ private static boolean sCheckArguments;
+ private static long sNativeDummySpnegoAuthenticator;
+ private static final int GSS_S_COMPLETE = 0;
+ private static final int GSS_S_CONTINUE_NEEDED = 1;
+ private static final int GSS_S_FAILURE = 2;
+
+ /**
+ * @param context
+ */
+ public DummySpnegoAuthenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse arg0, String accountType, String arg2,
+ String[] arg3, Bundle arg4) throws NetworkErrorException {
+ Bundle result = new Bundle();
+ result.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_BAD_REQUEST);
+ result.putString(AccountManager.KEY_ERROR_MESSAGE, "Can't add new SPNEGO accounts");
+ return result;
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse arg0, Account arg1, Bundle arg2)
+ throws NetworkErrorException {
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ return result;
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse arg0, String arg1) {
+ return new Bundle();
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) throws NetworkErrorException {
+ long nativeQuery = nativeGetNextQuery(sNativeDummySpnegoAuthenticator);
+ String incomingToken = options.getString(HttpNegotiateConstants.KEY_INCOMING_AUTH_TOKEN);
+ nativeCheckGetTokenArguments(nativeQuery, incomingToken);
+ Bundle result = new Bundle();
+ result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
+ result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
+ result.putString(AccountManager.KEY_AUTHTOKEN, nativeGetTokenToReturn(nativeQuery));
+ result.putInt(HttpNegotiateConstants.KEY_SPNEGO_RESULT,
+ decodeResult(nativeGetResult(nativeQuery)));
+ return result;
+ }
+
+ /**
+ * @param nativeGetResult
+ * @return
+ */
+ private int decodeResult(int gssApiResult) {
+ // This only handles the result values currently used in the tests.
+ switch (gssApiResult) {
+ case GSS_S_COMPLETE:
+ case GSS_S_CONTINUE_NEEDED:
+ return 0;
+ case GSS_S_FAILURE:
+ return HttpNegotiateConstants.ERR_MISSING_AUTH_CREDENTIALS;
+ default:
+ return HttpNegotiateConstants.ERR_UNEXPECTED;
+ }
+ }
+
+ @Override
+ public String getAuthTokenLabel(String arg0) {
+ return "Spnego " + arg0;
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse arg0, Account arg1, String[] features)
+ throws NetworkErrorException {
+ Bundle result = new Bundle();
+ for (String feature : features) {
+ if (!feature.equals(HttpNegotiateConstants.SPNEGO_FEATURE)) {
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
+ return result;
+ }
+ }
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ return result;
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse arg0, Account arg1, String arg2,
+ Bundle arg3) throws NetworkErrorException {
+ Bundle result = new Bundle();
+ result.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_BAD_REQUEST);
+ result.putString(AccountManager.KEY_ERROR_MESSAGE, "Can't add new SPNEGO accounts");
+ return result;
+ }
+
+ /**
+ * Called from tests, sets up the test account, if it doesn't already exist
+ */
+ @CalledByNative
+ private static void ensureTestAccountExists() {
+ Activity activity = ApplicationStatus.getLastTrackedFocusedActivity();
+ AccountManager am = AccountManager.get(activity);
+ Account account = new Account(ACCOUNT_NAME, ACCOUNT_TYPE);
+ am.addAccountExplicitly(account, null, null);
+ }
+
+ /**
+ * Called from tests to tidy up test accounts.
+ */
+ @SuppressWarnings("deprecation")
+ @CalledByNative
+ private static void removeTestAccounts() {
+ Activity activity = ApplicationStatus.getLastTrackedFocusedActivity();
+ AccountManager am = AccountManager.get(activity);
+ String features[] = {HttpNegotiateConstants.SPNEGO_FEATURE};
+ try {
+ Account accounts[] =
+ am.getAccountsByTypeAndFeatures(ACCOUNT_TYPE, features, null, null).getResult();
+ for (Account account : accounts) {
+ // Deprecated, but the replacement not available on Android JB.
+ am.removeAccount(account, null, null).getResult();
+ }
+ } catch (OperationCanceledException | AuthenticatorException | IOException e) {
+ // Should never happen. This is tidy-up after the tests. Ignore.
+ }
+ }
+
+ @CalledByNative
+ private static void setNativeAuthenticator(long nativeDummySpnegoAuthenticator) {
+ sNativeDummySpnegoAuthenticator = nativeDummySpnegoAuthenticator;
+ }
+
+ /**
+ * Send the relevant decoded arguments of getAuthToken to C++ for checking by googletest checks
+ * If the checks fail then the C++ unit test using this authenticator will fail.
+ *
+ * @param authTokenType
+ * @param spn
+ * @param incomingToken
+ */
+ @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
+ private native void nativeCheckGetTokenArguments(long nativeQuery, String incomingToken);
+
+ @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
+ private native String nativeGetTokenToReturn(long nativeQuery);
+
+ @NativeClassQualifiedName("DummySpnegoAuthenticator::SecurityContextQuery")
+ private native int nativeGetResult(long nativeQuery);
+
+ private native long nativeGetNextQuery(long nativeDummySpnegoAuthenticator);
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticatorService.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticatorService.java
new file mode 100644
index 00000000000..42e4ab39d29
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/DummySpnegoAuthenticatorService.java
@@ -0,0 +1,22 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * Authenticator service for testing SPNEGO (Kerberos) support.
+ */
+public class DummySpnegoAuthenticatorService extends Service {
+ private static DummySpnegoAuthenticator sAuthenticator;
+
+ @Override
+ public IBinder onBind(Intent arg0) {
+ if (sAuthenticator == null) sAuthenticator = new DummySpnegoAuthenticator(this);
+ return sAuthenticator.getIBinder();
+ }
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java
new file mode 100644
index 00000000000..d43f832a4b6
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java
@@ -0,0 +1,553 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+
+import org.junit.Assert;
+
+import org.chromium.base.Log;
+import org.chromium.base.ThreadUtils;
+import org.chromium.net.X509Util;
+import org.chromium.net.test.util.CertTestUtil;
+
+import java.io.File;
+
+/** A simple file server for java tests.
+ *
+ * An example use:
+ * EmbeddedTestServer s = EmbeddedTestServer.createAndStartServer(context);
+ *
+ * // serve requests...
+ * s.getURL("/foo/bar.txt");
+ *
+ * s.stopAndDestroyServer();
+ *
+ * Note that this runs net::test_server::EmbeddedTestServer in a service in a separate APK.
+ */
+public class EmbeddedTestServer {
+ private static final String TAG = "cr_TestServer";
+
+ private static final String EMBEDDED_TEST_SERVER_SERVICE =
+ "org.chromium.net.test.EMBEDDED_TEST_SERVER_SERVICE";
+ private static final long SERVICE_CONNECTION_WAIT_INTERVAL_MS = 5000;
+
+ private IEmbeddedTestServerImpl mImpl;
+ private ServiceConnection mConn = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (mImplMonitor) {
+ mImpl = IEmbeddedTestServerImpl.Stub.asInterface(service);
+ mImplMonitor.notify();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ synchronized (mImplMonitor) {
+ mImpl = null;
+ mImplMonitor.notify();
+ }
+ }
+ };
+
+ private Context mContext;
+ private final Object mImplMonitor = new Object();
+
+ // Whether the server should use HTTP or HTTPS.
+ public enum ServerHTTPSSetting {
+ USE_HTTP,
+ USE_HTTPS,
+ }
+
+ /**
+ * Exception class raised on failure in the EmbeddedTestServer.
+ */
+ public static final class EmbeddedTestServerFailure extends Error {
+ public EmbeddedTestServerFailure(String errorDesc) {
+ super(errorDesc);
+ }
+
+ public EmbeddedTestServerFailure(String errorDesc, Throwable cause) {
+ super(errorDesc, cause);
+ }
+ }
+
+ /**
+ * Connection listener class, to be notified of new connections and sockets reads.
+ *
+ * Notifications are asynchronous and delivered to the UI thread.
+ */
+ public static class ConnectionListener {
+ private final IConnectionListener mListener = new IConnectionListener.Stub() {
+ @Override
+ public void acceptedSocket(final long socketId) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ConnectionListener.this.acceptedSocket(socketId);
+ }
+ });
+ }
+
+ @Override
+ public void readFromSocket(final long socketId) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ConnectionListener.this.readFromSocket(socketId);
+ }
+ });
+ }
+ };
+
+ /**
+ * A new socket connection has been opened on the server.
+ *
+ * @param socketId Socket unique identifier. Unique as long as the socket stays open.
+ */
+ public void acceptedSocket(long socketId) {}
+
+ /**
+ * Data has been read from a socket.
+ *
+ * @param socketId Socket unique identifier. Unique as long as the socket stays open.
+ */
+ public void readFromSocket(long socketId) {}
+
+ private IConnectionListener getListener() {
+ return mListener;
+ }
+ }
+
+ /** Bind the service that will run the native server object.
+ *
+ * @param context The context to use to bind the service. This will also be used to unbind
+ * the service at server destruction time.
+ * @param httpsSetting Whether the server should use HTTPS.
+ */
+ public void initializeNative(Context context, ServerHTTPSSetting httpsSetting)
+ throws InterruptedException {
+ mContext = context;
+
+ Intent intent = new Intent(EMBEDDED_TEST_SERVER_SERVICE);
+ setIntentClassName(intent);
+ if (!mContext.bindService(intent, mConn, Context.BIND_AUTO_CREATE)) {
+ throw new EmbeddedTestServerFailure(
+ "Unable to bind to the EmbeddedTestServer service.");
+ }
+ synchronized (mImplMonitor) {
+ Log.i(TAG, "Waiting for EmbeddedTestServer service connection.");
+ while (mImpl == null) {
+ mImplMonitor.wait(SERVICE_CONNECTION_WAIT_INTERVAL_MS);
+ Log.i(TAG, "Still waiting for EmbeddedTestServer service connection.");
+ }
+ Log.i(TAG, "EmbeddedTestServer service connected.");
+ boolean initialized = false;
+ try {
+ initialized = mImpl.initializeNative(httpsSetting == ServerHTTPSSetting.USE_HTTPS);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to initialize native server.", e);
+ initialized = false;
+ }
+
+ if (!initialized) {
+ throw new EmbeddedTestServerFailure("Failed to initialize native server.");
+ }
+
+ if (httpsSetting == ServerHTTPSSetting.USE_HTTPS) {
+ try {
+ String rootCertPemPath = mImpl.getRootCertPemPath();
+ X509Util.addTestRootCertificate(CertTestUtil.pemToDer(rootCertPemPath));
+ } catch (Exception e) {
+ throw new EmbeddedTestServerFailure(
+ "Failed to install root certificate from native server.", e);
+ }
+ }
+ }
+ }
+
+ /** Set intent package and class name that will pass to the service.
+ *
+ * @param intent The intent to use to pass into the service.
+ */
+ protected void setIntentClassName(Intent intent) {
+ intent.setClassName(
+ "org.chromium.net.test.support", "org.chromium.net.test.EmbeddedTestServerService");
+ }
+
+ /** Add the default handlers and serve files from the provided directory relative to the
+ * external storage directory.
+ *
+ * @param directory The directory from which files should be served relative to the external
+ * storage directory.
+ */
+ public void addDefaultHandlers(File directory) {
+ addDefaultHandlers(directory.getPath());
+ }
+
+ /** Add the default handlers and serve files from the provided directory relative to the
+ * external storage directory.
+ *
+ * @param directoryPath The path of the directory from which files should be served relative
+ * to the external storage directory.
+ */
+ public void addDefaultHandlers(String directoryPath) {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ mImpl.addDefaultHandlers(directoryPath);
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure(
+ "Failed to add default handlers and start serving files from " + directoryPath
+ + ": " + e.toString());
+ }
+ }
+
+ /** Configure the server to use a particular type of SSL certificate.
+ *
+ * @param serverCertificate The type of certificate the server should use.
+ */
+ public void setSSLConfig(int serverCertificate) {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ mImpl.setSSLConfig(serverCertificate);
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure(
+ "Failed to set server certificate: " + e.toString());
+ }
+ }
+
+ /** Serve files from the provided directory.
+ *
+ * @param directory The directory from which files should be served.
+ */
+ public void serveFilesFromDirectory(File directory) {
+ serveFilesFromDirectory(directory.getPath());
+ }
+
+ /** Serve files from the provided directory.
+ *
+ * @param directoryPath The path of the directory from which files should be served.
+ */
+ public void serveFilesFromDirectory(String directoryPath) {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ mImpl.serveFilesFromDirectory(directoryPath);
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure(
+ "Failed to start serving files from " + directoryPath + ": " + e.toString());
+ }
+ }
+
+ /**
+ * Sets a connection listener. Must be called after the server has been initialized, but
+ * before calling {@link start()}.
+ *
+ * @param listener The listener to set.
+ */
+ public void setConnectionListener(ConnectionListener listener) {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ mImpl.setConnectionListener(listener.getListener());
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure("Cannot set the listener");
+ }
+ }
+
+ private void checkServiceLocked() {
+ if (mImpl == null) {
+ throw new EmbeddedTestServerFailure("Service disconnected.");
+ }
+ }
+
+ /** Starts the server with an automatically selected port.
+ *
+ * Note that this should be called after handlers are set up, including any relevant calls
+ * serveFilesFromDirectory.
+ *
+ * @return Whether the server was successfully initialized.
+ */
+ public boolean start() {
+ return start(0);
+ }
+
+ /** Starts the server with the specified port.
+ *
+ * Note that this should be called after handlers are set up, including any relevant calls
+ * serveFilesFromDirectory.
+ *
+ * @param port The port to use for the server, 0 to auto-select an unused port.
+ *
+ * @return Whether the server was successfully initialized.
+ */
+ public boolean start(int port) {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ return mImpl.start(port);
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure("Failed to start server.", e);
+ }
+ }
+
+ /** Create and initialize a server that serves files from the provided directory.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param context The context in which the server will run.
+ * @param directory The directory from which files should be served. This must be
+ * Environment.getExternalStorageDirectory().
+ * @return The created server.
+ */
+ public static EmbeddedTestServer createAndStartFileServer(Context context, File directory)
+ throws InterruptedException {
+ // TODO(jbudorick): Update all callers to use createAndStartServer() directly.
+ if (!directory.equals(Environment.getExternalStorageDirectory())) {
+ throw new IllegalArgumentException("Expected directory to be ExternalStorageDirectory");
+ }
+ return createAndStartServer(context);
+ }
+
+ /** Create and initialize a server with the default handlers.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param context The context in which the server will run.
+ * @return The created server.
+ */
+ public static EmbeddedTestServer createAndStartDefaultServer(Context context)
+ throws InterruptedException {
+ // TODO(pkotwicz): Update all callers to use createAndStartServer() directly.
+ return createAndStartServer(context);
+ }
+
+ /** Create and initialize a server with the default handlers.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param context The context in which the server will run.
+ * @return The created server.
+ */
+ public static EmbeddedTestServer createAndStartServer(Context context)
+ throws InterruptedException {
+ return createAndStartServerWithPort(context, 0);
+ }
+
+ /** Create and initialize a server with the default handlers and specified port.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param context The context in which the server will run.
+ * @param port The port to use for the server, 0 to auto-select an unused port.
+ * @return The created server.
+ */
+ public static EmbeddedTestServer createAndStartServerWithPort(Context context, int port)
+ throws InterruptedException {
+ Assert.assertNotEquals("EmbeddedTestServer should not be created on UiThread, "
+ + "the instantiation will hang forever waiting for tasks to post to UI thread",
+ Looper.getMainLooper(), Looper.myLooper());
+ EmbeddedTestServer server = new EmbeddedTestServer();
+ return initializeAndStartServer(server, context, port);
+ }
+
+ /** Create and initialize an HTTPS server with the default handlers.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param context The context in which the server will run.
+ * @param serverCertificate The certificate option that the server will use.
+ * @return The created server.
+ */
+ public static EmbeddedTestServer createAndStartHTTPSServer(
+ Context context, int serverCertificate) throws InterruptedException {
+ return createAndStartHTTPSServerWithPort(context, serverCertificate, 0 /* port */);
+ }
+
+ /** Create and initialize an HTTPS server with the default handlers and specified port.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param context The context in which the server will run.
+ * @param serverCertificate The certificate option that the server will use.
+ * @param port The port to use for the server, 0 to auto-select an unused port.
+ * @return The created server.
+ */
+ public static EmbeddedTestServer createAndStartHTTPSServerWithPort(
+ Context context, int serverCertificate, int port) throws InterruptedException {
+ Assert.assertNotEquals("EmbeddedTestServer should not be created on UiThread, "
+ + "the instantiation will hang forever waiting for tasks"
+ + " to post to UI thread",
+ Looper.getMainLooper(), Looper.myLooper());
+ EmbeddedTestServer server = new EmbeddedTestServer();
+ return initializeAndStartHTTPSServer(server, context, serverCertificate, port);
+ }
+
+ /** Initialize a server with the default handlers.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param server The server instance that will be initialized.
+ * @param context The context in which the server will run.
+ * @param port The port to use for the server, 0 to auto-select an unused port.
+ * @return The created server.
+ */
+ public static <T extends EmbeddedTestServer> T initializeAndStartServer(
+ T server, Context context, int port) throws InterruptedException {
+ server.initializeNative(context, ServerHTTPSSetting.USE_HTTP);
+ server.addDefaultHandlers("");
+ if (!server.start(port)) {
+ throw new EmbeddedTestServerFailure("Failed to start serving using default handlers.");
+ }
+ return server;
+ }
+
+ /** Initialize a server with the default handlers that uses HTTPS with the given certificate
+ * option.
+ *
+ * This handles native object initialization, server configuration, and server initialization.
+ * On returning, the server is ready for use.
+ *
+ * @param server The server instance that will be initialized.
+ * @param context The context in which the server will run.
+ * @param serverCertificate The certificate option that the server will use.
+ * @param port The port to use for the server.
+ * @return The created server.
+ */
+ public static <T extends EmbeddedTestServer> T initializeAndStartHTTPSServer(T server,
+ Context context, int serverCertificate, int port) throws InterruptedException {
+ server.initializeNative(context, ServerHTTPSSetting.USE_HTTPS);
+ server.addDefaultHandlers("");
+ server.setSSLConfig(serverCertificate);
+ if (!server.start(port)) {
+ throw new EmbeddedTestServerFailure("Failed to start serving using default handlers.");
+ }
+ return server;
+ }
+
+ /** Get the full URL for the given relative URL.
+ *
+ * @param relativeUrl The relative URL for which a full URL will be obtained.
+ * @return The URL as a String.
+ */
+ public String getURL(String relativeUrl) {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ return mImpl.getURL(relativeUrl);
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure("Failed to get URL for " + relativeUrl, e);
+ }
+ }
+
+ /** Get the full URL for the given relative URL. Similar to the above method but uses the given
+ * hostname instead of 127.0.0.1. The hostname should be resolved to 127.0.0.1.
+ *
+ * @param hostName The host name which should be used.
+ * @param relativeUrl The relative URL for which a full URL should be returned.
+ * @return The URL as a String.
+ */
+ public String getURLWithHostName(String hostname, String relativeUrl) {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ return mImpl.getURLWithHostName(hostname, relativeUrl);
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure(
+ "Failed to get URL for " + hostname + " and " + relativeUrl, e);
+ }
+ }
+
+ /** Get the full URLs for the given relative URLs.
+ *
+ * @see #getURL(String)
+ *
+ * @param relativeUrls The relative URLs for which full URLs will be obtained.
+ * @return The URLs as a String array.
+ */
+ public String[] getURLs(String... relativeUrls) {
+ String[] absoluteUrls = new String[relativeUrls.length];
+
+ for (int i = 0; i < relativeUrls.length; ++i) absoluteUrls[i] = getURL(relativeUrls[i]);
+
+ return absoluteUrls;
+ }
+
+ /** Shutdown the server.
+ *
+ * @return Whether the server was successfully shut down.
+ */
+ public boolean shutdownAndWaitUntilComplete() {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ return mImpl.shutdownAndWaitUntilComplete();
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure("Failed to shut down.", e);
+ }
+ }
+
+ /** Destroy the native EmbeddedTestServer object. */
+ public void destroy() {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ mImpl.destroy();
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure("Failed to destroy native server.", e);
+ } finally {
+ mContext.unbindService(mConn);
+ }
+ }
+
+ /** Stop and destroy the server.
+ *
+ * This handles stopping the server and destroying the native object.
+ */
+ public void stopAndDestroyServer() {
+ if (!shutdownAndWaitUntilComplete()) {
+ throw new EmbeddedTestServerFailure("Failed to stop server.");
+ }
+ destroy();
+ }
+
+ /** Get the path of the PEM file of the root cert. */
+ public String getRootCertPemPath() {
+ try {
+ synchronized (mImplMonitor) {
+ checkServiceLocked();
+ return mImpl.getRootCertPemPath();
+ }
+ } catch (RemoteException e) {
+ throw new EmbeddedTestServerFailure("Failed to get root cert's path", e);
+ }
+ }
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java
new file mode 100644
index 00000000000..07932f93e88
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerImpl.java
@@ -0,0 +1,333 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test;
+
+import android.content.Context;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.RemoteException;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.library_loader.ProcessInitException;
+import org.chromium.base.test.util.UrlUtils;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Java bindings for running a net::test_server::EmbeddedTestServer.
+ *
+ * This should not be used directly. Use {@link EmbeddedTestServer} instead.
+ */
+@JNINamespace("net::test_server")
+public class EmbeddedTestServerImpl extends IEmbeddedTestServerImpl.Stub {
+ private static final String TAG = "cr_TestServer";
+
+ private static AtomicInteger sCount = new AtomicInteger();
+
+ private final Context mContext;
+ private Handler mHandler;
+ private HandlerThread mHandlerThread;
+ private long mNativeEmbeddedTestServer;
+ private IConnectionListener mConnectionListener;
+
+ /** Create an uninitialized EmbeddedTestServer. */
+ public EmbeddedTestServerImpl(Context context) {
+ mContext = context;
+ }
+
+ private <V> V runOnHandlerThread(Callable<V> c) {
+ FutureTask<V> t = new FutureTask<>(c);
+ mHandler.post(t);
+ try {
+ return t.get();
+ } catch (ExecutionException e) {
+ Log.e(TAG, "Exception raised from native EmbeddedTestServer", e);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Interrupted while waiting for native EmbeddedTestServer", e);
+ }
+ return null;
+ }
+
+ /** Initialize the native EmbeddedTestServer object.
+ *
+ * @param https True if the server should use HTTPS, and false otherwise.
+ * @return Whether the native object was successfully initialized.
+ */
+ @Override
+ public boolean initializeNative(final boolean https) {
+ // This is necessary as EmbeddedTestServerImpl is in a different process than the tests
+ // using it, so it needs to initialize its own application context.
+ ContextUtils.initApplicationContext(mContext.getApplicationContext());
+ try {
+ LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
+ } catch (ProcessInitException e) {
+ Log.e(TAG, "Failed to load native libraries.", e);
+ return false;
+ }
+
+ mHandlerThread = new HandlerThread("EmbeddedTestServer" + sCount.getAndIncrement());
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ if (mNativeEmbeddedTestServer == 0) {
+ nativeInit(UrlUtils.getIsolatedTestRoot(), https);
+ }
+ assert mNativeEmbeddedTestServer != 0;
+ return null;
+ }
+ });
+ return true;
+ }
+
+ /** Starts the server.
+ *
+ * Note that this should be called after handlers are set up, including any relevant calls
+ * serveFilesFromDirectory.
+ *
+ * @param port The port to use for the server, 0 to auto-select an unused port.
+ *
+ * @return Whether the server was successfully started.
+ */
+ @Override
+ public boolean start(int port) {
+ return runOnHandlerThread(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return nativeStart(mNativeEmbeddedTestServer, port);
+ }
+ });
+ }
+
+ /** Returns the path to a PEM file containing the server's root certificate.
+ *
+ * @return The path to a PEM file containing the server's root certificate.
+ */
+ @Override
+ public String getRootCertPemPath() {
+ return runOnHandlerThread(new Callable<String>() {
+ @Override
+ public String call() {
+ return nativeGetRootCertPemPath(mNativeEmbeddedTestServer);
+ }
+ });
+ }
+
+ /** Add the default handlers and serve files from the provided directory relative to the
+ * external storage directory.
+ *
+ * @param directoryPath The path of the directory from which files should be served, relative
+ * to the external storage directory.
+ */
+ @Override
+ public void addDefaultHandlers(final String directoryPath) {
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ nativeAddDefaultHandlers(mNativeEmbeddedTestServer, directoryPath);
+ return null;
+ }
+ });
+ }
+
+ /** Configure the server to use a particular type of SSL certificate.
+ *
+ * @param serverCertificate The type of certificate the server should use.
+ */
+ @Override
+ public void setSSLConfig(final int serverCertificate) {
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ nativeSetSSLConfig(mNativeEmbeddedTestServer, serverCertificate);
+ return null;
+ }
+ });
+ }
+
+ /** Register multiple request handlers.
+ * Handlers must be registered before starting the server.
+ *
+ * @param handler The pointer of handler to be registered.
+ */
+ public void registerRequestHandler(final long handler) {
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ nativeRegisterRequestHandler(mNativeEmbeddedTestServer, handler);
+ return null;
+ }
+ });
+ }
+
+ /** Serve files from the provided directory.
+ *
+ * @param directoryPath The path of the directory from which files should be served.
+ */
+ @Override
+ public void serveFilesFromDirectory(final String directoryPath) {
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ nativeServeFilesFromDirectory(mNativeEmbeddedTestServer, directoryPath);
+ return null;
+ }
+ });
+ }
+
+ /** Sets a connection listener to be notified of new connections and socket reads.
+ *
+ * Must be done before starting the server. Setting a new one erases the previous one.
+ *
+ * @param listener Listener to notify.
+ */
+ @Override
+ public void setConnectionListener(final IConnectionListener listener) {
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ mConnectionListener = listener;
+ return null;
+ }
+ });
+ }
+
+ /** Get the full URL for the given relative URL.
+ *
+ * @param relativeUrl The relative URL for which a full URL should be returned.
+ * @return The URL as a String.
+ */
+ @Override
+ public String getURL(final String relativeUrl) {
+ return runOnHandlerThread(new Callable<String>() {
+ @Override
+ public String call() {
+ return nativeGetURL(mNativeEmbeddedTestServer, relativeUrl);
+ }
+ });
+ }
+
+ /** Get the full URL for the given relative URL. Similar to the above method but uses the given
+ * hostname instead of 127.0.0.1. The hostname should be resolved to 127.0.0.1.
+ *
+ * @param hostName The host name which should be used.
+ * @param relativeUrl The relative URL for which a full URL should be returned.
+ * @return The URL as a String.
+ */
+ @Override
+ public String getURLWithHostName(final String hostName, final String relativeUrl) {
+ return runOnHandlerThread(new Callable<String>() {
+ @Override
+ public String call() {
+ return nativeGetURLWithHostName(mNativeEmbeddedTestServer, hostName, relativeUrl);
+ }
+ });
+ }
+
+ /** Shut down the server.
+ *
+ * @return Whether the server was successfully shut down.
+ */
+ @Override
+ public boolean shutdownAndWaitUntilComplete() {
+ return runOnHandlerThread(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return nativeShutdownAndWaitUntilComplete(mNativeEmbeddedTestServer);
+ }
+ });
+ }
+
+ /** Destroy the native EmbeddedTestServer object. */
+ @Override
+ public void destroy() {
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ assert mNativeEmbeddedTestServer != 0;
+ nativeDestroy(mNativeEmbeddedTestServer);
+ assert mNativeEmbeddedTestServer == 0;
+ return null;
+ }
+ });
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ mHandlerThread.quitSafely();
+ } else {
+ runOnHandlerThread(new Callable<Void>() {
+ @Override
+ public Void call() {
+ mHandlerThread.quit();
+ return null;
+ }
+ });
+ }
+
+ try {
+ mHandlerThread.join();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ @CalledByNative
+ private void acceptedSocket(long socketId) {
+ if (mConnectionListener == null) return;
+ try {
+ mConnectionListener.acceptedSocket(socketId);
+ } catch (RemoteException e) {
+ // Callback, ignore exception.
+ }
+ }
+
+ @CalledByNative
+ private void readFromSocket(long socketId) {
+ if (mConnectionListener == null) return;
+ try {
+ mConnectionListener.readFromSocket(socketId);
+ } catch (RemoteException e) {
+ // Callback, ignore exception.
+ }
+ }
+
+ @CalledByNative
+ private void setNativePtr(long nativePtr) {
+ assert mNativeEmbeddedTestServer == 0;
+ mNativeEmbeddedTestServer = nativePtr;
+ }
+
+ @CalledByNative
+ private void clearNativePtr() {
+ assert mNativeEmbeddedTestServer != 0;
+ mNativeEmbeddedTestServer = 0;
+ }
+
+ private native void nativeInit(String testDataDir, boolean https);
+ private native void nativeDestroy(long nativeEmbeddedTestServerAndroid);
+ private native boolean nativeStart(long nativeEmbeddedTestServerAndroid, int port);
+ private native String nativeGetRootCertPemPath(long nativeEmbeddedTestServerAndroid);
+ private native boolean nativeShutdownAndWaitUntilComplete(long nativeEmbeddedTestServerAndroid);
+ private native void nativeAddDefaultHandlers(
+ long nativeEmbeddedTestServerAndroid, String directoryPath);
+ private native void nativeSetSSLConfig(
+ long nativeEmbeddedTestServerAndroid, int serverCertificate);
+ private native void nativeRegisterRequestHandler(
+ long nativeEmbeddedTestServerAndroid, long handler);
+ private native String nativeGetURL(long nativeEmbeddedTestServerAndroid, String relativeUrl);
+ private native String nativeGetURLWithHostName(
+ long nativeEmbeddedTestServerAndroid, String hostName, String relativeUrl);
+ private native void nativeServeFilesFromDirectory(
+ long nativeEmbeddedTestServerAndroid, String directoryPath);
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java
new file mode 100644
index 00000000000..6d20871c1a5
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test;
+
+import android.support.test.InstrumentationRegistry;
+
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+/**
+ * Junit4 rule for starting embedded test server before a test starts, and shutting it down when it
+ * finishes.
+ */
+public class EmbeddedTestServerRule extends TestWatcher {
+ EmbeddedTestServer mServer;
+
+ @Override
+ protected void starting(Description description) {
+ try {
+ mServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
+ } catch (InterruptedException e) {
+ throw new EmbeddedTestServer.EmbeddedTestServerFailure("Test server didn't start");
+ }
+ super.starting(description);
+ }
+
+ @Override
+ protected void finished(Description description) {
+ super.finished(description);
+ mServer.stopAndDestroyServer();
+ }
+
+ /**
+ * Get the test server.
+ *
+ * @return the test server.
+ */
+ public EmbeddedTestServer getServer() {
+ return mServer;
+ }
+
+ public String getOrigin() {
+ return mServer.getURL("/");
+ }
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerService.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerService.java
new file mode 100644
index 00000000000..1390b8c0cf7
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerService.java
@@ -0,0 +1,19 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * A {@link android.app.Service} that creates a new {@link EmbeddedTestServer} when bound.
+ */
+public class EmbeddedTestServerService extends Service {
+ @Override
+ public IBinder onBind(Intent intent) {
+ return new EmbeddedTestServerImpl(this);
+ }
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl b/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl
index 13372db9c10..6112b99eb32 100644
--- a/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/IEmbeddedTestServerImpl.aidl
@@ -13,9 +13,10 @@ interface IEmbeddedTestServerImpl {
/** Start the server.
*
+ * @param port The port to use for the server, 0 to auto-select an unused port.
* @return Whether the server was successfully started.
*/
- boolean start();
+ boolean start(int port);
/** Get the path of the server's root certificate.
*
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/util/CertTestUtil.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/CertTestUtil.java
new file mode 100644
index 00000000000..9994da921ff
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/CertTestUtil.java
@@ -0,0 +1,77 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test.util;
+
+import android.util.Base64;
+
+import org.chromium.base.test.util.UrlUtils;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+
+/**
+ * Certificate related utility methods.
+ */
+public class CertTestUtil {
+ /**
+ * The location of the directory that contains certificates for testing.
+ */
+ public static final String CERTS_DIRECTORY =
+ UrlUtils.getIsolatedTestFilePath("net/data/ssl/certificates/");
+
+ private static final String BEGIN_MARKER = "-----BEGIN CERTIFICATE-----";
+ private static final String END_MARKER = "-----END CERTIFICATE-----";
+
+ private CertTestUtil() {}
+
+ /**
+ * Converts a PEM formatted cert in a given file to the binary DER format.
+ *
+ * @param pemPathname the location of the certificate to convert.
+ * @return array of bytes that represent the certificate in DER format.
+ * @throws IOException if the file cannot be read.
+ */
+ public static byte[] pemToDer(String pemPathname) throws IOException {
+ BufferedReader reader = new BufferedReader(new FileReader(pemPathname));
+ StringBuilder builder = new StringBuilder();
+
+ // Skip past leading junk lines, if any.
+ String line = reader.readLine();
+ while (line != null && !line.contains(BEGIN_MARKER)) line = reader.readLine();
+
+ // Then skip the BEGIN_MARKER itself, if present.
+ while (line != null && line.contains(BEGIN_MARKER)) line = reader.readLine();
+
+ // Now gather the data lines into the builder.
+ while (line != null && !line.contains(END_MARKER)) {
+ builder.append(line.trim());
+ line = reader.readLine();
+ }
+
+ reader.close();
+ return Base64.decode(builder.toString(), Base64.DEFAULT);
+ }
+
+ /**
+ * Returns SHA256 hash of the public key of a given certificate.
+ *
+ * @param cert the cert that should be used to retrieve the public key from.
+ * @return SHA256 hash of the public key.
+ */
+ public static byte[] getPublicKeySha256(Certificate cert) {
+ try {
+ byte[] publicKey = cert.getPublicKey().getEncoded();
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ return digest.digest(publicKey);
+ } catch (NoSuchAlgorithmException ex) {
+ // This exception should never happen since SHA-256 is known algorithm
+ throw new RuntimeException(ex);
+ }
+ }
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/util/NetworkChangeNotifierTestUtil.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/NetworkChangeNotifierTestUtil.java
new file mode 100644
index 00000000000..3a03f1a0782
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/NetworkChangeNotifierTestUtil.java
@@ -0,0 +1,26 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test.util;
+
+import org.chromium.base.ThreadUtils;
+
+import java.util.concurrent.FutureTask;
+
+/**
+ * A utility class useful for testing NetworkChangeNotifier.
+ */
+public class NetworkChangeNotifierTestUtil {
+ /**
+ * Flushes UI thread task queue.
+ */
+ public static void flushUiThreadTaskQueue() throws Exception {
+ FutureTask<Void> task = new FutureTask<Void>(new Runnable() {
+ @Override
+ public void run() {}
+ }, null);
+ ThreadUtils.postOnUiThread(task);
+ task.get();
+ }
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
new file mode 100644
index 00000000000..58394a75b68
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
@@ -0,0 +1,437 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test.util;
+
+import android.util.Base64;
+import android.util.Log;
+import android.util.Pair;
+
+import org.chromium.base.ApiCompatibilityUtils;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Simple http test server for testing.
+ *
+ * Extends WebServer with the ability to map requests to prepared responses.
+ */
+public class TestWebServer extends WebServer {
+ private static final String TAG = "TestWebServer";
+
+ private static class Response {
+ final byte[] mResponseData;
+ final List<Pair<String, String>> mResponseHeaders;
+ final boolean mIsRedirect;
+ final Runnable mResponseAction;
+ final boolean mIsNotFound;
+ final boolean mIsNoContent;
+ final boolean mForWebSocket;
+ final boolean mIsEmptyResponse;
+
+ Response(byte[] responseData, List<Pair<String, String>> responseHeaders,
+ boolean isRedirect, boolean isNotFound, boolean isNoContent, boolean forWebSocket,
+ boolean isEmptyResponse, Runnable responseAction) {
+ mIsRedirect = isRedirect;
+ mIsNotFound = isNotFound;
+ mIsNoContent = isNoContent;
+ mForWebSocket = forWebSocket;
+ mIsEmptyResponse = isEmptyResponse;
+ mResponseData = responseData;
+ mResponseHeaders = responseHeaders == null ? new ArrayList<Pair<String, String>>()
+ : responseHeaders;
+ mResponseAction = responseAction;
+ }
+ }
+
+ // The Maps below are modified on both the client thread and the internal server thread, so
+ // need to use a lock when accessing them.
+ private final Object mLock = new Object();
+ private final Map<String, Response> mResponseMap = new HashMap<String, Response>();
+ private final Map<String, Integer> mResponseCountMap = new HashMap<String, Integer>();
+ private final Map<String, HTTPRequest> mLastRequestMap = new HashMap<String, HTTPRequest>();
+
+ /**
+ * Create and start a local HTTP server instance.
+ * @param port Port number the server must use, or 0 to automatically choose a free port.
+ * @param ssl True if the server should be using secure sockets.
+ * @throws Exception
+ */
+ private TestWebServer(int port, boolean ssl) throws Exception {
+ super(port, ssl);
+ setRequestHandler(new Handler());
+ }
+
+ private class Handler implements WebServer.RequestHandler {
+ @Override
+ public void handleRequest(WebServer.HTTPRequest request, OutputStream stream) {
+ WebServerPrintStream printStream = new WebServerPrintStream(stream);
+ try {
+ outputResponse(request, printStream);
+ } catch (NoSuchAlgorithmException ignore) {
+ } catch (IOException e) {
+ Log.w(TAG, e);
+ } finally {
+ printStream.close();
+ }
+ }
+ }
+
+ public static TestWebServer start(int port) throws Exception {
+ return new TestWebServer(port, false);
+ }
+
+ public static TestWebServer start() throws Exception {
+ return start(0);
+ }
+
+ public static TestWebServer startSsl(int port) throws Exception {
+ return new TestWebServer(port, true);
+ }
+
+ public static TestWebServer startSsl() throws Exception {
+ return startSsl(0);
+ }
+
+ private static final int RESPONSE_STATUS_NORMAL = 0;
+ 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 static final int RESPONSE_STATUS_EMPTY_RESPONSE = 5;
+
+ private String setResponseInternal(String requestPath, byte[] responseData,
+ List<Pair<String, String>> responseHeaders, Runnable responseAction, int status) {
+ 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);
+ final boolean isEmptyResponse = (status == RESPONSE_STATUS_EMPTY_RESPONSE);
+
+ synchronized (mLock) {
+ mResponseMap.put(requestPath,
+ new Response(responseData, responseHeaders, isRedirect, isNotFound, isNoContent,
+ forWebSocket, isEmptyResponse, responseAction));
+ mResponseCountMap.put(requestPath, Integer.valueOf(0));
+ mLastRequestMap.put(requestPath, null);
+ }
+ return getResponseUrl(requestPath);
+ }
+
+ /**
+ * Sets a 404 (not found) response to be returned when a particular request path is passed in.
+ *
+ * @param requestPath The path to respond to.
+ * @return The full URL including the path that should be requested to get the expected
+ * response.
+ */
+ public String setResponseWithNotFoundStatus(String requestPath) {
+ return setResponseWithNotFoundStatus(requestPath, null);
+ }
+
+ /**
+ * Sets a 404 (not found) response to be returned when a particular request path is passed in.
+ *
+ * @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 setResponseWithNotFoundStatus(
+ String requestPath, List<Pair<String, String>> responseHeaders) {
+ return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(""),
+ responseHeaders, null, RESPONSE_STATUS_NOT_FOUND);
+ }
+
+ /**
+ * Sets a 204 (no content) response to be returned when a particular request path is passed in.
+ *
+ * @param requestPath The path to respond to.
+ * @return The full URL including the path that should be requested to get the expected
+ * response.
+ */
+ public String setResponseWithNoContentStatus(String requestPath) {
+ return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(""), null, null,
+ RESPONSE_STATUS_NO_CONTENT);
+ }
+
+ /**
+ * Sets an empty response to be returned when a particular request path is passed in.
+ *
+ * @param requestPath The path to respond to.
+ * @return The full URL including the path that should be requested to get the expected
+ * response.
+ */
+ public String setEmptyResponse(String requestPath) {
+ return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(""), null, null,
+ RESPONSE_STATUS_EMPTY_RESPONSE);
+ }
+
+ /**
+ * Sets a response to be returned when a particular request path is passed
+ * in (with the option to specify additional headers).
+ *
+ * @param requestPath The path to respond to.
+ * @param responseString The response body that will be returned.
+ * @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 setResponse(
+ String requestPath, String responseString, List<Pair<String, String>> responseHeaders) {
+ return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(responseString),
+ responseHeaders, null, RESPONSE_STATUS_NORMAL);
+ }
+
+ /**
+ * Sets a response to be returned when a particular request path is passed
+ * in with the option to specify additional headers as well as an arbitrary action to be
+ * executed on each request.
+ *
+ * @param requestPath The path to respond to.
+ * @param responseString The response body that will be returned.
+ * @param responseHeaders Any additional headers that should be returned along with the
+ * response (null is acceptable).
+ * @param responseAction The action to be performed when fetching the response. This action
+ * will be executed for each request and will be handled on a background
+ * thread.
+ * @return The full URL including the path that should be requested to get the expected
+ * response.
+ */
+ public String setResponseWithRunnableAction(String requestPath, String responseString,
+ List<Pair<String, String>> responseHeaders, Runnable responseAction) {
+ return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(responseString),
+ responseHeaders, responseAction, RESPONSE_STATUS_NORMAL);
+ }
+
+ /**
+ * Sets a redirect.
+ *
+ * @param requestPath The path to respond to.
+ * @param targetPath The path to redirect to.
+ * @return The full URL including the path that should be requested to get the expected
+ * response.
+ */
+ public String setRedirect(String requestPath, String targetPath) {
+ List<Pair<String, String>> responseHeaders = new ArrayList<Pair<String, String>>();
+ responseHeaders.add(Pair.create("Location", targetPath));
+
+ return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(targetPath),
+ responseHeaders, null, RESPONSE_STATUS_MOVED_TEMPORARILY);
+ }
+
+ /**
+ * Sets a base64 encoded response to be returned when a particular request path is passed
+ * in (with the option to specify additional headers).
+ *
+ * @param requestPath The path to respond to.
+ * @param base64EncodedResponse The response body that is base64 encoded. The actual server
+ * response will the decoded binary form.
+ * @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 setResponseBase64(String requestPath, String base64EncodedResponse,
+ List<Pair<String, String>> responseHeaders) {
+ return setResponseInternal(requestPath,
+ Base64.decode(base64EncodedResponse, Base64.DEFAULT), responseHeaders, null,
+ RESPONSE_STATUS_NORMAL);
+ }
+
+ /**
+ * 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>>();
+ } else {
+ responseHeaders = new ArrayList<Pair<String, String>>(responseHeaders);
+ }
+ responseHeaders.add(Pair.create("Connection", "Upgrade"));
+ responseHeaders.add(Pair.create("Upgrade", "websocket"));
+ return setResponseInternal(requestPath, ApiCompatibilityUtils.getBytesUtf8(""),
+ 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) {
+ Integer count = null;
+ synchronized (mLock) {
+ count = mResponseCountMap.get(requestPath);
+ }
+ if (count == null) throw new IllegalArgumentException("Path not set: " + requestPath);
+ return count.intValue();
+ }
+
+ /**
+ * Returns the last HttpRequest at this path. Can return null if it is never requested.
+ */
+ public HTTPRequest getLastRequest(String requestPath) {
+ synchronized (mLock) {
+ if (!mLastRequestMap.containsKey(requestPath))
+ throw new IllegalArgumentException("Path not set: " + requestPath);
+ return mLastRequestMap.get(requestPath);
+ }
+ }
+
+ private static class WebServerPrintStream extends PrintStream {
+ WebServerPrintStream(OutputStream out) {
+ super(out);
+ }
+
+ @Override
+ public void println(String s) {
+ Log.w(TAG, s);
+ super.println(s);
+ }
+ }
+
+ /**
+ * Generate a response to the given request.
+ *
+ * <p>Always executed on the background server thread.
+ *
+ * <p>If there is an action associated with the response, it will be executed inside of
+ * this function.
+ *
+ * @throws NoSuchAlgorithmException, IOException
+ */
+ private void outputResponse(HTTPRequest request, WebServerPrintStream stream)
+ throws NoSuchAlgorithmException, IOException {
+ // Don't dump headers to decrease log.
+ Log.w(TAG, request.requestLine());
+
+ final String bodyTemplate = "<html><head><title>%s</title></head>"
+ + "<body>%s</body></html>";
+
+ boolean copyHeadersToResponse = true;
+ boolean copyBinaryBodyToResponse = false;
+ boolean contentLengthAlreadyIncluded = false;
+ boolean contentTypeAlreadyIncluded = false;
+ String path = URI.create(request.getURI()).getPath();
+ StringBuilder textBody = new StringBuilder();
+
+ Response response;
+ synchronized (mLock) {
+ response = mResponseMap.get(path);
+ }
+
+ if (response == null || response.mIsNotFound) {
+ stream.println("HTTP/1.0 404 Not Found");
+ textBody.append(String.format(bodyTemplate, "Not Found", "Not Found"));
+ } else if (response.mForWebSocket) {
+ String keyHeader = request.headerValue("Sec-WebSocket-Key");
+ if (!keyHeader.isEmpty()) {
+ stream.println("HTTP/1.0 101 Switching Protocols");
+ stream.println("Sec-WebSocket-Accept: " + computeWebSocketAccept(keyHeader));
+ } else {
+ stream.println("HTTP/1.0 404 Not Found");
+ textBody.append(String.format(bodyTemplate, "Not Found", "Not Found"));
+ copyHeadersToResponse = false;
+ }
+ } else if (response.mIsNoContent) {
+ stream.println("HTTP/1.0 200 OK");
+ copyHeadersToResponse = false;
+ } else if (response.mIsRedirect) {
+ stream.println("HTTP/1.0 302 Found");
+ textBody.append(String.format(bodyTemplate, "Found", "Found"));
+ } else if (response.mIsEmptyResponse) {
+ stream.println("HTTP/1.0 403 Forbidden");
+ copyHeadersToResponse = false;
+ } else {
+ if (response.mResponseAction != null) response.mResponseAction.run();
+
+ stream.println("HTTP/1.0 200 OK");
+ copyBinaryBodyToResponse = true;
+ }
+
+ if (response != null) {
+ if (copyHeadersToResponse) {
+ for (Pair<String, String> header : response.mResponseHeaders) {
+ stream.println(header.first + ": " + header.second);
+ if (header.first.toLowerCase(Locale.ENGLISH).equals("content-length")) {
+ contentLengthAlreadyIncluded = true;
+ } else if (header.first.toLowerCase(Locale.ENGLISH).equals("content-type")) {
+ contentTypeAlreadyIncluded = true;
+ }
+ }
+ }
+ synchronized (mLock) {
+ mResponseCountMap.put(
+ path, Integer.valueOf(mResponseCountMap.get(path).intValue() + 1));
+ mLastRequestMap.put(path, request);
+ }
+ }
+
+ // RFC 1123
+ final SimpleDateFormat dateFormat =
+ new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
+
+ // Using print and println() because we don't want to dump it into log.
+ stream.print("Date: " + dateFormat.format(new Date()));
+ stream.println();
+
+ if (textBody.length() != 0) {
+ if (!contentTypeAlreadyIncluded && (path.endsWith(".html") || path.endsWith(".htm"))) {
+ stream.println("Content-Type: text/html");
+ }
+ stream.println("Content-Length: " + textBody.length());
+ stream.println();
+ stream.print(textBody.toString());
+ } else if (copyBinaryBodyToResponse) {
+ if (!contentTypeAlreadyIncluded && path.endsWith(".js")) {
+ stream.println("Content-Type: application/javascript");
+ } else if (!contentTypeAlreadyIncluded
+ && (path.endsWith(".html") || path.endsWith(".htm"))) {
+ stream.println("Content-Type: text/html");
+ }
+ if (!contentLengthAlreadyIncluded) {
+ stream.println("Content-Length: " + response.mResponseData.length);
+ }
+ stream.println();
+ stream.write(response.mResponseData);
+ } else {
+ stream.println();
+ }
+ }
+
+ /**
+ * 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.NO_WRAP);
+ }
+}
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/util/WebServer.java b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/WebServer.java
new file mode 100644
index 00000000000..82cf22b62d1
--- /dev/null
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/util/WebServer.java
@@ -0,0 +1,506 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.net.test.util;
+
+import android.util.Base64;
+
+import org.chromium.base.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+
+/**
+ * Simple http test server for testing.
+ *
+ * This server runs in a thread in the current process, so it is convenient
+ * for loopback testing without the need to setup TCP forwarding to the
+ * host computer.
+ */
+public class WebServer {
+ private static final String TAG = "WebServer";
+
+ private static WebServer sInstance;
+ private static WebServer sSecureInstance;
+
+ private final ServerThread mServerThread;
+ private String mServerUri;
+ private final boolean mSsl;
+ private final int mPort;
+
+ public static final String STATUS_OK = "200 OK";
+
+ /**
+ * Writes an HTTP response to |output|.
+ * |status| should be one of the STATUS_* values above.
+ */
+ public static void writeResponse(OutputStream output, String status, byte[] body)
+ throws IOException {
+ if (body == null) {
+ body = new byte[0];
+ }
+ output.write(("HTTP/1.1 " + status + "\r\nContent-Length: " + String.valueOf(body.length)
+ + "\r\n\r\n")
+ .getBytes());
+ output.write(body);
+ output.flush();
+ }
+
+ /** Represents an HTTP header. */
+ public static class HTTPHeader {
+ public final String key;
+ public final String value;
+ /** Constructs an HTTP header. */
+ public HTTPHeader(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+ /**
+ * Parse an HTTP header from a string line. Returns null if the line is not a valid HTTP
+ * header.
+ */
+ public static HTTPHeader parseLine(String line) {
+ String[] parts = line.split(":", 2);
+ if (parts.length == 2) {
+ return new HTTPHeader(parts[0].trim(), parts[1].trim());
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return key + ": " + value;
+ }
+ }
+
+ /** Thrown when an HTTP request could not be parsed. */
+ public static class InvalidRequest extends Exception {
+ /** Constructor */
+ public InvalidRequest() {
+ super("Invalid HTTP request");
+ }
+ }
+
+ /** A parsed HTTP request. */
+ public static class HTTPRequest {
+ private String mMethod;
+ private String mURI;
+ private String mHTTPVersion;
+ private HTTPHeader[] mHeaders;
+ private byte[] mBody;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(requestLine());
+ builder.append("\r\n");
+ for (HTTPHeader header : mHeaders) {
+ builder.append(header.toString());
+ builder.append("\r\n");
+ }
+ if (mBody != null) {
+ builder.append("\r\n");
+ try {
+ builder.append(new String(mBody, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ builder.append("<binary body, length=").append(mBody.length).append(">\r\n");
+ }
+ }
+ return builder.toString();
+ }
+
+ /** Returns the request line as a String. */
+ public String requestLine() {
+ return mMethod + " " + mURI + " " + mHTTPVersion;
+ }
+
+ /** Returns the request method. */
+ public String getMethod() {
+ return mMethod;
+ }
+
+ /** Returns the request URI. */
+ public String getURI() {
+ return mURI;
+ }
+
+ /** Returns the request HTTP version. */
+ public String getHTTPVersion() {
+ return mHTTPVersion;
+ }
+
+ /** Returns the request headers. */
+ public HTTPHeader[] getHeaders() {
+ return mHeaders;
+ }
+
+ /** Returns the request body. */
+ public byte[] getBody() {
+ return mBody;
+ }
+
+ /**
+ * Returns the header value for the given header name. If a header is present multiple
+ * times, this only returns the first occurence. Returns "" if the header is not found.
+ */
+ public String headerValue(String headerName) {
+ for (String value : headerValues(headerName)) {
+ return value;
+ }
+ return "";
+ }
+
+ /** Returns all header values for the given header name. */
+ public List<String> headerValues(String headerName) {
+ List<String> matchingHeaders = new ArrayList<String>();
+ for (HTTPHeader header : mHeaders) {
+ if (header.key.equalsIgnoreCase(headerName)) {
+ matchingHeaders.add(header.value);
+ }
+ }
+ return matchingHeaders;
+ }
+
+ /** Parses an HTTP request from an input stream. */
+ static public HTTPRequest parse(InputStream stream) throws InvalidRequest, IOException {
+ boolean firstLine = true;
+ HTTPRequest req = new HTTPRequest();
+ ArrayList<HTTPHeader> mHeaders = new ArrayList<HTTPHeader>();
+ ByteArrayOutputStream line = new ByteArrayOutputStream();
+ for (int b = stream.read(); b != -1; b = stream.read()) {
+ if (b == '\r') {
+ int next = stream.read();
+ if (next == '\n') {
+ String lineString;
+ try {
+ lineString = new String(line.toByteArray(), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new InvalidRequest();
+ }
+ line.reset();
+ if (firstLine) {
+ String[] parts = lineString.split(" ", 3);
+ if (parts.length != 3) {
+ throw new InvalidRequest();
+ }
+ req.mMethod = parts[0];
+ req.mURI = parts[1];
+ req.mHTTPVersion = parts[2];
+ firstLine = false;
+ } else {
+ if (lineString.length() == 0) {
+ break;
+ }
+ HTTPHeader header = HTTPHeader.parseLine(lineString);
+ if (header != null) {
+ mHeaders.add(header);
+ }
+ }
+ } else if (next == -1) {
+ throw new InvalidRequest();
+ } else {
+ line.write(b);
+ line.write(next);
+ }
+ } else {
+ line.write(b);
+ }
+ }
+ if (firstLine) {
+ if (line.size() == 0) return null;
+ throw new InvalidRequest();
+ }
+ req.mHeaders = mHeaders.toArray(new HTTPHeader[0]);
+ int contentLength = -1;
+ if (req.mMethod.equals("GET") || req.mMethod.equals("HEAD")) {
+ contentLength = 0;
+ }
+ try {
+ contentLength = Integer.parseInt(req.headerValue("Content-Length"));
+ } catch (NumberFormatException e) {
+ }
+ if (contentLength >= 0) {
+ byte[] content = new byte[contentLength];
+ for (int offset = 0; offset < contentLength;) {
+ int bytesRead = stream.read(content, offset, contentLength);
+ if (bytesRead == -1) { // short read, keep truncated content.
+ content = Arrays.copyOf(content, offset);
+ break;
+ }
+ offset += bytesRead;
+ }
+ req.mBody = content;
+ } else {
+ ByteArrayOutputStream mBody = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1000];
+ int bytesRead;
+ while ((bytesRead = stream.read(buffer, 0, buffer.length)) != -1) {
+ mBody.write(buffer, 0, bytesRead);
+ }
+ req.mBody = mBody.toByteArray();
+ }
+ return req;
+ }
+ }
+
+ /** An interface for handling HTTP requests. */
+ public interface RequestHandler {
+ /** handleRequest is called when an HTTP request is received. handleRequest should write a
+ * response to stream. */
+ void handleRequest(HTTPRequest request, OutputStream stream);
+ }
+
+ private RequestHandler mRequestHandler;
+
+ /** Sets the request handler. */
+ public void setRequestHandler(RequestHandler handler) {
+ mRequestHandler = handler;
+ }
+
+ /** Handle an HTTP request. Calls |mRequestHandler| if set. */
+ private void handleRequest(HTTPRequest request, OutputStream stream) {
+ assert Thread.currentThread()
+ == mServerThread : "handleRequest called from non-server thread";
+ if (mRequestHandler != null) {
+ mRequestHandler.handleRequest(request, stream);
+ }
+ }
+
+ public void setServerHost(String hostname) {
+ try {
+ mServerUri = new java.net
+ .URI(mSsl ? "https" : "http", null, hostname,
+ mServerThread.mSocket.getLocalPort(), null, null, null)
+ .toString();
+ } catch (java.net.URISyntaxException e) {
+ Log.wtf(TAG, e.getMessage());
+ }
+ }
+
+ /**
+ * Create and start a local HTTP server instance.
+ * @param port Port number the server must use, or 0 to automatically choose a free port.
+ * @param ssl True if the server should be using secure sockets.
+ * @throws Exception
+ */
+ public WebServer(int port, boolean ssl) throws Exception {
+ mPort = port;
+ mSsl = ssl;
+
+ if (mSsl) {
+ if (sSecureInstance != null) {
+ throw new IllegalStateException("Tried to start multiple SSL TestWebServers");
+ }
+ } else {
+ if (sInstance != null) {
+ throw new IllegalStateException("Tried to start multiple TestWebServers");
+ }
+ }
+ mServerThread = new ServerThread(mPort, mSsl);
+
+ setServerHost("localhost");
+
+ mServerThread.start();
+ if (mSsl) {
+ WebServer.sSecureInstance = this;
+ } else {
+ WebServer.sInstance = this;
+ }
+ }
+
+ /**
+ * Terminate the http server.
+ */
+ public void shutdown() {
+ if (mSsl) {
+ WebServer.sSecureInstance = null;
+ } else {
+ WebServer.sInstance = null;
+ }
+
+ try {
+ mServerThread.cancelAllRequests();
+ // Block until the server thread is done shutting down.
+ mServerThread.join();
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(e);
+ } catch (InterruptedException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getBaseUrl() {
+ return mServerUri + "/";
+ }
+
+ /**
+ * Gets the URL on the server under which a particular request path will be accessible.
+ *
+ * This only gets the URL, you still need to set the response if you intend to access it.
+ *
+ * @param requestPath The path to respond to.
+ * @return The full URL including the requestPath.
+ */
+ public String getResponseUrl(String requestPath) {
+ return mServerUri + requestPath;
+ }
+
+ private class ServerThread extends Thread {
+ private final boolean mIsSsl;
+ private ServerSocket mSocket;
+ private SSLContext mSslContext;
+
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private boolean mIsCancelled;
+ @GuardedBy("mLock")
+ private Socket mCurrentRequestSocket;
+
+ /**
+ * Defines the keystore contents for the server, BKS version. Holds just a
+ * single self-generated key. The subject name is "Test Server".
+ */
+ private static final String SERVER_KEYS_BKS =
+ "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41"
+ + "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET"
+ + "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV"
+ + "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw"
+ + "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U"
+ + "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl"
+ + "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy"
+ + "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV"
+ + "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG"
+ + "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU"
+ + "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV"
+ + "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx"
+ + "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR"
+ + "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN"
+ + "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs"
+ + "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck"
+ + "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM"
+ + "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI"
+ + "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f"
+ + "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx"
+ + "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt"
+ + "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw"
+ + "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl"
+ + "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
+
+ private static final String PASSWORD = "android";
+
+ /**
+ * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
+ * for the result.
+ */
+ private KeyManager[] getKeyManagers() throws Exception {
+ byte[] bytes = Base64.decode(SERVER_KEYS_BKS, Base64.DEFAULT);
+ InputStream inputStream = new ByteArrayInputStream(bytes);
+
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(inputStream, PASSWORD.toCharArray());
+ inputStream.close();
+
+ String algorithm = KeyManagerFactory.getDefaultAlgorithm();
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
+ keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
+
+ return keyManagerFactory.getKeyManagers();
+ }
+
+ private void setCurrentRequestSocket(Socket socket) {
+ synchronized (mLock) {
+ mCurrentRequestSocket = socket;
+ }
+ }
+
+ private boolean getIsCancelled() {
+ synchronized (mLock) {
+ return mIsCancelled;
+ }
+ }
+
+ // Called from non-server thread.
+ public void cancelAllRequests() throws IOException {
+ synchronized (mLock) {
+ mIsCancelled = true;
+ if (mCurrentRequestSocket != null) {
+ try {
+ mCurrentRequestSocket.close();
+ } catch (IOException ignored) {
+ // Catching this to ensure the server socket is closed as well.
+ }
+ }
+ }
+ // Any current and subsequent accept call will throw instead of block.
+ mSocket.close();
+ }
+
+ public ServerThread(int port, boolean ssl) throws Exception {
+ super("ServerThread");
+ mIsSsl = ssl;
+ // If tests are run back-to-back, it may take time for the port to become available.
+ // Retry a few times with a sleep to wait for the port.
+ int retry = 3;
+ while (true) {
+ try {
+ if (mIsSsl) {
+ mSslContext = SSLContext.getInstance("TLS");
+ mSslContext.init(getKeyManagers(), null, null);
+ mSocket = mSslContext.getServerSocketFactory().createServerSocket(port);
+ } else {
+ mSocket = new ServerSocket(port);
+ }
+ return;
+ } catch (IOException e) {
+ Log.w(TAG, e.getMessage());
+ if (--retry == 0) {
+ throw e;
+ }
+ // sleep in case server socket is still being closed
+ Thread.sleep(1000);
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (!getIsCancelled()) {
+ Socket socket = mSocket.accept();
+ try {
+ setCurrentRequestSocket(socket);
+ HTTPRequest request = HTTPRequest.parse(socket.getInputStream());
+ if (request != null) {
+ handleRequest(request, socket.getOutputStream());
+ }
+ } catch (InvalidRequest e) {
+ Log.e(TAG, e.getMessage());
+ } finally {
+ socket.close();
+ }
+ }
+ } catch (SocketException e) {
+ } catch (IOException e) {
+ Log.w(TAG, e.getMessage());
+ }
+ }
+ }
+}
diff --git a/chromium/net/test/android/net_test_jni_onload.cc b/chromium/net/test/android/net_test_jni_onload.cc
new file mode 100644
index 00000000000..73739190643
--- /dev/null
+++ b/chromium/net/test/android/net_test_jni_onload.cc
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/test/android/net_test_jni_onload.h"
+
+#include "base/android/base_jni_onload.h"
+#include "base/android/jni_android.h"
+#include "base/bind.h"
+#include "net/test/embedded_test_server/android/embedded_test_server_android.h"
+
+namespace net {
+namespace test {
+
+bool OnJNIOnLoadInit() {
+ return base::android::OnJNIOnLoadInit();
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/test/android/net_test_jni_onload.h b/chromium/net/test/android/net_test_jni_onload.h
new file mode 100644
index 00000000000..35c734b8061
--- /dev/null
+++ b/chromium/net/test/android/net_test_jni_onload.h
@@ -0,0 +1,18 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TEST_ANDROID_NET_TEST_JNI_ONLOAD_H_
+#define NET_TEST_ANDROID_NET_TEST_JNI_ONLOAD_H_
+
+#include <jni.h>
+
+namespace net {
+namespace test {
+
+bool OnJNIOnLoadInit();
+
+} // namespace test
+} // namespace net
+
+#endif // NET_TEST_ANDROID_NET_TEST_JNI_ONLOAD_H_
diff --git a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc
index 16fe95014a8..6f6431e1a3a 100644
--- a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc
+++ b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.cc
@@ -56,8 +56,9 @@ EmbeddedTestServerAndroid::~EmbeddedTestServerAndroid() {
}
jboolean EmbeddedTestServerAndroid::Start(JNIEnv* env,
- const JavaParamRef<jobject>& jobj) {
- return test_server_.Start();
+ const JavaParamRef<jobject>& jobj,
+ jint port) {
+ return test_server_.Start(static_cast<int>(port));
}
ScopedJavaLocalRef<jstring> EmbeddedTestServerAndroid::GetRootCertPemPath(
diff --git a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h
index 7d96cec23b4..a3b22512dea 100644
--- a/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h
+++ b/chromium/net/test/embedded_test_server/android/embedded_test_server_android.h
@@ -28,7 +28,9 @@ class EmbeddedTestServerAndroid {
void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
- jboolean Start(JNIEnv* env, const base::android::JavaParamRef<jobject>& jobj);
+ jboolean Start(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& jobj,
+ jint port);
base::android::ScopedJavaLocalRef<jstring> GetRootCertPemPath(
JNIEnv* jenv,
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server.cc b/chromium/net/test/embedded_test_server/embedded_test_server.cc
index 3cd2e5c6afe..358d44e5f8e 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.cc
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.cc
@@ -89,15 +89,15 @@ void EmbeddedTestServer::SetConnectionListener(
connection_listener_ = listener;
}
-bool EmbeddedTestServer::Start() {
- bool success = InitializeAndListen();
+bool EmbeddedTestServer::Start(int port) {
+ bool success = InitializeAndListen(port);
if (!success)
return false;
StartAcceptingConnections();
return true;
}
-bool EmbeddedTestServer::InitializeAndListen() {
+bool EmbeddedTestServer::InitializeAndListen(int port) {
DCHECK(!Started());
const int max_tries = 5;
@@ -114,7 +114,8 @@ bool EmbeddedTestServer::InitializeAndListen() {
listen_socket_.reset(new TCPServerSocket(nullptr, NetLogSource()));
- int result = listen_socket_->ListenWithAddressAndPort("127.0.0.1", 0, 10);
+ int result =
+ listen_socket_->ListenWithAddressAndPort("127.0.0.1", port, 10);
if (result) {
LOG(ERROR) << "Listen failed: " << ErrorToString(result);
listen_socket_.reset();
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server.h b/chromium/net/test/embedded_test_server/embedded_test_server.h
index 2f273ae1f28..c663e1d12c3 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.h
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.h
@@ -145,11 +145,11 @@ class EmbeddedTestServer {
// This is the equivalent of calling InitializeAndListen() followed by
// StartAcceptingConnections().
// Returns whether a listening socket has been successfully created.
- bool Start() WARN_UNUSED_RESULT;
+ bool Start(int port = 0) WARN_UNUSED_RESULT;
// Starts listening for incoming connections but will not yet accept them.
// Returns whether a listening socket has been succesfully created.
- bool InitializeAndListen() WARN_UNUSED_RESULT;
+ bool InitializeAndListen(int port = 0) WARN_UNUSED_RESULT;
// Starts the Accept IO Thread and begins accepting connections.
void StartAcceptingConnections();
diff --git a/chromium/net/test/embedded_test_server/request_handler_util.cc b/chromium/net/test/embedded_test_server/request_handler_util.cc
index 3eff4f4ed9d..1d12833dcbc 100644
--- a/chromium/net/test/embedded_test_server/request_handler_util.cc
+++ b/chromium/net/test/embedded_test_server/request_handler_util.cc
@@ -32,6 +32,8 @@ const char kMockHttpHeadersExtension[] = "mock-http-headers";
std::string GetContentType(const base::FilePath& path) {
if (path.MatchesExtension(FILE_PATH_LITERAL(".crx")))
return "application/x-chrome-extension";
+ if (path.MatchesExtension(FILE_PATH_LITERAL(".css")))
+ return "text/css";
if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
return "application/octet-stream";
if (path.MatchesExtension(FILE_PATH_LITERAL(".gif")))
diff --git a/chromium/net/test/run_all_unittests.cc b/chromium/net/test/run_all_unittests.cc
index 5786dfea0aa..3e3eaf9ef3e 100644
--- a/chromium/net/test/run_all_unittests.cc
+++ b/chromium/net/test/run_all_unittests.cc
@@ -11,10 +11,7 @@
#include "net/socket/client_socket_pool_base.h"
#include "net/test/net_test_suite.h"
#include "url/url_features.h"
-
-#if !defined(OS_IOS)
#include "mojo/core/embedder/embedder.h" // nogncheck
-#endif
using net::internal::ClientSocketPoolBaseHelper;
@@ -57,9 +54,7 @@ int main(int argc, char** argv) {
NetTestSuite test_suite(argc, argv);
ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false);
-#if !defined(OS_IOS)
mojo::core::Init();
-#endif
return base::LaunchUnitTests(
argc, argv, base::Bind(&NetTestSuite::Run,
diff --git a/chromium/net/test/spawned_test_server/base_test_server.cc b/chromium/net/test/spawned_test_server/base_test_server.cc
index fb1163ee44e..0b5dd3cf604 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.cc
+++ b/chromium/net/test/spawned_test_server/base_test_server.cc
@@ -114,15 +114,6 @@ bool GetLocalCertificatesDir(const base::FilePath& certificates_dir,
return true;
}
-std::unique_ptr<base::ListValue> GetTokenBindingParams(
- std::vector<int> params) {
- std::unique_ptr<base::ListValue> values(new base::ListValue());
- for (int param : params) {
- values->AppendInteger(param);
- }
- return values;
-}
-
std::string OCSPStatusToString(
const BaseTestServer::SSLOptions::OCSPStatus& ocsp_status) {
switch (ocsp_status) {
@@ -417,9 +408,7 @@ bool BaseTestServer::GetFilePathWithReplacements(
std::string new_file_path = original_file_path;
bool first_query_parameter = true;
const std::vector<StringPair>::const_iterator end = text_to_replace.end();
- for (std::vector<StringPair>::const_iterator it = text_to_replace.begin();
- it != end;
- ++it) {
+ for (auto it = text_to_replace.begin(); it != end; ++it) {
const std::string& old_text = it->first;
const std::string& new_text = it->second;
std::string base64_old;
@@ -449,15 +438,23 @@ void BaseTestServer::RegisterTestCerts() {
bool BaseTestServer::LoadTestRootCert() const {
TestRootCerts* root_certs = TestRootCerts::GetInstance();
- if (!root_certs)
- return false;
+ DCHECK(root_certs);
// Should always use absolute path to load the root certificate.
base::FilePath root_certificate_path;
- if (!GetLocalCertificatesDir(certificates_dir_, &root_certificate_path))
+ if (!GetLocalCertificatesDir(certificates_dir_, &root_certificate_path)) {
+ LOG(ERROR) << "Could not get local certificates directory from "
+ << certificates_dir_ << ".";
+ return false;
+ }
+
+ if (!RegisterRootCertsInternal(root_certificate_path)) {
+ LOG(ERROR) << "Could not register root certificates from "
+ << root_certificate_path << ".";
return false;
+ }
- return RegisterRootCertsInternal(root_certificate_path);
+ return true;
}
scoped_refptr<X509Certificate> BaseTestServer::GetCertificate() const {
@@ -529,8 +526,10 @@ bool BaseTestServer::SetupWhenServerStarted() {
DCHECK(host_port_pair_.port());
DCHECK(!started_);
- if (UsingSSL(type_) && !LoadTestRootCert())
- return false;
+ if (UsingSSL(type_) && !LoadTestRootCert()) {
+ LOG(ERROR) << "Could not load test root certificate.";
+ return false;
+ }
started_ = true;
allowed_port_.reset(new ScopedPortException(host_port_pair_.port()));
@@ -719,13 +718,6 @@ bool BaseTestServer::GenerateArguments(base::DictionaryValue* arguments) const {
arguments->Set("disable-extended-master-secret",
std::make_unique<base::Value>());
}
- if (!ssl_options_.supported_token_binding_params.empty()) {
- std::unique_ptr<base::ListValue> token_binding_params(
- new base::ListValue());
- arguments->Set(
- "token-binding-params",
- GetTokenBindingParams(ssl_options_.supported_token_binding_params));
- }
}
return GenerateAdditionalArguments(arguments);
diff --git a/chromium/net/test/spawned_test_server/base_test_server.h b/chromium/net/test/spawned_test_server/base_test_server.h
index c5b71a51dba..da11ca28ba2 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.h
+++ b/chromium/net/test/spawned_test_server/base_test_server.h
@@ -342,9 +342,6 @@ class BaseTestServer {
// If true, disables extended master secret tls extension.
bool disable_extended_master_secret = false;
-
- // List of token binding params that the server supports and will negotiate.
- std::vector<int> supported_token_binding_params;
};
// Initialize a TestServer.
diff --git a/chromium/net/test/spawned_test_server/local_test_server.cc b/chromium/net/test/spawned_test_server/local_test_server.cc
index c4378a55334..e0522e0adf7 100644
--- a/chromium/net/test/spawned_test_server/local_test_server.cc
+++ b/chromium/net/test/spawned_test_server/local_test_server.cc
@@ -95,14 +95,20 @@ bool LocalTestServer::StartInBackground() {
// Get path to Python server script.
base::FilePath testserver_path;
- if (!GetTestServerPath(&testserver_path))
+ if (!GetTestServerPath(&testserver_path)) {
+ LOG(ERROR) << "Could not get test server path.";
return false;
+ }
- if (!SetPythonPath())
+ if (!SetPythonPath()) {
+ LOG(ERROR) << "Could not set Python path.";
return false;
+ }
- if (!LaunchPython(testserver_path))
+ if (!LaunchPython(testserver_path)) {
+ LOG(ERROR) << "Could not launch Python with path " << testserver_path;
return false;
+ }
return true;
}
@@ -201,8 +207,7 @@ bool LocalTestServer::AddCommandLineArguments(
const base::ListValue* list = NULL;
if (!value.GetAsList(&list) || !list || list->empty())
return false;
- for (base::ListValue::const_iterator list_it = list->begin();
- list_it != list->end(); ++list_it) {
+ for (auto list_it = list->begin(); list_it != list->end(); ++list_it) {
if (!AppendArgumentFromJSONValue(key, *list_it, command_line))
return false;
}
diff --git a/chromium/net/test/spawned_test_server/local_test_server_posix.cc b/chromium/net/test/spawned_test_server/local_test_server_posix.cc
index 0ba4ee34b71..dd601591a84 100644
--- a/chromium/net/test/spawned_test_server/local_test_server_posix.cc
+++ b/chromium/net/test/spawned_test_server/local_test_server_posix.cc
@@ -41,10 +41,8 @@ class OrphanedTestServerFilter : public base::ProcessFilter {
return false;
bool found_path_string = false;
bool found_port_string = false;
- for (std::vector<std::string>::const_iterator it =
- entry.cmd_line_args().begin();
- it != entry.cmd_line_args().end();
- ++it) {
+ for (auto it = entry.cmd_line_args().begin();
+ it != entry.cmd_line_args().end(); ++it) {
if (it->find(path_string_) != std::string::npos)
found_path_string = true;
if (it->find(port_string_) != std::string::npos)
diff --git a/chromium/net/test/spawned_test_server/remote_test_server_config.cc b/chromium/net/test/spawned_test_server/remote_test_server_config.cc
index 125ec6f8490..ac92e248652 100644
--- a/chromium/net/test/spawned_test_server/remote_test_server_config.cc
+++ b/chromium/net/test/spawned_test_server/remote_test_server_config.cc
@@ -29,7 +29,7 @@ base::FilePath GetTestServerConfigFilePath() {
#if defined(OS_ANDROID)
base::PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &dir);
#elif defined(OS_FUCHSIA)
- dir = base::FilePath("/data");
+ dir = base::FilePath("/test-shared");
#else
base::PathService::Get(base::DIR_TEMP, &dir);
#endif
diff --git a/chromium/net/test/url_request/url_request_slow_download_job.cc b/chromium/net/test/url_request/url_request_slow_download_job.cc
index dfba97ec634..72a2b5a5889 100644
--- a/chromium/net/test/url_request/url_request_slow_download_job.cc
+++ b/chromium/net/test/url_request/url_request_slow_download_job.cc
@@ -95,16 +95,14 @@ size_t URLRequestSlowDownloadJob::NumberOutstandingRequests() {
// static
void URLRequestSlowDownloadJob::FinishPendingRequests() {
- typedef std::set<URLRequestSlowDownloadJob*> JobList;
- for (JobList::iterator it = pending_requests_.Get().begin();
+ for (auto it = pending_requests_.Get().begin();
it != pending_requests_.Get().end(); ++it) {
(*it)->set_should_finish_download();
}
}
void URLRequestSlowDownloadJob::ErrorPendingRequests() {
- typedef std::set<URLRequestSlowDownloadJob*> JobList;
- for (JobList::iterator it = pending_requests_.Get().begin();
+ for (auto it = pending_requests_.Get().begin();
it != pending_requests_.Get().end(); ++it) {
(*it)->set_should_error_download();
}