0

Merge UrlRequest.java into ChromiumUrlRequest.java

BUG=390267

Review URL: https://codereview.chromium.org/458633002

Cr-Commit-Position: refs/heads/master@{#289894}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289894 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
mef@chromium.org
2014-08-15 16:11:50 +00:00
parent a4a1ffd21c
commit 9fb82e3883
16 changed files with 573 additions and 683 deletions

@ -11,8 +11,8 @@
'target_name': 'cronet_jni_headers',
'type': 'none',
'sources': [
'cronet/android/java/src/org/chromium/net/UrlRequest.java',
'cronet/android/java/src/org/chromium/net/UrlRequestContext.java',
'cronet/android/java/src/org/chromium/net/ChromiumUrlRequest.java',
'cronet/android/java/src/org/chromium/net/ChromiumUrlRequestContext.java',
],
'variables': {
'jni_gen_package': 'cronet',
@ -23,11 +23,11 @@
'target_name': 'cronet_url_request_error_list',
'type': 'none',
'sources': [
'cronet/android/java/src/org/chromium/net/UrlRequestError.template',
'cronet/android/java/src/org/chromium/net/ChromiumUrlRequestError.template',
],
'variables': {
'package_name': 'org/chromium/cronet',
'template_deps': ['cronet/android/org_chromium_net_UrlRequest_error_list.h'],
'template_deps': ['cronet/android/chromium_url_request_error_list.h'],
},
'includes': [ '../build/android/java_cpp_template.gypi' ],
},
@ -35,11 +35,11 @@
'target_name': 'cronet_url_request_priority_list',
'type': 'none',
'sources': [
'cronet/android/java/src/org/chromium/net/UrlRequestPriority.template',
'cronet/android/java/src/org/chromium/net/ChromiumUrlRequestPriority.template',
],
'variables': {
'package_name': 'org/chromium/cronet',
'template_deps': ['cronet/android/org_chromium_net_UrlRequest_priority_list.h'],
'template_deps': ['cronet/android/chromium_url_request_priority_list.h'],
},
'includes': [ '../build/android/java_cpp_template.gypi' ],
},
@ -110,14 +110,13 @@
'cronet/url_request_context_config.cc',
'cronet/url_request_context_config.h',
'cronet/url_request_context_config_list.h',
'cronet/android/chromium_url_request.cc',
'cronet/android/chromium_url_request.h',
'cronet/android/chromium_url_request_error_list.h',
'cronet/android/chromium_url_request_priority_list.h',
'cronet/android/chromium_url_request_context.cc',
'cronet/android/chromium_url_request_context.h',
'cronet/android/cronet_jni.cc',
'cronet/android/org_chromium_net_UrlRequest.cc',
'cronet/android/org_chromium_net_UrlRequest.h',
'cronet/android/org_chromium_net_UrlRequest_error_list.h',
'cronet/android/org_chromium_net_UrlRequest_priority_list.h',
'cronet/android/org_chromium_net_UrlRequestContext.cc',
'cronet/android/org_chromium_net_UrlRequestContext.h',
'cronet/android/org_chromium_net_UrlRequestContext_config_list.h',
'cronet/android/url_request_adapter.cc',
'cronet/android/url_request_adapter.h',
'cronet/android/url_request_context_adapter.cc',
@ -190,13 +189,11 @@
'java_in_dir': 'cronet/android/java',
'javac_includes': [
'**/ChromiumUrlRequest.java',
'**/ChromiumUrlRequestContext.java',
'**/ChromiumUrlRequestError.java',
'**/ChromiumUrlRequestFactory.java',
'**/ChromiumUrlRequestPriority.java',
'**/LibraryLoader.java',
# TODO(mef): Merge UrlRequest*.java into ChromiumUrlRequest*.java
'**/UrlRequest.java',
'**/UrlRequestContext.java',
'**/UrlRequestError.java',
'**/UrlRequestPriority.java',
'**/UsedByReflection.java',
],
},

@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/cronet/android/org_chromium_net_UrlRequest.h"
#include "components/cronet/android/chromium_url_request.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/macros.h"
#include "components/cronet/android/url_request_adapter.h"
#include "components/cronet/android/url_request_context_adapter.h"
#include "jni/UrlRequest_jni.h"
#include "jni/ChromiumUrlRequest_jni.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
@ -63,7 +63,7 @@ class JniURLRequestAdapterDelegate
virtual void OnResponseStarted(URLRequestAdapter* request) OVERRIDE {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_UrlRequest_onResponseStarted(env, owner_);
cronet::Java_ChromiumUrlRequest_onResponseStarted(env, owner_);
}
virtual void OnBytesRead(URLRequestAdapter* request) OVERRIDE {
@ -72,13 +72,14 @@ class JniURLRequestAdapterDelegate
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_buffer(
env, env->NewDirectByteBuffer(request->Data(), bytes_read));
cronet::Java_UrlRequest_onBytesRead(env, owner_, java_buffer.obj());
cronet::Java_ChromiumUrlRequest_onBytesRead(
env, owner_, java_buffer.obj());
}
}
virtual void OnRequestFinished(URLRequestAdapter* request) OVERRIDE {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_UrlRequest_finish(env, owner_);
cronet::Java_ChromiumUrlRequest_finish(env, owner_);
}
virtual int ReadFromUploadChannel(net::IOBuffer* buf,
@ -86,7 +87,7 @@ class JniURLRequestAdapterDelegate
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_buffer(
env, env->NewDirectByteBuffer(buf->data(), buf_length));
jint bytes_read = cronet::Java_UrlRequest_readFromUploadChannel(
jint bytes_read = cronet::Java_ChromiumUrlRequest_readFromUploadChannel(
env, owner_, java_buffer.obj());
return bytes_read;
}
@ -106,7 +107,9 @@ class JniURLRequestAdapterDelegate
} // namespace
// Explicitly register static JNI functions.
bool UrlRequestRegisterJni(JNIEnv* env) { return RegisterNativesImpl(env); }
bool ChromiumUrlRequestRegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
static jlong CreateRequestAdapter(JNIEnv* env,
jobject object,
@ -196,7 +199,6 @@ static void SetUploadChannel(JNIEnv* env,
request->SetUploadChannel(env, content_length);
}
/* synchronized */
static void Start(JNIEnv* env, jobject object, jlong urlRequestAdapter) {
URLRequestAdapter* request =
@ -353,7 +355,7 @@ static void GetAllHeaders(JNIEnv* env,
ConvertUTF8ToJavaString(env, header_name);
ScopedJavaLocalRef<jstring> value =
ConvertUTF8ToJavaString(env, header_value);
Java_UrlRequest_onAppendResponseHeader(
Java_ChromiumUrlRequest_onAppendResponseHeader(
env, object, headersMap, name.Release(), value.Release());
}
@ -361,7 +363,7 @@ static void GetAllHeaders(JNIEnv* env,
// null key; in HTTP's case, this maps to the HTTP status line.
ScopedJavaLocalRef<jstring> status_line =
ConvertUTF8ToJavaString(env, headers->GetStatusLine());
Java_UrlRequest_onAppendResponseHeader(
Java_ChromiumUrlRequest_onAppendResponseHeader(
env, object, headersMap, NULL, status_line.Release());
}

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CRONET_ANDROID_URLREQUEST_H_
#define COMPONENTS_CRONET_ANDROID_URLREQUEST_H_
#ifndef COMPONENTS_CRONET_ANDROID_CHROMIUM_URL_REQUEST_H_
#define COMPONENTS_CRONET_ANDROID_CHROMIUM_URL_REQUEST_H_
#include <jni.h>
@ -13,7 +13,7 @@ namespace cronet {
// way that ensures they're always the same than their Java counterpart.
enum UrlRequestPriority {
#define DEFINE_REQUEST_PRIORITY(x, y) REQUEST_PRIORITY_##x = y,
#include "components/cronet/android/org_chromium_net_UrlRequest_priority_list.h"
#include "components/cronet/android/chromium_url_request_priority_list.h"
#undef DEFINE_REQUEST_PRIORITY
};
@ -21,12 +21,12 @@ enum UrlRequestPriority {
// way that ensures they're always the same than their Java counterpart.
enum UrlRequestError {
#define DEFINE_REQUEST_ERROR(x, y) REQUEST_ERROR_##x = y,
#include "components/cronet/android/org_chromium_net_UrlRequest_error_list.h"
#include "components/cronet/android/chromium_url_request_error_list.h"
#undef DEFINE_REQUEST_ERROR
};
bool UrlRequestRegisterJni(JNIEnv* env);
bool ChromiumUrlRequestRegisterJni(JNIEnv* env);
} // namespace cronet
#endif // COMPONENTS_CRONET_ANDROID_URLREQUEST_H_
#endif // COMPONENTS_CRONET_ANDROID_CHROMIUM_URL_REQUEST_H_

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/cronet/android/org_chromium_net_UrlRequestContext.h"
#include "components/cronet/android/chromium_url_request_context.h"
#include <string>
@ -13,11 +13,11 @@
#include "base/memory/scoped_ptr.h"
#include "base/metrics/statistics_recorder.h"
#include "base/values.h"
#include "components/cronet/android/org_chromium_net_UrlRequest.h"
#include "components/cronet/android/chromium_url_request.h"
#include "components/cronet/android/url_request_adapter.h"
#include "components/cronet/android/url_request_context_adapter.h"
#include "components/cronet/url_request_context_config.h"
#include "jni/UrlRequestContext_jni.h"
#include "jni/ChromiumUrlRequestContext_jni.h"
namespace {
@ -33,7 +33,7 @@ class JniURLRequestContextAdapterDelegate
virtual void OnContextInitialized(
cronet::URLRequestContextAdapter* context) OVERRIDE {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_UrlRequestContext_initNetworkThread(env, owner_);
cronet::Java_ChromiumUrlRequestContext_initNetworkThread(env, owner_);
// TODO(dplotnikov): figure out if we need to detach from the thread.
// The documentation says we should detach just before the thread exits.
}
@ -53,7 +53,7 @@ class JniURLRequestContextAdapterDelegate
namespace cronet {
// Explicitly register static JNI functions.
bool UrlRequestContextRegisterJni(JNIEnv* env) {
bool ChromiumUrlRequestContextRegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}

@ -9,7 +9,7 @@
namespace cronet {
bool UrlRequestContextRegisterJni(JNIEnv* env);
bool ChromiumUrlRequestContextRegisterJni(JNIEnv* env);
} // namespace cronet

@ -6,8 +6,8 @@
#include "base/android/jni_android.h"
#include "base/android/jni_registrar.h"
#include "base/at_exit.h"
#include "components/cronet/android/org_chromium_net_UrlRequest.h"
#include "components/cronet/android/org_chromium_net_UrlRequestContext.h"
#include "components/cronet/android/chromium_url_request.h"
#include "components/cronet/android/chromium_url_request_context.h"
#include "net/android/net_jni_registrar.h"
#include "url/android/url_jni_registrar.h"
@ -18,11 +18,11 @@
namespace {
const base::android::RegistrationMethod kCronetRegisteredMethods[] = {
{"BaseAndroid", base::android::RegisterJni},
{"NetAndroid", net::android::RegisterJni},
{"UrlAndroid", url::android::RegisterJni},
{"UrlRequest", cronet::UrlRequestRegisterJni},
{"UrlRequestContext", cronet::UrlRequestContextRegisterJni},
{"BaseAndroid", base::android::RegisterJni},
{"ChromiumUrlRequest", cronet::ChromiumUrlRequestRegisterJni},
{"ChromiumUrlRequestContext", cronet::ChromiumUrlRequestContextRegisterJni},
{"NetAndroid", net::android::RegisterJni},
{"UrlAndroid", url::android::RegisterJni},
};
base::AtExitManager* g_at_exit_manager = NULL;

@ -4,35 +4,63 @@
package org.chromium.net;
import org.apache.http.conn.ConnectTimeoutException;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import java.io.IOException;
import java.net.MalformedURLException;
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.
*/
public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest {
@JNINamespace("cronet")
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 WritableByteChannel mOutputChannel;
private IOException mSinkException;
private volatile boolean mStarted;
private volatile boolean mCanceled;
private volatile boolean mRecycled;
private volatile boolean mFinished;
private boolean mHeadersAvailable;
private String mContentType;
private long mUploadContentLength;
private final HttpUrlRequestListener mListener;
private boolean mBufferFullResponse;
private long mOffset;
private long mContentLength;
private long mContentLengthLimit;
private boolean mCancelIfContentLengthOverLimit;
private boolean mContentLengthOverLimit;
private boolean mSkippingToOffset;
private long mSize;
private final Object mLock = new Object();
public ChromiumUrlRequest(UrlRequestContext requestContext,
public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext,
String url, int priority, Map<String, String> headers,
HttpUrlRequestListener listener) {
this(requestContext, url, priority, headers,
@ -40,29 +68,35 @@ public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest {
mBufferFullResponse = true;
}
public ChromiumUrlRequest(UrlRequestContext requestContext,
/**
* 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) {
super(requestContext, url, convertRequestPriority(priority), headers,
sink);
mListener = listener;
}
private static int convertRequestPriority(int priority) {
switch (priority) {
case HttpUrlRequest.REQUEST_PRIORITY_IDLE:
return UrlRequestPriority.IDLE;
case HttpUrlRequest.REQUEST_PRIORITY_LOWEST:
return UrlRequestPriority.LOWEST;
case HttpUrlRequest.REQUEST_PRIORITY_LOW:
return UrlRequestPriority.LOW;
case HttpUrlRequest.REQUEST_PRIORITY_MEDIUM:
return UrlRequestPriority.MEDIUM;
case HttpUrlRequest.REQUEST_PRIORITY_HIGHEST:
return UrlRequestPriority.HIGHEST;
default:
return UrlRequestPriority.MEDIUM;
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.getChromiumUrlRequestContextAdapter(),
mUrl,
mPriority);
mListener = listener;
}
@Override
@ -73,6 +107,13 @@ public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest {
}
}
/**
* 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;
@ -85,10 +126,289 @@ public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest {
}
@Override
protected void onResponseStarted() {
super.onResponseStarted();
public int getHttpStatusCode() {
int httpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter);
// 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 (httpStatusCode == 206) {
httpStatusCode = 200;
}
return httpStatusCode;
}
/**
* Returns an exception if any, or null if the request was completed
* successfully.
*/
@Override
public IOException getException() {
if (mSinkException != null) {
return mSinkException;
}
validateNotRecycled();
int errorCode = nativeGetErrorCode(mUrlRequestAdapter);
switch (errorCode) {
case ChromiumUrlRequestError.SUCCESS:
if (mContentLengthOverLimit) {
return new ResponseTooLargeException();
}
return null;
case ChromiumUrlRequestError.UNKNOWN:
return new IOException(
nativeGetErrorString(mUrlRequestAdapter));
case ChromiumUrlRequestError.MALFORMED_URL:
return new MalformedURLException("Malformed URL: " + mUrl);
case ChromiumUrlRequestError.CONNECTION_TIMED_OUT:
return new ConnectTimeoutException("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);
default:
throw new IllegalStateException(
"Unrecognized error code: " + errorCode);
}
}
@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.
*/
public void setUploadData(String contentType, byte[] data) {
synchronized (mLock) {
validateNotStarted();
mUploadContentType = contentType;
mUploadData = data;
mUploadChannel = null;
}
}
/**
* 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.
*/
public void setUploadChannel(String contentType,
ReadableByteChannel channel, long contentLength) {
synchronized (mLock) {
validateNotStarted();
mUploadContentType = contentType;
mUploadChannel = channel;
mUploadContentLength = contentLength;
mUploadData = null;
}
}
/**
* Sets HTTP method for upload request. Only PUT or POST are allowed.
*/
public void setHttpMethod(String method) {
validateNotStarted();
if (!("PUT".equals(method) || "POST".equals(method))) {
throw new IllegalArgumentException("Only PUT or POST are allowed.");
}
mMethod = method;
}
public WritableByteChannel getSink() {
return mSink;
}
public void start() {
synchronized (mLock) {
if (mCanceled) {
return;
}
validateNotStarted();
validateNotRecycled();
mStarted = true;
String method = mMethod;
if (method == null &&
((mUploadData != null && mUploadData.length > 0) ||
mUploadChannel != null)) {
// Default to POST if there is data to upload but no method was
// specified.
method = "POST";
}
if (method != null) {
nativeSetMethod(mUrlRequestAdapter, method);
}
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);
}
nativeStart(mUrlRequestAdapter);
}
}
public void cancel() {
synchronized (mLock) {
if (mCanceled) {
return;
}
mCanceled = true;
if (!mRecycled) {
nativeCancel(mUrlRequestAdapter);
}
}
}
public boolean isCanceled() {
synchronized (mLock) {
return mCanceled;
}
}
public boolean isRecycled() {
synchronized (mLock) {
return mRecycled;
}
}
public String getContentType() {
return mContentType;
}
public String getHeader(String name) {
validateHeadersAvailable();
return nativeGetHeader(mUrlRequestAdapter, name);
}
// All response headers.
public Map<String, List<String>> getAllHeaders() {
validateHeadersAvailable();
ResponseHeadersMap result = new ResponseHeadersMap();
nativeGetAllHeaders(mUrlRequestAdapter, result);
return result;
}
public String getUrl() {
return mUrl;
}
private static int convertRequestPriority(int priority) {
switch (priority) {
case HttpUrlRequest.REQUEST_PRIORITY_IDLE:
return ChromiumUrlRequestPriority.IDLE;
case HttpUrlRequest.REQUEST_PRIORITY_LOWEST:
return ChromiumUrlRequestPriority.LOWEST;
case HttpUrlRequest.REQUEST_PRIORITY_LOW:
return ChromiumUrlRequestPriority.LOW;
case HttpUrlRequest.REQUEST_PRIORITY_MEDIUM:
return ChromiumUrlRequestPriority.MEDIUM;
case HttpUrlRequest.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() {
mListener.onRequestComplete(this);
}
private void validateNotRecycled() {
if (mRecycled) {
throw new IllegalStateException("Accessing recycled request");
}
}
private void validateNotStarted() {
if (mStarted) {
throw new IllegalStateException("Request already started");
}
}
private void validateHeadersAvailable() {
if (!mHeadersAvailable) {
throw new IllegalStateException("Response headers not available");
}
}
// Private methods called by native library.
/**
* A callback invoked when the first chunk of the response has arrived.
*/
@CalledByNative
private void onResponseStarted() {
mContentType = nativeGetContentType(mUrlRequestAdapter);
mContentLength = nativeGetContentLength(mUrlRequestAdapter);
mHeadersAvailable = true;
mContentLength = super.getContentLength();
if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit
&& mCancelIfContentLengthOverLimit) {
onContentLengthOverLimit();
@ -102,8 +422,11 @@ public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest {
}
if (mOffset != 0) {
// The server may ignore the request for a byte range.
if (super.getHttpStatusCode() == 200) {
// 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 (nativeGetHttpStatusCode(mUrlRequestAdapter) == 200) {
// TODO(mef): Revisit this logic.
if (mContentLength != -1) {
mContentLength -= mOffset;
}
@ -115,8 +438,15 @@ public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest {
mListener.onResponseStarted(this);
}
@Override
protected void onBytesRead(ByteBuffer buffer) {
/**
* 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) {
if (mContentLengthOverLimit) {
return;
}
@ -132,58 +462,130 @@ public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest {
}
}
if (mContentLengthLimit != 0 && mSize > mContentLengthLimit) {
boolean contentLengthOverLimit =
(mContentLengthLimit != 0 && mSize > mContentLengthLimit);
if (contentLengthOverLimit) {
buffer.limit(size - (int)(mSize - mContentLengthLimit));
super.onBytesRead(buffer);
}
try {
while (buffer.hasRemaining()) {
mSink.write(buffer);
}
} catch (IOException e) {
mSinkException = e;
cancel();
}
if (contentLengthOverLimit) {
onContentLengthOverLimit();
return;
}
super.onBytesRead(buffer);
}
private void onContentLengthOverLimit() {
mContentLengthOverLimit = true;
cancel();
}
/**
* Notifies the listener, releases native data structures.
*/
@SuppressWarnings("unused")
@CalledByNative
private void finish() {
synchronized (mLock) {
mFinished = true;
@Override
protected void onRequestComplete() {
mListener.onRequestComplete(this);
}
@Override
public int getHttpStatusCode() {
int httpStatusCode = super.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 (httpStatusCode == 206) {
httpStatusCode = 200;
if (mRecycled) {
return;
}
try {
mSink.close();
} catch (IOException e) {
// Ignore
}
onRequestComplete();
nativeDestroyRequestAdapter(mUrlRequestAdapter);
mUrlRequestAdapter = 0;
mRecycled = true;
}
return httpStatusCode;
}
@Override
public IOException getException() {
IOException ex = super.getException();
if (ex == null && mContentLengthOverLimit) {
ex = new ResponseTooLargeException();
/**
* Appends header |name| with value |value| to |headersMap|.
*/
@SuppressWarnings("unused")
@CalledByNative
private void onAppendResponseHeader(ResponseHeadersMap headersMap,
String name, String value) {
if (!headersMap.containsKey(name)) {
headersMap.put(name, new ArrayList<String>());
}
return ex;
headersMap.get(name).add(value);
}
@Override
public ByteBuffer getByteBuffer() {
return ((ChunkedWritableByteChannel)getSink()).getByteBuffer();
/**
* 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) {
if (mUploadChannel == null || !mUploadChannel.isOpen())
return -1;
try {
int result = mUploadChannel.read(dest);
if (result < 0) {
mUploadChannel.close();
return 0;
}
return result;
} catch (IOException e) {
mSinkException = e;
try {
mUploadChannel.close();
} catch (IOException ignored) {
// Ignore this exception.
}
cancel();
return -1;
}
}
@Override
public byte[] getResponseAsBytes() {
return ((ChunkedWritableByteChannel)getSink()).getBytes();
// Native methods are implemented in chromium_url_request.cc.
private native long nativeCreateRequestAdapter(
long ChromiumUrlRequestContextAdapter, 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 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 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);
// Explicit class to work around JNI-generator generics confusion.
private class ResponseHeadersMap extends HashMap<String, List<String>> {
}
}

@ -16,16 +16,16 @@ import org.chromium.base.JNINamespace;
* Provides context for the native HTTP operations.
*/
@JNINamespace("cronet")
public class UrlRequestContext {
public class ChromiumUrlRequestContext {
private static final int LOG_NONE = 3; // LOG(FATAL), no VLOG.
private static final int LOG_DEBUG = -1; // LOG(FATAL...INFO), VLOG(1)
private static final int LOG_VERBOSE = -2; // LOG(FATAL...INFO), VLOG(2)
private static final String LOG_TAG = "ChromiumNetwork";
/**
* Native adapter object, owned by UrlRequestContext.
* Native adapter object, owned by ChromiumUrlRequestContext.
*/
private long mUrlRequestContextAdapter;
private long mChromiumUrlRequestContextAdapter;
private final ConditionVariable mStarted = new ConditionVariable();
@ -33,11 +33,11 @@ public class UrlRequestContext {
* Constructor.
*
*/
protected UrlRequestContext(Context context, String userAgent,
protected ChromiumUrlRequestContext(Context context, String userAgent,
String config) {
mUrlRequestContextAdapter = nativeCreateRequestContextAdapter(context,
userAgent, getLoggingLevel(), config);
if (mUrlRequestContextAdapter == 0)
mChromiumUrlRequestContextAdapter = nativeCreateRequestContextAdapter(
context, userAgent, getLoggingLevel(), config);
if (mChromiumUrlRequestContextAdapter == 0)
throw new NullPointerException("Context Adapter creation failed");
// TODO(mef): Revisit the need of block here.
@ -75,7 +75,7 @@ public class UrlRequestContext {
* If actively logging the call is ignored.
*/
public void startNetLogToFile(String fileName) {
nativeStartNetLogToFile(mUrlRequestContextAdapter, fileName);
nativeStartNetLogToFile(mChromiumUrlRequestContextAdapter, fileName);
}
/**
@ -83,7 +83,7 @@ public class UrlRequestContext {
* not in progress this call is ignored.
*/
public void stopNetLog() {
nativeStopNetLog(mUrlRequestContextAdapter);
nativeStopNetLog(mChromiumUrlRequestContextAdapter);
}
@CalledByNative
@ -95,12 +95,12 @@ public class UrlRequestContext {
@Override
protected void finalize() throws Throwable {
nativeReleaseRequestContextAdapter(mUrlRequestContextAdapter);
nativeReleaseRequestContextAdapter(mChromiumUrlRequestContextAdapter);
super.finalize();
}
protected long getUrlRequestContextAdapter() {
return mUrlRequestContextAdapter;
protected long getChromiumUrlRequestContextAdapter() {
return mChromiumUrlRequestContextAdapter;
}
/**
@ -119,20 +119,20 @@ public class UrlRequestContext {
return loggingLevel;
}
// Returns an instance URLRequestContextAdapter to be stored in
// mUrlRequestContextAdapter.
// Returns an instance ChromiumUrlRequestContextAdapter to be stored in
// mChromiumUrlRequestContextAdapter.
private native long nativeCreateRequestContextAdapter(Context context,
String userAgent, int loggingLevel, String config);
private native void nativeReleaseRequestContextAdapter(
long urlRequestContextAdapter);
long ChromiumUrlRequestContextAdapter);
private native void nativeInitializeStatistics();
private native String nativeGetStatisticsJSON(String filter);
private native void nativeStartNetLogToFile(long urlRequestContextAdapter,
String fileName);
private native void nativeStartNetLogToFile(
long ChromiumUrlRequestContextAdapter, String fileName);
private native void nativeStopNetLog(long urlRequestContextAdapter);
private native void nativeStopNetLog(long ChromiumUrlRequestContextAdapter);
}

@ -5,10 +5,10 @@
package org.chromium.net;
// A simple auto-generated interface used to list request errors as used by
// both org.chromium.net.UrlRequest and
// net/cronet/android/org_chromium_net_UrlRequest.h
public interface UrlRequestError {
// both org.chromium.net.ChromiumUrlRequest and
// net/cronet/android/chromium_url_request_error_list.h
public interface ChromiumUrlRequestError {
#define DEFINE_REQUEST_ERROR(x,y) public static final int x = y;
#include "components/cronet/android/org_chromium_net_UrlRequest_error_list.h"
#include "components/cronet/android/chromium_url_request_error_list.h"
#undef DEFINE_REQUEST_ERROR
}

@ -15,14 +15,14 @@ import java.util.Map;
*/
@UsedByReflection("HttpUrlRequestFactory.java")
public class ChromiumUrlRequestFactory extends HttpUrlRequestFactory {
private UrlRequestContext mRequestContext;
private ChromiumUrlRequestContext mRequestContext;
@UsedByReflection("HttpUrlRequestFactory.java")
public ChromiumUrlRequestFactory(
Context context, HttpUrlRequestFactoryConfig config) {
if (isEnabled()) {
System.loadLibrary("cronet");
mRequestContext = new UrlRequestContext(
mRequestContext = new ChromiumUrlRequestContext(
context.getApplicationContext(), UserAgent.from(context),
config.toString());
}
@ -35,7 +35,7 @@ public class ChromiumUrlRequestFactory extends HttpUrlRequestFactory {
@Override
public String getName() {
return "Chromium/" + UrlRequestContext.getVersion();
return "Chromium/" + ChromiumUrlRequestContext.getVersion();
}
@Override
@ -52,4 +52,8 @@ public class ChromiumUrlRequestFactory extends HttpUrlRequestFactory {
return new ChromiumUrlRequest(mRequestContext, url, requestPriority,
headers, channel, listener);
}
public ChromiumUrlRequestContext getRequestContext() {
return mRequestContext;
}
}

@ -5,10 +5,10 @@
package org.chromium.net;
// A simple auto-generated interface used to list request priorities as used by
// both org.chromium.net.UrlRequest and
// net/cronet/android/org_chromium_net_UrlRequest.h
public interface UrlRequestPriority {
// both org.chromium.net.ChromiumUrlRequest and
// net/cronet/android/chromium_url_request_priority_list.h
public interface ChromiumUrlRequestPriority {
#define DEFINE_REQUEST_PRIORITY(x,y) public static final int x = y;
#include "components/cronet/android/org_chromium_net_UrlRequest_priority_list.h"
#include "components/cronet/android/chromium_url_request_priority_list.h"
#undef DEFINE_REQUEST_PRIORITY
}

@ -1,452 +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 org.apache.http.conn.ConnectTimeoutException;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import java.io.IOException;
import java.net.MalformedURLException;
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.
*/
@JNINamespace("cronet")
public class UrlRequest {
private static final class ContextLock {
}
private final UrlRequestContext 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 WritableByteChannel mOutputChannel;
private IOException mSinkException;
private volatile boolean mStarted;
private volatile boolean mCanceled;
private volatile boolean mRecycled;
private volatile boolean mFinished;
private boolean mHeadersAvailable;
private String mContentType;
private long mContentLength;
private long mUploadContentLength;
private final ContextLock mLock;
/**
* Native adapter object, owned by UrlRequest.
*/
private long mUrlRequestAdapter;
/**
* 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 UrlRequest(UrlRequestContext requestContext, String url,
int priority, Map<String, String> headers,
WritableByteChannel sink) {
if (requestContext == null) {
throw new NullPointerException("Context is required");
}
if (url == null) {
throw new NullPointerException("URL is required");
}
mRequestContext = requestContext;
mUrl = url;
mPriority = priority;
mHeaders = headers;
mSink = sink;
mLock = new ContextLock();
mUrlRequestAdapter = nativeCreateRequestAdapter(
mRequestContext.getUrlRequestContextAdapter(), mUrl, mPriority);
}
/**
* Adds a request header.
*/
public void addHeader(String header, String value) {
validateNotStarted();
if (mAdditionalHeaders == null) {
mAdditionalHeaders = new HashMap<String, String>();
}
mAdditionalHeaders.put(header, value);
}
/**
* Sets data to upload as part of a POST request.
*
* @param contentType MIME type of the post content or null if this is not a
* POST.
* @param data The content that needs to be uploaded if this is a POST
* request.
*/
public void setUploadData(String contentType, byte[] data) {
synchronized (mLock) {
validateNotStarted();
mUploadContentType = contentType;
mUploadData = data;
mUploadChannel = null;
}
}
/**
* Sets a readable byte channel to upload as part of a POST request.
*
* @param contentType MIME type of the post content or null if this is not a
* POST request.
* @param channel The channel to read to read upload data from if this is a
* POST request.
* @param contentLength The length of data to upload.
*/
public void setUploadChannel(String contentType,
ReadableByteChannel channel, long contentLength) {
synchronized (mLock) {
validateNotStarted();
mUploadContentType = contentType;
mUploadChannel = channel;
mUploadContentLength = contentLength;
mUploadData = null;
}
}
public void setHttpMethod(String method) {
validateNotStarted();
if (!("PUT".equals(method) || "POST".equals(method))) {
throw new IllegalArgumentException("Only PUT or POST are allowed.");
}
mMethod = method;
}
public WritableByteChannel getSink() {
return mSink;
}
public void start() {
synchronized (mLock) {
if (mCanceled) {
return;
}
validateNotStarted();
validateNotRecycled();
mStarted = true;
String method = mMethod;
if (method == null &&
((mUploadData != null && mUploadData.length > 0) ||
mUploadChannel != null)) {
// Default to POST if there is data to upload but no method was
// specified.
method = "POST";
}
if (method != null) {
nativeSetMethod(mUrlRequestAdapter, method);
}
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);
}
nativeStart(mUrlRequestAdapter);
}
}
public void cancel() {
synchronized (mLock) {
if (mCanceled) {
return;
}
mCanceled = true;
if (!mRecycled) {
nativeCancel(mUrlRequestAdapter);
}
}
}
public boolean isCanceled() {
synchronized (mLock) {
return mCanceled;
}
}
public boolean isRecycled() {
synchronized (mLock) {
return mRecycled;
}
}
/**
* Returns an exception if any, or null if the request was completed
* successfully.
*/
public IOException getException() {
if (mSinkException != null) {
return mSinkException;
}
validateNotRecycled();
int errorCode = nativeGetErrorCode(mUrlRequestAdapter);
switch (errorCode) {
case UrlRequestError.SUCCESS:
return null;
case UrlRequestError.UNKNOWN:
return new IOException(
nativeGetErrorString(mUrlRequestAdapter));
case UrlRequestError.MALFORMED_URL:
return new MalformedURLException("Malformed URL: " + mUrl);
case UrlRequestError.CONNECTION_TIMED_OUT:
return new ConnectTimeoutException("Connection timed out");
case UrlRequestError.UNKNOWN_HOST:
String host;
try {
host = new URL(mUrl).getHost();
} catch (MalformedURLException e) {
host = mUrl;
}
return new UnknownHostException("Unknown host: " + host);
default:
throw new IllegalStateException(
"Unrecognized error code: " + errorCode);
}
}
public int getHttpStatusCode() {
return nativeGetHttpStatusCode(mUrlRequestAdapter);
}
/**
* Content length as reported by the server. May be -1 or incorrect if the
* server returns the wrong number, which happens even with Google servers.
*/
public long getContentLength() {
return mContentLength;
}
public String getContentType() {
return mContentType;
}
public String getHeader(String name) {
validateHeadersAvailable();
return nativeGetHeader(mUrlRequestAdapter, name);
}
// All response headers.
public Map<String, List<String>> getAllHeaders() {
validateHeadersAvailable();
ResponseHeadersMap result = new ResponseHeadersMap();
nativeGetAllHeaders(mUrlRequestAdapter, result);
return result;
}
/**
* A callback invoked when the first chunk of the response has arrived.
*/
@CalledByNative
protected void onResponseStarted() {
mContentType = nativeGetContentType(mUrlRequestAdapter);
mContentLength = nativeGetContentLength(mUrlRequestAdapter);
mHeadersAvailable = true;
}
/**
* A callback invoked when the response has been fully consumed.
*/
protected void onRequestComplete() {
}
/**
* 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
protected void onBytesRead(ByteBuffer byteBuffer) {
try {
while (byteBuffer.hasRemaining()) {
mSink.write(byteBuffer);
}
} catch (IOException e) {
mSinkException = e;
cancel();
}
}
/**
* Notifies the listener, releases native data structures.
*/
@SuppressWarnings("unused")
@CalledByNative
private void finish() {
synchronized (mLock) {
mFinished = true;
if (mRecycled) {
return;
}
try {
mSink.close();
} catch (IOException e) {
// Ignore
}
onRequestComplete();
nativeDestroyRequestAdapter(mUrlRequestAdapter);
mUrlRequestAdapter = 0;
mRecycled = true;
}
}
/**
* Appends header |name| with value |value| to |headersMap|.
*/
@SuppressWarnings("unused")
@CalledByNative
private void onAppendResponseHeader(ResponseHeadersMap headersMap,
String name, String value) {
if (!headersMap.containsKey(name)) {
headersMap.put(name, new ArrayList<String>());
}
headersMap.get(name).add(value);
}
/**
* 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) {
if (mUploadChannel == null || !mUploadChannel.isOpen())
return -1;
try {
int result = mUploadChannel.read(dest);
if (result < 0) {
mUploadChannel.close();
return 0;
}
return result;
} catch (IOException e) {
mSinkException = e;
try {
mUploadChannel.close();
} catch (IOException ignored) {
// Ignore this exception.
}
cancel();
return -1;
}
}
private void validateNotRecycled() {
if (mRecycled) {
throw new IllegalStateException("Accessing recycled request");
}
}
private void validateNotStarted() {
if (mStarted) {
throw new IllegalStateException("Request already started");
}
}
private void validateHeadersAvailable() {
if (!mHeadersAvailable) {
throw new IllegalStateException("Response headers not available");
}
}
public String getUrl() {
return mUrl;
}
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 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 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);
// Explicit class to work around JNI-generator generics confusion.
private class ResponseHeadersMap extends HashMap<String, List<String>> {
}
}

@ -78,10 +78,11 @@ public class CronetSampleUrlTest extends CronetSampleTestBase {
waitForActiveShellToBeDoneLoading();
File file = File.createTempFile("cronet", "json");
activity.mRequestContext.startNetLogToFile(file.getPath());
activity.startWithURL_UrlRequest(URL);
activity.mChromiumRequestFactory.getRequestContext().startNetLogToFile(
file.getPath());
activity.startWithURL(URL);
Thread.sleep(5000);
activity.mRequestContext.stopNetLog();
activity.mChromiumRequestFactory.getRequestContext().stopNetLog();
assertTrue(file.exists());
assertTrue(file.length() != 0);
assertTrue(file.delete());

@ -14,23 +14,19 @@ import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;
import org.chromium.net.ChromiumUrlRequestFactory;
import org.chromium.net.HttpUrlRequest;
import org.chromium.net.HttpUrlRequestFactory;
import org.chromium.net.HttpUrlRequestFactoryConfig;
import org.chromium.net.HttpUrlRequestListener;
import org.chromium.net.LibraryLoader;
import org.chromium.net.UrlRequest;
import org.chromium.net.UrlRequestContext;
import org.chromium.net.UrlRequestPriority;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.HashMap;
import java.util.Map;
/**
* Activity for managing the Cronet Sample.
@ -43,8 +39,7 @@ public class CronetSampleActivity extends Activity {
public static final String POST_DATA_KEY = "postData";
public static final String CONFIG_KEY = "config";
UrlRequestContext mRequestContext;
ChromiumUrlRequestFactory mChromiumRequestFactory;
HttpUrlRequestFactory mRequestFactory;
String mUrl;
@ -53,43 +48,6 @@ public class CronetSampleActivity extends Activity {
int mHttpStatusCode = 0;
class SampleRequestContext extends UrlRequestContext {
public SampleRequestContext() {
super(getApplicationContext(), "Cronet Sample",
new HttpUrlRequestFactoryConfig().toString());
}
}
class SampleRequest extends UrlRequest {
public SampleRequest(UrlRequestContext requestContext, String url,
int priority, Map<String, String> headers,
WritableByteChannel sink) {
super(requestContext, url, priority, headers, sink);
}
@Override
protected void onRequestComplete() {
mHttpStatusCode = super.getHttpStatusCode();
Log.i(TAG, "****** Request Complete, status code is "
+ mHttpStatusCode);
Intent intent = new Intent(getApplicationContext(),
CronetSampleActivity.class);
startActivity(intent);
final String url = super.getUrl();
final CharSequence text = "Completed " + url + " ("
+ mHttpStatusCode + ")";
CronetSampleActivity.this.runOnUiThread(new Runnable() {
public void run() {
mLoading = false;
Toast toast = Toast.makeText(getApplicationContext(), text,
Toast.LENGTH_SHORT);
toast.show();
promptForURL(url);
}
});
}
}
class SampleHttpUrlRequestListener implements HttpUrlRequestListener {
public SampleHttpUrlRequestListener() {
}
@ -136,7 +94,6 @@ public class CronetSampleActivity extends Activity {
return;
}
mRequestContext = new SampleRequestContext();
HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig();
config.enableHttpCache(HttpUrlRequestFactoryConfig.HttpCache.IN_MEMORY,
100 * 1024)
@ -159,6 +116,9 @@ public class CronetSampleActivity extends Activity {
mRequestFactory = HttpUrlRequestFactory.createFactory(
getApplicationContext(), config);
mChromiumRequestFactory = new ChromiumUrlRequestFactory(
getApplicationContext(), config);
String appUrl = getUrlFromIntent(getIntent());
if (appUrl == null) {
promptForURL("https://");
@ -219,7 +179,7 @@ public class CronetSampleActivity extends Activity {
}
}
private void startWithURL(String url) {
public void startWithURL(String url) {
Log.i(TAG, "Cronet started: " + url);
mUrl = url;
mLoading = true;
@ -227,36 +187,11 @@ public class CronetSampleActivity extends Activity {
HashMap<String, String> headers = new HashMap<String, String>();
HttpUrlRequestListener listener = new SampleHttpUrlRequestListener();
HttpUrlRequest request = mRequestFactory.createRequest(
url, UrlRequestPriority.MEDIUM, headers, listener);
url, HttpUrlRequest.REQUEST_PRIORITY_MEDIUM, headers, listener);
applyCommandLineToHttpUrlRequest(request);
request.start();
}
private void applyCommandLineToUrlRequest(UrlRequest request) {
String postData = getCommandLineArg(POST_DATA_KEY);
if (postData != null) {
InputStream dataStream = new ByteArrayInputStream(
postData.getBytes());
ReadableByteChannel dataChannel = Channels.newChannel(dataStream);
request.setUploadChannel("text/plain", dataChannel,
postData.length());
request.setHttpMethod("POST");
}
}
public void startWithURL_UrlRequest(String url) {
Log.i(TAG, "Cronet started: " + url);
mUrl = url;
mLoading = true;
HashMap<String, String> headers = new HashMap<String, String>();
WritableByteChannel sink = Channels.newChannel(System.out);
UrlRequest request = new SampleRequest(mRequestContext, url,
UrlRequestPriority.MEDIUM, headers, sink);
applyCommandLineToUrlRequest(request);
request.start();
}
public String getUrl() {
return mUrl;
}
@ -270,11 +205,12 @@ public class CronetSampleActivity extends Activity {
}
public void startNetLog() {
mRequestContext.startNetLogToFile(
Environment.getExternalStorageDirectory().getPath() + "/cronet_sample_netlog.json");
mChromiumRequestFactory.getRequestContext().startNetLogToFile(
Environment.getExternalStorageDirectory().getPath() +
"/cronet_sample_netlog.json");
}
public void stopNetLog() {
mRequestContext.stopNetLog();
mChromiumRequestFactory.getRequestContext().stopNetLog();
}
}