Index: net/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
diff --git a/net/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java b/net/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c17f19f2763de808712c24a3299efb5664f890f7 |
--- /dev/null |
+++ b/net/cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java |
@@ -0,0 +1,178 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.net; |
+ |
+import java.io.IOException; |
+import java.nio.ByteBuffer; |
+import java.nio.channels.WritableByteChannel; |
+import java.util.Map; |
+ |
+/** |
+ * Network request using the native http stack implementation. |
+ */ |
+class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest { |
+ |
+ private final HttpUrlRequestListener mListener; |
+ private boolean mBufferFullResponse; |
+ private long mOffset; |
dplotnikov
2014/03/07 20:01:12
Do you believe we should keep this resumable downl
mef
2014/03/07 20:54:12
Good question. At this point my primary goal was t
|
+ private long mContentLength; |
+ private long mContentLengthLimit; |
+ private boolean mCancelIfContentLengthOverLimit; |
+ private boolean mContentLengthOverLimit; |
+ private boolean mSkippingToOffset; |
+ private long mSize; |
mmenke
2014/03/07 17:02:39
Entire file should be using 4-space indent (Goes f
mef
2014/03/07 20:54:12
Yeah, is there some tool for that? 'git cl format'
mef
2014/03/14 20:03:24
Done.
|
+ |
+ public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, String url, |
mmenke
2014/03/07 17:02:39
Line too long (Goes for a bunch of lines in these
mef
2014/03/07 20:54:12
Roger that.
|
+ int priority, Map<String, String> headers, HttpUrlRequestListener listener) { |
mmenke
2014/03/07 17:02:39
All lines with arguments should be lined up.First
|
+ this(requestContext, url, priority, headers, new ChunkedWritableByteChannel(), listener); |
+ mBufferFullResponse = true; |
+ } |
+ |
+ public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, String url, |
+ int priority, Map<String, String> headers, WritableByteChannel sink, |
+ HttpUrlRequestListener listener) { |
+ super(requestContext, url, convertRequestPriority(priority), headers, sink); |
+ if (requestContext == null) { |
+ throw new NullPointerException("Context is required"); |
+ } |
+ if (url == null) { |
+ throw new NullPointerException("URL is required"); |
+ } |
+ mListener = listener; |
+ } |
+ |
+ private static int convertRequestPriority(int priority) { |
+ switch (priority) { |
+ case HttpUrlRequest.REQUEST_PRIORITY_IDLE: |
+ return UrlRequest.REQUEST_PRIORITY_IDLE; |
+ case HttpUrlRequest.REQUEST_PRIORITY_LOWEST: |
+ return UrlRequest.REQUEST_PRIORITY_LOWEST; |
+ case HttpUrlRequest.REQUEST_PRIORITY_LOW: |
+ return UrlRequest.REQUEST_PRIORITY_LOW; |
+ case HttpUrlRequest.REQUEST_PRIORITY_MEDIUM: |
+ return UrlRequest.REQUEST_PRIORITY_MEDIUM; |
+ case HttpUrlRequest.REQUEST_PRIORITY_HIGHEST: |
+ return UrlRequest.REQUEST_PRIORITY_HIGHEST; |
+ default: |
+ return UrlRequest.REQUEST_PRIORITY_MEDIUM; |
+ } |
+ } |
+ |
+ @Override |
+ public void setOffset(long offset) { |
+ mOffset = offset; |
+ if (offset != 0) { |
+ addHeader("Range", "bytes=" + offset + "-"); |
+ } |
+ } |
+ |
+ @Override |
+ public long getContentLength() { |
+ return mContentLength; |
+ } |
+ |
+ @Override |
+ public void setContentLengthLimit(long limit, boolean cancelEarly) { |
+ mContentLengthLimit = limit; |
+ mCancelIfContentLengthOverLimit = cancelEarly; |
+ } |
+ |
+ @Override |
+ protected void onResponseStarted() { |
+ super.onResponseStarted(); |
+ |
+ mContentLength = super.getContentLength(); |
+ if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit |
+ && mCancelIfContentLengthOverLimit) { |
+ onContentLengthOverLimit(); |
+ return; |
+ } |
+ |
+ if (mBufferFullResponse && mContentLength != -1 && !mContentLengthOverLimit) { |
+ ((ChunkedWritableByteChannel) getSink()).setCapacity((int) mContentLength); |
+ } |
+ |
+ if (mOffset != 0) { |
+ // The server may ignore the request for a byte range |
mmenke
2014/03/07 17:02:39
Suggestion adding a period. Android style guide d
mef
2014/03/07 20:54:12
Done. Agreed.
|
+ if (super.getHttpStatusCode() == 200) { |
+ if (mContentLength != -1) { |
+ mContentLength -= mOffset; |
+ } |
+ mSkippingToOffset = true; |
+ } else { |
+ mSize = mOffset; |
+ } |
+ } |
+ } |
+ |
+ @Override |
+ protected void onBytesRead(ByteBuffer buffer) { |
+ if (mContentLengthOverLimit) { |
+ return; |
+ } |
+ |
+ int size = buffer.remaining(); |
+ mSize += size; |
+ if (mSkippingToOffset) { |
+ if (mSize <= mOffset) { |
+ return; |
+ } else { |
+ mSkippingToOffset = false; |
+ buffer.position((int) (mOffset - (mSize - size))); |
+ } |
+ } |
+ |
+ if (mContentLengthLimit != 0 && mSize > mContentLengthLimit) { |
+ buffer.limit(size - (int) (mSize - mContentLengthLimit)); |
+ super.onBytesRead(buffer); |
+ onContentLengthOverLimit(); |
+ return; |
+ } |
+ |
+ super.onBytesRead(buffer); |
+ } |
+ |
+ private void onContentLengthOverLimit() { |
+ mContentLengthOverLimit = true; |
+ cancel(); |
+ } |
+ |
+ @Override |
+ protected void onRequestComplete() { |
+ mListener.onRequestComplete(this); |
+ } |
+ |
+ @Override |
+ public int getHttpStatusCode() { |
+ int httpStatusCode = super.getHttpStatusCode(); |
+ |
+ // 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. |
mmenke
2014/03/07 17:02:39
Add a TODO about investigating this - I'm not sure
mef
2014/03/07 20:54:12
Done.
|
+ if (httpStatusCode == 206) { |
+ httpStatusCode = 200; |
+ } |
+ return httpStatusCode; |
+ } |
+ |
+ @Override |
+ public IOException getException() { |
+ IOException ex = super.getException(); |
+ if (ex == null && mContentLengthOverLimit) { |
+ ex = new ResponseTooLargeException(); |
+ } |
+ return ex; |
+ } |
+ |
+ @Override |
+ public ByteBuffer getByteBuffer() { |
+ return ((ChunkedWritableByteChannel) getSink()).getByteBuffer(); |
+ } |
+ |
+ @Override |
+ public byte[] getResponseAsBytes() { |
+ return ((ChunkedWritableByteChannel) getSink()).getBytes(); |
+ } |
+} |