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

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

Issue 470443005: Cronet modifications to support AGSA. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Created 6 years, 4 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: components/cronet/android/java/src/org/chromium/net/UrlRequest.java
diff --git a/components/cronet/android/java/src/org/chromium/net/UrlRequest.java b/components/cronet/android/java/src/org/chromium/net/UrlRequest.java
index 73e9abac4030dd20e16712b8e4dad5d8ea893d22..f8912a39c30cb2db4b83f496e17654a7299d8b7e 100644
--- a/components/cronet/android/java/src/org/chromium/net/UrlRequest.java
+++ b/components/cronet/android/java/src/org/chromium/net/UrlRequest.java
@@ -16,20 +16,22 @@ import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.Semaphore;
/**
* Network request using the native http stack implementation.
*/
@JNINamespace("cronet")
public class UrlRequest {
+
mef 2014/08/15 13:30:22 nit: not needed nl?
mdumitrescu 2014/08/15 15:23:12 Done.
private static final class ContextLock {
}
private final UrlRequestContext mRequestContext;
private final String mUrl;
private final int mPriority;
private final Map<String, String> mHeaders;
@@ -45,14 +47,15 @@ public class UrlRequest {
private volatile boolean mCanceled;
private volatile boolean mRecycled;
private volatile boolean mFinished;
private boolean mHeadersAvailable;
private String mContentType;
private long mContentLength;
private long mUploadContentLength;
+ private Semaphore mAppendChunkSemaphore;
private final ContextLock mLock;
/**
* Native adapter object, owned by UrlRequest.
*/
private long mUrlRequestAdapter;
@@ -129,14 +132,64 @@ public class UrlRequest {
mUploadContentType = contentType;
mUploadChannel = channel;
mUploadContentLength = contentLength;
mUploadData = null;
}
}
+ public void setChunkedUpload(String contentType) {
+ synchronized (mLock) {
+ validateNotStarted();
+ mUploadContentType = contentType;
+ mUploadChannel = null;
+ mUploadData = null;
+ mAppendChunkSemaphore = new Semaphore(0);
+ }
+ }
+
+ /**
+ * Uploads a new chunk.
+ * @param chunk The data. It must not be empty and its position must be zero.
+ * @param isLastChunk Whether this chunk is the last one.
+ */
+ // Invokes {@link #nativeAppendChunk(long, ByteBuffer, int, boolean)} and waits for it
+ // to notify completion.
+ public void appendChunkBlocking(ByteBuffer chunk, boolean isLastChunk)
mef 2014/08/15 13:30:22 Due to limitations of our codereview tool we keep
mdumitrescu 2014/08/15 15:23:12 Done.
+ throws IOException {
+ if (!chunk.hasRemaining()) {
+ throw new IllegalArgumentException("Attempted to write empty buffer.");
+ }
+ if (chunk.position() != 0) {
+ throw new IllegalArgumentException("The position must be zero.");
+ }
+ synchronized (mLock) {
+ if (mAppendChunkSemaphore == null) {
+ throw new IllegalArgumentException("This is not a chunked upload request.");
+ }
+ if (mUrlRequestAdapter == 0) {
+ throw new IOException("Native peer destroyed.");
+ }
+ nativeAppendChunk(mUrlRequestAdapter, chunk, chunk.limit(), isLastChunk);
+ // Wait for the data to be actually consumed.
+ try {
+ mAppendChunkSemaphore.acquire();
+ } catch (InterruptedException e) {
+ // We were interrupted before the data was uploaded. Recovering
+ // from this state is complicated so we cancel the upload
+ // operation and fail.
+ Thread.currentThread().interrupt();
mef 2014/08/15 13:30:22 How does that work? Where would interrupt come fro
mdumitrescu 2014/08/15 15:23:12 Changed to using condition variable.
+
+ // TODO(miloslav): Not sure why do we set mSinkException here.
+ mSinkException = new IOException("Upload interrupted", e);
+ cancel();
+ throw mSinkException;
mef 2014/08/15 13:30:22 Um, so where all those exceptions are getting caug
mdumitrescu 2014/08/15 15:23:13 Changed to using condition variable. (The exceptio
+ }
+ }
+ }
+
public void setHttpMethod(String method) {
validateNotStarted();
if (!("PUT".equals(method) || "POST".equals(method))) {
throw new IllegalArgumentException("Only PUT or POST are allowed.");
}
mMethod = method;
}
@@ -155,15 +208,15 @@ public class UrlRequest {
validateNotRecycled();
mStarted = true;
String method = mMethod;
if (method == null &&
((mUploadData != null && mUploadData.length > 0) ||
- mUploadChannel != null)) {
+ mUploadChannel != null || mAppendChunkSemaphore != null)) {
// Default to POST if there is data to upload but no method was
// specified.
method = "POST";
}
if (method != null) {
nativeSetMethod(mUrlRequestAdapter, method);
@@ -186,14 +239,17 @@ public class UrlRequest {
if (mUploadData != null && mUploadData.length > 0) {
nativeSetUploadData(mUrlRequestAdapter, mUploadContentType,
mUploadData);
} else if (mUploadChannel != null) {
nativeSetUploadChannel(mUrlRequestAdapter, mUploadContentType,
mUploadContentLength);
+ } else if (mAppendChunkSemaphore != null) {
+ nativeEnableChunkedUpload(mUrlRequestAdapter,
+ mUploadContentType);
}
nativeStart(mUrlRequestAdapter);
}
}
public void cancel() {
@@ -284,14 +340,22 @@ public class UrlRequest {
validateHeadersAvailable();
ResponseHeadersMap result = new ResponseHeadersMap();
nativeGetAllHeaders(mUrlRequestAdapter, result);
return result;
}
/**
+ * 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(mUrlRequestAdapter);
mContentLength = nativeGetContentLength(mUrlRequestAdapter);
mHeadersAvailable = true;
@@ -326,14 +390,17 @@ public class UrlRequest {
* 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) {
@@ -421,14 +488,20 @@ public class UrlRequest {
private native void nativeSetUploadData(long urlRequestAdapter,
String contentType, byte[] content);
private native void nativeSetUploadChannel(long urlRequestAdapter,
String contentType, long contentLength);
+ private native void nativeEnableChunkedUpload(long urlRequestAdapter,
+ String contentType);
+
+ private native void nativeAppendChunk(long urlRequestAdapter, ByteBuffer chunk,
mef 2014/08/15 13:30:22 nit: limit line length to 80.
mdumitrescu 2014/08/15 15:23:12 Done.
+ int chunkSize, boolean isLastChunk);
+
private native void nativeStart(long urlRequestAdapter);
private native void nativeCancel(long urlRequestAdapter);
private native void nativeDestroyRequestAdapter(long urlRequestAdapter);
private native int nativeGetErrorCode(long urlRequestAdapter);
@@ -445,8 +518,9 @@ public class UrlRequest {
private native void nativeGetAllHeaders(long urlRequestAdapter,
ResponseHeadersMap headers);
// Explicit class to work around JNI-generator generics confusion.
private class ResponseHeadersMap extends HashMap<String, List<String>> {
}
+
mef 2014/08/15 13:30:22 nit: spurious nl?
mdumitrescu 2014/08/15 15:23:12 Done.
}

Powered by Google App Engine
This is Rietveld 408576698