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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.net; 5 package org.chromium.net;
6 6
7 import org.apache.http.conn.ConnectTimeoutException; 7 import org.apache.http.conn.ConnectTimeoutException;
8 import org.chromium.base.CalledByNative; 8 import org.chromium.base.CalledByNative;
9 import org.chromium.base.JNINamespace; 9 import org.chromium.base.JNINamespace;
10 10
11 import java.io.IOException; 11 import java.io.IOException;
12 import java.net.MalformedURLException; 12 import java.net.MalformedURLException;
13 import java.net.URL; 13 import java.net.URL;
14 import java.net.UnknownHostException; 14 import java.net.UnknownHostException;
15 import java.nio.ByteBuffer; 15 import java.nio.ByteBuffer;
16 import java.nio.channels.ReadableByteChannel; 16 import java.nio.channels.ReadableByteChannel;
17 import java.nio.channels.WritableByteChannel; 17 import java.nio.channels.WritableByteChannel;
18 import java.util.ArrayList; 18 import java.util.ArrayList;
19 import java.util.HashMap; 19 import java.util.HashMap;
20 import java.util.List; 20 import java.util.List;
21 import java.util.Map; 21 import java.util.Map;
22 import java.util.Map.Entry; 22 import java.util.Map.Entry;
23 import java.util.concurrent.Semaphore;
23 24
24 /** 25 /**
25 * Network request using the native http stack implementation. 26 * Network request using the native http stack implementation.
26 */ 27 */
27 @JNINamespace("cronet") 28 @JNINamespace("cronet")
28 public class UrlRequest { 29 public class UrlRequest {
30
mef 2014/08/15 13:30:22 nit: not needed nl?
mdumitrescu 2014/08/15 15:23:12 Done.
29 private static final class ContextLock { 31 private static final class ContextLock {
30 } 32 }
31 33
32 private final UrlRequestContext mRequestContext; 34 private final UrlRequestContext mRequestContext;
33 private final String mUrl; 35 private final String mUrl;
34 private final int mPriority; 36 private final int mPriority;
35 private final Map<String, String> mHeaders; 37 private final Map<String, String> mHeaders;
36 private final WritableByteChannel mSink; 38 private final WritableByteChannel mSink;
37 private Map<String, String> mAdditionalHeaders; 39 private Map<String, String> mAdditionalHeaders;
38 private String mUploadContentType; 40 private String mUploadContentType;
39 private String mMethod; 41 private String mMethod;
40 private byte[] mUploadData; 42 private byte[] mUploadData;
41 private ReadableByteChannel mUploadChannel; 43 private ReadableByteChannel mUploadChannel;
42 private WritableByteChannel mOutputChannel; 44 private WritableByteChannel mOutputChannel;
43 private IOException mSinkException; 45 private IOException mSinkException;
44 private volatile boolean mStarted; 46 private volatile boolean mStarted;
45 private volatile boolean mCanceled; 47 private volatile boolean mCanceled;
46 private volatile boolean mRecycled; 48 private volatile boolean mRecycled;
47 private volatile boolean mFinished; 49 private volatile boolean mFinished;
48 private boolean mHeadersAvailable; 50 private boolean mHeadersAvailable;
49 private String mContentType; 51 private String mContentType;
50 private long mContentLength; 52 private long mContentLength;
51 private long mUploadContentLength; 53 private long mUploadContentLength;
54 private Semaphore mAppendChunkSemaphore;
52 private final ContextLock mLock; 55 private final ContextLock mLock;
53 56
54 /** 57 /**
55 * Native adapter object, owned by UrlRequest. 58 * Native adapter object, owned by UrlRequest.
56 */ 59 */
57 private long mUrlRequestAdapter; 60 private long mUrlRequestAdapter;
58 61
59 /** 62 /**
60 * Constructor. 63 * Constructor.
61 * 64 *
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 ReadableByteChannel channel, long contentLength) { 129 ReadableByteChannel channel, long contentLength) {
127 synchronized (mLock) { 130 synchronized (mLock) {
128 validateNotStarted(); 131 validateNotStarted();
129 mUploadContentType = contentType; 132 mUploadContentType = contentType;
130 mUploadChannel = channel; 133 mUploadChannel = channel;
131 mUploadContentLength = contentLength; 134 mUploadContentLength = contentLength;
132 mUploadData = null; 135 mUploadData = null;
133 } 136 }
134 } 137 }
135 138
139 public void setChunkedUpload(String contentType) {
140 synchronized (mLock) {
141 validateNotStarted();
142 mUploadContentType = contentType;
143 mUploadChannel = null;
144 mUploadData = null;
145 mAppendChunkSemaphore = new Semaphore(0);
146 }
147 }
148
149 /**
150 * Uploads a new chunk.
151 * @param chunk The data. It must not be empty and its position must be zero .
152 * @param isLastChunk Whether this chunk is the last one.
153 */
154 // Invokes {@link #nativeAppendChunk(long, ByteBuffer, int, boolean)} and wa its for it
155 // to notify completion.
156 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.
157 throws IOException {
158 if (!chunk.hasRemaining()) {
159 throw new IllegalArgumentException("Attempted to write empty buffer. ");
160 }
161 if (chunk.position() != 0) {
162 throw new IllegalArgumentException("The position must be zero.");
163 }
164 synchronized (mLock) {
165 if (mAppendChunkSemaphore == null) {
166 throw new IllegalArgumentException("This is not a chunked upload request.");
167 }
168 if (mUrlRequestAdapter == 0) {
169 throw new IOException("Native peer destroyed.");
170 }
171 nativeAppendChunk(mUrlRequestAdapter, chunk, chunk.limit(), isLastCh unk);
172 // Wait for the data to be actually consumed.
173 try {
174 mAppendChunkSemaphore.acquire();
175 } catch (InterruptedException e) {
176 // We were interrupted before the data was uploaded. Recovering
177 // from this state is complicated so we cancel the upload
178 // operation and fail.
179 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.
180
181 // TODO(miloslav): Not sure why do we set mSinkException here.
182 mSinkException = new IOException("Upload interrupted", e);
183 cancel();
184 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
185 }
186 }
187 }
188
136 public void setHttpMethod(String method) { 189 public void setHttpMethod(String method) {
137 validateNotStarted(); 190 validateNotStarted();
138 if (!("PUT".equals(method) || "POST".equals(method))) { 191 if (!("PUT".equals(method) || "POST".equals(method))) {
139 throw new IllegalArgumentException("Only PUT or POST are allowed."); 192 throw new IllegalArgumentException("Only PUT or POST are allowed.");
140 } 193 }
141 mMethod = method; 194 mMethod = method;
142 } 195 }
143 196
144 public WritableByteChannel getSink() { 197 public WritableByteChannel getSink() {
145 return mSink; 198 return mSink;
146 } 199 }
147 200
148 public void start() { 201 public void start() {
149 synchronized (mLock) { 202 synchronized (mLock) {
150 if (mCanceled) { 203 if (mCanceled) {
151 return; 204 return;
152 } 205 }
153 206
154 validateNotStarted(); 207 validateNotStarted();
155 validateNotRecycled(); 208 validateNotRecycled();
156 209
157 mStarted = true; 210 mStarted = true;
158 211
159 String method = mMethod; 212 String method = mMethod;
160 if (method == null && 213 if (method == null &&
161 ((mUploadData != null && mUploadData.length > 0) || 214 ((mUploadData != null && mUploadData.length > 0) ||
162 mUploadChannel != null)) { 215 mUploadChannel != null || mAppendChunkSemaphore != null)) {
163 // Default to POST if there is data to upload but no method was 216 // Default to POST if there is data to upload but no method was
164 // specified. 217 // specified.
165 method = "POST"; 218 method = "POST";
166 } 219 }
167 220
168 if (method != null) { 221 if (method != null) {
169 nativeSetMethod(mUrlRequestAdapter, method); 222 nativeSetMethod(mUrlRequestAdapter, method);
170 } 223 }
171 224
172 if (mHeaders != null && !mHeaders.isEmpty()) { 225 if (mHeaders != null && !mHeaders.isEmpty()) {
(...skipping 10 matching lines...) Expand all
183 entry.getValue()); 236 entry.getValue());
184 } 237 }
185 } 238 }
186 239
187 if (mUploadData != null && mUploadData.length > 0) { 240 if (mUploadData != null && mUploadData.length > 0) {
188 nativeSetUploadData(mUrlRequestAdapter, mUploadContentType, 241 nativeSetUploadData(mUrlRequestAdapter, mUploadContentType,
189 mUploadData); 242 mUploadData);
190 } else if (mUploadChannel != null) { 243 } else if (mUploadChannel != null) {
191 nativeSetUploadChannel(mUrlRequestAdapter, mUploadContentType, 244 nativeSetUploadChannel(mUrlRequestAdapter, mUploadContentType,
192 mUploadContentLength); 245 mUploadContentLength);
246 } else if (mAppendChunkSemaphore != null) {
247 nativeEnableChunkedUpload(mUrlRequestAdapter,
248 mUploadContentType);
193 } 249 }
194 250
195 nativeStart(mUrlRequestAdapter); 251 nativeStart(mUrlRequestAdapter);
196 } 252 }
197 } 253 }
198 254
199 public void cancel() { 255 public void cancel() {
200 synchronized (mLock) { 256 synchronized (mLock) {
201 if (mCanceled) { 257 if (mCanceled) {
202 return; 258 return;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 337
282 // All response headers. 338 // All response headers.
283 public Map<String, List<String>> getAllHeaders() { 339 public Map<String, List<String>> getAllHeaders() {
284 validateHeadersAvailable(); 340 validateHeadersAvailable();
285 ResponseHeadersMap result = new ResponseHeadersMap(); 341 ResponseHeadersMap result = new ResponseHeadersMap();
286 nativeGetAllHeaders(mUrlRequestAdapter, result); 342 nativeGetAllHeaders(mUrlRequestAdapter, result);
287 return result; 343 return result;
288 } 344 }
289 345
290 /** 346 /**
347 * A callback invoked when appending a chunk to the request has completed.
348 */
349 @CalledByNative
350 protected void onAppendChunkCompleted() {
351 mAppendChunkSemaphore.release();
352 }
353
354 /**
291 * A callback invoked when the first chunk of the response has arrived. 355 * A callback invoked when the first chunk of the response has arrived.
292 */ 356 */
293 @CalledByNative 357 @CalledByNative
294 protected void onResponseStarted() { 358 protected void onResponseStarted() {
295 mContentType = nativeGetContentType(mUrlRequestAdapter); 359 mContentType = nativeGetContentType(mUrlRequestAdapter);
296 mContentLength = nativeGetContentLength(mUrlRequestAdapter); 360 mContentLength = nativeGetContentLength(mUrlRequestAdapter);
297 mHeadersAvailable = true; 361 mHeadersAvailable = true;
298 } 362 }
299 363
300 /** 364 /**
(...skipping 22 matching lines...) Expand all
323 } 387 }
324 388
325 /** 389 /**
326 * Notifies the listener, releases native data structures. 390 * Notifies the listener, releases native data structures.
327 */ 391 */
328 @SuppressWarnings("unused") 392 @SuppressWarnings("unused")
329 @CalledByNative 393 @CalledByNative
330 private void finish() { 394 private void finish() {
331 synchronized (mLock) { 395 synchronized (mLock) {
332 mFinished = true; 396 mFinished = true;
397 if (mAppendChunkSemaphore != null) {
398 mAppendChunkSemaphore.release();
399 }
333 400
334 if (mRecycled) { 401 if (mRecycled) {
335 return; 402 return;
336 } 403 }
337 try { 404 try {
338 mSink.close(); 405 mSink.close();
339 } catch (IOException e) { 406 } catch (IOException e) {
340 // Ignore 407 // Ignore
341 } 408 }
342 onRequestComplete(); 409 onRequestComplete();
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 String value); 485 String value);
419 486
420 private native void nativeSetMethod(long urlRequestAdapter, String method); 487 private native void nativeSetMethod(long urlRequestAdapter, String method);
421 488
422 private native void nativeSetUploadData(long urlRequestAdapter, 489 private native void nativeSetUploadData(long urlRequestAdapter,
423 String contentType, byte[] content); 490 String contentType, byte[] content);
424 491
425 private native void nativeSetUploadChannel(long urlRequestAdapter, 492 private native void nativeSetUploadChannel(long urlRequestAdapter,
426 String contentType, long contentLength); 493 String contentType, long contentLength);
427 494
495 private native void nativeEnableChunkedUpload(long urlRequestAdapter,
496 String contentType);
497
498 private native void nativeAppendChunk(long urlRequestAdapter, ByteBuffer chu nk,
mef 2014/08/15 13:30:22 nit: limit line length to 80.
mdumitrescu 2014/08/15 15:23:12 Done.
499 int chunkSize, boolean isLastChunk);
500
428 private native void nativeStart(long urlRequestAdapter); 501 private native void nativeStart(long urlRequestAdapter);
429 502
430 private native void nativeCancel(long urlRequestAdapter); 503 private native void nativeCancel(long urlRequestAdapter);
431 504
432 private native void nativeDestroyRequestAdapter(long urlRequestAdapter); 505 private native void nativeDestroyRequestAdapter(long urlRequestAdapter);
433 506
434 private native int nativeGetErrorCode(long urlRequestAdapter); 507 private native int nativeGetErrorCode(long urlRequestAdapter);
435 508
436 private native int nativeGetHttpStatusCode(long urlRequestAdapter); 509 private native int nativeGetHttpStatusCode(long urlRequestAdapter);
437 510
438 private native String nativeGetErrorString(long urlRequestAdapter); 511 private native String nativeGetErrorString(long urlRequestAdapter);
439 512
440 private native String nativeGetContentType(long urlRequestAdapter); 513 private native String nativeGetContentType(long urlRequestAdapter);
441 514
442 private native long nativeGetContentLength(long urlRequestAdapter); 515 private native long nativeGetContentLength(long urlRequestAdapter);
443 516
444 private native String nativeGetHeader(long urlRequestAdapter, String name); 517 private native String nativeGetHeader(long urlRequestAdapter, String name);
445 518
446 private native void nativeGetAllHeaders(long urlRequestAdapter, 519 private native void nativeGetAllHeaders(long urlRequestAdapter,
447 ResponseHeadersMap headers); 520 ResponseHeadersMap headers);
448 521
449 // Explicit class to work around JNI-generator generics confusion. 522 // Explicit class to work around JNI-generator generics confusion.
450 private class ResponseHeadersMap extends HashMap<String, List<String>> { 523 private class ResponseHeadersMap extends HashMap<String, List<String>> {
451 } 524 }
525
mef 2014/08/15 13:30:22 nit: spurious nl?
mdumitrescu 2014/08/15 15:23:12 Done.
452 } 526 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698