Chromium Code Reviews| 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 |