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::WriteData( |
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<jobject>& jbyte_buffer, |
133 jint jposition, | 154 jint jposition, |
134 jint jlimit, | 155 jint jlimit, |
135 jboolean jend_of_stream) { | 156 jboolean jend_of_stream) { |
136 DCHECK_LE(jposition, jlimit); | 157 DCHECK_LE(jposition, jlimit); |
137 | 158 |
138 void* data = env->GetDirectBufferAddress(jbyte_buffer); | 159 void* data = env->GetDirectBufferAddress(jbyte_buffer); |
139 if (!data) | 160 if (!data) |
140 return JNI_FALSE; | 161 return JNI_FALSE; |
141 | 162 |
142 scoped_refptr<IOBufferWithByteBuffer> write_buffer( | 163 scoped_refptr<IOBufferWithByteBuffer> write_buffer( |
143 new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit)); | 164 new IOBufferWithByteBuffer(env, jbyte_buffer, data, jposition, jlimit)); |
144 | 165 |
145 int remaining_capacity = jlimit - jposition; | |
146 | |
147 context_->PostTaskToNetworkThread( | 166 context_->PostTaskToNetworkThread( |
148 FROM_HERE, | 167 FROM_HERE, |
149 base::Bind(&CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread, | 168 base::Bind(&CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread, |
150 base::Unretained(this), write_buffer, remaining_capacity, | 169 base::Unretained(this), write_buffer, jend_of_stream)); |
151 jend_of_stream)); | 170 return JNI_TRUE; |
| 171 } |
| 172 |
| 173 jboolean CronetBidirectionalStreamAdapter::WritevData( |
| 174 JNIEnv* env, |
| 175 const base::android::JavaParamRef<jobject>& jcaller, |
| 176 const base::android::JavaParamRef<jobjectArray>& jbyte_buffers, |
| 177 const base::android::JavaParamRef<jintArray>& jbyte_buffers_pos, |
| 178 const base::android::JavaParamRef<jintArray>& jbyte_buffers_limit, |
| 179 jboolean jend_of_stream) { |
| 180 size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 181 size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 182 size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); |
| 183 if (buffers_array_size != pos_array_size || |
| 184 pos_array_size != limit_array_size || |
| 185 buffers_array_size != limit_array_size) { |
| 186 DLOG(ERROR) << "Illegal arguments."; |
| 187 return JNI_FALSE; |
| 188 } |
| 189 |
| 190 IOByteBufferList buffers; |
| 191 for (size_t i = 0; i < buffers_array_size; ++i) { |
| 192 ScopedJavaLocalRef<jobject> jbuffer( |
| 193 env, env->GetObjectArrayElement(jbyte_buffers, i)); |
| 194 void* data = env->GetDirectBufferAddress(jbuffer.obj()); |
| 195 if (!data) |
| 196 return JNI_FALSE; |
| 197 jint pos; |
| 198 env->GetIntArrayRegion(jbyte_buffers_pos.obj(), i, 1, &pos); |
| 199 jint limit; |
| 200 env->GetIntArrayRegion(jbyte_buffers_limit.obj(), i, 1, &limit); |
| 201 DCHECK_LE(pos, limit); |
| 202 scoped_refptr<IOBufferWithByteBuffer> write_buffer( |
| 203 new IOBufferWithByteBuffer( |
| 204 env, base::android::JavaParamRef<jobject>(env, jbuffer.Release()), |
| 205 data, pos, limit)); |
| 206 buffers.push_back(write_buffer); |
| 207 } |
| 208 context_->PostTaskToNetworkThread( |
| 209 FROM_HERE, |
| 210 base::Bind(&CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread, |
| 211 base::Unretained(this), buffers, jend_of_stream)); |
| 212 |
152 return JNI_TRUE; | 213 return JNI_TRUE; |
153 } | 214 } |
154 | 215 |
155 void CronetBidirectionalStreamAdapter::Destroy( | 216 void CronetBidirectionalStreamAdapter::Destroy( |
156 JNIEnv* env, | 217 JNIEnv* env, |
157 const JavaParamRef<jobject>& jcaller, | 218 const base::android::JavaParamRef<jobject>& jcaller, |
158 jboolean jsend_on_canceled) { | 219 jboolean jsend_on_canceled) { |
159 // Destroy could be called from any thread, including network thread (if | 220 // Destroy could be called from any thread, including network thread (if |
160 // posting task to executor throws an exception), but is posted, so |this| | 221 // 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 | 222 // 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 | 223 // within a synchronized java block that guarantees no future posts to the |
163 // network thread with the adapter pointer. | 224 // network thread with the adapter pointer. |
164 context_->PostTaskToNetworkThread( | 225 context_->PostTaskToNetworkThread( |
165 FROM_HERE, | 226 FROM_HERE, |
166 base::Bind(&CronetBidirectionalStreamAdapter::DestroyOnNetworkThread, | 227 base::Bind(&CronetBidirectionalStreamAdapter::DestroyOnNetworkThread, |
167 base::Unretained(this), jsend_on_canceled)); | 228 base::Unretained(this), jsend_on_canceled)); |
168 } | 229 } |
169 | 230 |
170 void CronetBidirectionalStreamAdapter::OnHeadersSent() { | 231 void CronetBidirectionalStreamAdapter::OnStreamReady() { |
171 DCHECK(context_->IsOnNetworkThread()); | 232 DCHECK(context_->IsOnNetworkThread()); |
172 JNIEnv* env = base::android::AttachCurrentThread(); | 233 JNIEnv* env = base::android::AttachCurrentThread(); |
173 cronet::Java_CronetBidirectionalStream_onRequestHeadersSent(env, | 234 cronet::Java_CronetBidirectionalStream_onStreamReady(env, owner_.obj()); |
174 owner_.obj()); | |
175 } | 235 } |
176 | 236 |
177 void CronetBidirectionalStreamAdapter::OnHeadersReceived( | 237 void CronetBidirectionalStreamAdapter::OnHeadersReceived( |
178 const net::SpdyHeaderBlock& response_headers) { | 238 const net::SpdyHeaderBlock& response_headers) { |
179 DCHECK(context_->IsOnNetworkThread()); | 239 DCHECK(context_->IsOnNetworkThread()); |
180 JNIEnv* env = base::android::AttachCurrentThread(); | 240 JNIEnv* env = base::android::AttachCurrentThread(); |
181 // Get http status code from response headers. | 241 // Get http status code from response headers. |
182 jint http_status_code = 0; | 242 jint http_status_code = 0; |
183 const auto http_status_header = response_headers.find(":status"); | 243 const auto http_status_header = response_headers.find(":status"); |
184 if (http_status_header != response_headers.end()) | 244 if (http_status_header != response_headers.end()) |
(...skipping 26 matching lines...) Expand all Loading... |
211 read_buffer_->initial_position(), read_buffer_->initial_limit(), | 271 read_buffer_->initial_position(), read_buffer_->initial_limit(), |
212 bidi_stream_->GetTotalReceivedBytes()); | 272 bidi_stream_->GetTotalReceivedBytes()); |
213 // Free the read buffer. This lets the Java ByteBuffer be freed, if the | 273 // Free the read buffer. This lets the Java ByteBuffer be freed, if the |
214 // embedder releases it, too. | 274 // embedder releases it, too. |
215 read_buffer_ = nullptr; | 275 read_buffer_ = nullptr; |
216 } | 276 } |
217 | 277 |
218 void CronetBidirectionalStreamAdapter::OnDataSent() { | 278 void CronetBidirectionalStreamAdapter::OnDataSent() { |
219 DCHECK(context_->IsOnNetworkThread()); | 279 DCHECK(context_->IsOnNetworkThread()); |
220 JNIEnv* env = base::android::AttachCurrentThread(); | 280 JNIEnv* env = base::android::AttachCurrentThread(); |
221 cronet::Java_CronetBidirectionalStream_onWriteCompleted( | 281 if (!disable_auto_flush_) { |
222 env, owner_.obj(), write_buffer_->byte_buffer(), | 282 cronet::Java_CronetBidirectionalStream_onWriteCompleted( |
223 write_buffer_->initial_position(), write_buffer_->initial_limit()); | 283 env, owner_.obj(), write_buffer_->byte_buffer(), |
224 // Free the write buffer. This lets the Java ByteBuffer be freed, if the | 284 write_buffer_->initial_position(), write_buffer_->initial_limit(), |
225 // embedder releases it, too. | 285 write_end_of_stream_); |
226 write_buffer_ = nullptr; | 286 // Free the write buffer. This lets the Java ByteBuffer be freed, if the |
| 287 // embedder releases it, too. |
| 288 write_buffer_ = nullptr; |
| 289 } else { |
| 290 DCHECK(!write_buffer_list_.empty()); |
| 291 base::android::ScopedJavaLocalRef<jclass> byte_buffer_clazz( |
| 292 env, env->GetObjectClass(write_buffer_list_[0]->byte_buffer())); |
| 293 size_t size = write_buffer_list_.size(); |
| 294 jobjectArray jbuffers = |
| 295 env->NewObjectArray(size, byte_buffer_clazz.obj(), NULL); |
| 296 base::android::CheckException(env); |
| 297 std::vector<int> initial_positions; |
| 298 std::vector<int> initial_limits; |
| 299 for (size_t i = 0; i < size; ++i) { |
| 300 env->SetObjectArrayElement(jbuffers, i, |
| 301 write_buffer_list_[i]->byte_buffer()); |
| 302 initial_positions.push_back(write_buffer_list_[i]->initial_position()); |
| 303 initial_limits.push_back(write_buffer_list_[i]->initial_limit()); |
| 304 } |
| 305 ScopedJavaLocalRef<jintArray> jinitial_positions = |
| 306 base::android::ToJavaIntArray(env, initial_positions); |
| 307 ScopedJavaLocalRef<jintArray> jinitial_limits = |
| 308 base::android::ToJavaIntArray(env, initial_limits); |
| 309 // Call into Java. |
| 310 cronet::Java_CronetBidirectionalStream_onWritevCompleted( |
| 311 env, owner_.obj(), jbuffers, jinitial_positions.obj(), |
| 312 jinitial_limits.obj(), write_end_of_stream_); |
| 313 // Free the write buffers. This lets the Java ByteBuffer be freed, if the |
| 314 // embedder releases it, too. |
| 315 write_buffer_list_.clear(); |
| 316 } |
227 } | 317 } |
228 | 318 |
229 void CronetBidirectionalStreamAdapter::OnTrailersReceived( | 319 void CronetBidirectionalStreamAdapter::OnTrailersReceived( |
230 const net::SpdyHeaderBlock& response_trailers) { | 320 const net::SpdyHeaderBlock& response_trailers) { |
231 DCHECK(context_->IsOnNetworkThread()); | 321 DCHECK(context_->IsOnNetworkThread()); |
232 JNIEnv* env = base::android::AttachCurrentThread(); | 322 JNIEnv* env = base::android::AttachCurrentThread(); |
233 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived( | 323 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived( |
234 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj()); | 324 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj()); |
235 } | 325 } |
236 | 326 |
(...skipping 11 matching lines...) Expand all Loading... |
248 DCHECK(context_->IsOnNetworkThread()); | 338 DCHECK(context_->IsOnNetworkThread()); |
249 DCHECK(!bidi_stream_); | 339 DCHECK(!bidi_stream_); |
250 request_info->extra_headers.SetHeaderIfMissing( | 340 request_info->extra_headers.SetHeaderIfMissing( |
251 net::HttpRequestHeaders::kUserAgent, context_->GetURLRequestContext() | 341 net::HttpRequestHeaders::kUserAgent, context_->GetURLRequestContext() |
252 ->http_user_agent_settings() | 342 ->http_user_agent_settings() |
253 ->GetUserAgent()); | 343 ->GetUserAgent()); |
254 bidi_stream_.reset(new net::BidirectionalStream( | 344 bidi_stream_.reset(new net::BidirectionalStream( |
255 std::move(request_info), context_->GetURLRequestContext() | 345 std::move(request_info), context_->GetURLRequestContext() |
256 ->http_transaction_factory() | 346 ->http_transaction_factory() |
257 ->GetSession(), | 347 ->GetSession(), |
258 this)); | 348 disable_auto_flush_, this)); |
259 } | 349 } |
260 | 350 |
261 void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread( | 351 void CronetBidirectionalStreamAdapter::ReadDataOnNetworkThread( |
262 scoped_refptr<IOBufferWithByteBuffer> read_buffer, | 352 scoped_refptr<IOBufferWithByteBuffer> read_buffer, |
263 int buffer_size) { | 353 int buffer_size) { |
264 DCHECK(context_->IsOnNetworkThread()); | 354 DCHECK(context_->IsOnNetworkThread()); |
265 DCHECK(read_buffer); | 355 DCHECK(read_buffer); |
266 DCHECK(!read_buffer_); | 356 DCHECK(!read_buffer_); |
267 | 357 |
268 read_buffer_ = read_buffer; | 358 read_buffer_ = read_buffer; |
269 | 359 |
270 int bytes_read = bidi_stream_->ReadData(read_buffer_.get(), buffer_size); | 360 int bytes_read = bidi_stream_->ReadData(read_buffer_.get(), buffer_size); |
271 // If IO is pending, wait for the BidirectionalStream to call OnDataRead. | 361 // If IO is pending, wait for the BidirectionalStream to call OnDataRead. |
272 if (bytes_read == net::ERR_IO_PENDING) | 362 if (bytes_read == net::ERR_IO_PENDING) |
273 return; | 363 return; |
274 | 364 |
275 if (bytes_read < 0) { | 365 if (bytes_read < 0) { |
276 OnFailed(bytes_read); | 366 OnFailed(bytes_read); |
277 return; | 367 return; |
278 } | 368 } |
279 OnDataRead(bytes_read); | 369 OnDataRead(bytes_read); |
280 } | 370 } |
281 | 371 |
282 void CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread( | 372 void CronetBidirectionalStreamAdapter::WriteDataOnNetworkThread( |
283 scoped_refptr<IOBufferWithByteBuffer> write_buffer, | 373 scoped_refptr<IOBufferWithByteBuffer> write_buffer, |
284 int buffer_size, | |
285 bool end_of_stream) { | 374 bool end_of_stream) { |
286 DCHECK(context_->IsOnNetworkThread()); | 375 DCHECK(context_->IsOnNetworkThread()); |
287 DCHECK(write_buffer); | 376 DCHECK(write_buffer); |
288 DCHECK(!write_buffer_); | 377 DCHECK(!write_buffer_); |
| 378 DCHECK(!write_end_of_stream_); |
289 | 379 |
| 380 write_end_of_stream_ = end_of_stream; |
290 write_buffer_ = write_buffer; | 381 write_buffer_ = write_buffer; |
| 382 int buffer_size = |
| 383 write_buffer->initial_limit() - write_buffer->initial_position(); |
291 bidi_stream_->SendData(write_buffer_.get(), buffer_size, end_of_stream); | 384 bidi_stream_->SendData(write_buffer_.get(), buffer_size, end_of_stream); |
292 } | 385 } |
293 | 386 |
| 387 void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread( |
| 388 const IOByteBufferList& write_buffer_list, |
| 389 bool end_of_stream) { |
| 390 DCHECK(context_->IsOnNetworkThread()); |
| 391 DCHECK(!write_buffer_); |
| 392 DCHECK(write_buffer_list_.empty()); |
| 393 DCHECK(!write_buffer_list.empty()); |
| 394 DCHECK(!write_end_of_stream_); |
| 395 |
| 396 write_end_of_stream_ = end_of_stream; |
| 397 std::vector<net::IOBuffer*> buffers; |
| 398 std::vector<int> lengths; |
| 399 for (const auto& buffer : write_buffer_list) { |
| 400 write_buffer_list_.push_back(buffer); |
| 401 buffers.push_back(buffer.get()); |
| 402 lengths.push_back(buffer->initial_limit() - buffer->initial_position()); |
| 403 } |
| 404 bidi_stream_->SendvData(buffers, lengths, end_of_stream); |
| 405 } |
| 406 |
294 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( | 407 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( |
295 bool send_on_canceled) { | 408 bool send_on_canceled) { |
296 DCHECK(context_->IsOnNetworkThread()); | 409 DCHECK(context_->IsOnNetworkThread()); |
297 if (send_on_canceled) { | 410 if (send_on_canceled) { |
298 JNIEnv* env = base::android::AttachCurrentThread(); | 411 JNIEnv* env = base::android::AttachCurrentThread(); |
299 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); | 412 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); |
300 } | 413 } |
301 delete this; | 414 delete this; |
302 } | 415 } |
303 | 416 |
304 base::android::ScopedJavaLocalRef<jobjectArray> | 417 base::android::ScopedJavaLocalRef<jobjectArray> |
305 CronetBidirectionalStreamAdapter::GetHeadersArray( | 418 CronetBidirectionalStreamAdapter::GetHeadersArray( |
306 JNIEnv* env, | 419 JNIEnv* env, |
307 const net::SpdyHeaderBlock& header_block) { | 420 const net::SpdyHeaderBlock& header_block) { |
308 DCHECK(context_->IsOnNetworkThread()); | 421 DCHECK(context_->IsOnNetworkThread()); |
309 | 422 |
310 std::vector<std::string> headers; | 423 std::vector<std::string> headers; |
311 for (const auto& header : header_block) { | 424 for (const auto& header : header_block) { |
312 headers.push_back(header.first.as_string()); | 425 headers.push_back(header.first.as_string()); |
313 headers.push_back(header.second.as_string()); | 426 headers.push_back(header.second.as_string()); |
314 } | 427 } |
315 return base::android::ToJavaArrayOfStrings(env, headers); | 428 return base::android::ToJavaArrayOfStrings(env, headers); |
316 } | 429 } |
317 | 430 |
318 } // namespace cronet | 431 } // namespace cronet |
OLD | NEW |