Index: components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
diff --git a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
index 05f933fed38ff8f74fd9942190623386aaed1ca9..9ec0f9efd78fd3d8783e2fcec3c1de41cf0c6b2c 100644 |
--- a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
+++ b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
@@ -47,22 +47,40 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
private IOException mSinkException; |
private volatile boolean mStarted; |
private volatile boolean mCanceled; |
- private volatile boolean mRecycled; |
private volatile boolean mFinished; |
private boolean mHeadersAvailable; |
- private String mContentType; |
private long mUploadContentLength; |
private final HttpUrlRequestListener mListener; |
private boolean mBufferFullResponse; |
private long mOffset; |
- private long mContentLength; |
private long mContentLengthLimit; |
private boolean mCancelIfContentLengthOverLimit; |
private boolean mContentLengthOverLimit; |
private boolean mSkippingToOffset; |
private long mSize; |
+ |
// Indicates whether redirects have been disabled. |
private boolean mDisableRedirects; |
+ |
+ // Http status code. Default to 0. Populated in onResponseStarted(). |
+ private int mHttpStatusCode = 0; |
+ |
+ // Http status text. Default to null. Populated in onResponseStarted(). |
+ private String mHttpStatusText; |
+ |
+ // Content type. Default to null. Populated in onResponseStarted(). |
+ private String mContentType; |
+ |
+ // Compressed content length as reported by the server. Populated in onResponseStarted(). |
+ private long mContentLength; |
+ |
+ // Native error code. Default to no error. Populated in onRequestComplete(). |
+ private int mErrorCode = ChromiumUrlRequestError.SUCCESS; |
+ |
+ // Native error string. Default to null. Populated in onRequestComplete(). |
+ private String mErrorString; |
+ |
+ // Protects access of mUrlRequestAdapter, mStarted, mCanceled, and mFinished. |
private final Object mLock = new Object(); |
public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, |
@@ -132,26 +150,24 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
@Override |
public int getHttpStatusCode() { |
- int httpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter); |
- |
// TODO(mef): Investigate the following: |
// If we have been able to successfully resume a previously interrupted |
// download, the status code will be 206, not 200. Since the rest of the |
// application is expecting 200 to indicate success, we need to fake it. |
- if (httpStatusCode == 206) { |
- httpStatusCode = 200; |
+ if (mHttpStatusCode == 206) { |
+ return 200; |
} |
- return httpStatusCode; |
+ return mHttpStatusCode; |
} |
@Override |
public String getHttpStatusText() { |
- return nativeGetHttpStatusText(mUrlRequestAdapter); |
+ return mHttpStatusText; |
} |
/** |
- * Returns an exception if any, or null if the request was completed |
- * successfully. |
+ * Returns an exception if any, or null if the request has not completed or |
+ * completed successfully. |
*/ |
@Override |
public IOException getException() { |
@@ -159,18 +175,14 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
return mSinkException; |
} |
- validateNotRecycled(); |
- |
- int errorCode = nativeGetErrorCode(mUrlRequestAdapter); |
- switch (errorCode) { |
+ switch (mErrorCode) { |
case ChromiumUrlRequestError.SUCCESS: |
if (mContentLengthOverLimit) { |
return new ResponseTooLargeException(); |
} |
return null; |
case ChromiumUrlRequestError.UNKNOWN: |
- return new IOException( |
- nativeGetErrorString(mUrlRequestAdapter)); |
+ return new IOException(mErrorString); |
case ChromiumUrlRequestError.MALFORMED_URL: |
return new MalformedURLException("Malformed URL: " + mUrl); |
case ChromiumUrlRequestError.CONNECTION_TIMED_OUT: |
@@ -188,7 +200,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
+ "many redirects or redirects have been disabled"); |
default: |
throw new IllegalStateException( |
- "Unrecognized error code: " + errorCode); |
+ "Unrecognized error code: " + mErrorCode); |
} |
} |
@@ -317,9 +329,12 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
@Override |
public void disableRedirects() { |
- mDisableRedirects = true; |
- validateNotStarted(); |
- nativeDisableRedirects(mUrlRequestAdapter); |
+ synchronized (mLock) { |
+ validateNotStarted(); |
+ validateNativeAdapterNotDestroyed(); |
+ mDisableRedirects = true; |
+ nativeDisableRedirects(mUrlRequestAdapter); |
+ } |
} |
public WritableByteChannel getSink() { |
@@ -334,7 +349,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
} |
validateNotStarted(); |
- validateNotRecycled(); |
+ validateNativeAdapterNotDestroyed(); |
mStarted = true; |
@@ -384,7 +399,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
mCanceled = true; |
- if (!mRecycled) { |
+ if (mUrlRequestAdapter != 0) { |
nativeCancel(mUrlRequestAdapter); |
} |
} |
@@ -397,17 +412,13 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
} |
} |
- public boolean isRecycled() { |
- synchronized (mLock) { |
- return mRecycled; |
- } |
- } |
- |
@Override |
public String getNegotiatedProtocol() { |
- validateNotRecycled(); |
- validateHeadersAvailable(); |
- return nativeGetNegotiatedProtocol(mUrlRequestAdapter); |
+ synchronized (mLock) { |
+ validateNativeAdapterNotDestroyed(); |
+ validateHeadersAvailable(); |
+ return nativeGetNegotiatedProtocol(mUrlRequestAdapter); |
+ } |
} |
@Override |
@@ -417,19 +428,23 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
@Override |
public String getHeader(String name) { |
- validateNotRecycled(); |
- validateHeadersAvailable(); |
- return nativeGetHeader(mUrlRequestAdapter, name); |
+ synchronized (mLock) { |
+ validateNativeAdapterNotDestroyed(); |
+ validateHeadersAvailable(); |
+ return nativeGetHeader(mUrlRequestAdapter, name); |
+ } |
} |
// All response headers. |
@Override |
public Map<String, List<String>> getAllHeaders() { |
- validateNotRecycled(); |
- validateHeadersAvailable(); |
- ResponseHeadersMap result = new ResponseHeadersMap(); |
- nativeGetAllHeaders(mUrlRequestAdapter, result); |
- return result; |
+ synchronized (mLock) { |
+ validateNativeAdapterNotDestroyed(); |
+ validateHeadersAvailable(); |
+ ResponseHeadersMap result = new ResponseHeadersMap(); |
+ nativeGetAllHeaders(mUrlRequestAdapter, result); |
+ return result; |
+ } |
} |
@Override |
@@ -463,12 +478,23 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
* A callback invoked when the response has been fully consumed. |
*/ |
private void onRequestComplete() { |
+ mErrorCode = nativeGetErrorCode(mUrlRequestAdapter); |
+ mErrorString = nativeGetErrorString(mUrlRequestAdapter); |
+ // When there is an error or redirects have been disabled, |
+ // onResponseStarted is often not invoked. |
+ // Populate status code and status text if that's the case. |
+ // Note that besides redirects, these two fields may be set on the |
+ // request for AUTH and CERT requests. |
+ if (mErrorCode != ChromiumUrlRequestError.SUCCESS) { |
+ mHttpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter); |
+ mHttpStatusText = nativeGetHttpStatusText(mUrlRequestAdapter); |
+ } |
mListener.onRequestComplete(this); |
} |
- private void validateNotRecycled() { |
- if (mRecycled) { |
- throw new IllegalStateException("Accessing recycled request"); |
+ private void validateNativeAdapterNotDestroyed() { |
+ if (mUrlRequestAdapter == 0) { |
+ throw new IllegalStateException("Adapter has been destroyed"); |
} |
} |
@@ -515,6 +541,8 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
@CalledByNative |
private void onResponseStarted() { |
try { |
+ mHttpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter); |
+ mHttpStatusText = nativeGetHttpStatusText(mUrlRequestAdapter); |
mContentType = nativeGetContentType(mUrlRequestAdapter); |
mContentLength = nativeGetContentLength(mUrlRequestAdapter); |
mHeadersAvailable = true; |
@@ -536,7 +564,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
// The server may ignore the request for a byte range, in which |
// case status code will be 200, instead of 206. Note that we |
// cannot call getHttpStatusCode as it rewrites 206 into 200. |
- if (nativeGetHttpStatusCode(mUrlRequestAdapter) == 200) { |
+ if (mHttpStatusCode == 200) { |
// TODO(mef): Revisit this logic. |
if (mContentLength != -1) { |
mContentLength -= mOffset; |
@@ -607,7 +635,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
} |
mFinished = true; |
- if (mRecycled) { |
+ if (mUrlRequestAdapter == 0) { |
return; |
} |
try { |
@@ -625,7 +653,6 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
onRequestComplete(); |
nativeDestroyRequestAdapter(mUrlRequestAdapter); |
mUrlRequestAdapter = 0; |
- mRecycled = true; |
} |
} catch (Exception e) { |
mSinkException = new IOException("Exception in finish", e); |