OLD | NEW |
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 |
(...skipping 17 matching lines...) Expand all Loading... |
28 public class UrlRequest { | 28 public class UrlRequest { |
29 private static final class ContextLock { | 29 private static final class ContextLock { |
30 } | 30 } |
31 | 31 |
32 private final UrlRequestContext mRequestContext; | 32 private final UrlRequestContext mRequestContext; |
33 private final String mUrl; | 33 private final String mUrl; |
34 private final int mPriority; | 34 private final int mPriority; |
35 private final Map<String, String> mHeaders; | 35 private final Map<String, String> mHeaders; |
36 private final WritableByteChannel mSink; | 36 private final WritableByteChannel mSink; |
37 private Map<String, String> mAdditionalHeaders; | 37 private Map<String, String> mAdditionalHeaders; |
38 private String mPostBodyContentType; | 38 private String mUploadContentType; |
39 private String mMethod; | 39 private String mMethod; |
40 private byte[] mPostBody; | 40 private byte[] mUploadData; |
41 private ReadableByteChannel mPostBodyChannel; | 41 private ReadableByteChannel mUploadChannel; |
42 private WritableByteChannel mOutputChannel; | 42 private WritableByteChannel mOutputChannel; |
43 private IOException mSinkException; | 43 private IOException mSinkException; |
44 private volatile boolean mStarted; | 44 private volatile boolean mStarted; |
45 private volatile boolean mCanceled; | 45 private volatile boolean mCanceled; |
46 private volatile boolean mRecycled; | 46 private volatile boolean mRecycled; |
47 private volatile boolean mFinished; | 47 private volatile boolean mFinished; |
48 private boolean mHeadersAvailable; | 48 private boolean mHeadersAvailable; |
49 private String mContentType; | 49 private String mContentType; |
50 private long mContentLength; | 50 private long mContentLength; |
51 private long mUploadContentLength; | 51 private long mUploadContentLength; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 * Sets data to upload as part of a POST request. | 100 * Sets data to upload as part of a POST request. |
101 * | 101 * |
102 * @param contentType MIME type of the post content or null if this is not a | 102 * @param contentType MIME type of the post content or null if this is not a |
103 * POST. | 103 * POST. |
104 * @param data The content that needs to be uploaded if this is a POST | 104 * @param data The content that needs to be uploaded if this is a POST |
105 * request. | 105 * request. |
106 */ | 106 */ |
107 public void setUploadData(String contentType, byte[] data) { | 107 public void setUploadData(String contentType, byte[] data) { |
108 synchronized (mLock) { | 108 synchronized (mLock) { |
109 validateNotStarted(); | 109 validateNotStarted(); |
110 mPostBodyContentType = contentType; | 110 mUploadContentType = contentType; |
111 mPostBody = data; | 111 mUploadData = data; |
112 mPostBodyChannel = null; | 112 mUploadChannel = null; |
113 } | 113 } |
114 } | 114 } |
115 | 115 |
116 /** | 116 /** |
117 * Sets a readable byte channel to upload as part of a POST request. | 117 * Sets a readable byte channel to upload as part of a POST request. |
118 * | 118 * |
119 * @param contentType MIME type of the post content or null if this is not a | 119 * @param contentType MIME type of the post content or null if this is not a |
120 * POST request. | 120 * POST request. |
121 * @param channel The channel to read to read upload data from if this is a | 121 * @param channel The channel to read to read upload data from if this is a |
122 * POST request. | 122 * POST request. |
123 * @param contentLength The length of data to upload. | 123 * @param contentLength The length of data to upload. |
124 */ | 124 */ |
125 public void setUploadChannel(String contentType, | 125 public void setUploadChannel(String contentType, |
126 ReadableByteChannel channel, long contentLength) { | 126 ReadableByteChannel channel, long contentLength) { |
127 synchronized (mLock) { | 127 synchronized (mLock) { |
128 validateNotStarted(); | 128 validateNotStarted(); |
129 mPostBodyContentType = contentType; | 129 mUploadContentType = contentType; |
130 mPostBodyChannel = channel; | 130 mUploadChannel = channel; |
131 mUploadContentLength = contentLength; | 131 mUploadContentLength = contentLength; |
132 mPostBody = null; | 132 mUploadData = null; |
133 } | 133 } |
134 } | 134 } |
135 | 135 |
136 public void setHttpMethod(String method) { | 136 public void setHttpMethod(String method) { |
137 validateNotStarted(); | 137 validateNotStarted(); |
138 if (!("PUT".equals(method) || "POST".equals(method))) { | 138 if (!("PUT".equals(method) || "POST".equals(method))) { |
139 throw new IllegalArgumentException("Only PUT and POST are allowed.")
; | 139 throw new IllegalArgumentException("Only PUT and POST are allowed.")
; |
140 } | 140 } |
141 mMethod = method; | 141 mMethod = method; |
142 } | 142 } |
143 | 143 |
144 public WritableByteChannel getSink() { | 144 public WritableByteChannel getSink() { |
145 return mSink; | 145 return mSink; |
146 } | 146 } |
147 | 147 |
148 public void start() { | 148 public void start() { |
149 synchronized (mLock) { | 149 synchronized (mLock) { |
150 if (mCanceled) { | 150 if (mCanceled) { |
151 return; | 151 return; |
152 } | 152 } |
153 | 153 |
154 validateNotStarted(); | 154 validateNotStarted(); |
155 validateNotRecycled(); | 155 validateNotRecycled(); |
156 | 156 |
157 mStarted = true; | 157 mStarted = true; |
158 | 158 |
159 String method = mMethod; | 159 String method = mMethod; |
160 if (method == null && | 160 if (method == null && |
161 ((mPostBody != null && mPostBody.length > 0) || | 161 ((mUploadData != null && mUploadData.length > 0) || |
162 mPostBodyChannel != null)) { | 162 mUploadChannel != null)) { |
163 // Default to POST if there is data to upload but no method was | 163 // Default to POST if there is data to upload but no method was |
164 // specified. | 164 // specified. |
165 method = "POST"; | 165 method = "POST"; |
166 } | 166 } |
167 | 167 |
168 if (method != null) { | 168 if (method != null) { |
169 nativeSetMethod(mUrlRequestPeer, method); | 169 nativeSetMethod(mUrlRequestPeer, method); |
170 } | 170 } |
171 | 171 |
172 if (mHeaders != null && !mHeaders.isEmpty()) { | 172 if (mHeaders != null && !mHeaders.isEmpty()) { |
173 for (Entry<String, String> entry : mHeaders.entrySet()) { | 173 for (Entry<String, String> entry : mHeaders.entrySet()) { |
174 nativeAddHeader(mUrlRequestPeer, entry.getKey(), | 174 nativeAddHeader(mUrlRequestPeer, entry.getKey(), |
175 entry.getValue()); | 175 entry.getValue()); |
176 } | 176 } |
177 } | 177 } |
178 | 178 |
179 if (mAdditionalHeaders != null) { | 179 if (mAdditionalHeaders != null) { |
180 for (Entry<String, String> entry : | 180 for (Entry<String, String> entry : |
181 mAdditionalHeaders.entrySet()) { | 181 mAdditionalHeaders.entrySet()) { |
182 nativeAddHeader(mUrlRequestPeer, entry.getKey(), | 182 nativeAddHeader(mUrlRequestPeer, entry.getKey(), |
183 entry.getValue()); | 183 entry.getValue()); |
184 } | 184 } |
185 } | 185 } |
186 | 186 |
187 if (mPostBody != null && mPostBody.length > 0) { | 187 if (mUploadData != null && mUploadData.length > 0) { |
188 nativeSetUploadData(mUrlRequestPeer, mPostBodyContentType, | 188 nativeSetUploadData(mUrlRequestPeer, mUploadContentType, |
189 mPostBody); | 189 mUploadData); |
190 } else if (mPostBodyChannel != null) { | 190 } else if (mUploadChannel != null) { |
191 nativeSetUploadChannel(mUrlRequestPeer, mPostBodyContentType, | 191 nativeSetUploadChannel(mUrlRequestPeer, mUploadContentType, |
192 mPostBodyChannel, mUploadContentLength); | 192 mUploadContentLength); |
193 } | 193 } |
194 | 194 |
195 nativeStart(mUrlRequestPeer); | 195 nativeStart(mUrlRequestPeer); |
196 } | 196 } |
197 } | 197 } |
198 | 198 |
199 public void cancel() { | 199 public void cancel() { |
200 synchronized (mLock) { | 200 synchronized (mLock) { |
201 if (mCanceled) { | 201 if (mCanceled) { |
202 return; | 202 return; |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 @SuppressWarnings("unused") | 351 @SuppressWarnings("unused") |
352 @CalledByNative | 352 @CalledByNative |
353 private void onAppendResponseHeader(ResponseHeadersMap headersMap, | 353 private void onAppendResponseHeader(ResponseHeadersMap headersMap, |
354 String name, String value) { | 354 String name, String value) { |
355 if (!headersMap.containsKey(name)) { | 355 if (!headersMap.containsKey(name)) { |
356 headersMap.put(name, new ArrayList<String>()); | 356 headersMap.put(name, new ArrayList<String>()); |
357 } | 357 } |
358 headersMap.get(name).add(value); | 358 headersMap.get(name).add(value); |
359 } | 359 } |
360 | 360 |
| 361 /** |
| 362 * Reads a sequence of bytes from upload channel into the given buffer. |
| 363 * @param dest The buffer into which bytes are to be transferred. |
| 364 * @return Returns number of bytes read (could be 0) or -1 and closes |
| 365 * the channel if error occured. |
| 366 */ |
| 367 @SuppressWarnings("unused") |
| 368 @CalledByNative |
| 369 private int readFromUploadChannel(ByteBuffer dest) { |
| 370 if (mUploadChannel == null || !mUploadChannel.isOpen()) |
| 371 return -1; |
| 372 try { |
| 373 int result = mUploadChannel.read(dest); |
| 374 if (result < 0) { |
| 375 mUploadChannel.close(); |
| 376 return 0; |
| 377 } |
| 378 return result; |
| 379 } catch (IOException e) { |
| 380 mSinkException = e; |
| 381 try { |
| 382 mUploadChannel.close(); |
| 383 } catch (IOException ignored) { |
| 384 // Ignore this exception. |
| 385 } |
| 386 cancel(); |
| 387 return -1; |
| 388 } |
| 389 } |
| 390 |
361 private void validateNotRecycled() { | 391 private void validateNotRecycled() { |
362 if (mRecycled) { | 392 if (mRecycled) { |
363 throw new IllegalStateException("Accessing recycled request"); | 393 throw new IllegalStateException("Accessing recycled request"); |
364 } | 394 } |
365 } | 395 } |
366 | 396 |
367 private void validateNotStarted() { | 397 private void validateNotStarted() { |
368 if (mStarted) { | 398 if (mStarted) { |
369 throw new IllegalStateException("Request already started"); | 399 throw new IllegalStateException("Request already started"); |
370 } | 400 } |
(...skipping 14 matching lines...) Expand all Loading... |
385 | 415 |
386 private native void nativeAddHeader(long urlRequestPeer, String name, | 416 private native void nativeAddHeader(long urlRequestPeer, String name, |
387 String value); | 417 String value); |
388 | 418 |
389 private native void nativeSetMethod(long urlRequestPeer, String method); | 419 private native void nativeSetMethod(long urlRequestPeer, String method); |
390 | 420 |
391 private native void nativeSetUploadData(long urlRequestPeer, | 421 private native void nativeSetUploadData(long urlRequestPeer, |
392 String contentType, byte[] content); | 422 String contentType, byte[] content); |
393 | 423 |
394 private native void nativeSetUploadChannel(long urlRequestPeer, | 424 private native void nativeSetUploadChannel(long urlRequestPeer, |
395 String contentType, ReadableByteChannel content, | 425 String contentType, long contentLength); |
396 long contentLength); | |
397 | 426 |
398 private native void nativeStart(long urlRequestPeer); | 427 private native void nativeStart(long urlRequestPeer); |
399 | 428 |
400 private native void nativeCancel(long urlRequestPeer); | 429 private native void nativeCancel(long urlRequestPeer); |
401 | 430 |
402 private native void nativeDestroyRequestPeer(long urlRequestPeer); | 431 private native void nativeDestroyRequestPeer(long urlRequestPeer); |
403 | 432 |
404 private native int nativeGetErrorCode(long urlRequestPeer); | 433 private native int nativeGetErrorCode(long urlRequestPeer); |
405 | 434 |
406 private native int nativeGetHttpStatusCode(long urlRequestPeer); | 435 private native int nativeGetHttpStatusCode(long urlRequestPeer); |
407 | 436 |
408 private native String nativeGetErrorString(long urlRequestPeer); | 437 private native String nativeGetErrorString(long urlRequestPeer); |
409 | 438 |
410 private native String nativeGetContentType(long urlRequestPeer); | 439 private native String nativeGetContentType(long urlRequestPeer); |
411 | 440 |
412 private native long nativeGetContentLength(long urlRequestPeer); | 441 private native long nativeGetContentLength(long urlRequestPeer); |
413 | 442 |
414 private native String nativeGetHeader(long urlRequestPeer, String name); | 443 private native String nativeGetHeader(long urlRequestPeer, String name); |
415 | 444 |
416 private native void nativeGetAllHeaders(long urlRequestPeer, | 445 private native void nativeGetAllHeaders(long urlRequestPeer, |
417 ResponseHeadersMap headers); | 446 ResponseHeadersMap headers); |
418 | 447 |
419 // Explicit class to work around JNI-generator generics confusion. | 448 // Explicit class to work around JNI-generator generics confusion. |
420 private class ResponseHeadersMap extends HashMap<String, List<String>> { | 449 private class ResponseHeadersMap extends HashMap<String, List<String>> { |
421 } | 450 } |
422 } | 451 } |
OLD | NEW |