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 android.content.Context; | 7 import android.content.Context; |
8 import android.text.TextUtils; | 8 import android.text.TextUtils; |
9 | 9 |
10 import org.apache.http.HttpStatus; | 10 import org.apache.http.HttpStatus; |
11 | 11 |
12 import java.io.FileNotFoundException; | 12 import java.io.FileNotFoundException; |
13 import java.io.IOException; | 13 import java.io.IOException; |
14 import java.io.InputStream; | 14 import java.io.InputStream; |
15 import java.io.OutputStream; | 15 import java.io.OutputStream; |
16 import java.net.HttpURLConnection; | 16 import java.net.HttpURLConnection; |
| 17 import java.net.ProtocolException; |
17 import java.net.URL; | 18 import java.net.URL; |
18 import java.nio.ByteBuffer; | 19 import java.nio.ByteBuffer; |
19 import java.nio.channels.ReadableByteChannel; | 20 import java.nio.channels.ReadableByteChannel; |
20 import java.nio.channels.WritableByteChannel; | 21 import java.nio.channels.WritableByteChannel; |
| 22 import java.util.List; |
21 import java.util.Map; | 23 import java.util.Map; |
22 import java.util.Map.Entry; | 24 import java.util.Map.Entry; |
23 import java.util.concurrent.ExecutorService; | 25 import java.util.concurrent.ExecutorService; |
24 import java.util.concurrent.Executors; | 26 import java.util.concurrent.Executors; |
25 import java.util.concurrent.ThreadFactory; | 27 import java.util.concurrent.ThreadFactory; |
26 import java.util.concurrent.atomic.AtomicInteger; | 28 import java.util.concurrent.atomic.AtomicInteger; |
27 import java.util.zip.GZIPInputStream; | 29 import java.util.zip.GZIPInputStream; |
28 | 30 |
29 /** | 31 /** |
30 * Network request using the HttpUrlConnection implementation. | 32 * Network request using the HttpUrlConnection implementation. |
(...skipping 17 matching lines...) Expand all Loading... |
48 private final HttpUrlRequestListener mListener; | 50 private final HttpUrlRequestListener mListener; |
49 | 51 |
50 private IOException mException; | 52 private IOException mException; |
51 | 53 |
52 private HttpURLConnection mConnection; | 54 private HttpURLConnection mConnection; |
53 | 55 |
54 private long mOffset; | 56 private long mOffset; |
55 | 57 |
56 private int mContentLength; | 58 private int mContentLength; |
57 | 59 |
| 60 private int mUploadContentLength; |
| 61 |
58 private long mContentLengthLimit; | 62 private long mContentLengthLimit; |
59 | 63 |
60 private boolean mCancelIfContentLengthOverLimit; | 64 private boolean mCancelIfContentLengthOverLimit; |
61 | 65 |
62 private boolean mContentLengthOverLimit; | 66 private boolean mContentLengthOverLimit; |
63 | 67 |
64 private boolean mSkippingToOffset; | 68 private boolean mSkippingToOffset; |
65 | 69 |
66 private long mSize; | 70 private long mSize; |
67 | 71 |
68 private String mPostContentType; | 72 private String mPostContentType; |
69 | 73 |
70 private byte[] mPostData; | 74 private byte[] mPostData; |
71 | 75 |
72 private ReadableByteChannel mPostDataChannel; | 76 private ReadableByteChannel mPostDataChannel; |
73 | 77 |
74 private String mContentType; | 78 private String mContentType; |
75 | 79 |
76 private int mHttpStatusCode; | 80 private int mHttpStatusCode; |
77 | 81 |
78 private boolean mStarted; | 82 private boolean mStarted; |
79 | 83 |
80 private boolean mCanceled; | 84 private boolean mCanceled; |
81 | 85 |
| 86 private String mMethod; |
| 87 |
82 private InputStream mResponseStream; | 88 private InputStream mResponseStream; |
83 | 89 |
84 private final Object mLock; | 90 private final Object mLock; |
85 | 91 |
86 private static ExecutorService sExecutorService; | 92 private static ExecutorService sExecutorService; |
87 | 93 |
88 private static final Object sExecutorServiceLock = new Object(); | 94 private static final Object sExecutorServiceLock = new Object(); |
89 | 95 |
90 HttpUrlConnectionUrlRequest(Context context, String url, | 96 HttpUrlConnectionUrlRequest(Context context, String url, |
91 int requestPriority, Map<String, String> headers, | 97 int requestPriority, Map<String, String> headers, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 validateNotStarted(); | 161 validateNotStarted(); |
156 mPostContentType = contentType; | 162 mPostContentType = contentType; |
157 mPostData = data; | 163 mPostData = data; |
158 mPostDataChannel = null; | 164 mPostDataChannel = null; |
159 } | 165 } |
160 | 166 |
161 @Override | 167 @Override |
162 public void setUploadChannel(String contentType, | 168 public void setUploadChannel(String contentType, |
163 ReadableByteChannel channel, long contentLength) { | 169 ReadableByteChannel channel, long contentLength) { |
164 validateNotStarted(); | 170 validateNotStarted(); |
| 171 if (contentLength > Integer.MAX_VALUE) { |
| 172 throw new IllegalArgumentException( |
| 173 "Upload contentLength is too big."); |
| 174 } |
| 175 mUploadContentLength = (int)contentLength; |
165 mPostContentType = contentType; | 176 mPostContentType = contentType; |
166 mPostDataChannel = channel; | 177 mPostDataChannel = channel; |
167 mPostData = null; | 178 mPostData = null; |
168 } | 179 } |
169 | 180 |
| 181 |
| 182 @Override |
| 183 public void setHttpMethod(String method) { |
| 184 validateNotStarted(); |
| 185 if (!("PUT".equals(method) || "POST".equals(method))) { |
| 186 throw new IllegalArgumentException( |
| 187 "Only PUT and POST are allowed."); |
| 188 } |
| 189 mMethod = method; |
| 190 } |
| 191 |
170 @Override | 192 @Override |
171 public void start() { | 193 public void start() { |
172 getExecutor().execute(new Runnable() { | 194 getExecutor().execute(new Runnable() { |
173 @Override | 195 @Override |
174 public void run() { | 196 public void run() { |
175 startOnExecutorThread(); | 197 startOnExecutorThread(); |
176 } | 198 } |
177 }); | 199 }); |
178 } | 200 } |
179 | 201 |
180 private void startOnExecutorThread() { | 202 private void startOnExecutorThread() { |
181 boolean readingResponse = false; | 203 boolean readingResponse = false; |
182 try { | 204 try { |
183 synchronized (mLock) { | 205 synchronized (mLock) { |
184 if (mCanceled) { | 206 if (mCanceled) { |
185 return; | 207 return; |
186 } | 208 } |
187 } | 209 } |
188 | 210 |
189 URL url = new URL(mUrl); | 211 URL url = new URL(mUrl); |
190 mConnection = (HttpURLConnection)url.openConnection(); | 212 mConnection = (HttpURLConnection)url.openConnection(); |
| 213 // If configured, use the provided http verb. |
| 214 if (mMethod != null) { |
| 215 try { |
| 216 mConnection.setRequestMethod(mMethod); |
| 217 } catch (ProtocolException e) { |
| 218 // Since request hasn't started earlier, it |
| 219 // must be an illegal HTTP verb. |
| 220 throw new IllegalArgumentException(e); |
| 221 } |
| 222 } |
191 mConnection.setConnectTimeout(CONNECT_TIMEOUT); | 223 mConnection.setConnectTimeout(CONNECT_TIMEOUT); |
192 mConnection.setReadTimeout(READ_TIMEOUT); | 224 mConnection.setReadTimeout(READ_TIMEOUT); |
193 mConnection.setInstanceFollowRedirects(true); | 225 mConnection.setInstanceFollowRedirects(true); |
194 if (mHeaders != null) { | 226 if (mHeaders != null) { |
195 for (Entry<String, String> header : mHeaders.entrySet()) { | 227 for (Entry<String, String> header : mHeaders.entrySet()) { |
196 mConnection.setRequestProperty(header.getKey(), | 228 mConnection.setRequestProperty(header.getKey(), |
197 header.getValue()); | 229 header.getValue()); |
198 } | 230 } |
199 } | 231 } |
200 | 232 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 mConnection.setRequestProperty("Content-Type", mPostContentType); | 315 mConnection.setRequestProperty("Content-Type", mPostContentType); |
284 } | 316 } |
285 | 317 |
286 OutputStream uploadStream = null; | 318 OutputStream uploadStream = null; |
287 try { | 319 try { |
288 if (mPostData != null) { | 320 if (mPostData != null) { |
289 mConnection.setFixedLengthStreamingMode(mPostData.length); | 321 mConnection.setFixedLengthStreamingMode(mPostData.length); |
290 uploadStream = mConnection.getOutputStream(); | 322 uploadStream = mConnection.getOutputStream(); |
291 uploadStream.write(mPostData); | 323 uploadStream.write(mPostData); |
292 } else { | 324 } else { |
293 mConnection.setChunkedStreamingMode(MAX_CHUNK_SIZE); | 325 mConnection.setFixedLengthStreamingMode(mUploadContentLength); |
294 uploadStream = mConnection.getOutputStream(); | 326 uploadStream = mConnection.getOutputStream(); |
295 byte[] bytes = new byte[MAX_CHUNK_SIZE]; | 327 byte[] bytes = new byte[MAX_CHUNK_SIZE]; |
296 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); | 328 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); |
297 while (mPostDataChannel.read(byteBuffer) > 0) { | 329 while (mPostDataChannel.read(byteBuffer) > 0) { |
298 byteBuffer.flip(); | 330 byteBuffer.flip(); |
299 uploadStream.write(bytes, 0, byteBuffer.limit()); | 331 uploadStream.write(bytes, 0, byteBuffer.limit()); |
300 byteBuffer.clear(); | 332 byteBuffer.clear(); |
301 } | 333 } |
302 } | 334 } |
303 } finally { | 335 } finally { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 public String getContentType() { | 475 public String getContentType() { |
444 return mContentType; | 476 return mContentType; |
445 } | 477 } |
446 | 478 |
447 | 479 |
448 @Override | 480 @Override |
449 public String getHeader(String name) { | 481 public String getHeader(String name) { |
450 if (mConnection == null) { | 482 if (mConnection == null) { |
451 throw new IllegalStateException("Response headers not available"); | 483 throw new IllegalStateException("Response headers not available"); |
452 } | 484 } |
453 return mConnection.getHeaderField(name); | 485 Map<String, List<String>> headerFields = mConnection.getHeaderFields(); |
| 486 if (headerFields != null) { |
| 487 List<String> headerValues = headerFields.get(name); |
| 488 if (headerValues != null) { |
| 489 return TextUtils.join(", ", headerValues); |
| 490 } |
| 491 } |
| 492 return null; |
454 } | 493 } |
455 | 494 |
456 private void validateNotStarted() { | 495 private void validateNotStarted() { |
457 if (mStarted) { | 496 if (mStarted) { |
458 throw new IllegalStateException("Request already started"); | 497 throw new IllegalStateException("Request already started"); |
459 } | 498 } |
460 } | 499 } |
461 } | 500 } |
OLD | NEW |