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 long 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 mUploadContentLength = contentLength; | |
165 mPostContentType = contentType; | 172 mPostContentType = contentType; |
166 mPostDataChannel = channel; | 173 mPostDataChannel = channel; |
167 mPostData = null; | 174 mPostData = null; |
168 } | 175 } |
169 | 176 |
177 | |
178 @Override | |
179 public void setHttpMethod(String method) { | |
180 validateNotStarted(); | |
181 if (!("PUT".equals(method) || "POST".equals(method))) { | |
182 throw new IllegalArgumentException( | |
183 "Only PUT and POST are allowed."); | |
184 } | |
185 mMethod = method; | |
186 } | |
187 | |
170 @Override | 188 @Override |
171 public void start() { | 189 public void start() { |
172 getExecutor().execute(new Runnable() { | 190 getExecutor().execute(new Runnable() { |
173 @Override | 191 @Override |
174 public void run() { | 192 public void run() { |
175 startOnExecutorThread(); | 193 startOnExecutorThread(); |
176 } | 194 } |
177 }); | 195 }); |
178 } | 196 } |
179 | 197 |
180 private void startOnExecutorThread() { | 198 private void startOnExecutorThread() { |
181 boolean readingResponse = false; | 199 boolean readingResponse = false; |
182 try { | 200 try { |
183 synchronized (mLock) { | 201 synchronized (mLock) { |
184 if (mCanceled) { | 202 if (mCanceled) { |
185 return; | 203 return; |
186 } | 204 } |
187 } | 205 } |
188 | 206 |
189 URL url = new URL(mUrl); | 207 URL url = new URL(mUrl); |
190 mConnection = (HttpURLConnection)url.openConnection(); | 208 mConnection = (HttpURLConnection)url.openConnection(); |
209 // If configured, use the provided http verb. | |
210 if (mMethod != null) { | |
211 try { | |
212 mConnection.setRequestMethod(mMethod); | |
213 } catch (ProtocolException e) { | |
214 // Since request hasn't started earlier, it | |
215 // must be an illegal HTTP verb. | |
216 throw new IllegalArgumentException(e); | |
217 } | |
218 } | |
191 mConnection.setConnectTimeout(CONNECT_TIMEOUT); | 219 mConnection.setConnectTimeout(CONNECT_TIMEOUT); |
192 mConnection.setReadTimeout(READ_TIMEOUT); | 220 mConnection.setReadTimeout(READ_TIMEOUT); |
193 mConnection.setInstanceFollowRedirects(true); | 221 mConnection.setInstanceFollowRedirects(true); |
194 if (mHeaders != null) { | 222 if (mHeaders != null) { |
195 for (Entry<String, String> header : mHeaders.entrySet()) { | 223 for (Entry<String, String> header : mHeaders.entrySet()) { |
196 mConnection.setRequestProperty(header.getKey(), | 224 mConnection.setRequestProperty(header.getKey(), |
197 header.getValue()); | 225 header.getValue()); |
198 } | 226 } |
199 } | 227 } |
200 | 228 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 mConnection.setRequestProperty("Content-Type", mPostContentType); | 311 mConnection.setRequestProperty("Content-Type", mPostContentType); |
284 } | 312 } |
285 | 313 |
286 OutputStream uploadStream = null; | 314 OutputStream uploadStream = null; |
287 try { | 315 try { |
288 if (mPostData != null) { | 316 if (mPostData != null) { |
289 mConnection.setFixedLengthStreamingMode(mPostData.length); | 317 mConnection.setFixedLengthStreamingMode(mPostData.length); |
290 uploadStream = mConnection.getOutputStream(); | 318 uploadStream = mConnection.getOutputStream(); |
291 uploadStream.write(mPostData); | 319 uploadStream.write(mPostData); |
292 } else { | 320 } else { |
293 mConnection.setChunkedStreamingMode(MAX_CHUNK_SIZE); | 321 mConnection.setFixedLengthStreamingMode( |
322 (int)mUploadContentLength); | |
mmenke
2014/07/11 20:04:05
Not really a big fan of casting and just crossing
mef
2014/07/14 15:02:17
Done.
| |
294 uploadStream = mConnection.getOutputStream(); | 323 uploadStream = mConnection.getOutputStream(); |
295 byte[] bytes = new byte[MAX_CHUNK_SIZE]; | 324 byte[] bytes = new byte[MAX_CHUNK_SIZE]; |
296 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); | 325 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); |
297 while (mPostDataChannel.read(byteBuffer) > 0) { | 326 while (mPostDataChannel.read(byteBuffer) > 0) { |
298 byteBuffer.flip(); | 327 byteBuffer.flip(); |
299 uploadStream.write(bytes, 0, byteBuffer.limit()); | 328 uploadStream.write(bytes, 0, byteBuffer.limit()); |
300 byteBuffer.clear(); | 329 byteBuffer.clear(); |
301 } | 330 } |
302 } | 331 } |
303 } finally { | 332 } finally { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
443 public String getContentType() { | 472 public String getContentType() { |
444 return mContentType; | 473 return mContentType; |
445 } | 474 } |
446 | 475 |
447 | 476 |
448 @Override | 477 @Override |
449 public String getHeader(String name) { | 478 public String getHeader(String name) { |
450 if (mConnection == null) { | 479 if (mConnection == null) { |
451 throw new IllegalStateException("Response headers not available"); | 480 throw new IllegalStateException("Response headers not available"); |
452 } | 481 } |
453 return mConnection.getHeaderField(name); | 482 Map<String, List<String>> headerFields = mConnection.getHeaderFields(); |
483 if (headerFields != null) { | |
484 List<String> headerValues = headerFields.get(name); | |
485 if (headerValues != null) { | |
486 return TextUtils.join(", ", headerValues); | |
487 } | |
488 } | |
489 return null; | |
454 } | 490 } |
455 | 491 |
456 private void validateNotStarted() { | 492 private void validateNotStarted() { |
457 if (mStarted) { | 493 if (mStarted) { |
458 throw new IllegalStateException("Request already started"); | 494 throw new IllegalStateException("Request already started"); |
459 } | 495 } |
460 } | 496 } |
461 } | 497 } |
OLD | NEW |