| Index: net/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java
|
| diff --git a/net/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java b/net/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java
|
| deleted file mode 100644
|
| index 21ce9c94bf196dfd40d18dee435d17c47a51b28c..0000000000000000000000000000000000000000
|
| --- a/net/cronet/android/java/src/org/chromium/net/HttpUrlConnectionUrlRequest.java
|
| +++ /dev/null
|
| @@ -1,433 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package org.chromium.net;
|
| -
|
| -import android.content.Context;
|
| -import android.text.TextUtils;
|
| -
|
| -import org.apache.http.HttpStatus;
|
| -
|
| -import java.io.FileNotFoundException;
|
| -import java.io.IOException;
|
| -import java.io.InputStream;
|
| -import java.io.OutputStream;
|
| -import java.net.HttpURLConnection;
|
| -import java.net.URL;
|
| -import java.nio.ByteBuffer;
|
| -import java.nio.channels.ReadableByteChannel;
|
| -import java.nio.channels.WritableByteChannel;
|
| -import java.util.Map;
|
| -import java.util.Map.Entry;
|
| -import java.util.concurrent.ExecutorService;
|
| -import java.util.concurrent.Executors;
|
| -import java.util.concurrent.ThreadFactory;
|
| -import java.util.concurrent.atomic.AtomicInteger;
|
| -import java.util.zip.GZIPInputStream;
|
| -
|
| -/**
|
| - * Network request using the HttpUrlConnection implementation.
|
| - */
|
| -class HttpUrlConnectionUrlRequest implements HttpUrlRequest {
|
| -
|
| - private static final int MAX_CHUNK_SIZE = 8192;
|
| -
|
| - private static final int CONNECT_TIMEOUT = 3000;
|
| -
|
| - private static final int READ_TIMEOUT = 90000;
|
| -
|
| - private final Context mContext;
|
| -
|
| - private final String mUrl;
|
| -
|
| - private final Map<String, String> mHeaders;
|
| -
|
| - private final WritableByteChannel mSink;
|
| -
|
| - private final HttpUrlRequestListener mListener;
|
| -
|
| - private IOException mException;
|
| -
|
| - private HttpURLConnection mConnection;
|
| -
|
| - private long mOffset;
|
| -
|
| - private int mContentLength;
|
| -
|
| - private long mContentLengthLimit;
|
| -
|
| - private boolean mCancelIfContentLengthOverLimit;
|
| -
|
| - private boolean mContentLengthOverLimit;
|
| -
|
| - private boolean mSkippingToOffset;
|
| -
|
| - private long mSize;
|
| -
|
| - private String mPostContentType;
|
| -
|
| - private byte[] mPostData;
|
| -
|
| - private ReadableByteChannel mPostDataChannel;
|
| -
|
| - private String mContentType;
|
| -
|
| - private int mHttpStatusCode;
|
| -
|
| - private boolean mStarted;
|
| -
|
| - private boolean mCanceled;
|
| -
|
| - private InputStream mResponseStream;
|
| -
|
| - private final Object mLock;
|
| -
|
| - private static ExecutorService sExecutorService;
|
| -
|
| - private static final Object sExecutorServiceLock = new Object();
|
| -
|
| - HttpUrlConnectionUrlRequest(Context context, String url,
|
| - int requestPriority, Map<String, String> headers,
|
| - HttpUrlRequestListener listener) {
|
| - this(context, url, requestPriority, headers,
|
| - new ChunkedWritableByteChannel(), listener);
|
| - }
|
| -
|
| - HttpUrlConnectionUrlRequest(Context context, String url,
|
| - int requestPriority, Map<String, String> headers,
|
| - WritableByteChannel sink, HttpUrlRequestListener listener) {
|
| - if (context == null) {
|
| - throw new NullPointerException("Context is required");
|
| - }
|
| - if (url == null) {
|
| - throw new NullPointerException("URL is required");
|
| - }
|
| - mContext = context;
|
| - mUrl = url;
|
| - mHeaders = headers;
|
| - mSink = sink;
|
| - mListener = listener;
|
| - mLock = new Object();
|
| - }
|
| -
|
| - private static ExecutorService getExecutor() {
|
| - synchronized (sExecutorServiceLock) {
|
| - if (sExecutorService == null) {
|
| - ThreadFactory threadFactory = new ThreadFactory() {
|
| - private final AtomicInteger mCount = new AtomicInteger(1);
|
| -
|
| - @Override
|
| - public Thread newThread(Runnable r) {
|
| - Thread thread = new Thread(r,
|
| - "HttpUrlConnection #" +
|
| - mCount.getAndIncrement());
|
| - // Note that this thread is not doing actual networking.
|
| - // It's only a controller.
|
| - thread.setPriority(Thread.NORM_PRIORITY);
|
| - return thread;
|
| - }
|
| - };
|
| - sExecutorService = Executors.newCachedThreadPool(threadFactory);
|
| - }
|
| - return sExecutorService;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public String getUrl() {
|
| - return mUrl;
|
| - }
|
| -
|
| - @Override
|
| - public void setOffset(long offset) {
|
| - mOffset = offset;
|
| - }
|
| -
|
| - @Override
|
| - public void setContentLengthLimit(long limit, boolean cancelEarly) {
|
| - mContentLengthLimit = limit;
|
| - mCancelIfContentLengthOverLimit = cancelEarly;
|
| - }
|
| -
|
| - @Override
|
| - public void setUploadData(String contentType, byte[] data) {
|
| - validateNotStarted();
|
| - mPostContentType = contentType;
|
| - mPostData = data;
|
| - mPostDataChannel = null;
|
| - }
|
| -
|
| - @Override
|
| - public void setUploadChannel(String contentType,
|
| - ReadableByteChannel channel) {
|
| - validateNotStarted();
|
| - mPostContentType = contentType;
|
| - mPostDataChannel = channel;
|
| - mPostData = null;
|
| - }
|
| -
|
| - @Override
|
| - public void start() {
|
| - boolean readingResponse = false;
|
| - try {
|
| - synchronized (mLock) {
|
| - if (mCanceled) {
|
| - return;
|
| - }
|
| - }
|
| -
|
| - URL url = new URL(mUrl);
|
| - mConnection = (HttpURLConnection)url.openConnection();
|
| - mConnection.setConnectTimeout(CONNECT_TIMEOUT);
|
| - mConnection.setReadTimeout(READ_TIMEOUT);
|
| - mConnection.setInstanceFollowRedirects(true);
|
| - if (mHeaders != null) {
|
| - for (Entry<String, String> header : mHeaders.entrySet()) {
|
| - mConnection.setRequestProperty(header.getKey(),
|
| - header.getValue());
|
| - }
|
| - }
|
| -
|
| - if (mOffset != 0) {
|
| - mConnection.setRequestProperty("Range",
|
| - "bytes=" + mOffset + "-");
|
| - }
|
| -
|
| - if (mConnection.getRequestProperty("User-Agent") == null) {
|
| - mConnection.setRequestProperty("User-Agent",
|
| - UserAgent.from(mContext));
|
| - }
|
| -
|
| - if (mPostData != null || mPostDataChannel != null) {
|
| - uploadData();
|
| - }
|
| -
|
| - InputStream stream = null;
|
| - try {
|
| - // We need to open the stream before asking for the response
|
| - // code.
|
| - stream = mConnection.getInputStream();
|
| - } catch (FileNotFoundException ex) {
|
| - // Ignore - the response has no body.
|
| - }
|
| -
|
| - mHttpStatusCode = mConnection.getResponseCode();
|
| - mContentType = mConnection.getContentType();
|
| - mContentLength = mConnection.getContentLength();
|
| - if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit
|
| - && mCancelIfContentLengthOverLimit) {
|
| - onContentLengthOverLimit();
|
| - return;
|
| - }
|
| -
|
| - mResponseStream = isError(mHttpStatusCode) ? mConnection
|
| - .getErrorStream()
|
| - : stream;
|
| -
|
| - if (mResponseStream != null
|
| - && "gzip".equals(mConnection.getContentEncoding())) {
|
| - mResponseStream = new GZIPInputStream(mResponseStream);
|
| - mContentLength = -1;
|
| - }
|
| -
|
| - if (mOffset != 0) {
|
| - // The server may ignore the request for a byte range.
|
| - if (mHttpStatusCode == HttpStatus.SC_OK) {
|
| - if (mContentLength != -1) {
|
| - mContentLength -= mOffset;
|
| - }
|
| - mSkippingToOffset = true;
|
| - } else {
|
| - mSize = mOffset;
|
| - }
|
| - }
|
| -
|
| - if (mResponseStream != null) {
|
| - readingResponse = true;
|
| - readResponseAsync();
|
| - }
|
| - } catch (IOException e) {
|
| - mException = e;
|
| - } finally {
|
| - // Don't call onRequestComplete yet if we are reading the response
|
| - // on a separate thread
|
| - if (!readingResponse) {
|
| - mListener.onRequestComplete(this);
|
| - }
|
| - }
|
| - }
|
| -
|
| - private void uploadData() throws IOException {
|
| - mConnection.setDoOutput(true);
|
| - if (!TextUtils.isEmpty(mPostContentType)) {
|
| - mConnection.setRequestProperty("Content-Type", mPostContentType);
|
| - }
|
| -
|
| - OutputStream uploadStream = null;
|
| - try {
|
| - if (mPostData != null) {
|
| - mConnection.setFixedLengthStreamingMode(mPostData.length);
|
| - uploadStream = mConnection.getOutputStream();
|
| - uploadStream.write(mPostData);
|
| - } else {
|
| - mConnection.setChunkedStreamingMode(MAX_CHUNK_SIZE);
|
| - uploadStream = mConnection.getOutputStream();
|
| - byte[] bytes = new byte[MAX_CHUNK_SIZE];
|
| - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
| - while (mPostDataChannel.read(byteBuffer) > 0) {
|
| - byteBuffer.flip();
|
| - uploadStream.write(bytes, 0, byteBuffer.limit());
|
| - byteBuffer.clear();
|
| - }
|
| - }
|
| - } finally {
|
| - if (uploadStream != null) {
|
| - uploadStream.close();
|
| - }
|
| - }
|
| - }
|
| -
|
| - private void readResponseAsync() {
|
| - getExecutor().execute(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - readResponse();
|
| - }
|
| - });
|
| - }
|
| -
|
| - private void readResponse() {
|
| - try {
|
| - if (mResponseStream != null) {
|
| - readResponseStream();
|
| - }
|
| - } catch (IOException e) {
|
| - mException = e;
|
| - } finally {
|
| - try {
|
| - mConnection.disconnect();
|
| - } catch (ArrayIndexOutOfBoundsException t) {
|
| - // Ignore it.
|
| - }
|
| -
|
| - try {
|
| - mSink.close();
|
| - } catch (IOException e) {
|
| - if (mException == null) {
|
| - mException = e;
|
| - }
|
| - }
|
| - }
|
| - mListener.onRequestComplete(this);
|
| - }
|
| -
|
| - private void readResponseStream() throws IOException {
|
| - byte[] buffer = new byte[MAX_CHUNK_SIZE];
|
| - int size;
|
| - while (!isCanceled() && (size = mResponseStream.read(buffer)) != -1) {
|
| - int start = 0;
|
| - int count = size;
|
| - mSize += size;
|
| - if (mSkippingToOffset) {
|
| - if (mSize <= mOffset) {
|
| - continue;
|
| - } else {
|
| - mSkippingToOffset = false;
|
| - start = (int)(mOffset - (mSize - size));
|
| - count -= start;
|
| - }
|
| - }
|
| -
|
| - if (mContentLengthLimit != 0 && mSize > mContentLengthLimit) {
|
| - count -= (int)(mSize - mContentLengthLimit);
|
| - if (count > 0) {
|
| - mSink.write(ByteBuffer.wrap(buffer, start, count));
|
| - }
|
| - onContentLengthOverLimit();
|
| - return;
|
| - }
|
| -
|
| - mSink.write(ByteBuffer.wrap(buffer, start, count));
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void cancel() {
|
| - synchronized (mLock) {
|
| - if (mCanceled) {
|
| - return;
|
| - }
|
| -
|
| - mCanceled = true;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public boolean isCanceled() {
|
| - synchronized (mLock) {
|
| - return mCanceled;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public int getHttpStatusCode() {
|
| - int httpStatusCode = mHttpStatusCode;
|
| -
|
| - // If we have been able to successfully resume a previously interrupted
|
| - // download,
|
| - // the status code will be 206, not 200. Since the rest of the
|
| - // application is
|
| - // expecting 200 to indicate success, we need to fake it.
|
| - if (httpStatusCode == HttpStatus.SC_PARTIAL_CONTENT) {
|
| - httpStatusCode = HttpStatus.SC_OK;
|
| - }
|
| - return httpStatusCode;
|
| - }
|
| -
|
| - @Override
|
| - public IOException getException() {
|
| - if (mException == null && mContentLengthOverLimit) {
|
| - mException = new ResponseTooLargeException();
|
| - }
|
| - return mException;
|
| - }
|
| -
|
| - private void onContentLengthOverLimit() {
|
| - mContentLengthOverLimit = true;
|
| - cancel();
|
| - }
|
| -
|
| - private static boolean isError(int statusCode) {
|
| - return (statusCode / 100) != 2;
|
| - }
|
| -
|
| - /**
|
| - * Returns the response as a ByteBuffer.
|
| - */
|
| - @Override
|
| - public ByteBuffer getByteBuffer() {
|
| - return ((ChunkedWritableByteChannel)mSink).getByteBuffer();
|
| - }
|
| -
|
| - @Override
|
| - public byte[] getResponseAsBytes() {
|
| - return ((ChunkedWritableByteChannel)mSink).getBytes();
|
| - }
|
| -
|
| - @Override
|
| - public long getContentLength() {
|
| - return mContentLength;
|
| - }
|
| -
|
| - @Override
|
| - public String getContentType() {
|
| - return mContentType;
|
| - }
|
| -
|
| - private void validateNotStarted() {
|
| - if (mStarted) {
|
| - throw new IllegalStateException("Request already started");
|
| - }
|
| - }
|
| -}
|
|
|