Index: components/cronet/android/java/src/org/chromium/net/impl/ChromiumUrlRequest.java |
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/ChromiumUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/impl/ChromiumUrlRequest.java |
deleted file mode 100644 |
index aff3f7a197b77a81b9a39fea2455a807cbd185de..0000000000000000000000000000000000000000 |
--- a/components/cronet/android/java/src/org/chromium/net/impl/ChromiumUrlRequest.java |
+++ /dev/null |
@@ -1,750 +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.impl; |
- |
-import android.util.Log; |
- |
-import org.chromium.base.annotations.CalledByNative; |
-import org.chromium.base.annotations.JNINamespace; |
-import org.chromium.base.annotations.SuppressFBWarnings; |
-import org.chromium.net.ChromiumUrlRequestError; |
-import org.chromium.net.ChromiumUrlRequestPriority; |
-import org.chromium.net.ChunkedWritableByteChannel; |
-import org.chromium.net.HttpUrlRequest; |
-import org.chromium.net.HttpUrlRequestListener; |
-import org.chromium.net.ResponseTooLargeException; |
- |
-import java.io.IOException; |
-import java.net.MalformedURLException; |
-import java.net.SocketTimeoutException; |
-import java.net.URL; |
-import java.net.UnknownHostException; |
-import java.nio.ByteBuffer; |
-import java.nio.channels.ReadableByteChannel; |
-import java.nio.channels.WritableByteChannel; |
-import java.util.ArrayList; |
-import java.util.HashMap; |
-import java.util.List; |
-import java.util.Map; |
-import java.util.Map.Entry; |
- |
-/** |
- * Network request using the native http stack implementation. |
- * @deprecated Use {@link CronetUrlRequest} instead. |
- */ |
-@JNINamespace("cronet") |
-@Deprecated |
-public class ChromiumUrlRequest implements HttpUrlRequest { |
- /** |
- * Native adapter object, owned by UrlRequest. |
- */ |
- private long mUrlRequestAdapter; |
- private final ChromiumUrlRequestContext mRequestContext; |
- private final String mUrl; |
- private final int mPriority; |
- private final Map<String, String> mHeaders; |
- private final WritableByteChannel mSink; |
- private Map<String, String> mAdditionalHeaders; |
- private String mUploadContentType; |
- private String mMethod; |
- private byte[] mUploadData; |
- private ReadableByteChannel mUploadChannel; |
- private boolean mChunkedUpload; |
- private IOException mSinkException; |
- private volatile boolean mStarted; |
- private volatile boolean mCanceled; |
- private volatile boolean mFinished; |
- private boolean mHeadersAvailable; |
- private long mUploadContentLength; |
- private final HttpUrlRequestListener mListener; |
- private boolean mBufferFullResponse; |
- private long mOffset; |
- private long mContentLengthLimit; |
- private boolean mCancelIfContentLengthOverLimit; |
- private boolean mContentLengthOverLimit; |
- private boolean mSkippingToOffset; |
- private long mSize; |
- |
- // Indicates whether redirects have been disabled. |
- private boolean mDisableRedirects; |
- |
- // Http status code. Default to 0. Populated in onResponseStarted(). |
- private int mHttpStatusCode = 0; |
- |
- // Http status text. Default to null. Populated in onResponseStarted(). |
- private String mHttpStatusText; |
- |
- // Content type. Default to null. Populated in onResponseStarted(). |
- private String mContentType; |
- |
- // Compressed content length as reported by the server. Populated in onResponseStarted(). |
- private long mContentLength; |
- |
- // Native error code. Default to no error. Populated in onRequestComplete(). |
- private int mErrorCode = ChromiumUrlRequestError.SUCCESS; |
- |
- // Native error string. Default to null. Populated in onRequestComplete(). |
- private String mErrorString; |
- |
- // Protects access of mUrlRequestAdapter, mStarted, mCanceled, and mFinished. |
- private final Object mLock = new Object(); |
- |
- public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, String url, int priority, |
- Map<String, String> headers, HttpUrlRequestListener listener) { |
- this(requestContext, url, priority, headers, new ChunkedWritableByteChannel(), listener); |
- mBufferFullResponse = true; |
- } |
- |
- /** |
- * Constructor. |
- * |
- * @param requestContext The context. |
- * @param url The URL. |
- * @param priority Request priority, e.g. {@link #REQUEST_PRIORITY_MEDIUM}. |
- * @param headers HTTP headers. |
- * @param sink The output channel into which downloaded content will be |
- * written. |
- */ |
- public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, String url, int priority, |
- Map<String, String> headers, WritableByteChannel sink, |
- HttpUrlRequestListener listener) { |
- if (requestContext == null) { |
- throw new NullPointerException("Context is required"); |
- } |
- if (url == null) { |
- throw new NullPointerException("URL is required"); |
- } |
- mRequestContext = requestContext; |
- mUrl = url; |
- mPriority = convertRequestPriority(priority); |
- mHeaders = headers; |
- mSink = sink; |
- mUrlRequestAdapter = nativeCreateRequestAdapter( |
- mRequestContext.getUrlRequestContextAdapter(), mUrl, mPriority); |
- mListener = listener; |
- } |
- |
- @Override |
- public void setOffset(long offset) { |
- mOffset = offset; |
- if (offset != 0) { |
- addHeader("Range", "bytes=" + offset + "-"); |
- } |
- } |
- |
- /** |
- * The compressed content length as reported by the server. May be -1 if |
- * the server did not provide a length. Some servers may also report the |
- * wrong number. Since this is the compressed content length, and only |
- * uncompressed content is returned by the consumer, the consumer should |
- * not rely on this value. |
- */ |
- @Override |
- public long getContentLength() { |
- return mContentLength; |
- } |
- |
- @Override |
- public void setContentLengthLimit(long limit, boolean cancelEarly) { |
- mContentLengthLimit = limit; |
- mCancelIfContentLengthOverLimit = cancelEarly; |
- } |
- |
- @Override |
- public int getHttpStatusCode() { |
- // TODO(mef): Investigate the following: |
- // 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 (mHttpStatusCode == 206) { |
- return 200; |
- } |
- return mHttpStatusCode; |
- } |
- |
- @Override |
- public String getHttpStatusText() { |
- return mHttpStatusText; |
- } |
- |
- /** |
- * Returns an exception if any, or null if the request has not completed or |
- * completed successfully. |
- */ |
- @Override |
- public IOException getException() { |
- if (mSinkException != null) { |
- return mSinkException; |
- } |
- |
- switch (mErrorCode) { |
- case ChromiumUrlRequestError.SUCCESS: |
- if (mContentLengthOverLimit) { |
- return new ResponseTooLargeException(); |
- } |
- return null; |
- case ChromiumUrlRequestError.UNKNOWN: |
- return new IOException(mErrorString); |
- case ChromiumUrlRequestError.MALFORMED_URL: |
- return new MalformedURLException("Malformed URL: " + mUrl); |
- case ChromiumUrlRequestError.CONNECTION_TIMED_OUT: |
- return new SocketTimeoutException("Connection timed out"); |
- case ChromiumUrlRequestError.UNKNOWN_HOST: |
- String host; |
- try { |
- host = new URL(mUrl).getHost(); |
- } catch (MalformedURLException e) { |
- host = mUrl; |
- } |
- return new UnknownHostException("Unknown host: " + host); |
- case ChromiumUrlRequestError.TOO_MANY_REDIRECTS: |
- return new IOException("Request failed because there were too " |
- + "many redirects or redirects have been disabled"); |
- default: |
- throw new IllegalStateException("Unrecognized error code: " + mErrorCode); |
- } |
- } |
- |
- @Override |
- public ByteBuffer getByteBuffer() { |
- return ((ChunkedWritableByteChannel) getSink()).getByteBuffer(); |
- } |
- |
- @Override |
- public byte[] getResponseAsBytes() { |
- return ((ChunkedWritableByteChannel) getSink()).getBytes(); |
- } |
- |
- /** |
- * Adds a request header. Must be done before request has started. |
- */ |
- public void addHeader(String header, String value) { |
- synchronized (mLock) { |
- validateNotStarted(); |
- if (mAdditionalHeaders == null) { |
- mAdditionalHeaders = new HashMap<String, String>(); |
- } |
- mAdditionalHeaders.put(header, value); |
- } |
- } |
- |
- /** |
- * Sets data to upload as part of a POST or PUT request. |
- * |
- * @param contentType MIME type of the upload content or null if this is not |
- * an upload. |
- * @param data The content that needs to be uploaded. |
- */ |
- @Override |
- @SuppressFBWarnings("EI_EXPOSE_REP2") |
- public void setUploadData(String contentType, byte[] data) { |
- synchronized (mLock) { |
- validateNotStarted(); |
- validateContentType(contentType); |
- mUploadContentType = contentType; |
- mUploadData = data; |
- mUploadChannel = null; |
- mChunkedUpload = false; |
- } |
- } |
- |
- /** |
- * Sets a readable byte channel to upload as part of a POST or PUT request. |
- * |
- * @param contentType MIME type of the upload content or null if this is not |
- * an upload request. |
- * @param channel The channel to read to read upload data from if this is an |
- * upload request. |
- * @param contentLength The length of data to upload. |
- */ |
- @Override |
- public void setUploadChannel( |
- String contentType, ReadableByteChannel channel, long contentLength) { |
- synchronized (mLock) { |
- validateNotStarted(); |
- validateContentType(contentType); |
- mUploadContentType = contentType; |
- mUploadChannel = channel; |
- mUploadContentLength = contentLength; |
- mUploadData = null; |
- mChunkedUpload = false; |
- } |
- } |
- |
- /** |
- * Sets this request up for chunked uploading. To upload data call |
- * {@link #appendChunk(ByteBuffer, boolean)} after {@link #start()}. |
- * |
- * @param contentType MIME type of the post content or null if this is not a |
- * POST request. |
- */ |
- public void setChunkedUpload(String contentType) { |
- synchronized (mLock) { |
- validateNotStarted(); |
- validateContentType(contentType); |
- mUploadContentType = contentType; |
- mChunkedUpload = true; |
- mUploadData = null; |
- mUploadChannel = null; |
- } |
- } |
- |
- /** |
- * Uploads a new chunk. Must have called {@link #setChunkedUpload(String)} |
- * and {@link #start()}. |
- * |
- * @param chunk The data, which will not be modified. Its current position. |
- * must be zero. The last chunk can be empty, but all other |
- * chunks must be non-empty. |
- * @param isLastChunk Whether this chunk is the last one. |
- */ |
- public void appendChunk(ByteBuffer chunk, boolean isLastChunk) throws IOException { |
- if (!isLastChunk && !chunk.hasRemaining()) { |
- throw new IllegalArgumentException("Attempted to write empty buffer."); |
- } |
- if (chunk.position() != 0) { |
- throw new IllegalArgumentException("The position must be zero."); |
- } |
- synchronized (mLock) { |
- if (!mStarted) { |
- throw new IllegalStateException("Request not yet started."); |
- } |
- if (!mChunkedUpload) { |
- throw new IllegalStateException("Request not set for chunked uploadind."); |
- } |
- if (mUrlRequestAdapter == 0) { |
- throw new IOException("Native peer destroyed."); |
- } |
- nativeAppendChunk(mUrlRequestAdapter, chunk, chunk.limit(), isLastChunk); |
- } |
- } |
- |
- @Override |
- public void setHttpMethod(String method) { |
- validateNotStarted(); |
- mMethod = method; |
- } |
- |
- @Override |
- public void disableRedirects() { |
- synchronized (mLock) { |
- validateNotStarted(); |
- validateNativeAdapterNotDestroyed(); |
- mDisableRedirects = true; |
- nativeDisableRedirects(mUrlRequestAdapter); |
- } |
- } |
- |
- public WritableByteChannel getSink() { |
- return mSink; |
- } |
- |
- @Override |
- public void start() { |
- synchronized (mLock) { |
- if (mCanceled) { |
- return; |
- } |
- |
- validateNotStarted(); |
- validateNativeAdapterNotDestroyed(); |
- |
- mStarted = true; |
- |
- if (mHeaders != null && !mHeaders.isEmpty()) { |
- for (Entry<String, String> entry : mHeaders.entrySet()) { |
- nativeAddHeader(mUrlRequestAdapter, entry.getKey(), entry.getValue()); |
- } |
- } |
- |
- if (mAdditionalHeaders != null) { |
- for (Entry<String, String> entry : mAdditionalHeaders.entrySet()) { |
- nativeAddHeader(mUrlRequestAdapter, entry.getKey(), entry.getValue()); |
- } |
- } |
- |
- if (mUploadData != null && mUploadData.length > 0) { |
- nativeSetUploadData(mUrlRequestAdapter, mUploadContentType, mUploadData); |
- } else if (mUploadChannel != null) { |
- nativeSetUploadChannel( |
- mUrlRequestAdapter, mUploadContentType, mUploadContentLength); |
- } else if (mChunkedUpload) { |
- nativeEnableChunkedUpload(mUrlRequestAdapter, mUploadContentType); |
- } |
- |
- // Note: The above functions to set the upload body also set the |
- // method to POST, behind the scenes, so if mMethod is null but |
- // there's an upload body, the method will default to POST. |
- if (mMethod != null) { |
- nativeSetMethod(mUrlRequestAdapter, mMethod); |
- } |
- |
- nativeStart(mUrlRequestAdapter); |
- } |
- } |
- |
- @Override |
- public void cancel() { |
- synchronized (mLock) { |
- if (mCanceled) { |
- return; |
- } |
- |
- mCanceled = true; |
- |
- if (mUrlRequestAdapter != 0) { |
- nativeCancel(mUrlRequestAdapter); |
- } |
- } |
- } |
- |
- @Override |
- public boolean isCanceled() { |
- synchronized (mLock) { |
- return mCanceled; |
- } |
- } |
- |
- @Override |
- public String getNegotiatedProtocol() { |
- synchronized (mLock) { |
- validateNativeAdapterNotDestroyed(); |
- validateHeadersAvailable(); |
- return nativeGetNegotiatedProtocol(mUrlRequestAdapter); |
- } |
- } |
- |
- @Override |
- public boolean wasCached() { |
- synchronized (mLock) { |
- validateNativeAdapterNotDestroyed(); |
- validateHeadersAvailable(); |
- return nativeGetWasCached(mUrlRequestAdapter); |
- } |
- } |
- |
- @Override |
- public String getContentType() { |
- return mContentType; |
- } |
- |
- @Override |
- public String getHeader(String name) { |
- synchronized (mLock) { |
- validateNativeAdapterNotDestroyed(); |
- validateHeadersAvailable(); |
- return nativeGetHeader(mUrlRequestAdapter, name); |
- } |
- } |
- |
- // All response headers. |
- @Override |
- public Map<String, List<String>> getAllHeaders() { |
- synchronized (mLock) { |
- validateNativeAdapterNotDestroyed(); |
- validateHeadersAvailable(); |
- ResponseHeadersMap result = new ResponseHeadersMap(); |
- nativeGetAllHeaders(mUrlRequestAdapter, result); |
- return result; |
- } |
- } |
- |
- @Override |
- public String getUrl() { |
- return mUrl; |
- } |
- |
- private static int convertRequestPriority(int priority) { |
- switch (priority) { |
- case REQUEST_PRIORITY_IDLE: |
- return ChromiumUrlRequestPriority.IDLE; |
- case REQUEST_PRIORITY_LOWEST: |
- return ChromiumUrlRequestPriority.LOWEST; |
- case REQUEST_PRIORITY_LOW: |
- return ChromiumUrlRequestPriority.LOW; |
- case REQUEST_PRIORITY_MEDIUM: |
- return ChromiumUrlRequestPriority.MEDIUM; |
- case REQUEST_PRIORITY_HIGHEST: |
- return ChromiumUrlRequestPriority.HIGHEST; |
- default: |
- return ChromiumUrlRequestPriority.MEDIUM; |
- } |
- } |
- |
- private void onContentLengthOverLimit() { |
- mContentLengthOverLimit = true; |
- cancel(); |
- } |
- |
- /** |
- * A callback invoked when the response has been fully consumed. |
- */ |
- private void onRequestComplete() { |
- mErrorCode = nativeGetErrorCode(mUrlRequestAdapter); |
- mErrorString = nativeGetErrorString(mUrlRequestAdapter); |
- // When there is an error or redirects have been disabled, |
- // onResponseStarted is often not invoked. |
- // Populate status code and status text if that's the case. |
- // Note that besides redirects, these two fields may be set on the |
- // request for AUTH and CERT requests. |
- if (mErrorCode != ChromiumUrlRequestError.SUCCESS) { |
- mHttpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter); |
- mHttpStatusText = nativeGetHttpStatusText(mUrlRequestAdapter); |
- } |
- mListener.onRequestComplete(this); |
- } |
- |
- private void validateNativeAdapterNotDestroyed() { |
- if (mUrlRequestAdapter == 0) { |
- throw new IllegalStateException("Adapter has been destroyed"); |
- } |
- } |
- |
- private void validateNotStarted() { |
- if (mStarted) { |
- throw new IllegalStateException("Request already started"); |
- } |
- } |
- |
- private void validateHeadersAvailable() { |
- if (!mHeadersAvailable) { |
- throw new IllegalStateException("Response headers not available"); |
- } |
- } |
- |
- private void validateContentType(String contentType) { |
- if (contentType == null) { |
- throw new NullPointerException("contentType is required"); |
- } |
- } |
- |
- // Private methods called by native library. |
- |
- /** |
- * If @CalledByNative method throws an exception, request gets canceled |
- * and exception could be retrieved from request using getException(). |
- */ |
- private void onCalledByNativeException(Exception e) { |
- mSinkException = new IOException("CalledByNative method has thrown an exception", e); |
- Log.e(ChromiumUrlRequestContext.LOG_TAG, "Exception in CalledByNative method", e); |
- try { |
- cancel(); |
- } catch (Exception cancel_exception) { |
- Log.e(ChromiumUrlRequestContext.LOG_TAG, "Exception trying to cancel request", |
- cancel_exception); |
- } |
- } |
- |
- /** |
- * A callback invoked when the first chunk of the response has arrived. |
- */ |
- @CalledByNative |
- private void onResponseStarted() { |
- try { |
- mHttpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter); |
- mHttpStatusText = nativeGetHttpStatusText(mUrlRequestAdapter); |
- mContentType = nativeGetContentType(mUrlRequestAdapter); |
- mContentLength = nativeGetContentLength(mUrlRequestAdapter); |
- mHeadersAvailable = true; |
- |
- if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit |
- && mCancelIfContentLengthOverLimit) { |
- onContentLengthOverLimit(); |
- return; |
- } |
- |
- if (mBufferFullResponse && mContentLength != -1 && !mContentLengthOverLimit) { |
- ((ChunkedWritableByteChannel) getSink()).setCapacity((int) mContentLength); |
- } |
- |
- if (mOffset != 0) { |
- // The server may ignore the request for a byte range, in which |
- // case status code will be 200, instead of 206. Note that we |
- // cannot call getHttpStatusCode as it rewrites 206 into 200. |
- if (mHttpStatusCode == 200) { |
- // TODO(mef): Revisit this logic. |
- if (mContentLength != -1) { |
- mContentLength -= mOffset; |
- } |
- mSkippingToOffset = true; |
- } else { |
- mSize = mOffset; |
- } |
- } |
- mListener.onResponseStarted(this); |
- } catch (Exception e) { |
- onCalledByNativeException(e); |
- } |
- } |
- |
- /** |
- * Consumes a portion of the response. |
- * |
- * @param byteBuffer The ByteBuffer to append. Must be a direct buffer, and |
- * no references to it may be retained after the method ends, as |
- * it wraps code managed on the native heap. |
- */ |
- @CalledByNative |
- private void onBytesRead(ByteBuffer buffer) { |
- try { |
- if (mContentLengthOverLimit) { |
- return; |
- } |
- |
- int size = buffer.remaining(); |
- mSize += size; |
- if (mSkippingToOffset) { |
- if (mSize <= mOffset) { |
- return; |
- } else { |
- mSkippingToOffset = false; |
- buffer.position((int) (mOffset - (mSize - size))); |
- } |
- } |
- |
- boolean contentLengthOverLimit = |
- (mContentLengthLimit != 0 && mSize > mContentLengthLimit); |
- if (contentLengthOverLimit) { |
- buffer.limit(size - (int) (mSize - mContentLengthLimit)); |
- } |
- |
- while (buffer.hasRemaining()) { |
- mSink.write(buffer); |
- } |
- if (contentLengthOverLimit) { |
- onContentLengthOverLimit(); |
- } |
- } catch (Exception e) { |
- onCalledByNativeException(e); |
- } |
- } |
- |
- /** |
- * Notifies the listener, releases native data structures. |
- */ |
- @SuppressWarnings("unused") |
- @CalledByNative |
- private void finish() { |
- try { |
- synchronized (mLock) { |
- if (mDisableRedirects) { |
- mHeadersAvailable = true; |
- } |
- mFinished = true; |
- |
- if (mUrlRequestAdapter == 0) { |
- return; |
- } |
- try { |
- mSink.close(); |
- } catch (IOException e) { |
- // Ignore |
- } |
- try { |
- if (mUploadChannel != null && mUploadChannel.isOpen()) { |
- mUploadChannel.close(); |
- } |
- } catch (IOException e) { |
- // Ignore |
- } |
- onRequestComplete(); |
- nativeDestroyRequestAdapter(mUrlRequestAdapter); |
- mUrlRequestAdapter = 0; |
- } |
- } catch (Exception e) { |
- mSinkException = new IOException("Exception in finish", e); |
- } |
- } |
- |
- /** |
- * Appends header |name| with value |value| to |headersMap|. |
- */ |
- @SuppressWarnings("unused") |
- @CalledByNative |
- private void onAppendResponseHeader(ResponseHeadersMap headersMap, String name, String value) { |
- try { |
- if (!headersMap.containsKey(name)) { |
- headersMap.put(name, new ArrayList<String>()); |
- } |
- headersMap.get(name).add(value); |
- } catch (Exception e) { |
- onCalledByNativeException(e); |
- } |
- } |
- |
- /** |
- * Reads a sequence of bytes from upload channel into the given buffer. |
- * @param dest The buffer into which bytes are to be transferred. |
- * @return Returns number of bytes read (could be 0) or -1 and closes |
- * the channel if error occured. |
- */ |
- @SuppressWarnings("unused") |
- @CalledByNative |
- private int readFromUploadChannel(ByteBuffer dest) { |
- try { |
- if (mUploadChannel == null || !mUploadChannel.isOpen()) return -1; |
- int result = mUploadChannel.read(dest); |
- if (result < 0) { |
- mUploadChannel.close(); |
- return 0; |
- } |
- return result; |
- } catch (Exception e) { |
- onCalledByNativeException(e); |
- } |
- return -1; |
- } |
- |
- // Native methods are implemented in chromium_url_request.cc. |
- |
- private native long nativeCreateRequestAdapter( |
- long urlRequestContextAdapter, String url, int priority); |
- |
- private native void nativeAddHeader(long urlRequestAdapter, String name, String value); |
- |
- private native void nativeSetMethod(long urlRequestAdapter, String method); |
- |
- private native void nativeSetUploadData( |
- long urlRequestAdapter, String contentType, byte[] content); |
- |
- private native void nativeSetUploadChannel( |
- long urlRequestAdapter, String contentType, long contentLength); |
- |
- private native void nativeEnableChunkedUpload(long urlRequestAdapter, String contentType); |
- |
- private native void nativeDisableRedirects(long urlRequestAdapter); |
- |
- private native void nativeAppendChunk( |
- long urlRequestAdapter, ByteBuffer chunk, int chunkSize, boolean isLastChunk); |
- |
- private native void nativeStart(long urlRequestAdapter); |
- |
- private native void nativeCancel(long urlRequestAdapter); |
- |
- private native void nativeDestroyRequestAdapter(long urlRequestAdapter); |
- |
- private native int nativeGetErrorCode(long urlRequestAdapter); |
- |
- private native int nativeGetHttpStatusCode(long urlRequestAdapter); |
- |
- private native String nativeGetHttpStatusText(long urlRequestAdapter); |
- |
- private native String nativeGetErrorString(long urlRequestAdapter); |
- |
- private native String nativeGetContentType(long urlRequestAdapter); |
- |
- private native long nativeGetContentLength(long urlRequestAdapter); |
- |
- private native String nativeGetHeader(long urlRequestAdapter, String name); |
- |
- private native void nativeGetAllHeaders(long urlRequestAdapter, ResponseHeadersMap headers); |
- |
- private native String nativeGetNegotiatedProtocol(long urlRequestAdapter); |
- |
- private native boolean nativeGetWasCached(long urlRequestAdapter); |
- |
- // Explicit class to work around JNI-generator generics confusion. |
- private static class ResponseHeadersMap extends HashMap<String, List<String>> {} |
-} |