| 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);
|
|
|