Commit a8177757 authored by xunjieli's avatar xunjieli Committed by Commit bot

This CL uses @NativeClassQualifiedName in

CronetUrlRequest.java to reduce JNI code. After the
refactoring, cronet_url_request.cc is merged with
cronet_url_request_adapter.cc, since the former mostly
contains JNI code that can be generated by
@NativeClassQualifiedName.
This CL also inlines CronetUrlRequestAdapterDelegate, since
we have only one file now.

BUG=458276

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

Cr-Commit-Position: refs/heads/master@{#323976}
parent 1b4701c7
......@@ -18,7 +18,7 @@
#include "components/cronet/android/chromium_url_request_context.h"
#include "components/cronet/android/cronet_histogram_manager.h"
#include "components/cronet/android/cronet_upload_data_stream_delegate.h"
#include "components/cronet/android/cronet_url_request.h"
#include "components/cronet/android/cronet_url_request_adapter.h"
#include "components/cronet/android/cronet_url_request_context_adapter.h"
#include "jni/CronetLibraryLoader_jni.h"
#include "net/android/net_jni_registrar.h"
......@@ -42,7 +42,7 @@ const base::android::RegistrationMethod kCronetRegisteredMethods[] = {
{"CronetLibraryLoader", RegisterNativesImpl},
{"CronetUploadDataStreamDelegate",
CronetUploadDataStreamDelegateRegisterJni},
{"CronetUrlRequest", CronetUrlRequestRegisterJni},
{"CronetUrlRequestAdapter", CronetUrlRequestAdapterRegisterJni},
{"CronetUrlRequestContextAdapter",
CronetUrlRequestContextAdapterRegisterJni},
{"NetAndroid", net::android::RegisterJni},
......
// 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.
#include "components/cronet/android/cronet_url_request.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/logging.h"
#include "base/macros.h"
#include "components/cronet/android/cronet_url_request_adapter.h"
#include "components/cronet/android/cronet_url_request_context_adapter.h"
#include "jni/CronetUrlRequest_jni.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
using base::android::ConvertUTF8ToJavaString;
// This file contains all the plumbing to handle the bidirectional communication
// between the Java CronetURLRequest and C++ CronetURLRequestAdapter.
namespace cronet {
namespace {
// A delegate of CronetURLRequestAdapter that delivers callbacks to the Java
// layer. Created on a Java thread, but always called and destroyed on the
// Network thread.
class JniCronetURLRequestAdapterDelegate
: public CronetURLRequestAdapter::CronetURLRequestAdapterDelegate {
public:
JniCronetURLRequestAdapterDelegate(JNIEnv* env, jobject owner) {
owner_.Reset(env, owner);
}
// CronetURLRequestAdapter::CronetURLRequestAdapterDelegate implementation.
void OnRedirect(const GURL& new_location, int http_status_code) override {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onRedirect(
env,
owner_.obj(),
ConvertUTF8ToJavaString(env, new_location.spec()).obj(),
http_status_code);
}
void OnResponseStarted(int http_status_code) override {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onResponseStarted(env,
owner_.obj(),
http_status_code);
}
void OnBytesRead(unsigned char* bytes,
int bytes_read) override {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_buffer(
env, env->NewDirectByteBuffer(bytes, bytes_read));
cronet::Java_CronetUrlRequest_onDataReceived(
env, owner_.obj(), java_buffer.obj());
}
void OnRequestFinished() override {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onSucceeded(env, owner_.obj());
}
void OnError(int net_error) override {
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onError(
env,
owner_.obj(),
net_error,
ConvertUTF8ToJavaString(env, net::ErrorToString(net_error)).obj());
}
private:
~JniCronetURLRequestAdapterDelegate() override {
}
// Java object that owns the CronetURLRequestContextAdapter, which owns this
// delegate.
base::android::ScopedJavaGlobalRef<jobject> owner_;
DISALLOW_COPY_AND_ASSIGN(JniCronetURLRequestAdapterDelegate);
};
} // namespace
// Explicitly register static JNI functions.
bool CronetUrlRequestRegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
static jlong CreateRequestAdapter(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_context_adapter,
jstring jurl_string,
jint jpriority) {
CronetURLRequestContextAdapter* context_adapter =
reinterpret_cast<CronetURLRequestContextAdapter*>(
jurl_request_context_adapter);
DCHECK(context_adapter);
GURL url(base::android::ConvertJavaStringToUTF8(env, jurl_string));
VLOG(1) << "New chromium network request_adapter: "
<< url.possibly_invalid_spec();
scoped_ptr<CronetURLRequestAdapter::CronetURLRequestAdapterDelegate> delegate(
new JniCronetURLRequestAdapterDelegate(env, jurl_request));
CronetURLRequestAdapter* adapter = new CronetURLRequestAdapter(
context_adapter,
delegate.Pass(),
url,
static_cast<net::RequestPriority>(jpriority));
return reinterpret_cast<jlong>(adapter);
}
static jboolean SetHttpMethod(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter,
jstring jmethod) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(!request_adapter->IsOnNetworkThread());
std::string method(base::android::ConvertJavaStringToUTF8(env, jmethod));
// Http method is a token, just as header name.
if (!net::HttpUtil::IsValidHeaderName(method))
return JNI_FALSE;
request_adapter->set_method(method);
return JNI_TRUE;
}
static jboolean AddHeader(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter,
jstring jname,
jstring jvalue) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(!request_adapter->IsOnNetworkThread());
std::string name(base::android::ConvertJavaStringToUTF8(env, jname));
std::string value(base::android::ConvertJavaStringToUTF8(env, jvalue));
if (!net::HttpUtil::IsValidHeaderName(name) ||
!net::HttpUtil::IsValidHeaderValue(value)) {
return JNI_FALSE;
}
request_adapter->AddRequestHeader(name, value);
return JNI_TRUE;
}
static void Start(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(!request_adapter->IsOnNetworkThread());
request_adapter->PostTaskToNetworkThread(
FROM_HERE,
base::Bind(&CronetURLRequestAdapter::Start,
base::Unretained(request_adapter)));
}
static void DestroyRequestAdapter(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(!request_adapter->IsOnNetworkThread());
request_adapter->PostTaskToNetworkThread(
FROM_HERE,
base::Bind(&CronetURLRequestAdapter::Destroy,
base::Unretained(request_adapter)));
}
static void ReceiveData(JNIEnv* env,
jobject jcaller,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(!request_adapter->IsOnNetworkThread());
request_adapter->PostTaskToNetworkThread(
FROM_HERE,
base::Bind(&CronetURLRequestAdapter::ReadData,
base::Unretained(request_adapter)));
}
static void FollowDeferredRedirect(JNIEnv* env,
jobject jcaller,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(!request_adapter->IsOnNetworkThread());
request_adapter->PostTaskToNetworkThread(
FROM_HERE,
base::Bind(&CronetURLRequestAdapter::FollowDeferredRedirect,
base::Unretained(request_adapter)));
}
static void DisableCache(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(!request_adapter->IsOnNetworkThread());
request_adapter->DisableCache();
}
static void PopulateResponseHeaders(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter,
jobject jheaders_list) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(request_adapter->IsOnNetworkThread());
const net::HttpResponseHeaders* headers =
request_adapter->GetResponseHeaders();
if (headers == nullptr)
return;
void* iter = nullptr;
std::string header_name;
std::string header_value;
while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
ScopedJavaLocalRef<jstring> name =
ConvertUTF8ToJavaString(env, header_name);
ScopedJavaLocalRef<jstring> value =
ConvertUTF8ToJavaString(env, header_value);
Java_CronetUrlRequest_onAppendResponseHeader(
env, jurl_request, jheaders_list, name.obj(), value.obj());
}
}
static jstring GetNegotiatedProtocol(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(request_adapter->IsOnNetworkThread());
return ConvertUTF8ToJavaString(
env, request_adapter->GetNegotiatedProtocol()).Release();
}
static jboolean GetWasCached(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(request_adapter->IsOnNetworkThread());
return request_adapter->GetWasCached() ? JNI_TRUE : JNI_FALSE;
}
static jlong GetTotalReceivedBytes(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(request_adapter->IsOnNetworkThread());
return request_adapter->GetTotalReceivedBytes();
}
static jstring GetHttpStatusText(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_adapter) {
DCHECK(jurl_request_adapter);
CronetURLRequestAdapter* request_adapter =
reinterpret_cast<CronetURLRequestAdapter*>(jurl_request_adapter);
DCHECK(request_adapter->IsOnNetworkThread());
const net::HttpResponseHeaders* headers =
request_adapter->GetResponseHeaders();
if (headers == NULL)
return ConvertUTF8ToJavaString(env, "").Release();
return ConvertUTF8ToJavaString(env, headers->GetStatusText()).Release();
}
} // namespace cronet
// 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.
#ifndef COMPONENTS_CRONET_ANDROID_CRONET_URL_REQUEST_H_
#define COMPONENTS_CRONET_ANDROID_CRONET_URL_REQUEST_H_
#include <jni.h>
namespace cronet {
bool CronetUrlRequestRegisterJni(JNIEnv* env);
} // namespace cronet
#endif // COMPONENTS_CRONET_ANDROID_CRONET_URL_REQUEST_H_
......@@ -8,122 +8,184 @@
#include "base/location.h"
#include "base/logging.h"
#include "components/cronet/android/cronet_url_request_context_adapter.h"
#include "components/cronet/android/wrapped_channel_upload_element_reader.h"
#include "jni/CronetUrlRequest_jni.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_context.h"
using base::android::ConvertUTF8ToJavaString;
namespace cronet {
static const int kReadBufferSize = 32768;
// Explicitly register static JNI functions.
bool CronetUrlRequestAdapterRegisterJni(JNIEnv* env) {
return RegisterNativesImpl(env);
}
static jlong CreateRequestAdapter(JNIEnv* env,
jobject jurl_request,
jlong jurl_request_context_adapter,
jstring jurl_string,
jint jpriority) {
CronetURLRequestContextAdapter* context_adapter =
reinterpret_cast<CronetURLRequestContextAdapter*>(
jurl_request_context_adapter);
DCHECK(context_adapter);
GURL url(base::android::ConvertJavaStringToUTF8(env, jurl_string));
VLOG(1) << "New chromium network request_adapter: "
<< url.possibly_invalid_spec();
CronetURLRequestAdapter* adapter =
new CronetURLRequestAdapter(context_adapter, env, jurl_request, url,
static_cast<net::RequestPriority>(jpriority));
return reinterpret_cast<jlong>(adapter);
}
CronetURLRequestAdapter::CronetURLRequestAdapter(
CronetURLRequestContextAdapter* context,
scoped_ptr<CronetURLRequestAdapterDelegate> delegate,
JNIEnv* env,
jobject jurl_request,
const GURL& url,
net::RequestPriority priority)
: context_(context),
delegate_(delegate.Pass()),
initial_url_(url),
initial_priority_(priority),
initial_method_("GET"),
load_flags_(context->default_load_flags()) {
DCHECK(!context_->IsOnNetworkThread());
owner_.Reset(env, jurl_request);
}
CronetURLRequestAdapter::~CronetURLRequestAdapter() {
DCHECK(IsOnNetworkThread());
DCHECK(context_->IsOnNetworkThread());
}
void CronetURLRequestAdapter::AddRequestHeader(const std::string& name,
const std::string& value) {
DCHECK(!IsOnNetworkThread());
initial_request_headers_.SetHeader(name, value);
jboolean CronetURLRequestAdapter::SetHttpMethod(JNIEnv* env,
jobject jcaller,
jstring jmethod) {
DCHECK(!context_->IsOnNetworkThread());
std::string method(base::android::ConvertJavaStringToUTF8(env, jmethod));
// Http method is a token, just as header name.
if (!net::HttpUtil::IsValidHeaderName(method))
return JNI_FALSE;
initial_method_ = method;
return JNI_TRUE;
}
void CronetURLRequestAdapter::DisableCache() {
DCHECK(!IsOnNetworkThread());
load_flags_ |= net::LOAD_DISABLE_CACHE;
}
void CronetURLRequestAdapter::PostTaskToNetworkThread(
const tracked_objects::Location& from_here,
const base::Closure& task) {
DCHECK(!IsOnNetworkThread());
context_->PostTaskToNetworkThread(from_here, task);
jboolean CronetURLRequestAdapter::AddRequestHeader(JNIEnv* env,
jobject jcaller,
jstring jname,
jstring jvalue) {
DCHECK(!context_->IsOnNetworkThread());
std::string name(base::android::ConvertJavaStringToUTF8(env, jname));
std::string value(base::android::ConvertJavaStringToUTF8(env, jvalue));
if (!net::HttpUtil::IsValidHeaderName(name) ||
!net::HttpUtil::IsValidHeaderValue(value)) {
return JNI_FALSE;
}
initial_request_headers_.SetHeader(name, value);
return JNI_TRUE;
}
bool CronetURLRequestAdapter::IsOnNetworkThread() const {
return context_->IsOnNetworkThread();
void CronetURLRequestAdapter::DisableCache(JNIEnv* env, jobject jcaller) {
DCHECK(!context_->IsOnNetworkThread());
load_flags_ |= net::LOAD_DISABLE_CACHE;
}
void CronetURLRequestAdapter::SetUpload(
scoped_ptr<net::UploadDataStream> upload) {
DCHECK(!IsOnNetworkThread());
DCHECK(!context_->IsOnNetworkThread());
DCHECK(!upload_);
upload_ = upload.Pass();
}
void CronetURLRequestAdapter::Start() {
DCHECK(IsOnNetworkThread());
VLOG(1) << "Starting chromium request: "
<< initial_url_.possibly_invalid_spec().c_str()
<< " priority: " << RequestPriorityToString(initial_priority_);
url_request_ = context_->GetURLRequestContext()->CreateRequest(
initial_url_, net::DEFAULT_PRIORITY, this);
url_request_->SetLoadFlags(load_flags_);
url_request_->set_method(initial_method_);
url_request_->SetExtraRequestHeaders(initial_request_headers_);
url_request_->SetPriority(initial_priority_);
if (upload_)
url_request_->set_upload(upload_.Pass());
url_request_->Start();
void CronetURLRequestAdapter::Start(JNIEnv* env, jobject jcaller) {
DCHECK(!context_->IsOnNetworkThread());
context_->PostTaskToNetworkThread(
FROM_HERE, base::Bind(&CronetURLRequestAdapter::StartOnNetworkThread,
base::Unretained(this)));
}
void CronetURLRequestAdapter::FollowDeferredRedirect() {
DCHECK(IsOnNetworkThread());
void CronetURLRequestAdapter::FollowDeferredRedirect(JNIEnv* env,
jobject jcaller) {
DCHECK(!context_->IsOnNetworkThread());
context_->PostTaskToNetworkThread(
FROM_HERE,
base::Bind(
&CronetURLRequestAdapter::FollowDeferredRedirectOnNetworkThread,
base::Unretained(this)));
}
url_request_->FollowDeferredRedirect();
void CronetURLRequestAdapter::ReadData(JNIEnv* env, jobject jcaller) {
DCHECK(!context_->IsOnNetworkThread());
context_->PostTaskToNetworkThread(
FROM_HERE, base::Bind(&CronetURLRequestAdapter::ReadDataOnNetworkThread,
base::Unretained(this)));
}
void CronetURLRequestAdapter::ReadData() {
DCHECK(IsOnNetworkThread());
if (!read_buffer_.get())
read_buffer_ = new net::IOBufferWithSize(kReadBufferSize);
void CronetURLRequestAdapter::Destroy(JNIEnv* env, jobject jcaller) {
DCHECK(!context_->IsOnNetworkThread());
context_->PostTaskToNetworkThread(
FROM_HERE, base::Bind(&CronetURLRequestAdapter::DestroyOnNetworkThread,
base::Unretained(this)));
}
int bytes_read = 0;
url_request_->Read(read_buffer_.get(), read_buffer_->size(), &bytes_read);
// If IO is pending, wait for the URLRequest to call OnReadCompleted.
if (url_request_->status().is_io_pending())
void CronetURLRequestAdapter::PopulateResponseHeaders(JNIEnv* env,
jobject jurl_request,
jobject jheaders_list) {
DCHECK(context_->IsOnNetworkThread());
const net::HttpResponseHeaders* headers = url_request_->response_headers();
if (headers == nullptr)
return;
OnReadCompleted(url_request_.get(), bytes_read);
}
void CronetURLRequestAdapter::Destroy() {
DCHECK(IsOnNetworkThread());
delete this;
void* iter = nullptr;
std::string header_name;
std::string header_value;
while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
base::android::ScopedJavaLocalRef<jstring> name =
ConvertUTF8ToJavaString(env, header_name);
base::android::ScopedJavaLocalRef<jstring> value =
ConvertUTF8ToJavaString(env, header_value);
Java_CronetUrlRequest_onAppendResponseHeader(
env, jurl_request, jheaders_list, name.obj(), value.obj());
}
}
const net::HttpResponseHeaders*
CronetURLRequestAdapter::GetResponseHeaders() const {
DCHECK(IsOnNetworkThread());
return url_request_->response_headers();
base::android::ScopedJavaLocalRef<jstring>
CronetURLRequestAdapter::GetHttpStatusText(JNIEnv* env, jobject jcaller) const {
DCHECK(context_->IsOnNetworkThread());
const net::HttpResponseHeaders* headers = url_request_->response_headers();
return ConvertUTF8ToJavaString(env, headers->GetStatusText());
}
const std::string& CronetURLRequestAdapter::GetNegotiatedProtocol() const {
DCHECK(IsOnNetworkThread());
return url_request_->response_info().npn_negotiated_protocol;
base::android::ScopedJavaLocalRef<jstring>
CronetURLRequestAdapter::GetNegotiatedProtocol(JNIEnv* env,
jobject jcaller) const {
DCHECK(context_->IsOnNetworkThread());
return ConvertUTF8ToJavaString(
env, url_request_->response_info().npn_negotiated_protocol);
}
bool CronetURLRequestAdapter::GetWasCached() const {
DCHECK(IsOnNetworkThread());
jboolean CronetURLRequestAdapter::GetWasCached(JNIEnv* env,
jobject jcaller) const {
DCHECK(context_->IsOnNetworkThread());
return url_request_->response_info().was_cached;
}
int64 CronetURLRequestAdapter::GetTotalReceivedBytes() const {
DCHECK(IsOnNetworkThread());
int64 CronetURLRequestAdapter::GetTotalReceivedBytes(JNIEnv* env,
jobject jcaller) const {
DCHECK(context_->IsOnNetworkThread());
return url_request_->GetTotalReceivedBytes();
}
......@@ -133,40 +195,94 @@ void CronetURLRequestAdapter::OnReceivedRedirect(
net::URLRequest* request,
const net::RedirectInfo& redirect_info,
bool* defer_redirect) {
DCHECK(IsOnNetworkThread());
DCHECK(context_->IsOnNetworkThread());
DCHECK(request->status().is_success());
delegate_->OnRedirect(redirect_info.new_url, redirect_info.status_code);
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onRedirect(
env, owner_.obj(),
ConvertUTF8ToJavaString(env, redirect_info.new_url.spec()).obj(),
redirect_info.status_code);
*defer_redirect = true;
}
void CronetURLRequestAdapter::OnResponseStarted(net::URLRequest* request) {
DCHECK(IsOnNetworkThread());
DCHECK(context_->IsOnNetworkThread());
if (MaybeReportError(request))
return;
delegate_->OnResponseStarted(request->GetResponseCode());
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onResponseStarted(env, owner_.obj(),
request->GetResponseCode());
}
void CronetURLRequestAdapter::OnReadCompleted(net::URLRequest* request,
int bytes_read) {
DCHECK(IsOnNetworkThread());
DCHECK(context_->IsOnNetworkThread());
if (MaybeReportError(request))
return;
if (bytes_read != 0) {
delegate_->OnBytesRead(
reinterpret_cast<unsigned char*>(read_buffer_->data()), bytes_read);
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> java_buffer(
env, env->NewDirectByteBuffer(read_buffer_->data(), bytes_read));
cronet::Java_CronetUrlRequest_onDataReceived(env, owner_.obj(),
java_buffer.obj());
} else {
delegate_->OnRequestFinished();
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onSucceeded(env, owner_.obj());
}
}
void CronetURLRequestAdapter::StartOnNetworkThread() {
DCHECK(context_->IsOnNetworkThread());
VLOG(1) << "Starting chromium request: "
<< initial_url_.possibly_invalid_spec().c_str()
<< " priority: " << RequestPriorityToString(initial_priority_);
url_request_ = context_->GetURLRequestContext()->CreateRequest(
initial_url_, net::DEFAULT_PRIORITY, this);
url_request_->SetLoadFlags(load_flags_);
url_request_->set_method(initial_method_);
url_request_->SetExtraRequestHeaders(initial_request_headers_);
url_request_->SetPriority(initial_priority_);
if (upload_)
url_request_->set_upload(upload_.Pass());
url_request_->Start();
}
void CronetURLRequestAdapter::FollowDeferredRedirectOnNetworkThread() {
DCHECK(context_->IsOnNetworkThread());
url_request_->FollowDeferredRedirect();
}
void CronetURLRequestAdapter::ReadDataOnNetworkThread() {
DCHECK(context_->IsOnNetworkThread());
if (!read_buffer_.get())
read_buffer_ = new net::IOBufferWithSize(kReadBufferSize);
int bytes_read = 0;
url_request_->Read(read_buffer_.get(), read_buffer_->size(), &bytes_read);
// If IO is pending, wait for the URLRequest to call OnReadCompleted.
if (url_request_->status().is_io_pending())
return;
OnReadCompleted(url_request_.get(), bytes_read);
}
void CronetURLRequestAdapter::DestroyOnNetworkThread() {
DCHECK(context_->IsOnNetworkThread());
delete this;
}
bool CronetURLRequestAdapter::MaybeReportError(net::URLRequest* request) const {
DCHECK_NE(net::URLRequestStatus::IO_PENDING, url_request_->status().status());
DCHECK_EQ(request, url_request_);
if (url_request_->status().is_success())
return false;
VLOG(1) << "Error " << url_request_->status().error()
int net_error = url_request_->status().error();
VLOG(1) << "Error " << net::ErrorToString(net_error)
<< " on chromium request: " << initial_url_.possibly_invalid_spec();
delegate_->OnError(url_request_->status().error());
JNIEnv* env = base::android::AttachCurrentThread();
cronet::Java_CronetUrlRequest_onError(
env, owner_.obj(), net_error,
ConvertUTF8ToJavaString(env, net::ErrorToString(net_error)).obj());
return true;
}
......
......@@ -5,14 +5,17 @@
#ifndef COMPONENTS_CRONET_ANDROID_CRONET_URL_REQUEST_ADAPTER_H_
#define COMPONENTS_CRONET_ANDROID_CRONET_URL_REQUEST_ADAPTER_H_
#include <jni.h>
#include <string>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/request_priority.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
......@@ -22,6 +25,7 @@ class SingleThreadTaskRunner;
namespace net {
class GrowableIOBuffer;
class HttpRequestHeaders;
class HttpResponseHeaders;
class UploadDataStream;
} // namespace net
......@@ -30,43 +34,20 @@ namespace cronet {
class CronetURLRequestContextAdapter;
// An adapter from the JNI CronetUrlRequest object to the Chromium URLRequest.
// Created and configured from random thread. Start is posted to network
// thread and all callbacks into CronetURLRequestAdapterDelegate are done on
// network thread. Each delegate callback is expected to initiate next step like
// FollowDeferredRedirect, ReadData or Destroy. All methods except those needed
// to set up a request must be called exclusively on the network thread.
bool CronetUrlRequestAdapterRegisterJni(JNIEnv* env);
// An adapter from Java CronetUrlRequest object to net::URLRequest.
// Created and configured from a Java thread. Start, ReadData, and Destroy are
// posted to network thread and all callbacks into the Java CronetUrlRequest are
// done on the network thread. Java CronetUrlRequest is expected to initiate the
// next step like FollowDeferredRedirect, ReadData or Destroy. Public methods
// can be called on any thread except PopulateResponseHeaders and Get* methods,
// which can only be called on the network thread.
class CronetURLRequestAdapter : public net::URLRequest::Delegate {
public:
// The delegate which is called when the request adapter completes a step.
// Always called on network thread.
class CronetURLRequestAdapterDelegate {
public:
// Called on redirect. Consumer should either destroy the request, or
// call FollowDeferredRedirect.
virtual void OnRedirect(const GURL& newLocation, int http_status_code) = 0;
// Called when response has started and headers have been received. Consumer
// should either destroy the request, or call ReadData.
virtual void OnResponseStarted(int http_status_code) = 0;
// Called when response bytes were read. Consumer should consume data and
// either destroy the request, or call ReadData. The request may only be
// destroyed after the embedder is done with |bytes|, as deleting the
// request frees the buffer.
virtual void OnBytesRead(unsigned char* bytes,
int bytes_read) = 0;
// Called when response has finished successfully. Consumer should destroy
// the request.
virtual void OnRequestFinished() = 0;
// Called when response has finished with error. Consumer should destroy
// the request.
virtual void OnError(int net_error) = 0;
virtual ~CronetURLRequestAdapterDelegate() {}
};
CronetURLRequestAdapter(
CronetURLRequestContextAdapter* context,
scoped_ptr<CronetURLRequestAdapterDelegate> delegate,
CronetURLRequestAdapter(CronetURLRequestContextAdapter* context,
JNIEnv* env,
jobject jurl_request,
const GURL& url,
net::RequestPriority priority);
~CronetURLRequestAdapter() override;
......@@ -74,62 +55,62 @@ class CronetURLRequestAdapter : public net::URLRequest::Delegate {
// Methods called prior to Start are never called on network thread.
// Sets the request method GET, POST etc.
void set_method(const std::string& method) {
initial_method_ = method;
}
jboolean SetHttpMethod(JNIEnv* env, jobject jcaller, jstring jmethod);
// Adds a header to the request before it starts.
void AddRequestHeader(const std::string& name, const std::string& value);
jboolean AddRequestHeader(JNIEnv* env,
jobject jcaller,
jstring jname,
jstring jvalue);
// Bypasses cache. If context is not set up to use cache, this call has no
// effect.
void DisableCache(JNIEnv* env, jobject jcaller);
// Adds a request body to the request before it starts.
void SetUpload(scoped_ptr<net::UploadDataStream> upload);
// Methods called on any thread.
// Posts tasks to network thread.
void PostTaskToNetworkThread(const tracked_objects::Location& from_here,
const base::Closure& task);
// Returns true if called on network thread.
bool IsOnNetworkThread() const;
// Methods called only on network thread.
// Starts the request.
void Start();
void Start(JNIEnv* env, jobject jcaller);
// Follows redirect.
void FollowDeferredRedirect();
void FollowDeferredRedirect(JNIEnv* env, jobject jcaller);
// Reads more data.
void ReadData();
void ReadData(JNIEnv* env, jobject jcaller);
// Releases all resources for the request and deletes the object itself.
void Destroy();
void Destroy(JNIEnv* env, jobject jcaller);
// Populate response headers on network thread.
void PopulateResponseHeaders(JNIEnv* env,
jobject jcaller,
jobject jheaders_list);
// When called during a OnRedirect or OnResponseStarted callback, these
// methods return the corresponding response information.
// methods return the corresponding response information. These methods
// can only be called on the network thread.
// Gets all response headers, as a HttpResponseHeaders object. Returns NULL
// if the last attempted request received no headers.
const net::HttpResponseHeaders* GetResponseHeaders() const;
// Gets http status text from the response headers.
base::android::ScopedJavaLocalRef<jstring> GetHttpStatusText(
JNIEnv* env,
jobject jcaller) const;
// Gets NPN or ALPN Negotiated Protocol (if any) from HttpResponseInfo.
const std::string& GetNegotiatedProtocol() const;
base::android::ScopedJavaLocalRef<jstring> GetNegotiatedProtocol(
JNIEnv* env,
jobject jcaller) const;
// Returns true if response is coming from the cache.
bool GetWasCached() const;
jboolean GetWasCached(JNIEnv* env, jobject jcaller) const;
// Gets the total amount of body data received from network after
// SSL/SPDY/QUIC decoding and proxy handling. Basically the size of the body
// prior to decompression.
int64 GetTotalReceivedBytes() const;
int64 GetTotalReceivedBytes(JNIEnv* env, jobject jcaller) const;
// Bypasses cache. If context is not set up to use cache, this call has no
// effect.
void DisableCache();
// net::URLRequest::Delegate implementations:
// net::URLRequest::Delegate overrides.
void OnReceivedRedirect(net::URLRequest* request,
const net::RedirectInfo& redirect_info,
bool* defer_redirect) override;
......@@ -137,12 +118,19 @@ class CronetURLRequestAdapter : public net::URLRequest::Delegate {
void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
private:
void StartOnNetworkThread();
void FollowDeferredRedirectOnNetworkThread();
void ReadDataOnNetworkThread();
void DestroyOnNetworkThread();
// Checks status of the request_adapter, return false if |is_success()| is
// true, otherwise report error and cancel request_adapter.
bool MaybeReportError(net::URLRequest* request) const;
CronetURLRequestContextAdapter* context_;
scoped_ptr<CronetURLRequestAdapterDelegate> delegate_;
// Java object that owns this CronetURLRequestContextAdapter.
base::android::ScopedJavaGlobalRef<jobject> owner_;
const GURL initial_url_;
const net::RequestPriority initial_priority_;
......
......@@ -9,6 +9,7 @@ import android.util.Pair;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.NativeClassQualifiedName;
import java.nio.ByteBuffer;
import java.util.ArrayList;
......@@ -99,7 +100,7 @@ final class CronetUrlRequest implements UrlRequest {
destroyRequestAdapter();
return;
}
nativeReceiveData(mUrlRequestAdapter);
nativeReadData(mUrlRequestAdapter);
}
} catch (Exception e) {
synchronized (mUrlRequestAdapterLock) {
......@@ -291,7 +292,7 @@ final class CronetUrlRequest implements UrlRequest {
&& !header.second.isEmpty()) {
hasContentType = true;
}
if (!nativeAddHeader(mUrlRequestAdapter, header.first, header.second)) {
if (!nativeAddRequestHeader(mUrlRequestAdapter, header.first, header.second)) {
destroyRequestAdapter();
throw new IllegalArgumentException(
"Invalid header " + header.first + "=" + header.second);
......@@ -423,7 +424,7 @@ final class CronetUrlRequest implements UrlRequest {
if (mUrlRequestAdapter == 0) {
return;
}
nativeDestroyRequestAdapter(mUrlRequestAdapter);
nativeDestroy(mUrlRequestAdapter);
mRequestContext.onRequestDestroyed(this);
mUrlRequestAdapter = 0;
}
......@@ -540,7 +541,7 @@ final class CronetUrlRequest implements UrlRequest {
if (isCanceled()) {
return;
}
nativeReceiveData(mUrlRequestAdapter);
nativeReadData(mUrlRequestAdapter);
}
} catch (Exception e) {
onListenerException(e);
......@@ -657,30 +658,39 @@ final class CronetUrlRequest implements UrlRequest {
private native long nativeCreateRequestAdapter(
long urlRequestContextAdapter, String url, int priority);
private native boolean nativeAddHeader(long urlRequestAdapter, String name,
String value);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native boolean nativeSetHttpMethod(long nativePtr, String method);
private native boolean nativeSetHttpMethod(long urlRequestAdapter,
String method);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native boolean nativeAddRequestHeader(long nativePtr, String name, String value);
private native void nativeStart(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native void nativeDisableCache(long nativePtr);
private native void nativeDestroyRequestAdapter(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native void nativeStart(long nativePtr);
private native void nativeFollowDeferredRedirect(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native void nativeFollowDeferredRedirect(long nativePtr);
private native void nativeReceiveData(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native void nativeReadData(long nativePtr);
private native void nativePopulateResponseHeaders(long urlRequestAdapter,
HeadersList headers);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native void nativeDestroy(long nativePtr);
private native String nativeGetNegotiatedProtocol(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native void nativePopulateResponseHeaders(long nativePtr, HeadersList headers);
private native String nativeGetHttpStatusText(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native String nativeGetHttpStatusText(long nativePtr);
private native boolean nativeGetWasCached(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native String nativeGetNegotiatedProtocol(long nativePtr);
private native long nativeGetTotalReceivedBytes(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native boolean nativeGetWasCached(long nativePtr);
private native void nativeDisableCache(long urlRequestAdapter);
@NativeClassQualifiedName("CronetURLRequestAdapter")
private native long nativeGetTotalReceivedBytes(long nativePtr);
}
......@@ -29,8 +29,6 @@
'android/cronet_upload_data_stream_adapter.h',
'android/cronet_upload_data_stream_delegate.cc',
'android/cronet_upload_data_stream_delegate.h',
'android/cronet_url_request.cc',
'android/cronet_url_request.h',
'android/cronet_url_request_adapter.cc',
'android/cronet_url_request_adapter.h',
'android/cronet_url_request_context_adapter.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment