| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.net.test; |
| 6 |
| 7 import android.content.ComponentName; |
| 8 import android.content.Context; |
| 9 import android.content.Intent; |
| 10 import android.content.ServiceConnection; |
| 11 import android.os.Environment; |
| 12 import android.os.IBinder; |
| 13 import android.os.RemoteException; |
| 14 |
| 15 import org.chromium.base.Log; |
| 16 |
| 17 import java.io.File; |
| 18 |
| 19 /** A simple file server for java android webview tests which extends |
| 20 * from class EmbeddedTestServer. It is able to add custom handlers |
| 21 * which registers with net::test_server::EmbeddedTestServer native code. |
| 22 * |
| 23 * An example use: |
| 24 * AwEmbeddedTestServer s = new AwEmbeddedTestServer(); |
| 25 * s.initializeNative(); |
| 26 * s.serveFilesFromDirectory("/path/to/my/directory"); |
| 27 * if (!s.start()) { |
| 28 * throw new SomeKindOfException("Unable to initialize EmbeddedTestServer.
"); |
| 29 * } |
| 30 * |
| 31 * // serve requests... |
| 32 * s.getURL("/foo/bar.txt"); |
| 33 * |
| 34 * s.shutdownAndWait(); |
| 35 * s.destroy(); |
| 36 * |
| 37 * Note that this runs net::test_server::EmbeddedTestServer in a service in a se
parate APK. |
| 38 */ |
| 39 public class AwEmbeddedTestServer { |
| 40 private static final String TAG = "cr_TestServer"; |
| 41 |
| 42 private static final String AW_EMBEDDED_TEST_SERVER_SERVICE = |
| 43 "org.chromium.net.test.AW_EMBEDDED_TEST_SERVER_SERVICE"; |
| 44 private static final long SERVICE_CONNECTION_WAIT_INTERVAL_MS = 5000; |
| 45 private static long[] sCustomHandlers; |
| 46 |
| 47 private IAwEmbeddedTestServerImpl mImpl; |
| 48 private ServiceConnection mConn = new ServiceConnection() { |
| 49 @Override |
| 50 public void onServiceConnected(ComponentName name, IBinder service) { |
| 51 synchronized (mImplMonitor) { |
| 52 mImpl = IAwEmbeddedTestServerImpl.Stub.asInterface(service); |
| 53 mImplMonitor.notify(); |
| 54 } |
| 55 } |
| 56 |
| 57 @Override |
| 58 public void onServiceDisconnected(ComponentName name) { |
| 59 synchronized (mImplMonitor) { |
| 60 mImpl = null; |
| 61 mImplMonitor.notify(); |
| 62 } |
| 63 } |
| 64 }; |
| 65 |
| 66 private Context mContext; |
| 67 private final Object mImplMonitor = new Object(); |
| 68 |
| 69 /** |
| 70 * Exception class raised on failure in the EmbeddedTestServer. |
| 71 */ |
| 72 public static final class EmbeddedTestServerFailure extends Error { |
| 73 public EmbeddedTestServerFailure(String errorDesc) { |
| 74 super(errorDesc); |
| 75 } |
| 76 |
| 77 public EmbeddedTestServerFailure(String errorDesc, Throwable cause) { |
| 78 super(errorDesc, cause); |
| 79 } |
| 80 } |
| 81 |
| 82 /** Bind the service that will run the native server object. |
| 83 * |
| 84 * @param context The context to use to bind the service. This will also be
used to unbind |
| 85 # the service at server destruction time. |
| 86 */ |
| 87 public void initializeNative(Context context) throws InterruptedException { |
| 88 mContext = context; |
| 89 |
| 90 Intent intent = new Intent(AW_EMBEDDED_TEST_SERVER_SERVICE); |
| 91 intent.setClassName("org.chromium.net.test.awsupport", |
| 92 "org.chromium.net.test.AwEmbeddedTestServerService"); |
| 93 if (!mContext.bindService(intent, mConn, Context.BIND_AUTO_CREATE)) { |
| 94 throw new EmbeddedTestServerFailure( |
| 95 "Unable to bind to the EmbeddedTestServer service."); |
| 96 } |
| 97 synchronized (mImplMonitor) { |
| 98 Log.i(TAG, "Waiting for AEmbeddedTestServer service connection."); |
| 99 while (mImpl == null) { |
| 100 mImplMonitor.wait(SERVICE_CONNECTION_WAIT_INTERVAL_MS); |
| 101 Log.i(TAG, "Still waiting for EmbeddedTestServer service connect
ion."); |
| 102 } |
| 103 Log.i(TAG, "EmbeddedTestServer service connected."); |
| 104 boolean initialized = false; |
| 105 try { |
| 106 initialized = mImpl.initializeNative(); |
| 107 } catch (RemoteException e) { |
| 108 Log.e(TAG, "Failed to initialize native server.", e); |
| 109 initialized = false; |
| 110 } |
| 111 |
| 112 if (!initialized) { |
| 113 throw new EmbeddedTestServerFailure("Failed to initialize native
server."); |
| 114 } |
| 115 } |
| 116 } |
| 117 |
| 118 public long[] getsCustomHandlers() { |
| 119 try { |
| 120 synchronized (mImplMonitor) { |
| 121 checkServiceLocked(); |
| 122 return mImpl.getsCustomHandlers(); |
| 123 } |
| 124 } catch (RemoteException e) { |
| 125 throw new EmbeddedTestServerFailure("Failed to get custom handlers."
, e); |
| 126 } |
| 127 } |
| 128 |
| 129 /** Add the default handlers and serve files from the provided directory rel
ative to the |
| 130 * external storage directory. |
| 131 * |
| 132 * @param directory The directory from which files should be served relativ
e to the external |
| 133 * storage directory. |
| 134 */ |
| 135 public void addDefaultHandlers(File directory) { |
| 136 addDefaultHandlers(directory.getPath()); |
| 137 } |
| 138 |
| 139 /** Add the default handlers and serve files from the provided directory rel
ative to the |
| 140 * external storage directory. |
| 141 * |
| 142 * @param directoryPath The path of the directory from which files should b
e served relative |
| 143 * to the external storage directory. |
| 144 */ |
| 145 public void addDefaultHandlers(String directoryPath) { |
| 146 try { |
| 147 synchronized (mImplMonitor) { |
| 148 checkServiceLocked(); |
| 149 mImpl.addDefaultHandlers(directoryPath); |
| 150 } |
| 151 } catch (RemoteException e) { |
| 152 throw new EmbeddedTestServerFailure( |
| 153 "Failed to add default handlers and start serving files from
" + directoryPath |
| 154 + ": " + e.toString()); |
| 155 } |
| 156 } |
| 157 |
| 158 /** Register multiple request handlers. |
| 159 * Handlers must be registered before starting the server. |
| 160 * |
| 161 * @param handlers The pointers of handlers to be registered. |
| 162 */ |
| 163 public void registerRequestHandlers(final long[] handlers) { |
| 164 try { |
| 165 synchronized (mImplMonitor) { |
| 166 checkServiceLocked(); |
| 167 mImpl.registerRequestHandlers(handlers); |
| 168 } |
| 169 } catch (RemoteException e) { |
| 170 throw new EmbeddedTestServerFailure("Failed to add request handlers:
" + e.toString()); |
| 171 } |
| 172 } |
| 173 |
| 174 /** Serve files from the provided directory. |
| 175 * |
| 176 * @param directory The directory from which files should be served. |
| 177 */ |
| 178 public void serveFilesFromDirectory(File directory) { |
| 179 serveFilesFromDirectory(directory.getPath()); |
| 180 } |
| 181 |
| 182 /** Serve files from the provided directory. |
| 183 * |
| 184 * @param directoryPath The path of the directory from which files should b
e served. |
| 185 */ |
| 186 public void serveFilesFromDirectory(String directoryPath) { |
| 187 try { |
| 188 synchronized (mImplMonitor) { |
| 189 checkServiceLocked(); |
| 190 mImpl.serveFilesFromDirectory(directoryPath); |
| 191 } |
| 192 } catch (RemoteException e) { |
| 193 throw new EmbeddedTestServerFailure( |
| 194 "Failed to start serving files from " + directoryPath + ": "
+ e.toString()); |
| 195 } |
| 196 } |
| 197 |
| 198 private void checkServiceLocked() { |
| 199 if (mImpl == null) { |
| 200 throw new EmbeddedTestServerFailure("Service disconnected."); |
| 201 } |
| 202 } |
| 203 |
| 204 /** Starts the server. |
| 205 * |
| 206 * Note that this should be called after handlers are set up, including any
relevant calls |
| 207 * serveFilesFromDirectory. |
| 208 * |
| 209 * @return Whether the server was successfully initialized. |
| 210 */ |
| 211 public boolean start() { |
| 212 try { |
| 213 synchronized (mImplMonitor) { |
| 214 checkServiceLocked(); |
| 215 return mImpl.start(); |
| 216 } |
| 217 } catch (RemoteException e) { |
| 218 throw new EmbeddedTestServerFailure("Failed to start server.", e); |
| 219 } |
| 220 } |
| 221 |
| 222 /** Create and initialize a server that serves files from the provided direc
tory. |
| 223 * |
| 224 * This handles native object initialization, server configuration, and ser
ver initialization. |
| 225 * On returning, the server is ready for use. |
| 226 * |
| 227 * @param context The context in which the server will run. |
| 228 * @param directory The directory from which files should be served. This m
ust be |
| 229 * Environment.getExternalStorageDirectory(). |
| 230 * @return The created server. |
| 231 */ |
| 232 public static AwEmbeddedTestServer createAndStartFileServer(Context context,
File directory) |
| 233 throws InterruptedException { |
| 234 // TODO(jbudorick): Update all callers to use createAndStartServer() dir
ectly. |
| 235 if (!directory.equals(Environment.getExternalStorageDirectory())) { |
| 236 throw new IllegalArgumentException("Expected directory to be Externa
lStorageDirectory"); |
| 237 } |
| 238 return createAndStartServer(context); |
| 239 } |
| 240 |
| 241 /** Create and initialize a server with the default handlers. |
| 242 * |
| 243 * This handles native object initialization, server configuration, and ser
ver initialization. |
| 244 * On returning, the server is ready for use. |
| 245 * |
| 246 * @param context The context in which the server will run. |
| 247 * @return The created server. |
| 248 */ |
| 249 public static AwEmbeddedTestServer createAndStartDefaultServer(Context conte
xt) |
| 250 throws InterruptedException { |
| 251 // TODO(pkotwicz): Update all callers to use createAndStartServer() dire
ctly. |
| 252 return createAndStartServer(context); |
| 253 } |
| 254 |
| 255 /** Create and initialize a server with the default and custom handlers. |
| 256 * |
| 257 * This handles native object initialization, server configuration, and ser
ver initialization. |
| 258 * On returning, the server is ready for use. |
| 259 * |
| 260 * @param context The context in which the server will run. |
| 261 * @return The created server. |
| 262 */ |
| 263 public static AwEmbeddedTestServer createAndStartServer(Context context) |
| 264 throws InterruptedException { |
| 265 AwEmbeddedTestServer server = new AwEmbeddedTestServer(); |
| 266 server.initializeNative(context); |
| 267 AwEmbeddedTestServer.sCustomHandlers = server.getsCustomHandlers(); |
| 268 server.addDefaultHandlers(""); |
| 269 server.registerRequestHandlers(sCustomHandlers); |
| 270 if (!server.start()) { |
| 271 throw new EmbeddedTestServerFailure( |
| 272 "Failed to start serving using default or custom handlers.")
; |
| 273 } |
| 274 return server; |
| 275 } |
| 276 |
| 277 /** Get the full URL for the given relative URL. |
| 278 * |
| 279 * @param relativeUrl The relative URL for which a full URL will be obtaine
d. |
| 280 * @return The URL as a String. |
| 281 */ |
| 282 public String getURL(String relativeUrl) { |
| 283 try { |
| 284 synchronized (mImplMonitor) { |
| 285 checkServiceLocked(); |
| 286 return mImpl.getURL(relativeUrl); |
| 287 } |
| 288 } catch (RemoteException e) { |
| 289 throw new EmbeddedTestServerFailure("Failed to get URL for " + relat
iveUrl, e); |
| 290 } |
| 291 } |
| 292 |
| 293 /** Shutdown the server. |
| 294 * |
| 295 * @return Whether the server was successfully shut down. |
| 296 */ |
| 297 public boolean shutdownAndWaitUntilComplete() { |
| 298 try { |
| 299 synchronized (mImplMonitor) { |
| 300 checkServiceLocked(); |
| 301 return mImpl.shutdownAndWaitUntilComplete(); |
| 302 } |
| 303 } catch (RemoteException e) { |
| 304 throw new EmbeddedTestServerFailure("Failed to shut down.", e); |
| 305 } |
| 306 } |
| 307 |
| 308 /** Destroy the native EmbeddedTestServer object. */ |
| 309 public void destroy() { |
| 310 try { |
| 311 synchronized (mImplMonitor) { |
| 312 checkServiceLocked(); |
| 313 mImpl.destroy(); |
| 314 } |
| 315 } catch (RemoteException e) { |
| 316 throw new EmbeddedTestServerFailure("Failed to destroy native server
.", e); |
| 317 } finally { |
| 318 mContext.unbindService(mConn); |
| 319 } |
| 320 } |
| 321 |
| 322 /** Stop and destroy the server. |
| 323 * |
| 324 * This handles stopping the server and destroying the native object. |
| 325 */ |
| 326 public void stopAndDestroyServer() { |
| 327 if (!shutdownAndWaitUntilComplete()) { |
| 328 throw new EmbeddedTestServerFailure("Failed to stop server."); |
| 329 } |
| 330 destroy(); |
| 331 } |
| 332 } |
| OLD | NEW |