Chromium Code Reviews| Index: components/cronet/android/cronet_url_request_adapter.cc |
| diff --git a/components/cronet/android/cronet_url_request_adapter.cc b/components/cronet/android/cronet_url_request_adapter.cc |
| index ff36601caf397ea73e79e892620c55fee18fe6a3..7a43c776bea2abe7940b34c47d3b58e5c4747b5c 100644 |
| --- a/components/cronet/android/cronet_url_request_adapter.cc |
| +++ b/components/cronet/android/cronet_url_request_adapter.cc |
| @@ -4,69 +4,124 @@ |
| #include "cronet_url_request_adapter.h" |
| +#include <jni.h> |
|
mmenke
2015/04/02 21:07:05
nit: Not needed (included in header file)
xunjieli
2015/04/02 21:50:13
Done.
|
| + |
| +#include "base/android/jni_android.h" |
| +#include "base/android/jni_string.h" |
|
mmenke
2015/04/02 21:07:05
nit: These two are used in the header
xunjieli
2015/04/02 21:50:13
Done.
|
| #include "base/bind.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| +#include "base/macros.h" |
|
mmenke
2015/04/02 21:07:05
nit: in header
xunjieli
2015/04/02 21:50:13
Done.
|
| #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 { |
| +namespace { |
| + |
| static const int kReadBufferSize = 32768; |
| +} // namespace |
|
mmenke
2015/04/02 21:07:05
nit: Either need static or anonymous namespace, n
xunjieli
2015/04/02 21:50:12
Done.
|
| + |
| +// 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()) { |
| + owner_.Reset(env, jurl_request); |
|
mmenke
2015/04/02 21:07:05
DCHECK(!context_->IsOnNetworkThread());?
xunjieli
2015/04/02 21:50:13
Done.
|
| } |
| CronetURLRequestAdapter::~CronetURLRequestAdapter() { |
| - DCHECK(IsOnNetworkThread()); |
| -} |
| - |
| -void CronetURLRequestAdapter::AddRequestHeader(const std::string& name, |
| - const std::string& value) { |
| - DCHECK(!IsOnNetworkThread()); |
| - initial_request_headers_.SetHeader(name, value); |
| -} |
| - |
| -void CronetURLRequestAdapter::DisableCache() { |
| - DCHECK(!IsOnNetworkThread()); |
| - load_flags_ |= net::LOAD_DISABLE_CACHE; |
| + DCHECK(context_->IsOnNetworkThread()); |
| } |
| -void CronetURLRequestAdapter::PostTaskToNetworkThread( |
| - const tracked_objects::Location& from_here, |
| - const base::Closure& task) { |
| - DCHECK(!IsOnNetworkThread()); |
| - context_->PostTaskToNetworkThread(from_here, task); |
| +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; |
| } |
| -bool CronetURLRequestAdapter::IsOnNetworkThread() const { |
| - return context_->IsOnNetworkThread(); |
| +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; |
| } |
| void CronetURLRequestAdapter::SetUpload( |
| scoped_ptr<net::UploadDataStream> upload) { |
| - DCHECK(!IsOnNetworkThread()); |
| + DCHECK(!context_->IsOnNetworkThread()); |
| DCHECK(!upload_); |
| upload_ = upload.Pass(); |
| } |
| -void CronetURLRequestAdapter::Start() { |
| - DCHECK(IsOnNetworkThread()); |
| +void CronetURLRequestAdapter::Start(JNIEnv* env, jobject jcaller) { |
| + DCHECK(!context_->IsOnNetworkThread()); |
| + context_->PostTaskToNetworkThread( |
| + FROM_HERE, base::Bind(&CronetURLRequestAdapter::StartOnNetworkThread, |
| + base::Unretained(this))); |
| +} |
| + |
| +void CronetURLRequestAdapter::StartOnNetworkThread() { |
|
mmenke
2015/04/02 21:07:05
For this, ReadDataOnNetworkThread, and DestroyOnNe
xunjieli
2015/04/02 21:50:12
Done.
|
| + DCHECK(context_->IsOnNetworkThread()); |
| VLOG(1) << "Starting chromium request: " |
| << initial_url_.possibly_invalid_spec().c_str() |
| << " priority: " << RequestPriorityToString(initial_priority_); |
| @@ -81,14 +136,15 @@ void CronetURLRequestAdapter::Start() { |
| url_request_->Start(); |
| } |
| -void CronetURLRequestAdapter::FollowDeferredRedirect() { |
| - DCHECK(IsOnNetworkThread()); |
| - |
| - 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()); |
| +void CronetURLRequestAdapter::ReadDataOnNetworkThread() { |
| + DCHECK(context_->IsOnNetworkThread()); |
| if (!read_buffer_.get()) |
| read_buffer_ = new net::IOBufferWithSize(kReadBufferSize); |
| @@ -101,29 +157,76 @@ void CronetURLRequestAdapter::ReadData() { |
| OnReadCompleted(url_request_.get(), bytes_read); |
| } |
| -void CronetURLRequestAdapter::Destroy() { |
| - DCHECK(IsOnNetworkThread()); |
| +void CronetURLRequestAdapter::Destroy(JNIEnv* env, jobject jcaller) { |
| + DCHECK(!context_->IsOnNetworkThread()); |
| + context_->PostTaskToNetworkThread( |
| + FROM_HERE, base::Bind(&CronetURLRequestAdapter::DestroyOnNetworkThread, |
| + base::Unretained(this))); |
| +} |
| + |
| +void CronetURLRequestAdapter::DestroyOnNetworkThread() { |
| + DCHECK(context_->IsOnNetworkThread()); |
| delete this; |
| } |
| -const net::HttpResponseHeaders* |
| -CronetURLRequestAdapter::GetResponseHeaders() const { |
| - DCHECK(IsOnNetworkThread()); |
| - return url_request_->response_headers(); |
| +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; |
| + |
| + 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()); |
| + } |
| +} |
| + |
| +void CronetURLRequestAdapter::FollowDeferredRedirect(JNIEnv* env, |
| + jobject jcaller) { |
| + DCHECK(!context_->IsOnNetworkThread()); |
| + context_->PostTaskToNetworkThread( |
| + FROM_HERE, base::Bind(&net::URLRequest::FollowDeferredRedirect, |
| + base::Unretained(url_request_.get()))); |
|
mmenke
2015/04/02 21:07:05
While this works, I think it's a little ugly and m
xunjieli
2015/04/02 21:50:13
Done.
|
| +} |
| + |
| +void CronetURLRequestAdapter::DisableCache(JNIEnv* env, jobject jcaller) { |
| + DCHECK(!context_->IsOnNetworkThread()); |
| + load_flags_ |= net::LOAD_DISABLE_CACHE; |
| +} |
| + |
| +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,29 +236,39 @@ 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()); |
| } |
| } |
| @@ -164,9 +277,13 @@ bool CronetURLRequestAdapter::MaybeReportError(net::URLRequest* request) const { |
| 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; |
| } |