Chromium Code Reviews| 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..dd086958d32ccb243a3b959f5a4af7cc4d8b8344 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); |
| } |
| } |
| @@ -334,7 +346,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| } |
| validateNotStarted(); |
| - validateNotRecycled(); |
| + validateNativeAdapterNotDestroyed(); |
| mStarted = true; |
| @@ -384,7 +396,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| mCanceled = true; |
| - if (!mRecycled) { |
| + if (mUrlRequestAdapter != 0) { |
| nativeCancel(mUrlRequestAdapter); |
| } |
| } |
| @@ -397,17 +409,13 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| } |
| } |
| - public boolean isRecycled() { |
| - synchronized (mLock) { |
| - return mRecycled; |
| - } |
| - } |
| - |
| @Override |
| public String getNegotiatedProtocol() { |
| - validateNotRecycled(); |
| - validateHeadersAvailable(); |
| - return nativeGetNegotiatedProtocol(mUrlRequestAdapter); |
| + synchronized (mLock) { |
|
xunjieli
2015/03/03 22:53:12
I realize there can be a race when we call get* me
|
| + validateNativeAdapterNotDestroyed(); |
| + validateHeadersAvailable(); |
| + return nativeGetNegotiatedProtocol(mUrlRequestAdapter); |
| + } |
| } |
| @Override |
| @@ -417,19 +425,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 +475,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 +538,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 +561,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 +632,7 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| } |
| mFinished = true; |
| - if (mRecycled) { |
| + if (mUrlRequestAdapter == 0) { |
| return; |
| } |
| try { |
| @@ -625,7 +650,6 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| onRequestComplete(); |
| nativeDestroyRequestAdapter(mUrlRequestAdapter); |
| mUrlRequestAdapter = 0; |
| - mRecycled = true; |
| } |
| } catch (Exception e) { |
| mSinkException = new IOException("Exception in finish", e); |