Process synchronous requests in the same RequestQueue.
Use a dedicated Connection to process a synchronous request using the main
RequestQueue and on the WebCore thread.
HttpConnection, HttpsConnection, Connection:
No need for ConnectionManager, just pass the proxy host to
HttpsConnection. In Connection.clearPipe, empty should be set to true if the
RequestFeeder does _not_ have a request for the host. I don't think that
broke anything but it is incorrect.
ConnectionThread:
Refactor the proxy selection into ConnectionManager.getConnection
RequestHandle:
Add a new constructor that takes a Connection argument. Add processRequest
to process a single request on that Connection.
RequestQueue:
Add determine host to select between the request's host and the proxy. Add
queueSynchronousRequest to make a new request that operates on a private
connection. Add SyncFeeder to handle RequestFeeder.requeueRequest if the
request fails.
Network: Use the new RequestQueue api to handle a synchronous request.
Bug: 1315832
This commit is contained in:
@@ -94,7 +94,6 @@ abstract class Connection {
|
||||
*/
|
||||
private static final String HTTP_CONNECTION = "http.connection";
|
||||
|
||||
RequestQueue.ConnectionManager mConnectionManager;
|
||||
RequestFeeder mRequestFeeder;
|
||||
|
||||
/**
|
||||
@@ -104,11 +103,9 @@ abstract class Connection {
|
||||
private byte[] mBuf;
|
||||
|
||||
protected Connection(Context context, HttpHost host,
|
||||
RequestQueue.ConnectionManager connectionManager,
|
||||
RequestFeeder requestFeeder) {
|
||||
mContext = context;
|
||||
mHost = host;
|
||||
mConnectionManager = connectionManager;
|
||||
mRequestFeeder = requestFeeder;
|
||||
|
||||
mCanPersist = false;
|
||||
@@ -124,18 +121,15 @@ abstract class Connection {
|
||||
* necessary
|
||||
*/
|
||||
static Connection getConnection(
|
||||
Context context, HttpHost host,
|
||||
RequestQueue.ConnectionManager connectionManager,
|
||||
Context context, HttpHost host, HttpHost proxy,
|
||||
RequestFeeder requestFeeder) {
|
||||
|
||||
if (host.getSchemeName().equals("http")) {
|
||||
return new HttpConnection(context, host, connectionManager,
|
||||
requestFeeder);
|
||||
return new HttpConnection(context, host, requestFeeder);
|
||||
}
|
||||
|
||||
// Otherwise, default to https
|
||||
return new HttpsConnection(context, host, connectionManager,
|
||||
requestFeeder);
|
||||
return new HttpsConnection(context, host, proxy, requestFeeder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -338,7 +332,7 @@ abstract class Connection {
|
||||
mRequestFeeder.requeueRequest(tReq);
|
||||
empty = false;
|
||||
}
|
||||
if (empty) empty = mRequestFeeder.haveRequest(mHost);
|
||||
if (empty) empty = !mRequestFeeder.haveRequest(mHost);
|
||||
}
|
||||
return empty;
|
||||
}
|
||||
|
||||
@@ -108,24 +108,11 @@ class ConnectionThread extends Thread {
|
||||
if (HttpLog.LOGV) HttpLog.v("ConnectionThread: new request " +
|
||||
request.mHost + " " + request );
|
||||
|
||||
HttpHost proxy = mConnectionManager.getProxyHost();
|
||||
|
||||
HttpHost host;
|
||||
if (false) {
|
||||
// Allow https proxy
|
||||
host = proxy == null ? request.mHost : proxy;
|
||||
} else {
|
||||
// Disallow https proxy -- tmob proxy server
|
||||
// serves a request loop for https reqs
|
||||
host = (proxy == null ||
|
||||
request.mHost.getSchemeName().equals("https")) ?
|
||||
request.mHost : proxy;
|
||||
}
|
||||
mConnection = mConnectionManager.getConnection(mContext, host);
|
||||
mConnection = mConnectionManager.getConnection(mContext,
|
||||
request.mHost);
|
||||
mConnection.processRequests(request);
|
||||
if (mConnection.getCanPersist()) {
|
||||
if (!mConnectionManager.recycleConnection(host,
|
||||
mConnection)) {
|
||||
if (!mConnectionManager.recycleConnection(mConnection)) {
|
||||
mConnection.closeConnection();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -35,9 +35,8 @@ import org.apache.http.params.HttpConnectionParams;
|
||||
class HttpConnection extends Connection {
|
||||
|
||||
HttpConnection(Context context, HttpHost host,
|
||||
RequestQueue.ConnectionManager connectionManager,
|
||||
RequestFeeder requestFeeder) {
|
||||
super(context, host, connectionManager, requestFeeder);
|
||||
super(context, host, requestFeeder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -131,13 +131,16 @@ public class HttpsConnection extends Connection {
|
||||
*/
|
||||
private boolean mAborted = false;
|
||||
|
||||
// Used when connecting through a proxy.
|
||||
private HttpHost mProxyHost;
|
||||
|
||||
/**
|
||||
* Contructor for a https connection.
|
||||
*/
|
||||
HttpsConnection(Context context, HttpHost host,
|
||||
RequestQueue.ConnectionManager connectionManager,
|
||||
HttpsConnection(Context context, HttpHost host, HttpHost proxy,
|
||||
RequestFeeder requestFeeder) {
|
||||
super(context, host, connectionManager, requestFeeder);
|
||||
super(context, host, requestFeeder);
|
||||
mProxyHost = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,8 +162,7 @@ public class HttpsConnection extends Connection {
|
||||
AndroidHttpClientConnection openConnection(Request req) throws IOException {
|
||||
SSLSocket sslSock = null;
|
||||
|
||||
HttpHost proxyHost = mConnectionManager.getProxyHost();
|
||||
if (proxyHost != null) {
|
||||
if (mProxyHost != null) {
|
||||
// If we have a proxy set, we first send a CONNECT request
|
||||
// to the proxy; if the proxy returns 200 OK, we negotiate
|
||||
// a secure connection to the target server via the proxy.
|
||||
@@ -172,7 +174,7 @@ public class HttpsConnection extends Connection {
|
||||
Socket proxySock = null;
|
||||
try {
|
||||
proxySock = new Socket
|
||||
(proxyHost.getHostName(), proxyHost.getPort());
|
||||
(mProxyHost.getHostName(), mProxyHost.getPort());
|
||||
|
||||
proxySock.setSoTimeout(60 * 1000);
|
||||
|
||||
|
||||
@@ -42,15 +42,13 @@ public class RequestHandle {
|
||||
private WebAddress mUri;
|
||||
private String mMethod;
|
||||
private Map<String, String> mHeaders;
|
||||
|
||||
private RequestQueue mRequestQueue;
|
||||
|
||||
private Request mRequest;
|
||||
|
||||
private InputStream mBodyProvider;
|
||||
private int mBodyLength;
|
||||
|
||||
private int mRedirectCount = 0;
|
||||
// Used only with synchronous requests.
|
||||
private Connection mConnection;
|
||||
|
||||
private final static String AUTHORIZATION_HEADER = "Authorization";
|
||||
private final static String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization";
|
||||
@@ -80,6 +78,19 @@ public class RequestHandle {
|
||||
mRequest = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new request session with a given Connection. This connection
|
||||
* is used during a synchronous load to handle this request.
|
||||
*/
|
||||
public RequestHandle(RequestQueue requestQueue, String url, WebAddress uri,
|
||||
String method, Map<String, String> headers,
|
||||
InputStream bodyProvider, int bodyLength, Request request,
|
||||
Connection conn) {
|
||||
this(requestQueue, url, uri, method, headers, bodyProvider, bodyLength,
|
||||
request);
|
||||
mConnection = conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels this request
|
||||
*/
|
||||
@@ -262,6 +273,12 @@ public class RequestHandle {
|
||||
mRequest.waitUntilComplete();
|
||||
}
|
||||
|
||||
public void processRequest() {
|
||||
if (mConnection != null) {
|
||||
mConnection.processRequests(mRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Digest-scheme authentication response.
|
||||
*/
|
||||
|
||||
@@ -171,16 +171,17 @@ public class RequestQueue implements RequestFeeder {
|
||||
}
|
||||
|
||||
public Connection getConnection(Context context, HttpHost host) {
|
||||
host = RequestQueue.this.determineHost(host);
|
||||
Connection con = mIdleCache.getConnection(host);
|
||||
if (con == null) {
|
||||
mTotalConnection++;
|
||||
con = Connection.getConnection(
|
||||
mContext, host, this, RequestQueue.this);
|
||||
con = Connection.getConnection(mContext, host, mProxyHost,
|
||||
RequestQueue.this);
|
||||
}
|
||||
return con;
|
||||
}
|
||||
public boolean recycleConnection(HttpHost host, Connection connection) {
|
||||
return mIdleCache.cacheConnection(host, connection);
|
||||
public boolean recycleConnection(Connection connection) {
|
||||
return mIdleCache.cacheConnection(connection.getHost(), connection);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -342,6 +343,66 @@ public class RequestQueue implements RequestFeeder {
|
||||
req);
|
||||
}
|
||||
|
||||
private static class SyncFeeder implements RequestFeeder {
|
||||
// This is used in the case where the request fails and needs to be
|
||||
// requeued into the RequestFeeder.
|
||||
private Request mRequest;
|
||||
SyncFeeder() {
|
||||
}
|
||||
public Request getRequest() {
|
||||
Request r = mRequest;
|
||||
mRequest = null;
|
||||
return r;
|
||||
}
|
||||
public Request getRequest(HttpHost host) {
|
||||
return getRequest();
|
||||
}
|
||||
public boolean haveRequest(HttpHost host) {
|
||||
return mRequest != null;
|
||||
}
|
||||
public void requeueRequest(Request r) {
|
||||
mRequest = r;
|
||||
}
|
||||
}
|
||||
|
||||
public RequestHandle queueSynchronousRequest(String url, WebAddress uri,
|
||||
String method, Map<String, String> headers,
|
||||
EventHandler eventHandler, InputStream bodyProvider,
|
||||
int bodyLength) {
|
||||
if (HttpLog.LOGV) {
|
||||
HttpLog.v("RequestQueue.dispatchSynchronousRequest " + uri);
|
||||
}
|
||||
|
||||
HttpHost host = new HttpHost(uri.mHost, uri.mPort, uri.mScheme);
|
||||
|
||||
Request req = new Request(method, host, mProxyHost, uri.mPath,
|
||||
bodyProvider, bodyLength, eventHandler, headers);
|
||||
|
||||
// Open a new connection that uses our special RequestFeeder
|
||||
// implementation.
|
||||
host = determineHost(host);
|
||||
Connection conn = Connection.getConnection(mContext, host, mProxyHost,
|
||||
new SyncFeeder());
|
||||
|
||||
// TODO: I would like to process the request here but LoadListener
|
||||
// needs a RequestHandle to process some messages.
|
||||
return new RequestHandle(this, url, uri, method, headers, bodyProvider,
|
||||
bodyLength, req, conn);
|
||||
|
||||
}
|
||||
|
||||
// Chooses between the proxy and the request's host.
|
||||
private HttpHost determineHost(HttpHost host) {
|
||||
// There used to be a comment in ConnectionThread about t-mob's proxy
|
||||
// being really bad about https. But, HttpsConnection actually looks
|
||||
// for a proxy and connects through it anyway. I think that this check
|
||||
// is still valid because if a site is https, we will use
|
||||
// HttpsConnection rather than HttpConnection if the proxy address is
|
||||
// not secure.
|
||||
return (mProxyHost == null || "https".equals(host.getSchemeName()))
|
||||
? host : mProxyHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff there are any non-active requests pending
|
||||
*/
|
||||
@@ -478,6 +539,6 @@ public class RequestQueue implements RequestFeeder {
|
||||
interface ConnectionManager {
|
||||
HttpHost getProxyHost();
|
||||
Connection getConnection(Context context, HttpHost host);
|
||||
boolean recycleConnection(HttpHost host, Connection connection);
|
||||
boolean recycleConnection(Connection connection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,20 +180,24 @@ class Network {
|
||||
}
|
||||
|
||||
RequestQueue q = mRequestQueue;
|
||||
RequestHandle handle = null;
|
||||
if (loader.isSynchronous()) {
|
||||
q = new RequestQueue(loader.getContext(), 1);
|
||||
}
|
||||
|
||||
RequestHandle handle = q.queueRequest(
|
||||
url, loader.getWebAddress(), method, headers, loader,
|
||||
bodyProvider, bodyLength);
|
||||
loader.attachRequestHandle(handle);
|
||||
|
||||
if (loader.isSynchronous()) {
|
||||
handle.waitUntilComplete();
|
||||
handle = q.queueSynchronousRequest(url, loader.getWebAddress(),
|
||||
method, headers, loader, bodyProvider, bodyLength);
|
||||
loader.attachRequestHandle(handle);
|
||||
handle.processRequest();
|
||||
loader.loadSynchronousMessages();
|
||||
q.shutdown();
|
||||
} else {
|
||||
handle = q.queueRequest(url, loader.getWebAddress(), method,
|
||||
headers, loader, bodyProvider, bodyLength);
|
||||
// FIXME: Although this is probably a rare condition, normal network
|
||||
// requests are processed in a separate thread. This means that it
|
||||
// is possible to process part of the request before setting the
|
||||
// request handle on the loader. We should probably refactor this to
|
||||
// ensure the handle is attached before processing begins.
|
||||
loader.attachRequestHandle(handle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user