| Index: components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java
|
| diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java
|
| index 104b7220197f4a273da0dfc35d066254f8464087..a3d96b392892ae5b4027ba8ea581ecbd03787f02 100644
|
| --- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java
|
| +++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java
|
| @@ -5,7 +5,6 @@
|
| package org.chromium.net;
|
|
|
| import android.util.Log;
|
| -import android.util.Pair;
|
|
|
| import org.chromium.base.VisibleForTesting;
|
| import org.chromium.base.annotations.CalledByNative;
|
| @@ -14,11 +13,10 @@ import org.chromium.base.annotations.JNINamespace;
|
| import org.chromium.base.annotations.NativeClassQualifiedName;
|
|
|
| import java.nio.ByteBuffer;
|
| +import java.util.AbstractMap;
|
| import java.util.ArrayList;
|
| -import java.util.Collections;
|
| import java.util.List;
|
| import java.util.Map;
|
| -import java.util.TreeMap;
|
| import java.util.concurrent.Executor;
|
| import java.util.concurrent.RejectedExecutionException;
|
|
|
| @@ -64,6 +62,7 @@ final class CronetUrlRequest implements UrlRequest {
|
| * mListener.onReceivedRedirect is called.
|
| */
|
| private final List<String> mUrlChain = new ArrayList<String>();
|
| + private long mReceivedBytesCountFromRedirects;
|
|
|
| private final UrlRequestListener mListener;
|
| private final String mInitialUrl;
|
| @@ -73,7 +72,7 @@ final class CronetUrlRequest implements UrlRequest {
|
|
|
| private CronetUploadDataStream mUploadDataStream;
|
|
|
| - private NativeResponseInfo mResponseInfo;
|
| + private UrlResponseInfo mResponseInfo;
|
|
|
| /*
|
| * Listener callback is repeatedly called when each read is completed, so it
|
| @@ -83,7 +82,7 @@ final class CronetUrlRequest implements UrlRequest {
|
|
|
| private Runnable mOnDestroyedCallbackForTests;
|
|
|
| - private static final class HeadersList extends ArrayList<Pair<String, String>> {}
|
| + private static final class HeadersList extends ArrayList<Map.Entry<String, String>> {}
|
|
|
| private final class OnReadCompletedRunnable implements Runnable {
|
| ByteBuffer mByteBuffer;
|
| @@ -113,113 +112,6 @@ final class CronetUrlRequest implements UrlRequest {
|
| }
|
| }
|
|
|
| - private static final class NativeResponseInfo implements ResponseInfo {
|
| - private final String[] mResponseInfoUrlChain;
|
| - private final int mHttpStatusCode;
|
| - private final String mHttpStatusText;
|
| - private final boolean mWasCached;
|
| - private final String mNegotiatedProtocol;
|
| - private final String mProxyServer;
|
| - private final HeadersList mAllHeaders = new HeadersList();
|
| - private Map<String, List<String>> mResponseHeaders;
|
| - private List<Pair<String, String>> mUnmodifiableAllHeaders;
|
| -
|
| - NativeResponseInfo(String[] urlChain, int httpStatusCode,
|
| - String httpStatusText, boolean wasCached,
|
| - String negotiatedProtocol, String proxyServer) {
|
| - mResponseInfoUrlChain = urlChain;
|
| - mHttpStatusCode = httpStatusCode;
|
| - mHttpStatusText = httpStatusText;
|
| - mWasCached = wasCached;
|
| - mNegotiatedProtocol = negotiatedProtocol;
|
| - mProxyServer = proxyServer;
|
| - }
|
| -
|
| - @Override
|
| - public String getUrl() {
|
| - return mResponseInfoUrlChain[mResponseInfoUrlChain.length - 1];
|
| - }
|
| -
|
| - @Override
|
| - public String[] getUrlChain() {
|
| - return mResponseInfoUrlChain;
|
| - }
|
| -
|
| - @Override
|
| - public int getHttpStatusCode() {
|
| - return mHttpStatusCode;
|
| - }
|
| -
|
| - @Override
|
| - public String getHttpStatusText() {
|
| - return mHttpStatusText;
|
| - }
|
| -
|
| - @Override
|
| - public List<Pair<String, String>> getAllHeadersAsList() {
|
| - if (mUnmodifiableAllHeaders == null) {
|
| - mUnmodifiableAllHeaders =
|
| - Collections.unmodifiableList(mAllHeaders);
|
| - }
|
| - return mUnmodifiableAllHeaders;
|
| - }
|
| -
|
| - @Override
|
| - public Map<String, List<String>> getAllHeaders() {
|
| - if (mResponseHeaders != null) {
|
| - return mResponseHeaders;
|
| - }
|
| - Map<String, List<String>> map = new TreeMap<String, List<String>>(
|
| - String.CASE_INSENSITIVE_ORDER);
|
| - for (Pair<String, String> entry : mAllHeaders) {
|
| - List<String> values = new ArrayList<String>();
|
| - if (map.containsKey(entry.first)) {
|
| - values.addAll(map.get(entry.first));
|
| - }
|
| - values.add(entry.second);
|
| - map.put(entry.first, Collections.unmodifiableList(values));
|
| - }
|
| - mResponseHeaders = Collections.unmodifiableMap(map);
|
| - return mResponseHeaders;
|
| - }
|
| -
|
| - @Override
|
| - public boolean wasCached() {
|
| - return mWasCached;
|
| - }
|
| -
|
| - @Override
|
| - public String getNegotiatedProtocol() {
|
| - return mNegotiatedProtocol;
|
| - }
|
| -
|
| - @Override
|
| - public String getProxyServer() {
|
| - return mProxyServer;
|
| - }
|
| - };
|
| -
|
| - private static final class NativeExtendedResponseInfo implements ExtendedResponseInfo {
|
| - private final ResponseInfo mResponseInfo;
|
| - private final long mTotalReceivedBytes;
|
| -
|
| - NativeExtendedResponseInfo(ResponseInfo responseInfo,
|
| - long totalReceivedBytes) {
|
| - mResponseInfo = responseInfo;
|
| - mTotalReceivedBytes = totalReceivedBytes;
|
| - }
|
| -
|
| - @Override
|
| - public ResponseInfo getResponseInfo() {
|
| - return mResponseInfo;
|
| - }
|
| -
|
| - @Override
|
| - public long getTotalReceivedBytes() {
|
| - return mTotalReceivedBytes;
|
| - }
|
| - };
|
| -
|
| CronetUrlRequest(CronetUrlRequestContext requestContext,
|
| long urlRequestContextAdapter,
|
| String url,
|
| @@ -262,7 +154,7 @@ final class CronetUrlRequest implements UrlRequest {
|
| if (value == null) {
|
| throw new NullPointerException("Invalid header value.");
|
| }
|
| - mRequestHeaders.add(Pair.create(header, value));
|
| + mRequestHeaders.add(new AbstractMap.SimpleImmutableEntry<String, String>(header, value));
|
| }
|
|
|
| @Override
|
| @@ -292,15 +184,16 @@ final class CronetUrlRequest implements UrlRequest {
|
| }
|
|
|
| boolean hasContentType = false;
|
| - for (Pair<String, String> header : mRequestHeaders) {
|
| - if (header.first.equalsIgnoreCase("Content-Type")
|
| - && !header.second.isEmpty()) {
|
| + for (Map.Entry<String, String> header : mRequestHeaders) {
|
| + if (header.getKey().equalsIgnoreCase("Content-Type")
|
| + && !header.getValue().isEmpty()) {
|
| hasContentType = true;
|
| }
|
| - if (!nativeAddRequestHeader(mUrlRequestAdapter, header.first, header.second)) {
|
| + if (!nativeAddRequestHeader(
|
| + mUrlRequestAdapter, header.getKey(), header.getValue())) {
|
| destroyRequestAdapter();
|
| throw new IllegalArgumentException(
|
| - "Invalid header " + header.first + "=" + header.second);
|
| + "Invalid header " + header.getKey() + "=" + header.getValue());
|
| }
|
| }
|
| if (mUploadDataStream != null) {
|
| @@ -481,8 +374,7 @@ final class CronetUrlRequest implements UrlRequest {
|
| }
|
| }
|
|
|
| - private NativeResponseInfo prepareResponseInfoOnNetworkThread(
|
| - int httpStatusCode) {
|
| + private UrlResponseInfo prepareResponseInfoOnNetworkThread(int httpStatusCode) {
|
| long urlRequestAdapter;
|
| synchronized (mUrlRequestAdapterLock) {
|
| if (mUrlRequestAdapter == 0) {
|
| @@ -494,15 +386,14 @@ final class CronetUrlRequest implements UrlRequest {
|
| // safe to preserve and use urlRequestAdapter outside the lock.
|
| urlRequestAdapter = mUrlRequestAdapter;
|
| }
|
| - NativeResponseInfo responseInfo = new NativeResponseInfo(
|
| - mUrlChain.toArray(new String[mUrlChain.size()]),
|
| - httpStatusCode,
|
| - nativeGetHttpStatusText(urlRequestAdapter),
|
| + HeadersList headersList = new HeadersList();
|
| + nativePopulateResponseHeaders(urlRequestAdapter, headersList);
|
| +
|
| + UrlResponseInfo responseInfo = new UrlResponseInfo(new ArrayList<String>(mUrlChain),
|
| + httpStatusCode, nativeGetHttpStatusText(urlRequestAdapter), headersList,
|
| nativeGetWasCached(urlRequestAdapter),
|
| nativeGetNegotiatedProtocol(urlRequestAdapter),
|
| nativeGetProxyServer(urlRequestAdapter));
|
| - nativePopulateResponseHeaders(urlRequestAdapter,
|
| - responseInfo.mAllHeaders);
|
| return responseInfo;
|
| }
|
|
|
| @@ -601,13 +492,15 @@ final class CronetUrlRequest implements UrlRequest {
|
| *
|
| * @param newLocation Location where request is redirected.
|
| * @param httpStatusCode from redirect response
|
| + * @param receivedBytesCount count of bytes received for redirect response
|
| */
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| - private void onReceivedRedirect(final String newLocation,
|
| - int httpStatusCode) {
|
| - final NativeResponseInfo responseInfo =
|
| - prepareResponseInfoOnNetworkThread(httpStatusCode);
|
| + private void onReceivedRedirect(
|
| + final String newLocation, int httpStatusCode, long receivedBytesCount) {
|
| + final UrlResponseInfo responseInfo = prepareResponseInfoOnNetworkThread(httpStatusCode);
|
| + mReceivedBytesCountFromRedirects += receivedBytesCount;
|
| + responseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects);
|
| // Have to do this after creating responseInfo.
|
| mUrlChain.add(newLocation);
|
|
|
| @@ -672,11 +565,13 @@ final class CronetUrlRequest implements UrlRequest {
|
| * @param initialPosition Original position of byteBuffer when passed to
|
| * read(). Used as a minimal check that the buffer hasn't been
|
| * modified while reading from the network.
|
| + * @param receivedBytesCount number of bytes received.
|
| */
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| - private void onReadCompleted(final ByteBuffer byteBuffer, int bytesRead,
|
| - int initialPosition) {
|
| + private void onReadCompleted(final ByteBuffer byteBuffer, int bytesRead, int initialPosition,
|
| + long receivedBytesCount) {
|
| + mResponseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects + receivedBytesCount);
|
| if (byteBuffer.position() != initialPosition) {
|
| failWithException(new UrlRequestException(
|
| "ByteBuffer modified externally during read", null));
|
| @@ -697,13 +592,13 @@ final class CronetUrlRequest implements UrlRequest {
|
| /**
|
| * Called when request is completed successfully, no callbacks will be
|
| * called afterwards.
|
| + *
|
| + * @param receivedBytesCount number of bytes received.
|
| */
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| - private void onSucceeded(long totalReceivedBytes) {
|
| - final NativeExtendedResponseInfo extendedResponseInfo =
|
| - new NativeExtendedResponseInfo(mResponseInfo,
|
| - totalReceivedBytes);
|
| + private void onSucceeded(long receivedBytesCount) {
|
| + mResponseInfo.setReceivedBytesCount(mReceivedBytesCountFromRedirects + receivedBytesCount);
|
| Runnable task = new Runnable() {
|
| public void run() {
|
| synchronized (mUrlRequestAdapterLock) {
|
| @@ -715,8 +610,7 @@ final class CronetUrlRequest implements UrlRequest {
|
| destroyRequestAdapter();
|
| }
|
| try {
|
| - mListener.onSucceeded(CronetUrlRequest.this,
|
| - extendedResponseInfo);
|
| + mListener.onSucceeded(CronetUrlRequest.this, mResponseInfo);
|
| } catch (Exception e) {
|
| Log.e(CronetUrlRequestContext.LOG_TAG,
|
| "Exception in onComplete method", e);
|
| @@ -731,10 +625,15 @@ final class CronetUrlRequest implements UrlRequest {
|
| *
|
| * @param nativeError native net error code.
|
| * @param errorString textual representation of the error code.
|
| + * @param receivedBytesCount number of bytes received.
|
| */
|
| @SuppressWarnings("unused")
|
| @CalledByNative
|
| - private void onError(final int nativeError, final String errorString) {
|
| + private void onError(final int nativeError, final String errorString, long receivedBytesCount) {
|
| + if (mResponseInfo != null) {
|
| + mResponseInfo.setReceivedBytesCount(
|
| + mReceivedBytesCountFromRedirects + receivedBytesCount);
|
| + }
|
| UrlRequestException requestError = new UrlRequestException(
|
| "Exception in CronetUrlRequest: " + errorString,
|
| nativeError);
|
| @@ -748,7 +647,7 @@ final class CronetUrlRequest implements UrlRequest {
|
| @CalledByNative
|
| private void onAppendResponseHeader(HeadersList headersList,
|
| String name, String value) {
|
| - headersList.add(Pair.create(name, value));
|
| + headersList.add(new AbstractMap.SimpleImmutableEntry<String, String>(name, value));
|
| }
|
|
|
| /**
|
|
|