| 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) {} | 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) {} |
| 62 | 83 |
| 63 CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() { | 84 CronetBidirectionalStreamAdapter::~CronetBidirectionalStreamAdapter() { |
| 64 DCHECK(context_->IsOnNetworkThread()); | 85 DCHECK(context_->IsOnNetworkThread()); |
| 65 } | 86 } |
| 66 | 87 |
| 67 jint CronetBidirectionalStreamAdapter::Start( | 88 jint CronetBidirectionalStreamAdapter::Start( |
| 68 JNIEnv* env, | 89 JNIEnv* env, |
| 69 const JavaParamRef<jobject>& jcaller, | 90 const base::android::JavaParamRef<jobject>& jcaller, |
| 70 const JavaParamRef<jstring>& jurl, | 91 const base::android::JavaParamRef<jstring>& jurl, |
| 71 jint jpriority, | 92 jint jpriority, |
| 72 const JavaParamRef<jstring>& jmethod, | 93 const base::android::JavaParamRef<jstring>& jmethod, |
| 73 const JavaParamRef<jobjectArray>& jheaders, | 94 const base::android::JavaParamRef<jobjectArray>& jheaders, |
| 74 jboolean jend_of_stream) { | 95 jboolean jend_of_stream) { |
| 75 // Prepare request info here to be able to return the error. | 96 // Prepare request info here to be able to return the error. |
| 76 scoped_ptr<net::BidirectionalStreamRequestInfo> request_info( | 97 scoped_ptr<net::BidirectionalStreamRequestInfo> request_info( |
| 77 new net::BidirectionalStreamRequestInfo()); | 98 new net::BidirectionalStreamRequestInfo()); |
| 78 request_info->url = GURL(ConvertJavaStringToUTF8(env, jurl)); | 99 request_info->url = GURL(ConvertJavaStringToUTF8(env, jurl)); |
| 79 request_info->priority = static_cast<net::RequestPriority>(jpriority); | 100 request_info->priority = static_cast<net::RequestPriority>(jpriority); |
| 80 // Http method is a token, just as header name. | 101 // Http method is a token, just as header name. |
| 81 request_info->method = ConvertJavaStringToUTF8(env, jmethod); | 102 request_info->method = ConvertJavaStringToUTF8(env, jmethod); |
| 82 if (!net::HttpUtil::IsValidHeaderName(request_info->method)) | 103 if (!net::HttpUtil::IsValidHeaderName(request_info->method)) |
| 83 return -1; | 104 return -1; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 97 | 118 |
| 98 context_->PostTaskToNetworkThread( | 119 context_->PostTaskToNetworkThread( |
| 99 FROM_HERE, | 120 FROM_HERE, |
| 100 base::Bind(&CronetBidirectionalStreamAdapter::StartOnNetworkThread, | 121 base::Bind(&CronetBidirectionalStreamAdapter::StartOnNetworkThread, |
| 101 base::Unretained(this), base::Passed(&request_info))); | 122 base::Unretained(this), base::Passed(&request_info))); |
| 102 return 0; | 123 return 0; |
| 103 } | 124 } |
| 104 | 125 |
| 105 jboolean CronetBidirectionalStreamAdapter::ReadData( | 126 jboolean CronetBidirectionalStreamAdapter::ReadData( |
| 106 JNIEnv* env, | 127 JNIEnv* env, |
| 107 const JavaParamRef<jobject>& jcaller, | 128 const base::android::JavaParamRef<jobject>& jcaller, |
| 108 const JavaParamRef<jobject>& jbyte_buffer, | 129 const base::android::JavaParamRef<jobject>& jbyte_buffer, |
| 109 jint jposition, | 130 jint jposition, |
| 110 jint jlimit) { | 131 jint jlimit) { |
| 111 DCHECK_LT(jposition, jlimit); | 132 DCHECK_LT(jposition, jlimit); |
| 112 | 133 |
| 113 void* data = env->GetDirectBufferAddress(jbyte_buffer); | 134 void* data = env->GetDirectBufferAddress(jbyte_buffer); |
| 114 if (!data) | 135 if (!data) |
| 115 return JNI_FALSE; | 136 return JNI_FALSE; |
| 116 | 137 |
| 117 scoped_refptr<IOBufferWithByteBuffer> read_buffer( | 138 scoped_refptr<IOBufferWithByteBuffer> read_buffer( |
| 118 new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit)); | 139 new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit)); |
| 119 | 140 |
| 120 int remaining_capacity = jlimit - jposition; | 141 int remaining_capacity = jlimit - jposition; |
| 121 | 142 |
| 122 context_->PostTaskToNetworkThread( | 143 context_->PostTaskToNetworkThread( |
| 123 FROM_HERE, | 144 FROM_HERE, |
| 124 base::Bind(&CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread, | 145 base::Bind(&CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread, |
| 125 base::Unretained(this), read_buffer, remaining_capacity)); | 146 base::Unretained(this), read_buffer, remaining_capacity)); |
| 126 return JNI_TRUE; | 147 return JNI_TRUE; |
| 127 } | 148 } |
| 128 | 149 |
| 129 jboolean CronetBidirectionalStreamAdapter::WriteData( | 150 jboolean CronetBidirectionalStreamAdapter::WritevData( |
| 130 JNIEnv* env, | 151 JNIEnv* env, |
| 131 const JavaParamRef<jobject>& jcaller, | 152 const base::android::JavaParamRef<jobject>& jcaller, |
| 132 const JavaParamRef<jobject>& jbyte_buffer, | 153 const base::android::JavaParamRef<jobjectArray>& jbyte_buffers, |
| 133 jint jposition, | 154 const base::android::JavaParamRef<jintArray>& jbyte_buffers_pos, |
| 134 jint jlimit, | 155 const base::android::JavaParamRef<jintArray>& jbyte_buffers_limit, |
| 135 jboolean jend_of_stream) { | 156 jboolean jend_of_stream) { |
| 136 DCHECK_LE(jposition, jlimit); | 157 size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 158 size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 159 size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 160 if (buffers_array_size != pos_array_size || |
| 161 pos_array_size != limit_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 11 matching lines...) Expand all Loading... |
| 248 DCHECK(context_->IsOnNetworkThread()); | 306 DCHECK(context_->IsOnNetworkThread()); |
| 249 DCHECK(!bidi_stream_); | 307 DCHECK(!bidi_stream_); |
| 250 request_info->extra_headers.SetHeaderIfMissing( | 308 request_info->extra_headers.SetHeaderIfMissing( |
| 251 net::HttpRequestHeaders::kUserAgent, context_->GetURLRequestContext() | 309 net::HttpRequestHeaders::kUserAgent, context_->GetURLRequestContext() |
| 252 ->http_user_agent_settings() | 310 ->http_user_agent_settings() |
| 253 ->GetUserAgent()); | 311 ->GetUserAgent()); |
| 254 bidi_stream_.reset(new net::BidirectionalStream( | 312 bidi_stream_.reset(new net::BidirectionalStream( |
| 255 std::move(request_info), context_->GetURLRequestContext() | 313 std::move(request_info), context_->GetURLRequestContext() |
| 256 ->http_transaction_factory() | 314 ->http_transaction_factory() |
| 257 ->GetSession(), | 315 ->GetSession(), |
| 258 this)); | 316 disable_auto_flush_, this)); |
| 259 } | 317 } |
| 260 | 318 |
| 261 void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread( | 319 void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread( |
| 262 scoped_refptr<IOBufferWithByteBuffer> read_buffer, | 320 scoped_refptr<IOBufferWithByteBuffer> read_buffer, |
| 263 int buffer_size) { | 321 int buffer_size) { |
| 264 DCHECK(context_->IsOnNetworkThread()); | 322 DCHECK(context_->IsOnNetworkThread()); |
| 265 DCHECK(read_buffer); | 323 DCHECK(read_buffer); |
| 266 DCHECK(!read_buffer_); | 324 DCHECK(!read_buffer_); |
| 267 | 325 |
| 268 read_buffer_ = read_buffer; | 326 read_buffer_ = read_buffer; |
| 269 | 327 |
| 270 int bytes_read = bidi_stream_->ReadData(read_buffer_.get(), buffer_size); | 328 int bytes_read = bidi_stream_->ReadData(read_buffer_.get(), buffer_size); |
| 271 // If IO is pending, wait for the BidirectionalStream to call OnDataRead. | 329 // If IO is pending, wait for the BidirectionalStream to call OnDataRead. |
| 272 if (bytes_read == net::ERR_IO_PENDING) | 330 if (bytes_read == net::ERR_IO_PENDING) |
| 273 return; | 331 return; |
| 274 | 332 |
| 275 if (bytes_read < 0) { | 333 if (bytes_read < 0) { |
| 276 OnFailed(bytes_read); | 334 OnFailed(bytes_read); |
| 277 return; | 335 return; |
| 278 } | 336 } |
| 279 OnDataRead(bytes_read); | 337 OnDataRead(bytes_read); |
| 280 } | 338 } |
| 281 | 339 |
| 282 void CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread( | 340 void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread( |
| 283 scoped_refptr<IOBufferWithByteBuffer> write_buffer, | 341 const IOByteBufferList& write_buffer_list, |
| 284 int buffer_size, | |
| 285 bool end_of_stream) { | 342 bool end_of_stream) { |
| 286 DCHECK(context_->IsOnNetworkThread()); | 343 DCHECK(context_->IsOnNetworkThread()); |
| 287 DCHECK(write_buffer); | 344 DCHECK(write_buffer_list_.empty()); |
| 288 DCHECK(!write_buffer_); | 345 DCHECK(!write_buffer_list.empty()); |
| 346 DCHECK(!write_end_of_stream_); |
| 289 | 347 |
| 290 write_buffer_ = write_buffer; | 348 write_end_of_stream_ = end_of_stream; |
| 291 bidi_stream_->SendData(write_buffer_.get(), buffer_size, end_of_stream); | 349 std::vector<net::IOBuffer*> buffers; |
| 350 std::vector<int> lengths; |
| 351 for (const auto& buffer : write_buffer_list) { |
| 352 write_buffer_list_.push_back(buffer); |
| 353 buffers.push_back(buffer.get()); |
| 354 lengths.push_back(buffer->initial_limit() - buffer->initial_position()); |
| 355 } |
| 356 if (buffers.size() == 1) { |
| 357 bidi_stream_->SendData(buffers[0], lengths[0], end_of_stream); |
| 358 } else { |
| 359 bidi_stream_->SendvData(buffers, lengths, end_of_stream); |
| 360 } |
| 292 } | 361 } |
| 293 | 362 |
| 294 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( | 363 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( |
| 295 bool send_on_canceled) { | 364 bool send_on_canceled) { |
| 296 DCHECK(context_->IsOnNetworkThread()); | 365 DCHECK(context_->IsOnNetworkThread()); |
| 297 if (send_on_canceled) { | 366 if (send_on_canceled) { |
| 298 JNIEnv* env = base::android::AttachCurrentThread(); | 367 JNIEnv* env = base::android::AttachCurrentThread(); |
| 299 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); | 368 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); |
| 300 } | 369 } |
| 301 delete this; | 370 delete this; |
| 302 } | 371 } |
| 303 | 372 |
| 304 base::android::ScopedJavaLocalRef<jobjectArray> | 373 base::android::ScopedJavaLocalRef<jobjectArray> |
| 305 CronetBidirectionalStreamAdapter::GetHeadersArray( | 374 CronetBidirectionalStreamAdapter::GetHeadersArray( |
| 306 JNIEnv* env, | 375 JNIEnv* env, |
| 307 const net::SpdyHeaderBlock& header_block) { | 376 const net::SpdyHeaderBlock& header_block) { |
| 308 DCHECK(context_->IsOnNetworkThread()); | 377 DCHECK(context_->IsOnNetworkThread()); |
| 309 | 378 |
| 310 std::vector<std::string> headers; | 379 std::vector<std::string> headers; |
| 311 for (const auto& header : header_block) { | 380 for (const auto& header : header_block) { |
| 312 headers.push_back(header.first.as_string()); | 381 headers.push_back(header.first.as_string()); |
| 313 headers.push_back(header.second.as_string()); | 382 headers.push_back(header.second.as_string()); |
| 314 } | 383 } |
| 315 return base::android::ToJavaArrayOfStrings(env, headers); | 384 return base::android::ToJavaArrayOfStrings(env, headers); |
| 316 } | 385 } |
| 317 | 386 |
| 318 } // namespace cronet | 387 } // namespace cronet |
| OLD | NEW |