Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Unified Diff: net/cronet/android/java/src/org/chromium/net/UrlRequest.java

Issue 183333002: Cronet Java wrappers to fallback to HttpUrlConnection if Cronet is not available. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address formatting comments. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/cronet/android/java/src/org/chromium/net/UrlRequest.java
diff --git a/net/cronet/android/java/src/org/chromium/net/UrlRequest.java b/net/cronet/android/java/src/org/chromium/net/UrlRequest.java
index 5f8c76b30d8102b5374183d6f324f6c2286eed03..81787c3706697a261d03962678ac56d3f64e4e35 100644
--- a/net/cronet/android/java/src/org/chromium/net/UrlRequest.java
+++ b/net/cronet/android/java/src/org/chromium/net/UrlRequest.java
@@ -24,404 +24,407 @@ import java.util.concurrent.Semaphore;
* Network request using the native http stack implementation.
*/
public class UrlRequest {
- private static final class ContextLock {
- }
-
- /**
- * Must match definitions in the native source.
- */
- public static final int REQUEST_PRIORITY_IDLE = 0;
- public static final int REQUEST_PRIORITY_LOWEST = 1;
- public static final int REQUEST_PRIORITY_LOW = 2;
- public static final int REQUEST_PRIORITY_MEDIUM = 3;
- public static final int REQUEST_PRIORITY_HIGHEST = 4;
-
- /**
- * Must match definitions in the native source.
- */
- private static final int SUCCESS = 0;
- private static final int UNKNOWN_ERROR = 1;
- private static final int MALFORMED_URL_ERROR = 2;
- private static final int CONNECTION_TIMED_OUT = 3;
- private static final int UNKNOWN_HOST = 4;
-
- private static final int UPLOAD_BYTE_BUFFER_SIZE = 32768;
-
- // TODO(mef) : Rename to follow Google Java style guide:
- // In Google Style special prefixes or suffixes, like those seen in the
- // examples name_, mName, s_name and kName, are not used.
- private final UrlRequestContext mRequestContext;
- private final String mUrl;
- private final int mPriority;
- private final Map<String, String> mHeaders;
- private final WritableByteChannel mSink;
-
- private Map<String, String> mAdditionalHeaders;
- private boolean mPostBodySet;
- private ReadableByteChannel mPostBodyChannel;
- private WritableByteChannel mOutputChannel;
- private IOException mSinkException;
- private volatile boolean mStarted;
- private volatile boolean mCanceled;
- private volatile boolean mRecycled;
- private volatile boolean mFinished;
- private String mContentType;
- private long mContentLength;
- private Semaphore mAppendChunkSemaphore;
- private final ContextLock mLock;
-
- /**
- * This field is accessed exclusively from the native layer.
- */
- @AccessedByNative
- @SuppressWarnings("unused")
- private long mRequest;
-
- /**
- * Constructor.
- *
- * @param requestContext The context.
- * @param url The URL.
- * @param priority Request priority, e.g. {@link #REQUEST_PRIORITY_MEDIUM}.
- * @param headers HTTP headers.
- * @param sink The output channel into which downloaded content will be
- * written.
- */
- public UrlRequest(UrlRequestContext requestContext,
- String url,
- int priority,
- Map<String, String> headers,
- WritableByteChannel sink) {
- mRequestContext = requestContext;
- mUrl = url;
- mPriority = priority;
- mHeaders = headers;
- mSink = sink;
- mLock = new ContextLock();
- nativeInit(mRequestContext, mUrl, mPriority);
- mPostBodySet = false;
- }
-
- /**
- * Adds a request header.
- */
- public void addHeader(String header, String value) {
- validateNotStarted();
- if (mAdditionalHeaders == null) {
- mAdditionalHeaders = new HashMap<String, String>();
+ private static final class ContextLock {
}
- mAdditionalHeaders.put(header, value);
- }
-
- /**
- * Sets data to upload as part of a POST request.
- *
- * @param contentType MIME type of the post content or null if this is not a
- * POST.
- * @param data The content that needs to be uploaded if this is a POST
- * request.
- */
- public void setUploadData(String contentType, byte[] data) {
- synchronized (mLock) {
- validateNotStarted();
- validatePostBodyNotSet();
- nativeSetPostData(contentType, data);
- mPostBodySet = true;
+
+ /**
+ * Must match definitions in the native source.
+ */
+ public static final int REQUEST_PRIORITY_IDLE = 0;
+ public static final int REQUEST_PRIORITY_LOWEST = 1;
+ public static final int REQUEST_PRIORITY_LOW = 2;
+ public static final int REQUEST_PRIORITY_MEDIUM = 3;
+ public static final int REQUEST_PRIORITY_HIGHEST = 4;
+
+ /**
+ * Must match definitions in the native source.
+ */
+ private static final int SUCCESS = 0;
+ private static final int UNKNOWN_ERROR = 1;
+ private static final int MALFORMED_URL_ERROR = 2;
+ private static final int CONNECTION_TIMED_OUT = 3;
+ private static final int UNKNOWN_HOST = 4;
+ private static final int UPLOAD_BYTE_BUFFER_SIZE = 32768;
+
+ // TODO(mef) : Rename to follow Google Java style guide:
+ // In Google Style special prefixes or suffixes, like those seen in the
+ // examples name_, mName, s_name and kName, are not used.
+ private final UrlRequestContext mRequestContext;
+ private final String mUrl;
+ private final int mPriority;
+ private final Map<String, String> mHeaders;
+ private final WritableByteChannel mSink;
+ private Map<String, String> mAdditionalHeaders;
+ private boolean mPostBodySet;
+ private ReadableByteChannel mPostBodyChannel;
+ private WritableByteChannel mOutputChannel;
+ private IOException mSinkException;
+ private volatile boolean mStarted;
+ private volatile boolean mCanceled;
+ private volatile boolean mRecycled;
+ private volatile boolean mFinished;
+ private String mContentType;
+ private long mContentLength;
+ private Semaphore mAppendChunkSemaphore;
+ private final ContextLock mLock;
+
+ /**
+ * This field is accessed exclusively from the native layer.
+ */
+ @AccessedByNative
+ @SuppressWarnings("unused")
+ private long mRequest;
+
+ /**
+ * Constructor.
+ *
+ * @param requestContext The context.
+ * @param url The URL.
+ * @param priority Request priority, e.g. {@link #REQUEST_PRIORITY_MEDIUM}.
+ * @param headers HTTP headers.
+ * @param sink The output channel into which downloaded content will be
+ * written.
+ */
+ public UrlRequest(UrlRequestContext requestContext, String url,
+ int priority, Map<String, String> headers,
+ WritableByteChannel sink) {
+ mRequestContext = requestContext;
+ mUrl = url;
+ mPriority = priority;
+ mHeaders = headers;
+ mSink = sink;
+ mLock = new ContextLock();
+ nativeInit(mRequestContext, mUrl, mPriority);
+ mPostBodySet = false;
}
- }
-
- /**
- * Sets a readable byte channel to upload as part of a POST request.
- *
- * @param contentType MIME type of the post content or null if this is not a
- * POST request.
- * @param channel The channel to read to read upload data from if this is a
- * POST request.
- */
- public void setUploadChannel(String contentType,
- ReadableByteChannel channel) {
- synchronized (mLock) {
- validateNotStarted();
- validatePostBodyNotSet();
- nativeBeginChunkedUpload(contentType);
- mPostBodyChannel = channel;
- mPostBodySet = true;
+
+ /**
+ * Adds a request header.
+ */
+ public void addHeader(String header, String value) {
+ validateNotStarted();
+ if (mAdditionalHeaders == null) {
+ mAdditionalHeaders = new HashMap<String, String>();
+ }
+ mAdditionalHeaders.put(header, value);
}
- mAppendChunkSemaphore = new Semaphore(0);
- }
- public WritableByteChannel getSink() {
- return mSink;
- }
+ /**
+ * Sets data to upload as part of a POST request.
+ *
+ * @param contentType MIME type of the post content or null if this is not a
+ * POST.
+ * @param data The content that needs to be uploaded if this is a POST
+ * request.
+ */
+ public void setUploadData(String contentType, byte[] data) {
+ synchronized (mLock) {
+ validateNotStarted();
+ validatePostBodyNotSet();
+ nativeSetPostData(contentType, data);
+ mPostBodySet = true;
+ }
+ }
- public void start() {
- synchronized (mLock) {
- if (mCanceled) {
- return;
- }
+ /**
+ * Sets a readable byte channel to upload as part of a POST request.
+ *
+ * @param contentType MIME type of the post content or null if this is not a
+ * POST request.
+ * @param channel The channel to read to read upload data from if this is a
+ * POST request.
+ */
+ public void setUploadChannel(String contentType,
+ ReadableByteChannel channel) {
+ synchronized (mLock) {
+ validateNotStarted();
+ validatePostBodyNotSet();
+ nativeBeginChunkedUpload(contentType);
+ mPostBodyChannel = channel;
+ mPostBodySet = true;
+ }
+ mAppendChunkSemaphore = new Semaphore(0);
+ }
- validateNotStarted();
- validateNotRecycled();
+ public WritableByteChannel getSink() {
+ return mSink;
+ }
+
+ public void start() {
+ synchronized (mLock) {
+ if (mCanceled) {
+ return;
+ }
+
+ validateNotStarted();
+ validateNotRecycled();
- mStarted = true;
+ mStarted = true;
- if (mHeaders != null && !mHeaders.isEmpty()) {
- for (Entry<String, String> entry : mHeaders.entrySet()) {
- nativeAddHeader(entry.getKey(), entry.getValue());
+ if (mHeaders != null && !mHeaders.isEmpty()) {
+ for (Entry<String, String> entry : mHeaders.entrySet()) {
+ nativeAddHeader(entry.getKey(), entry.getValue());
+ }
+ }
+
+ if (mAdditionalHeaders != null && !mAdditionalHeaders.isEmpty()) {
+ for (Entry<String, String> entry :
+ mAdditionalHeaders.entrySet()) {
+ nativeAddHeader(entry.getKey(), entry.getValue());
+ }
+ }
+
+ nativeStart();
}
- }
- if (mAdditionalHeaders != null && !mAdditionalHeaders.isEmpty()) {
- for (Entry<String, String> entry : mAdditionalHeaders.entrySet()) {
- nativeAddHeader(entry.getKey(), entry.getValue());
+ if (mPostBodyChannel != null) {
+ uploadFromChannel(mPostBodyChannel);
}
- }
+ }
- nativeStart();
+ /**
+ * Uploads data from a {@code ReadableByteChannel} using chunked transfer
+ * encoding. The native call to append a chunk is asynchronous so a
+ * semaphore is used to delay writing into the buffer again until chromium
+ * is finished with it.
+ *
+ * @param channel the channel to read data from.
+ */
+ private void uploadFromChannel(ReadableByteChannel channel) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(UPLOAD_BYTE_BUFFER_SIZE);
+
+ // The chromium API requires us to specify in advance if a chunk is the
+ // last one. This extra ByteBuffer is needed to peek ahead and check for
+ // the end of the channel.
+ ByteBuffer checkForEnd = ByteBuffer.allocate(1);
+
+ try {
+ boolean lastChunk;
+ do {
+ // First dump in the one byte we read to check for the end of
+ // the channel. (The first time through the loop the checkForEnd
+ // buffer will be empty).
+ checkForEnd.flip();
+ buffer.clear();
+ buffer.put(checkForEnd);
+ checkForEnd.clear();
+
+ channel.read(buffer);
+ lastChunk = channel.read(checkForEnd) <= 0;
+ buffer.flip();
+ nativeAppendChunk(buffer, buffer.limit(), lastChunk);
+
+ if (lastChunk) {
+ break;
+ }
+
+ // Acquire permit before writing to the buffer again to ensure
+ // chromium is done with it.
+ mAppendChunkSemaphore.acquire();
+ } while (!lastChunk && !mFinished);
+ } catch (IOException e) {
+ mSinkException = e;
+ cancel();
+ } catch (InterruptedException e) {
+ mSinkException = new IOException(e);
+ cancel();
+ } finally {
+ try {
+ mPostBodyChannel.close();
+ } catch (IOException ignore) {
+ ;
+ }
+ }
}
- if (mPostBodyChannel != null) {
- uploadFromChannel(mPostBodyChannel);
+ public void cancel() {
+ synchronized (mLock) {
+ if (mCanceled) {
+ return;
+ }
+
+ mCanceled = true;
+
+ if (!mRecycled) {
+ nativeCancel();
+ }
+ }
}
- }
-
- /**
- * Uploads data from a {@code ReadableByteChannel} using chunked transfer
- * encoding.
- *
- * The native call to append a chunk is asynchronous so a semaphore is used
- * to delay writing into the buffer again until chromium is finished with it.
- *
- * @param channel the channel to read data from.
- */
- private void uploadFromChannel(ReadableByteChannel channel) {
- ByteBuffer buffer = ByteBuffer.allocateDirect(UPLOAD_BYTE_BUFFER_SIZE);
-
- // The chromium API requires us to specify in advance if a chunk is the last
- // one. This extra ByteBuffer is needed to peek ahead and check for the end
- // of the channel.
- ByteBuffer checkForEnd = ByteBuffer.allocate(1);
-
- try {
- boolean lastChunk;
- do {
- // First dump in the one byte we read to check for the end of the
- // channel. (The first time through the loop the checkForEnd buffer will
- // be empty).
- checkForEnd.flip();
- buffer.clear();
- buffer.put(checkForEnd);
- checkForEnd.clear();
-
- channel.read(buffer);
- lastChunk = channel.read(checkForEnd) <= 0;
- buffer.flip();
- nativeAppendChunk(buffer, buffer.limit(), lastChunk);
-
- if (lastChunk) {
- break;
+
+ public boolean isCanceled() {
+ synchronized (mLock) {
+ return mCanceled;
}
+ }
- // Acquire permit before writing to the buffer again to ensure chromium
- // is done with it.
- mAppendChunkSemaphore.acquire();
-
- } while (!lastChunk && !mFinished);
-
- } catch (IOException e) {
- mSinkException = e;
- cancel();
- } catch (InterruptedException e) {
- mSinkException = new IOException(e);
- cancel();
- } finally {
- try {
- mPostBodyChannel.close();
- } catch (IOException ignore) {
- ;
- }
+ public boolean isRecycled() {
+ synchronized (mLock) {
+ return mRecycled;
+ }
}
- }
- public void cancel() {
- synchronized (mLock) {
- if (mCanceled) {
- return;
- }
+ /**
+ * Returns an exception if any, or null if the request was completed
+ * successfully.
+ */
+ public IOException getException() {
+ if (mSinkException != null) {
+ return mSinkException;
+ }
- mCanceled = true;
+ validateNotRecycled();
+
+ int errorCode = nativeGetErrorCode();
+ switch (errorCode) {
+ case SUCCESS:
+ return null;
+ case UNKNOWN_ERROR:
+ return new IOException(nativeGetErrorString());
+ case MALFORMED_URL_ERROR:
+ return new MalformedURLException("Malformed URL: " + mUrl);
+ case CONNECTION_TIMED_OUT:
+ return new ConnectTimeoutException("Connection timed out");
+ case UNKNOWN_HOST:
+ String host;
+ try {
+ host = new URL(mUrl).getHost();
+ } catch (MalformedURLException e) {
+ host = mUrl;
+ }
+ return new UnknownHostException("Unknown host: " + host);
+ default:
+ throw new IllegalStateException(
+ "Unrecognized error code: " + errorCode);
+ }
+ }
- if (!mRecycled) {
- nativeCancel();
- }
+ public native int getHttpStatusCode();
+
+ /**
+ * Content length as reported by the server. May be -1 or incorrect if the
+ * server returns the wrong number, which happens even with Google servers.
+ */
+ public long getContentLength() {
+ return mContentLength;
+ }
+
+ public String getContentType() {
+ return mContentType;
}
- }
- public boolean isCanceled() {
- synchronized (mLock) {
- return mCanceled;
+ /**
+ * A callback invoked when appending a chunk to the request has completed.
+ */
+ @CalledByNative
+ protected void onAppendChunkCompleted() {
+ mAppendChunkSemaphore.release();
}
- }
- public boolean isRecycled() {
- synchronized (mLock) {
- return mRecycled;
+ /**
+ * A callback invoked when the first chunk of the response has arrived.
+ */
+ @CalledByNative
+ protected void onResponseStarted() {
+ mContentType = nativeGetContentType();
+ mContentLength = nativeGetContentLength();
}
- }
-
- /**
- * Returns an exception if any, or null if the request was completed
- * successfully.
- */
- public IOException getException() {
- if (mSinkException != null) {
- return mSinkException;
+
+ /**
+ * A callback invoked when the response has been fully consumed.
+ */
+ protected void onRequestComplete() {
}
- validateNotRecycled();
-
- int errorCode = nativeGetErrorCode();
- switch (errorCode) {
- case SUCCESS:
- return null;
- case UNKNOWN_ERROR:
- return new IOException(nativeGetErrorString());
- case MALFORMED_URL_ERROR:
- return new MalformedURLException("Malformed URL: " + mUrl);
- case CONNECTION_TIMED_OUT:
- return new ConnectTimeoutException("Connection timed out");
- case UNKNOWN_HOST:
- String host;
+ /**
+ * Consumes a portion of the response.
+ *
+ * @param byteBuffer The ByteBuffer to append. Must be a direct buffer, and
+ * no references to it may be retained after the method ends, as
+ * it wraps code managed on the native heap.
+ */
+ @CalledByNative
+ protected void onBytesRead(ByteBuffer byteBuffer) {
try {
- host = new URL(mUrl).getHost();
- } catch (MalformedURLException e) {
- host = mUrl;
+ while (byteBuffer.hasRemaining()) {
+ mSink.write(byteBuffer);
+ }
+ } catch (IOException e) {
+ mSinkException = e;
+ cancel();
}
- return new UnknownHostException("Unknown host: " + host);
- default:
- throw new IllegalStateException("Unrecognized error code: " +
- errorCode);
}
- }
-
- public native int getHttpStatusCode();
-
- /**
- * Content length as reported by the server. May be -1 or incorrect if the
- * server returns the wrong number, which happens even with Google servers.
- */
- public long getContentLength() {
- return mContentLength;
- }
-
- public String getContentType() {
- return mContentType;
- }
-
- /**
- * A callback invoked when appending a chunk to the request has completed.
- */
- @CalledByNative
- protected void onAppendChunkCompleted() {
- mAppendChunkSemaphore.release();
- }
-
- /**
- * A callback invoked when the first chunk of the response has arrived.
- */
- @CalledByNative
- protected void onResponseStarted() {
- mContentType = nativeGetContentType();
- mContentLength = nativeGetContentLength();
- }
-
- /**
- * A callback invoked when the response has been fully consumed.
- */
- protected void onRequestComplete() {
- }
-
- /**
- * Consumes a portion of the response.
- *
- * @param byteBuffer The ByteBuffer to append. Must be a direct buffer, and
- * no references to it may be retained after the method ends, as it
- * wraps code managed on the native heap.
- */
- @CalledByNative
- protected void onBytesRead(ByteBuffer byteBuffer) {
- try {
- while (byteBuffer.hasRemaining()) {
- mSink.write(byteBuffer);
- }
- } catch (IOException e) {
- mSinkException = e;
- cancel();
+
+ /**
+ * Notifies the listener, releases native data structures.
+ */
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private void finish() {
+ synchronized (mLock) {
+ mFinished = true;
+ if (mAppendChunkSemaphore != null) {
+ mAppendChunkSemaphore.release();
+ }
+
+ if (mRecycled) {
+ return;
+ }
+ try {
+ mSink.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ onRequestComplete();
+ nativeRecycle();
+ mRecycled = true;
+ }
}
- }
-
- /**
- * Notifies the listener, releases native data structures.
- */
- @SuppressWarnings("unused")
- @CalledByNative
- private void finish() {
- synchronized (mLock) {
- mFinished = true;
- if (mAppendChunkSemaphore != null) {
- mAppendChunkSemaphore.release();
- }
-
- if (mRecycled) {
- return;
- }
- try {
- mSink.close();
- } catch (IOException e) {
- // Ignore
- }
- onRequestComplete();
- nativeRecycle();
- mRecycled = true;
+
+ private void validateNotRecycled() {
+ if (mRecycled) {
+ throw new IllegalStateException("Accessing recycled request");
+ }
}
- }
- private void validateNotRecycled() {
- if (mRecycled) {
- throw new IllegalStateException("Accessing recycled request");
+ private void validateNotStarted() {
+ if (mStarted) {
+ throw new IllegalStateException("Request already started");
+ }
}
- }
- private void validateNotStarted() {
- if (mStarted) {
- throw new IllegalStateException("Request already started");
+ private void validatePostBodyNotSet() {
+ if (mPostBodySet) {
+ throw new IllegalStateException("Post Body already set");
+ }
}
- }
- private void validatePostBodyNotSet() {
- if (mPostBodySet) {
- throw new IllegalStateException("Post Body already set");
+ public String getUrl() {
+ return mUrl;
}
- }
-
- public String getUrl() {
- return mUrl;
- }
-
- private native void nativeInit(UrlRequestContext requestContext,
- String url,
- int priority);
- private native void nativeAddHeader(String name, String value);
- private native void nativeSetPostData(String contentType, byte[] content);
- private native void nativeBeginChunkedUpload(String contentType);
- private native void nativeAppendChunk(ByteBuffer chunk,
- int chunkSize,
- boolean isLastChunk);
- private native void nativeStart();
- private native void nativeCancel();
- private native void nativeRecycle();
- private native int nativeGetErrorCode();
- private native String nativeGetErrorString();
- private native String nativeGetContentType();
- private native long nativeGetContentLength();
+
+ private native void nativeInit(UrlRequestContext requestContext, String url,
+ int priority);
+
+ private native void nativeAddHeader(String name, String value);
+
+ private native void nativeSetPostData(String contentType, byte[] content);
+
+ private native void nativeBeginChunkedUpload(String contentType);
+
+ private native void nativeAppendChunk(ByteBuffer chunk, int chunkSize,
+ boolean isLastChunk);
+
+ private native void nativeStart();
+
+ private native void nativeCancel();
+
+ private native void nativeRecycle();
+
+ private native int nativeGetErrorCode();
+
+ private native String nativeGetErrorString();
+
+ private native String nativeGetContentType();
+
+ private native long nativeGetContentLength();
}

Powered by Google App Engine
This is Rietveld 408576698