| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_bidirectional_stream_adapter.h" | 5 #include "cronet_bidirectional_stream_adapter.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 #include "net/ssl/ssl_info.h" | 27 #include "net/ssl/ssl_info.h" |
| 28 #include "net/url_request/http_user_agent_settings.h" | 28 #include "net/url_request/http_user_agent_settings.h" |
| 29 #include "net/url_request/url_request_context.h" | 29 #include "net/url_request/url_request_context.h" |
| 30 #include "url/gurl.h" | 30 #include "url/gurl.h" |
| 31 | 31 |
| 32 using base::android::ConvertUTF8ToJavaString; | 32 using base::android::ConvertUTF8ToJavaString; |
| 33 using base::android::ConvertJavaStringToUTF8; | 33 using base::android::ConvertJavaStringToUTF8; |
| 34 | 34 |
| 35 namespace cronet { | 35 namespace cronet { |
| 36 | 36 |
| 37 namespace { |
| 38 |
| 39 // As |GetArrayLength| makes no guarantees about the returned value (e.g., it |
| 40 // may be -1 if |array| is not a valid Java array), provide a safe wrapper |
| 41 // that always returns a valid, non-negative size. |
| 42 template <typename JavaArrayType> |
| 43 size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) { |
| 44 DCHECK(jarray); |
| 45 jsize length = env->GetArrayLength(jarray); |
| 46 DCHECK_GE(length, 0) << "Invalid array length: " << length; |
| 47 return static_cast<size_t>(std::max(0, length)); |
| 48 } |
| 49 |
| 50 } // namespace |
| 51 |
| 37 static jlong CreateBidirectionalStream( | 52 static jlong CreateBidirectionalStream( |
| 38 JNIEnv* env, | 53 JNIEnv* env, |
| 39 const JavaParamRef<jobject>& jbidi_stream, | 54 const base::android::JavaParamRef<jobject>& jbidi_stream, |
| 40 jlong jurl_request_context_adapter) { | 55 jlong jurl_request_context_adapter, |
| 56 jboolean jdisable_auto_flush) { |
| 41 CronetURLRequestContextAdapter* context_adapter = | 57 CronetURLRequestContextAdapter* context_adapter = |
| 42 reinterpret_cast<CronetURLRequestContextAdapter*>( | 58 reinterpret_cast<CronetURLRequestContextAdapter*>( |
| 43 jurl_request_context_adapter); | 59 jurl_request_context_adapter); |
| 44 DCHECK(context_adapter); | 60 DCHECK(context_adapter); |
| 45 | 61 |
| 46 CronetBidirectionalStreamAdapter* adapter = | 62 CronetBidirectionalStreamAdapter* adapter = |
| 47 new CronetBidirectionalStreamAdapter(context_adapter, env, jbidi_stream); | 63 new CronetBidirectionalStreamAdapter(context_adapter, env, jbidi_stream, |
| 64 jdisable_auto_flush); |
| 48 | 65 |
| 49 return reinterpret_cast<jlong>(adapter); | 66 return reinterpret_cast<jlong>(adapter); |
| 50 } | 67 } |
| 51 | 68 |
| 52 // static | 69 // static |
| 53 bool CronetBidirectionalStreamAdapter::RegisterJni(JNIEnv* env) { | 70 bool CronetBidirectionalStreamAdapter::RegisterJni(JNIEnv* env) { |
| 54 return RegisterNativesImpl(env); | 71 return RegisterNativesImpl(env); |
| 55 } | 72 } |
| 56 | 73 |
| 57 CronetBidirectionalStreamAdapter::CronetBidirectionalStreamAdapter( | 74 CronetBidirectionalStreamAdapter::CronetBidirectionalStreamAdapter( |
| 58 CronetURLRequestContextAdapter* context, | 75 CronetURLRequestContextAdapter* context, |
| 59 JNIEnv* env, | 76 JNIEnv* env, |
| 60 const JavaParamRef<jobject>& jbidi_stream) | 77 const base::android::JavaParamRef<jobject>& jbidi_stream, |
| 61 : context_(context), owner_(env, jbidi_stream), stream_failed_(false) {} | 78 bool disable_auto_flush) |
| 79 : context_(context), |
| 80 owner_(env, jbidi_stream), |
| 81 disable_auto_flush_(disable_auto_flush), |
| 82 write_end_of_stream_(false), |
| 83 stream_failed_(false) {} |
| 62 | 84 |
| 63 CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() { | 85 CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() { |
| 64 DCHECK(context_->IsOnNetworkThread()); | 86 DCHECK(context_->IsOnNetworkThread()); |
| 65 } | 87 } |
| 66 | 88 |
| 67 jint CronetBidirectionalStreamAdapter::Start( | 89 jint CronetBidirectionalStreamAdapter::Start( |
| 68 JNIEnv* env, | 90 JNIEnv* env, |
| 69 const JavaParamRef<jobject>& jcaller, | 91 const base::android::JavaParamRef<jobject>& jcaller, |
| 70 const JavaParamRef<jstring>& jurl, | 92 const base::android::JavaParamRef<jstring>& jurl, |
| 71 jint jpriority, | 93 jint jpriority, |
| 72 const JavaParamRef<jstring>& jmethod, | 94 const base::android::JavaParamRef<jstring>& jmethod, |
| 73 const JavaParamRef<jobjectArray>& jheaders, | 95 const base::android::JavaParamRef<jobjectArray>& jheaders, |
| 74 jboolean jend_of_stream) { | 96 jboolean jend_of_stream) { |
| 75 // Prepare request info here to be able to return the error. | 97 // Prepare request info here to be able to return the error. |
| 76 std::unique_ptr<net::BidirectionalStreamRequestInfo> request_info( | 98 std::unique_ptr<net::BidirectionalStreamRequestInfo> request_info( |
| 77 new net::BidirectionalStreamRequestInfo()); | 99 new net::BidirectionalStreamRequestInfo()); |
| 78 request_info->url = GURL(ConvertJavaStringToUTF8(env, jurl)); | 100 request_info->url = GURL(ConvertJavaStringToUTF8(env, jurl)); |
| 79 request_info->priority = static_cast<net::RequestPriority>(jpriority); | 101 request_info->priority = static_cast<net::RequestPriority>(jpriority); |
| 80 // Http method is a token, just as header name. | 102 // Http method is a token, just as header name. |
| 81 request_info->method = ConvertJavaStringToUTF8(env, jmethod); | 103 request_info->method = ConvertJavaStringToUTF8(env, jmethod); |
| 82 if (!net::HttpUtil::IsValidHeaderName(request_info->method)) | 104 if (!net::HttpUtil::IsValidHeaderName(request_info->method)) |
| 83 return -1; | 105 return -1; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 97 | 119 |
| 98 context_->PostTaskToNetworkThread( | 120 context_->PostTaskToNetworkThread( |
| 99 FROM_HERE, | 121 FROM_HERE, |
| 100 base::Bind(&CronetBidirectionalStreamAdapter::StartOnNetworkThread, | 122 base::Bind(&CronetBidirectionalStreamAdapter::StartOnNetworkThread, |
| 101 base::Unretained(this), base::Passed(&request_info))); | 123 base::Unretained(this), base::Passed(&request_info))); |
| 102 return 0; | 124 return 0; |
| 103 } | 125 } |
| 104 | 126 |
| 105 jboolean CronetBidirectionalStreamAdapter::ReadData( | 127 jboolean CronetBidirectionalStreamAdapter::ReadData( |
| 106 JNIEnv* env, | 128 JNIEnv* env, |
| 107 const JavaParamRef<jobject>& jcaller, | 129 const base::android::JavaParamRef<jobject>& jcaller, |
| 108 const JavaParamRef<jobject>& jbyte_buffer, | 130 const base::android::JavaParamRef<jobject>& jbyte_buffer, |
| 109 jint jposition, | 131 jint jposition, |
| 110 jint jlimit) { | 132 jint jlimit) { |
| 111 DCHECK_LT(jposition, jlimit); | 133 DCHECK_LT(jposition, jlimit); |
| 112 | 134 |
| 113 void* data = env->GetDirectBufferAddress(jbyte_buffer); | 135 void* data = env->GetDirectBufferAddress(jbyte_buffer); |
| 114 if (!data) | 136 if (!data) |
| 115 return JNI_FALSE; | 137 return JNI_FALSE; |
| 116 | 138 |
| 117 scoped_refptr<IOBufferWithByteBuffer> read_buffer( | 139 scoped_refptr<IOBufferWithByteBuffer> read_buffer( |
| 118 new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit)); | 140 new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit)); |
| 119 | 141 |
| 120 int remaining_capacity = jlimit - jposition; | 142 int remaining_capacity = jlimit - jposition; |
| 121 | 143 |
| 122 context_->PostTaskToNetworkThread( | 144 context_->PostTaskToNetworkThread( |
| 123 FROM_HERE, | 145 FROM_HERE, |
| 124 base::Bind(&CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread, | 146 base::Bind(&CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread, |
| 125 base::Unretained(this), read_buffer, remaining_capacity)); | 147 base::Unretained(this), read_buffer, remaining_capacity)); |
| 126 return JNI_TRUE; | 148 return JNI_TRUE; |
| 127 } | 149 } |
| 128 | 150 |
| 129 jboolean CronetBidirectionalStreamAdapter::WriteData( | 151 jboolean CronetBidirectionalStreamAdapter::WritevData( |
| 130 JNIEnv* env, | 152 JNIEnv* env, |
| 131 const JavaParamRef<jobject>& jcaller, | 153 const base::android::JavaParamRef<jobject>& jcaller, |
| 132 const JavaParamRef<jobject>& jbyte_buffer, | 154 const base::android::JavaParamRef<jobjectArray>& jbyte_buffers, |
| 133 jint jposition, | 155 const base::android::JavaParamRef<jintArray>& jbyte_buffers_pos, |
| 134 jint jlimit, | 156 const base::android::JavaParamRef<jintArray>& jbyte_buffers_limit, |
| 135 jboolean jend_of_stream) { | 157 jboolean jend_of_stream) { |
| 136 DCHECK_LE(jposition, jlimit); | 158 size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 159 size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 160 size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 161 if (buffers_array_size != pos_array_size || |
| 162 buffers_array_size != limit_array_size) { |
| 163 DLOG(ERROR) << "Illegal arguments."; |
| 164 return JNI_FALSE; |
| 165 } |
| 137 | 166 |
| 138 void* data = env->GetDirectBufferAddress(jbyte_buffer); | 167 IOByteBufferList buffers; |
| 139 if (!data) | 168 for (size_t i = 0; i < buffers_array_size; ++i) { |
| 140 return JNI_FALSE; | 169 ScopedJavaLocalRef<jobject> jbuffer( |
| 141 | 170 env, env->GetObjectArrayElement(jbyte_buffers, i)); |
| 142 scoped_refptr<IOBufferWithByteBuffer> write_buffer( | 171 void* data = env->GetDirectBufferAddress(jbuffer.obj()); |
| 143 new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit)); | 172 if (!data) |
| 144 | 173 return JNI_FALSE; |
| 145 int remaining_capacity = jlimit - jposition; | 174 jint pos; |
| 146 | 175 env->GetIntArrayRegion(jbyte_buffers_pos.obj(), i, 1, &pos); |
| 176 jint limit; |
| 177 env->GetIntArrayRegion(jbyte_buffers_limit.obj(), i, 1, &limit); |
| 178 DCHECK_LE(pos, limit); |
| 179 scoped_refptr<IOBufferWithByteBuffer> write_buffer( |
| 180 new IOBufferWithByteBuffer( |
| 181 env, base::android::JavaParamRef<jobject>(env, jbuffer.Release()), |
| 182 data, pos, limit)); |
| 183 buffers.push_back(write_buffer); |
| 184 } |
| 147 context_->PostTaskToNetworkThread( | 185 context_->PostTaskToNetworkThread( |
| 148 FROM_HERE, | 186 FROM_HERE, |
| 149 base::Bind(&CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread, | 187 base::Bind(&CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread, |
| 150 base::Unretained(this), write_buffer, remaining_capacity, | 188 base::Unretained(this), buffers, jend_of_stream)); |
| 151 jend_of_stream)); | 189 |
| 152 return JNI_TRUE; | 190 return JNI_TRUE; |
| 153 } | 191 } |
| 154 | 192 |
| 155 void CronetBidirectionalStreamAdapter::Destroy( | 193 void CronetBidirectionalStreamAdapter::Destroy( |
| 156 JNIEnv* env, | 194 JNIEnv* env, |
| 157 const JavaParamRef<jobject>& jcaller, | 195 const base::android::JavaParamRef<jobject>& jcaller, |
| 158 jboolean jsend_on_canceled) { | 196 jboolean jsend_on_canceled) { |
| 159 // Destroy could be called from any thread, including network thread (if | 197 // Destroy could be called from any thread, including network thread (if |
| 160 // posting task to executor throws an exception), but is posted, so |this| | 198 // posting task to executor throws an exception), but is posted, so |this| |
| 161 // is valid until calling task is complete. Destroy() is always called from | 199 // is valid until calling task is complete. Destroy() is always called from |
| 162 // within a synchronized java block that guarantees no future posts to the | 200 // within a synchronized java block that guarantees no future posts to the |
| 163 // network thread with the adapter pointer. | 201 // network thread with the adapter pointer. |
| 164 context_->PostTaskToNetworkThread( | 202 context_->PostTaskToNetworkThread( |
| 165 FROM_HERE, | 203 FROM_HERE, |
| 166 base::Bind(&CronetBidirectionalStreamAdapter::DestroyOnNetworkThread, | 204 base::Bind(&CronetBidirectionalStreamAdapter::DestroyOnNetworkThread, |
| 167 base::Unretained(this), jsend_on_canceled)); | 205 base::Unretained(this), jsend_on_canceled)); |
| 168 } | 206 } |
| 169 | 207 |
| 170 void CronetBidirectionalStreamAdapter::OnHeadersSent() { | 208 void CronetBidirectionalStreamAdapter::OnStreamReady() { |
| 171 DCHECK(context_->IsOnNetworkThread()); | 209 DCHECK(context_->IsOnNetworkThread()); |
| 172 JNIEnv* env = base::android::AttachCurrentThread(); | 210 JNIEnv* env = base::android::AttachCurrentThread(); |
| 173 cronet::Java_CronetBidirectionalStream_onRequestHeadersSent(env, | 211 cronet::Java_CronetBidirectionalStream_onStreamReady(env, owner_.obj()); |
| 174 owner_.obj()); | |
| 175 } | 212 } |
| 176 | 213 |
| 177 void CronetBidirectionalStreamAdapter::OnHeadersReceived( | 214 void CronetBidirectionalStreamAdapter::OnHeadersReceived( |
| 178 const net::SpdyHeaderBlock& response_headers) { | 215 const net::SpdyHeaderBlock& response_headers) { |
| 179 DCHECK(context_->IsOnNetworkThread()); | 216 DCHECK(context_->IsOnNetworkThread()); |
| 180 JNIEnv* env = base::android::AttachCurrentThread(); | 217 JNIEnv* env = base::android::AttachCurrentThread(); |
| 181 // Get http status code from response headers. | 218 // Get http status code from response headers. |
| 182 jint http_status_code = 0; | 219 jint http_status_code = 0; |
| 183 const auto http_status_header = response_headers.find(":status"); | 220 const auto http_status_header = response_headers.find(":status"); |
| 184 if (http_status_header != response_headers.end()) | 221 if (http_status_header != response_headers.end()) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 210 env, owner_.obj(), read_buffer_->byte_buffer(), bytes_read, | 247 env, owner_.obj(), read_buffer_->byte_buffer(), bytes_read, |
| 211 read_buffer_->initial_position(), read_buffer_->initial_limit(), | 248 read_buffer_->initial_position(), read_buffer_->initial_limit(), |
| 212 bidi_stream_->GetTotalReceivedBytes()); | 249 bidi_stream_->GetTotalReceivedBytes()); |
| 213 // Free the read buffer. This lets the Java ByteBuffer be freed, if the | 250 // Free the read buffer. This lets the Java ByteBuffer be freed, if the |
| 214 // embedder releases it, too. | 251 // embedder releases it, too. |
| 215 read_buffer_ = nullptr; | 252 read_buffer_ = nullptr; |
| 216 } | 253 } |
| 217 | 254 |
| 218 void CronetBidirectionalStreamAdapter::OnDataSent() { | 255 void CronetBidirectionalStreamAdapter::OnDataSent() { |
| 219 DCHECK(context_->IsOnNetworkThread()); | 256 DCHECK(context_->IsOnNetworkThread()); |
| 257 DCHECK(!write_buffer_list_.empty()); |
| 258 |
| 220 JNIEnv* env = base::android::AttachCurrentThread(); | 259 JNIEnv* env = base::android::AttachCurrentThread(); |
| 221 cronet::Java_CronetBidirectionalStream_onWriteCompleted( | 260 base::android::ScopedJavaLocalRef<jclass> byte_buffer_clazz( |
| 222 env, owner_.obj(), write_buffer_->byte_buffer(), | 261 env, env->GetObjectClass(write_buffer_list_[0]->byte_buffer())); |
| 223 write_buffer_->initial_position(), write_buffer_->initial_limit()); | 262 size_t size = write_buffer_list_.size(); |
| 224 // Free the write buffer. This lets the Java ByteBuffer be freed, if the | 263 jobjectArray jbuffers = |
| 264 env->NewObjectArray(size, byte_buffer_clazz.obj(), NULL); |
| 265 base::android::CheckException(env); |
| 266 std::vector<int> initial_positions; |
| 267 std::vector<int> initial_limits; |
| 268 for (size_t i = 0; i < size; ++i) { |
| 269 env->SetObjectArrayElement(jbuffers, i, |
| 270 write_buffer_list_[i]->byte_buffer()); |
| 271 initial_positions.push_back(write_buffer_list_[i]->initial_position()); |
| 272 initial_limits.push_back(write_buffer_list_[i]->initial_limit()); |
| 273 } |
| 274 ScopedJavaLocalRef<jintArray> jinitial_positions = |
| 275 base::android::ToJavaIntArray(env, initial_positions); |
| 276 ScopedJavaLocalRef<jintArray> jinitial_limits = |
| 277 base::android::ToJavaIntArray(env, initial_limits); |
| 278 // Call into Java. |
| 279 cronet::Java_CronetBidirectionalStream_onWritevCompleted( |
| 280 env, owner_.obj(), jbuffers, jinitial_positions.obj(), |
| 281 jinitial_limits.obj(), write_end_of_stream_); |
| 282 // Free the write buffers. This lets the Java ByteBuffer be freed, if the |
| 225 // embedder releases it, too. | 283 // embedder releases it, too. |
| 226 write_buffer_ = nullptr; | 284 write_buffer_list_.clear(); |
| 227 } | 285 } |
| 228 | 286 |
| 229 void CronetBidirectionalStreamAdapter::OnTrailersReceived( | 287 void CronetBidirectionalStreamAdapter::OnTrailersReceived( |
| 230 const net::SpdyHeaderBlock& response_trailers) { | 288 const net::SpdyHeaderBlock& response_trailers) { |
| 231 DCHECK(context_->IsOnNetworkThread()); | 289 DCHECK(context_->IsOnNetworkThread()); |
| 232 JNIEnv* env = base::android::AttachCurrentThread(); | 290 JNIEnv* env = base::android::AttachCurrentThread(); |
| 233 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived( | 291 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived( |
| 234 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj()); | 292 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj()); |
| 235 } | 293 } |
| 236 | 294 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 249 DCHECK(context_->IsOnNetworkThread()); | 307 DCHECK(context_->IsOnNetworkThread()); |
| 250 DCHECK(!bidi_stream_); | 308 DCHECK(!bidi_stream_); |
| 251 request_info->extra_headers.SetHeaderIfMissing( | 309 request_info->extra_headers.SetHeaderIfMissing( |
| 252 net::HttpRequestHeaders::kUserAgent, context_->GetURLRequestContext() | 310 net::HttpRequestHeaders::kUserAgent, context_->GetURLRequestContext() |
| 253 ->http_user_agent_settings() | 311 ->http_user_agent_settings() |
| 254 ->GetUserAgent()); | 312 ->GetUserAgent()); |
| 255 bidi_stream_.reset(new net::BidirectionalStream( | 313 bidi_stream_.reset(new net::BidirectionalStream( |
| 256 std::move(request_info), context_->GetURLRequestContext() | 314 std::move(request_info), context_->GetURLRequestContext() |
| 257 ->http_transaction_factory() | 315 ->http_transaction_factory() |
| 258 ->GetSession(), | 316 ->GetSession(), |
| 259 this)); | 317 disable_auto_flush_, this)); |
| 260 } | 318 } |
| 261 | 319 |
| 262 void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread( | 320 void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread( |
| 263 scoped_refptr<IOBufferWithByteBuffer> read_buffer, | 321 scoped_refptr<IOBufferWithByteBuffer> read_buffer, |
| 264 int buffer_size) { | 322 int buffer_size) { |
| 265 DCHECK(context_->IsOnNetworkThread()); | 323 DCHECK(context_->IsOnNetworkThread()); |
| 266 DCHECK(read_buffer); | 324 DCHECK(read_buffer); |
| 267 DCHECK(!read_buffer_); | 325 DCHECK(!read_buffer_); |
| 268 | 326 |
| 269 read_buffer_ = read_buffer; | 327 read_buffer_ = read_buffer; |
| 270 | 328 |
| 271 int bytes_read = bidi_stream_->ReadData(read_buffer_.get(), buffer_size); | 329 int bytes_read = bidi_stream_->ReadData(read_buffer_.get(), buffer_size); |
| 272 // If IO is pending, wait for the BidirectionalStream to call OnDataRead. | 330 // If IO is pending, wait for the BidirectionalStream to call OnDataRead. |
| 273 if (bytes_read == net::ERR_IO_PENDING) | 331 if (bytes_read == net::ERR_IO_PENDING) |
| 274 return; | 332 return; |
| 275 | 333 |
| 276 if (bytes_read < 0) { | 334 if (bytes_read < 0) { |
| 277 OnFailed(bytes_read); | 335 OnFailed(bytes_read); |
| 278 return; | 336 return; |
| 279 } | 337 } |
| 280 OnDataRead(bytes_read); | 338 OnDataRead(bytes_read); |
| 281 } | 339 } |
| 282 | 340 |
| 283 void CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread( | 341 void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread( |
| 284 scoped_refptr<IOBufferWithByteBuffer> write_buffer, | 342 const IOByteBufferList& write_buffer_list, |
| 285 int buffer_size, | |
| 286 bool end_of_stream) { | 343 bool end_of_stream) { |
| 287 DCHECK(context_->IsOnNetworkThread()); | 344 DCHECK(context_->IsOnNetworkThread()); |
| 288 DCHECK(write_buffer); | 345 DCHECK(write_buffer_list_.empty()); |
| 289 DCHECK(!write_buffer_); | 346 DCHECK(!write_buffer_list.empty()); |
| 347 DCHECK(!write_end_of_stream_); |
| 290 | 348 |
| 291 if (stream_failed_) { | 349 if (stream_failed_) { |
| 292 // If stream failed between the time when WriteData is invoked and | 350 // If stream failed between the time when WriteData is invoked and |
| 293 // WriteDataOnNetworkThread is executed, do not call into |bidi_stream_| | 351 // WriteDataOnNetworkThread is executed, do not call into |bidi_stream_| |
| 294 // since the underlying stream might have been destroyed. Do not invoke | 352 // since the underlying stream might have been destroyed. Do not invoke |
| 295 // Java callback either, since onError is posted when |stream_failed_| is | 353 // Java callback either, since onError is posted when |stream_failed_| is |
| 296 // set to true. | 354 // set to true. |
| 297 return; | 355 return; |
| 298 } | 356 } |
| 299 write_buffer_ = write_buffer; | 357 |
| 300 bidi_stream_->SendData(write_buffer_.get(), buffer_size, end_of_stream); | 358 write_end_of_stream_ = end_of_stream; |
| 359 std::vector<net::IOBuffer*> buffers; |
| 360 std::vector<int> lengths; |
| 361 for (const auto& buffer : write_buffer_list) { |
| 362 write_buffer_list_.push_back(buffer); |
| 363 buffers.push_back(buffer.get()); |
| 364 lengths.push_back(buffer->initial_limit() - buffer->initial_position()); |
| 365 } |
| 366 if (buffers.size() == 1) { |
| 367 bidi_stream_->SendData(buffers[0], lengths[0], end_of_stream); |
| 368 } else { |
| 369 bidi_stream_->SendvData(buffers, lengths, end_of_stream); |
| 370 } |
| 301 } | 371 } |
| 302 | 372 |
| 303 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( | 373 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( |
| 304 bool send_on_canceled) { | 374 bool send_on_canceled) { |
| 305 DCHECK(context_->IsOnNetworkThread()); | 375 DCHECK(context_->IsOnNetworkThread()); |
| 306 if (send_on_canceled) { | 376 if (send_on_canceled) { |
| 307 JNIEnv* env = base::android::AttachCurrentThread(); | 377 JNIEnv* env = base::android::AttachCurrentThread(); |
| 308 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); | 378 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); |
| 309 } | 379 } |
| 310 delete this; | 380 delete this; |
| 311 } | 381 } |
| 312 | 382 |
| 313 base::android::ScopedJavaLocalRef<jobjectArray> | 383 base::android::ScopedJavaLocalRef<jobjectArray> |
| 314 CronetBidirectionalStreamAdapter::GetHeadersArray( | 384 CronetBidirectionalStreamAdapter::GetHeadersArray( |
| 315 JNIEnv* env, | 385 JNIEnv* env, |
| 316 const net::SpdyHeaderBlock& header_block) { | 386 const net::SpdyHeaderBlock& header_block) { |
| 317 DCHECK(context_->IsOnNetworkThread()); | 387 DCHECK(context_->IsOnNetworkThread()); |
| 318 | 388 |
| 319 std::vector<std::string> headers; | 389 std::vector<std::string> headers; |
| 320 for (const auto& header : header_block) { | 390 for (const auto& header : header_block) { |
| 321 headers.push_back(header.first.as_string()); | 391 headers.push_back(header.first.as_string()); |
| 322 headers.push_back(header.second.as_string()); | 392 headers.push_back(header.second.as_string()); |
| 323 } | 393 } |
| 324 return base::android::ToJavaArrayOfStrings(env, headers); | 394 return base::android::ToJavaArrayOfStrings(env, headers); |
| 325 } | 395 } |
| 326 | 396 |
| 327 } // namespace cronet | 397 } // namespace cronet |
| OLD | NEW |