Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cronet_url_request_adapter.h" | 5 #include "cronet_url_request_adapter.h" |
| 6 | 6 |
| 7 #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.
| |
| 8 | |
| 9 #include "base/android/jni_android.h" | |
| 10 #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.
| |
| 7 #include "base/bind.h" | 11 #include "base/bind.h" |
| 8 #include "base/location.h" | 12 #include "base/location.h" |
| 9 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/macros.h" | |
|
mmenke
2015/04/02 21:07:05
nit: in header
xunjieli
2015/04/02 21:50:13
Done.
| |
| 10 #include "components/cronet/android/cronet_url_request_context_adapter.h" | 15 #include "components/cronet/android/cronet_url_request_context_adapter.h" |
| 11 #include "components/cronet/android/wrapped_channel_upload_element_reader.h" | 16 #include "jni/CronetUrlRequest_jni.h" |
| 12 #include "net/base/io_buffer.h" | 17 #include "net/base/io_buffer.h" |
| 13 #include "net/base/load_flags.h" | 18 #include "net/base/load_flags.h" |
| 19 #include "net/base/net_errors.h" | |
| 20 #include "net/base/request_priority.h" | |
| 21 #include "net/http/http_response_headers.h" | |
| 14 #include "net/http/http_status_code.h" | 22 #include "net/http/http_status_code.h" |
| 23 #include "net/http/http_util.h" | |
| 15 #include "net/url_request/redirect_info.h" | 24 #include "net/url_request/redirect_info.h" |
| 16 #include "net/url_request/url_request_context.h" | 25 #include "net/url_request/url_request_context.h" |
| 17 | 26 |
| 27 using base::android::ConvertUTF8ToJavaString; | |
| 28 | |
| 18 namespace cronet { | 29 namespace cronet { |
| 19 | 30 |
| 31 namespace { | |
| 32 | |
| 20 static const int kReadBufferSize = 32768; | 33 static const int kReadBufferSize = 32768; |
| 21 | 34 |
| 35 } // namespace | |
|
mmenke
2015/04/02 21:07:05
nit: Either need static or anonymous namespace, n
xunjieli
2015/04/02 21:50:12
Done.
| |
| 36 | |
| 37 // Explicitly register static JNI functions. | |
| 38 bool CronetUrlRequestAdapterRegisterJni(JNIEnv* env) { | |
| 39 return RegisterNativesImpl(env); | |
| 40 } | |
| 41 | |
| 42 static jlong CreateRequestAdapter(JNIEnv* env, | |
| 43 jobject jurl_request, | |
| 44 jlong jurl_request_context_adapter, | |
| 45 jstring jurl_string, | |
| 46 jint jpriority) { | |
| 47 CronetURLRequestContextAdapter* context_adapter = | |
| 48 reinterpret_cast<CronetURLRequestContextAdapter*>( | |
| 49 jurl_request_context_adapter); | |
| 50 DCHECK(context_adapter); | |
| 51 | |
| 52 GURL url(base::android::ConvertJavaStringToUTF8(env, jurl_string)); | |
| 53 | |
| 54 VLOG(1) << "New chromium network request_adapter: " | |
| 55 << url.possibly_invalid_spec(); | |
| 56 | |
| 57 CronetURLRequestAdapter* adapter = | |
| 58 new CronetURLRequestAdapter(context_adapter, env, jurl_request, url, | |
| 59 static_cast<net::RequestPriority>(jpriority)); | |
| 60 | |
| 61 return reinterpret_cast<jlong>(adapter); | |
| 62 } | |
| 63 | |
| 22 CronetURLRequestAdapter::CronetURLRequestAdapter( | 64 CronetURLRequestAdapter::CronetURLRequestAdapter( |
| 23 CronetURLRequestContextAdapter* context, | 65 CronetURLRequestContextAdapter* context, |
| 24 scoped_ptr<CronetURLRequestAdapterDelegate> delegate, | 66 JNIEnv* env, |
| 67 jobject jurl_request, | |
| 25 const GURL& url, | 68 const GURL& url, |
| 26 net::RequestPriority priority) | 69 net::RequestPriority priority) |
| 27 : context_(context), | 70 : context_(context), |
| 28 delegate_(delegate.Pass()), | |
| 29 initial_url_(url), | 71 initial_url_(url), |
| 30 initial_priority_(priority), | 72 initial_priority_(priority), |
| 31 initial_method_("GET"), | 73 initial_method_("GET"), |
| 32 load_flags_(context->default_load_flags()) { | 74 load_flags_(context->default_load_flags()) { |
| 75 owner_.Reset(env, jurl_request); | |
|
mmenke
2015/04/02 21:07:05
DCHECK(!context_->IsOnNetworkThread());?
xunjieli
2015/04/02 21:50:13
Done.
| |
| 33 } | 76 } |
| 34 | 77 |
| 35 CronetURLRequestAdapter::~CronetURLRequestAdapter() { | 78 CronetURLRequestAdapter::~CronetURLRequestAdapter() { |
| 36 DCHECK(IsOnNetworkThread()); | 79 DCHECK(context_->IsOnNetworkThread()); |
| 37 } | 80 } |
| 38 | 81 |
| 39 void CronetURLRequestAdapter::AddRequestHeader(const std::string& name, | 82 jboolean CronetURLRequestAdapter::SetHttpMethod(JNIEnv* env, |
| 40 const std::string& value) { | 83 jobject jcaller, |
| 41 DCHECK(!IsOnNetworkThread()); | 84 jstring jmethod) { |
| 42 initial_request_headers_.SetHeader(name, value); | 85 DCHECK(!context_->IsOnNetworkThread()); |
| 86 std::string method(base::android::ConvertJavaStringToUTF8(env, jmethod)); | |
| 87 // Http method is a token, just as header name. | |
| 88 if (!net::HttpUtil::IsValidHeaderName(method)) | |
| 89 return JNI_FALSE; | |
| 90 initial_method_ = method; | |
| 91 return JNI_TRUE; | |
| 43 } | 92 } |
| 44 | 93 |
| 45 void CronetURLRequestAdapter::DisableCache() { | 94 jboolean CronetURLRequestAdapter::AddRequestHeader(JNIEnv* env, |
| 46 DCHECK(!IsOnNetworkThread()); | 95 jobject jcaller, |
| 47 load_flags_ |= net::LOAD_DISABLE_CACHE; | 96 jstring jname, |
| 48 } | 97 jstring jvalue) { |
| 49 | 98 DCHECK(!context_->IsOnNetworkThread()); |
| 50 void CronetURLRequestAdapter::PostTaskToNetworkThread( | 99 std::string name(base::android::ConvertJavaStringToUTF8(env, jname)); |
| 51 const tracked_objects::Location& from_here, | 100 std::string value(base::android::ConvertJavaStringToUTF8(env, jvalue)); |
| 52 const base::Closure& task) { | 101 if (!net::HttpUtil::IsValidHeaderName(name) || |
| 53 DCHECK(!IsOnNetworkThread()); | 102 !net::HttpUtil::IsValidHeaderValue(value)) { |
| 54 context_->PostTaskToNetworkThread(from_here, task); | 103 return JNI_FALSE; |
| 55 } | 104 } |
| 56 | 105 initial_request_headers_.SetHeader(name, value); |
| 57 bool CronetURLRequestAdapter::IsOnNetworkThread() const { | 106 return JNI_TRUE; |
| 58 return context_->IsOnNetworkThread(); | |
| 59 } | 107 } |
| 60 | 108 |
| 61 void CronetURLRequestAdapter::SetUpload( | 109 void CronetURLRequestAdapter::SetUpload( |
| 62 scoped_ptr<net::UploadDataStream> upload) { | 110 scoped_ptr<net::UploadDataStream> upload) { |
| 63 DCHECK(!IsOnNetworkThread()); | 111 DCHECK(!context_->IsOnNetworkThread()); |
| 64 DCHECK(!upload_); | 112 DCHECK(!upload_); |
| 65 upload_ = upload.Pass(); | 113 upload_ = upload.Pass(); |
| 66 } | 114 } |
| 67 | 115 |
| 68 void CronetURLRequestAdapter::Start() { | 116 void CronetURLRequestAdapter::Start(JNIEnv* env, jobject jcaller) { |
| 69 DCHECK(IsOnNetworkThread()); | 117 DCHECK(!context_->IsOnNetworkThread()); |
| 118 context_->PostTaskToNetworkThread( | |
| 119 FROM_HERE, base::Bind(&CronetURLRequestAdapter::StartOnNetworkThread, | |
| 120 base::Unretained(this))); | |
| 121 } | |
| 122 | |
| 123 void CronetURLRequestAdapter::StartOnNetworkThread() { | |
|
mmenke
2015/04/02 21:07:05
For this, ReadDataOnNetworkThread, and DestroyOnNe
xunjieli
2015/04/02 21:50:12
Done.
| |
| 124 DCHECK(context_->IsOnNetworkThread()); | |
| 70 VLOG(1) << "Starting chromium request: " | 125 VLOG(1) << "Starting chromium request: " |
| 71 << initial_url_.possibly_invalid_spec().c_str() | 126 << initial_url_.possibly_invalid_spec().c_str() |
| 72 << " priority: " << RequestPriorityToString(initial_priority_); | 127 << " priority: " << RequestPriorityToString(initial_priority_); |
| 73 url_request_ = context_->GetURLRequestContext()->CreateRequest( | 128 url_request_ = context_->GetURLRequestContext()->CreateRequest( |
| 74 initial_url_, net::DEFAULT_PRIORITY, this); | 129 initial_url_, net::DEFAULT_PRIORITY, this); |
| 75 url_request_->SetLoadFlags(load_flags_); | 130 url_request_->SetLoadFlags(load_flags_); |
| 76 url_request_->set_method(initial_method_); | 131 url_request_->set_method(initial_method_); |
| 77 url_request_->SetExtraRequestHeaders(initial_request_headers_); | 132 url_request_->SetExtraRequestHeaders(initial_request_headers_); |
| 78 url_request_->SetPriority(initial_priority_); | 133 url_request_->SetPriority(initial_priority_); |
| 79 if (upload_) | 134 if (upload_) |
| 80 url_request_->set_upload(upload_.Pass()); | 135 url_request_->set_upload(upload_.Pass()); |
| 81 url_request_->Start(); | 136 url_request_->Start(); |
| 82 } | 137 } |
| 83 | 138 |
| 84 void CronetURLRequestAdapter::FollowDeferredRedirect() { | 139 void CronetURLRequestAdapter::ReadData(JNIEnv* env, jobject jcaller) { |
| 85 DCHECK(IsOnNetworkThread()); | 140 DCHECK(!context_->IsOnNetworkThread()); |
| 86 | 141 context_->PostTaskToNetworkThread( |
| 87 url_request_->FollowDeferredRedirect(); | 142 FROM_HERE, base::Bind(&CronetURLRequestAdapter::ReadDataOnNetworkThread, |
| 143 base::Unretained(this))); | |
| 88 } | 144 } |
| 89 | 145 |
| 90 void CronetURLRequestAdapter::ReadData() { | 146 void CronetURLRequestAdapter::ReadDataOnNetworkThread() { |
| 91 DCHECK(IsOnNetworkThread()); | 147 DCHECK(context_->IsOnNetworkThread()); |
| 92 if (!read_buffer_.get()) | 148 if (!read_buffer_.get()) |
| 93 read_buffer_ = new net::IOBufferWithSize(kReadBufferSize); | 149 read_buffer_ = new net::IOBufferWithSize(kReadBufferSize); |
| 94 | 150 |
| 95 int bytes_read = 0; | 151 int bytes_read = 0; |
| 96 url_request_->Read(read_buffer_.get(), read_buffer_->size(), &bytes_read); | 152 url_request_->Read(read_buffer_.get(), read_buffer_->size(), &bytes_read); |
| 97 // If IO is pending, wait for the URLRequest to call OnReadCompleted. | 153 // If IO is pending, wait for the URLRequest to call OnReadCompleted. |
| 98 if (url_request_->status().is_io_pending()) | 154 if (url_request_->status().is_io_pending()) |
| 99 return; | 155 return; |
| 100 | 156 |
| 101 OnReadCompleted(url_request_.get(), bytes_read); | 157 OnReadCompleted(url_request_.get(), bytes_read); |
| 102 } | 158 } |
| 103 | 159 |
| 104 void CronetURLRequestAdapter::Destroy() { | 160 void CronetURLRequestAdapter::Destroy(JNIEnv* env, jobject jcaller) { |
| 105 DCHECK(IsOnNetworkThread()); | 161 DCHECK(!context_->IsOnNetworkThread()); |
| 162 context_->PostTaskToNetworkThread( | |
| 163 FROM_HERE, base::Bind(&CronetURLRequestAdapter::DestroyOnNetworkThread, | |
| 164 base::Unretained(this))); | |
| 165 } | |
| 166 | |
| 167 void CronetURLRequestAdapter::DestroyOnNetworkThread() { | |
| 168 DCHECK(context_->IsOnNetworkThread()); | |
| 106 delete this; | 169 delete this; |
| 107 } | 170 } |
| 108 | 171 |
| 109 const net::HttpResponseHeaders* | 172 void CronetURLRequestAdapter::PopulateResponseHeaders(JNIEnv* env, |
| 110 CronetURLRequestAdapter::GetResponseHeaders() const { | 173 jobject jurl_request, |
| 111 DCHECK(IsOnNetworkThread()); | 174 jobject jheaders_list) { |
| 112 return url_request_->response_headers(); | 175 DCHECK(context_->IsOnNetworkThread()); |
| 176 const net::HttpResponseHeaders* headers = url_request_->response_headers(); | |
| 177 if (headers == nullptr) | |
| 178 return; | |
| 179 | |
| 180 void* iter = nullptr; | |
| 181 std::string header_name; | |
| 182 std::string header_value; | |
| 183 while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) { | |
| 184 base::android::ScopedJavaLocalRef<jstring> name = | |
| 185 ConvertUTF8ToJavaString(env, header_name); | |
| 186 base::android::ScopedJavaLocalRef<jstring> value = | |
| 187 ConvertUTF8ToJavaString(env, header_value); | |
| 188 Java_CronetUrlRequest_onAppendResponseHeader( | |
| 189 env, jurl_request, jheaders_list, name.obj(), value.obj()); | |
| 190 } | |
| 113 } | 191 } |
| 114 | 192 |
| 115 const std::string& CronetURLRequestAdapter::GetNegotiatedProtocol() const { | 193 void CronetURLRequestAdapter::FollowDeferredRedirect(JNIEnv* env, |
| 116 DCHECK(IsOnNetworkThread()); | 194 jobject jcaller) { |
| 117 return url_request_->response_info().npn_negotiated_protocol; | 195 DCHECK(!context_->IsOnNetworkThread()); |
| 196 context_->PostTaskToNetworkThread( | |
| 197 FROM_HERE, base::Bind(&net::URLRequest::FollowDeferredRedirect, | |
| 198 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.
| |
| 118 } | 199 } |
| 119 | 200 |
| 120 bool CronetURLRequestAdapter::GetWasCached() const { | 201 void CronetURLRequestAdapter::DisableCache(JNIEnv* env, jobject jcaller) { |
| 121 DCHECK(IsOnNetworkThread()); | 202 DCHECK(!context_->IsOnNetworkThread()); |
| 203 load_flags_ |= net::LOAD_DISABLE_CACHE; | |
| 204 } | |
| 205 | |
| 206 base::android::ScopedJavaLocalRef<jstring> | |
| 207 CronetURLRequestAdapter::GetHttpStatusText(JNIEnv* env, jobject jcaller) const { | |
| 208 DCHECK(context_->IsOnNetworkThread()); | |
| 209 const net::HttpResponseHeaders* headers = url_request_->response_headers(); | |
| 210 return ConvertUTF8ToJavaString(env, headers->GetStatusText()); | |
| 211 } | |
| 212 | |
| 213 base::android::ScopedJavaLocalRef<jstring> | |
| 214 CronetURLRequestAdapter::GetNegotiatedProtocol(JNIEnv* env, | |
| 215 jobject jcaller) const { | |
| 216 DCHECK(context_->IsOnNetworkThread()); | |
| 217 return ConvertUTF8ToJavaString( | |
| 218 env, url_request_->response_info().npn_negotiated_protocol); | |
| 219 } | |
| 220 | |
| 221 jboolean CronetURLRequestAdapter::GetWasCached(JNIEnv* env, | |
| 222 jobject jcaller) const { | |
| 223 DCHECK(context_->IsOnNetworkThread()); | |
| 122 return url_request_->response_info().was_cached; | 224 return url_request_->response_info().was_cached; |
| 123 } | 225 } |
| 124 | 226 |
| 125 int64 CronetURLRequestAdapter::GetTotalReceivedBytes() const { | 227 int64 CronetURLRequestAdapter::GetTotalReceivedBytes(JNIEnv* env, |
| 126 DCHECK(IsOnNetworkThread()); | 228 jobject jcaller) const { |
| 229 DCHECK(context_->IsOnNetworkThread()); | |
| 127 return url_request_->GetTotalReceivedBytes(); | 230 return url_request_->GetTotalReceivedBytes(); |
| 128 } | 231 } |
| 129 | 232 |
| 130 // net::URLRequest::Delegate overrides (called on network thread). | 233 // net::URLRequest::Delegate overrides (called on network thread). |
| 131 | 234 |
| 132 void CronetURLRequestAdapter::OnReceivedRedirect( | 235 void CronetURLRequestAdapter::OnReceivedRedirect( |
| 133 net::URLRequest* request, | 236 net::URLRequest* request, |
| 134 const net::RedirectInfo& redirect_info, | 237 const net::RedirectInfo& redirect_info, |
| 135 bool* defer_redirect) { | 238 bool* defer_redirect) { |
| 136 DCHECK(IsOnNetworkThread()); | 239 DCHECK(context_->IsOnNetworkThread()); |
| 137 DCHECK(request->status().is_success()); | 240 DCHECK(request->status().is_success()); |
| 138 delegate_->OnRedirect(redirect_info.new_url, redirect_info.status_code); | 241 JNIEnv* env = base::android::AttachCurrentThread(); |
| 242 cronet::Java_CronetUrlRequest_onRedirect( | |
| 243 env, owner_.obj(), | |
| 244 ConvertUTF8ToJavaString(env, redirect_info.new_url.spec()).obj(), | |
| 245 redirect_info.status_code); | |
| 139 *defer_redirect = true; | 246 *defer_redirect = true; |
| 140 } | 247 } |
| 141 | 248 |
| 142 void CronetURLRequestAdapter::OnResponseStarted(net::URLRequest* request) { | 249 void CronetURLRequestAdapter::OnResponseStarted(net::URLRequest* request) { |
| 143 DCHECK(IsOnNetworkThread()); | 250 DCHECK(context_->IsOnNetworkThread()); |
| 144 if (MaybeReportError(request)) | 251 if (MaybeReportError(request)) |
| 145 return; | 252 return; |
| 146 delegate_->OnResponseStarted(request->GetResponseCode()); | 253 JNIEnv* env = base::android::AttachCurrentThread(); |
| 254 cronet::Java_CronetUrlRequest_onResponseStarted(env, owner_.obj(), | |
| 255 request->GetResponseCode()); | |
| 147 } | 256 } |
| 148 | 257 |
| 149 void CronetURLRequestAdapter::OnReadCompleted(net::URLRequest* request, | 258 void CronetURLRequestAdapter::OnReadCompleted(net::URLRequest* request, |
| 150 int bytes_read) { | 259 int bytes_read) { |
| 151 DCHECK(IsOnNetworkThread()); | 260 DCHECK(context_->IsOnNetworkThread()); |
| 152 if (MaybeReportError(request)) | 261 if (MaybeReportError(request)) |
| 153 return; | 262 return; |
| 154 if (bytes_read != 0) { | 263 if (bytes_read != 0) { |
| 155 delegate_->OnBytesRead( | 264 JNIEnv* env = base::android::AttachCurrentThread(); |
| 156 reinterpret_cast<unsigned char*>(read_buffer_->data()), bytes_read); | 265 base::android::ScopedJavaLocalRef<jobject> java_buffer( |
| 266 env, env->NewDirectByteBuffer(read_buffer_->data(), bytes_read)); | |
| 267 cronet::Java_CronetUrlRequest_onDataReceived(env, owner_.obj(), | |
| 268 java_buffer.obj()); | |
| 157 } else { | 269 } else { |
| 158 delegate_->OnRequestFinished(); | 270 JNIEnv* env = base::android::AttachCurrentThread(); |
| 271 cronet::Java_CronetUrlRequest_onSucceeded(env, owner_.obj()); | |
| 159 } | 272 } |
| 160 } | 273 } |
| 161 | 274 |
| 162 bool CronetURLRequestAdapter::MaybeReportError(net::URLRequest* request) const { | 275 bool CronetURLRequestAdapter::MaybeReportError(net::URLRequest* request) const { |
| 163 DCHECK_NE(net::URLRequestStatus::IO_PENDING, url_request_->status().status()); | 276 DCHECK_NE(net::URLRequestStatus::IO_PENDING, url_request_->status().status()); |
| 164 DCHECK_EQ(request, url_request_); | 277 DCHECK_EQ(request, url_request_); |
| 165 if (url_request_->status().is_success()) | 278 if (url_request_->status().is_success()) |
| 166 return false; | 279 return false; |
| 167 VLOG(1) << "Error " << url_request_->status().error() | 280 int net_error = url_request_->status().error(); |
| 281 VLOG(1) << "Error " << net::ErrorToString(net_error) | |
| 168 << " on chromium request: " << initial_url_.possibly_invalid_spec(); | 282 << " on chromium request: " << initial_url_.possibly_invalid_spec(); |
| 169 delegate_->OnError(url_request_->status().error()); | 283 JNIEnv* env = base::android::AttachCurrentThread(); |
| 284 cronet::Java_CronetUrlRequest_onError( | |
| 285 env, owner_.obj(), net_error, | |
| 286 ConvertUTF8ToJavaString(env, net::ErrorToString(net_error)).obj()); | |
| 170 return true; | 287 return true; |
| 171 } | 288 } |
| 172 | 289 |
| 173 } // namespace cronet | 290 } // namespace cronet |
| OLD | NEW |