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 db833d782842dcf26d6094659e6e6332da7ce776..7c7c392dd8b4cd31aac62caf596902f20e68c9c8 100644 |
| --- a/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
| +++ b/components/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
| @@ -4,6 +4,8 @@ |
| package org.chromium.net; |
| +import android.util.Log; |
| + |
| import org.apache.http.conn.ConnectTimeoutException; |
| import org.chromium.base.CalledByNative; |
| import org.chromium.base.JNINamespace; |
| @@ -401,41 +403,63 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| // Private methods called by native library. |
| /** |
| + * If @CalledByNative method throws an exception, request gets cancelled |
| + * and exception could be retrieved from request using getException(). |
| + */ |
| + private void onCalledByNativeException(Exception e) { |
| + mSinkException = new IOException( |
| + "CalledByNative method has thrown an exception", e); |
| + Log.e(ChromiumUrlRequestContext.LOG_TAG, |
| + "Exception in CalledByNative method", e); |
| + try { |
| + cancel(); |
| + } catch (Exception cancel_exception) { |
| + Log.e(ChromiumUrlRequestContext.LOG_TAG, |
| + "Exception trying to cancel request", cancel_exception); |
| + } |
| + } |
| + |
| + /** |
| * A callback invoked when the first chunk of the response has arrived. |
| */ |
| @CalledByNative |
| private void onResponseStarted() { |
| - mContentType = nativeGetContentType(mUrlRequestAdapter); |
| - mContentLength = nativeGetContentLength(mUrlRequestAdapter); |
| - mHeadersAvailable = true; |
| - |
| - if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit |
| - && mCancelIfContentLengthOverLimit) { |
| - onContentLengthOverLimit(); |
| - return; |
| - } |
| + try { |
| + mContentType = nativeGetContentType(mUrlRequestAdapter); |
| + mContentLength = nativeGetContentLength(mUrlRequestAdapter); |
| + mHeadersAvailable = true; |
| + |
| + if (mContentLengthLimit > 0 && |
| + mContentLength > mContentLengthLimit && |
| + mCancelIfContentLengthOverLimit) { |
| + onContentLengthOverLimit(); |
| + return; |
| + } |
| - if (mBufferFullResponse && mContentLength != -1 |
| - && !mContentLengthOverLimit) { |
| - ((ChunkedWritableByteChannel)getSink()).setCapacity( |
| - (int)mContentLength); |
| - } |
| + if (mBufferFullResponse && mContentLength != -1 |
| + && !mContentLengthOverLimit) { |
| + ((ChunkedWritableByteChannel)getSink()).setCapacity( |
| + (int)mContentLength); |
| + } |
| - if (mOffset != 0) { |
| - // 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) { |
| - // TODO(mef): Revisit this logic. |
| - if (mContentLength != -1) { |
| - mContentLength -= mOffset; |
| + if (mOffset != 0) { |
| + // 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) { |
| + // TODO(mef): Revisit this logic. |
| + if (mContentLength != -1) { |
| + mContentLength -= mOffset; |
| + } |
| + mSkippingToOffset = true; |
| + } else { |
| + mSize = mOffset; |
| } |
| - mSkippingToOffset = true; |
| - } else { |
| - mSize = mOffset; |
| } |
| + mListener.onResponseStarted(this); |
| + } catch (Exception e) { |
| + onCalledByNativeException(e); |
| } |
| - mListener.onResponseStarted(this); |
| } |
| /** |
| @@ -447,37 +471,36 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| */ |
| @CalledByNative |
| private void onBytesRead(ByteBuffer buffer) { |
| - if (mContentLengthOverLimit) { |
| - return; |
| - } |
| - |
| - int size = buffer.remaining(); |
| - mSize += size; |
| - if (mSkippingToOffset) { |
| - if (mSize <= mOffset) { |
| + try { |
| + if (mContentLengthOverLimit) { |
| return; |
| - } else { |
| - mSkippingToOffset = false; |
| - buffer.position((int)(mOffset - (mSize - size))); |
| } |
| - } |
| - boolean contentLengthOverLimit = |
| - (mContentLengthLimit != 0 && mSize > mContentLengthLimit); |
| - if (contentLengthOverLimit) { |
| - buffer.limit(size - (int)(mSize - mContentLengthLimit)); |
| - } |
| + int size = buffer.remaining(); |
| + mSize += size; |
| + if (mSkippingToOffset) { |
| + if (mSize <= mOffset) { |
| + return; |
| + } else { |
| + mSkippingToOffset = false; |
| + buffer.position((int)(mOffset - (mSize - size))); |
| + } |
| + } |
| + |
| + boolean contentLengthOverLimit = |
| + (mContentLengthLimit != 0 && mSize > mContentLengthLimit); |
| + if (contentLengthOverLimit) { |
| + buffer.limit(size - (int)(mSize - mContentLengthLimit)); |
| + } |
| - try { |
| while (buffer.hasRemaining()) { |
| mSink.write(buffer); |
| } |
| - } catch (IOException e) { |
| - mSinkException = e; |
| - cancel(); |
| - } |
| - if (contentLengthOverLimit) { |
| - onContentLengthOverLimit(); |
| + if (contentLengthOverLimit) { |
| + onContentLengthOverLimit(); |
|
mef
2014/08/15 16:03:35
onContentLengthOverLimit is no longer called if ex
mmenke
2014/08/15 16:12:22
I agree
|
| + } |
| + } catch (Exception e) { |
| + onCalledByNativeException(e); |
| } |
| } |
| @@ -487,21 +510,25 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private void finish() { |
| - synchronized (mLock) { |
| - mFinished = true; |
| + try { |
| + synchronized (mLock) { |
| + mFinished = true; |
| - if (mRecycled) { |
| - return; |
| - } |
| - try { |
| - mSink.close(); |
| - } catch (IOException e) { |
| - // Ignore |
| + if (mRecycled) { |
| + return; |
| + } |
| + try { |
| + mSink.close(); |
| + } catch (IOException e) { |
| + // Ignore |
| + } |
| + onRequestComplete(); |
| + nativeDestroyRequestAdapter(mUrlRequestAdapter); |
| + mUrlRequestAdapter = 0; |
| + mRecycled = true; |
| } |
| - onRequestComplete(); |
| - nativeDestroyRequestAdapter(mUrlRequestAdapter); |
| - mUrlRequestAdapter = 0; |
| - mRecycled = true; |
| + } catch (Exception e) { |
| + onCalledByNativeException(e); |
| } |
| } |
| @@ -512,10 +539,14 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| @CalledByNative |
| private void onAppendResponseHeader(ResponseHeadersMap headersMap, |
| String name, String value) { |
| - if (!headersMap.containsKey(name)) { |
| - headersMap.put(name, new ArrayList<String>()); |
| + try { |
| + if (!headersMap.containsKey(name)) { |
| + headersMap.put(name, new ArrayList<String>()); |
| + } |
| + headersMap.get(name).add(value); |
| + } catch (Exception e) { |
| + onCalledByNativeException(e); |
| } |
| - headersMap.get(name).add(value); |
| } |
| /** |
| @@ -527,25 +558,24 @@ public class ChromiumUrlRequest implements HttpUrlRequest { |
| @SuppressWarnings("unused") |
| @CalledByNative |
| private int readFromUploadChannel(ByteBuffer dest) { |
| - if (mUploadChannel == null || !mUploadChannel.isOpen()) |
| - return -1; |
| try { |
| + if (mUploadChannel == null || !mUploadChannel.isOpen()) |
| + return -1; |
| int result = mUploadChannel.read(dest); |
| if (result < 0) { |
| mUploadChannel.close(); |
|
mef
2014/08/15 17:15:01
Per clm it is better to close the channel as soon
|
| return 0; |
| } |
| return result; |
| - } catch (IOException e) { |
| - mSinkException = e; |
| + } catch (Exception e) { |
| + onCalledByNativeException(e); |
| try { |
| mUploadChannel.close(); |
|
mmenke
2014/08/15 16:12:22
Question: Why does this matter, anyways? We aren
mef
2014/08/15 17:15:01
I've discussed with clm@, and we have to close upl
|
| } catch (IOException ignored) { |
| // Ignore this exception. |
| } |
| - cancel(); |
| - return -1; |
| } |
| + return -1; |
| } |
| // Native methods are implemented in chromium_url_request.cc. |