| 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 |