| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "upload_data_stream_handler.h" |
| 6 |
| 7 #include <string> |
| 8 |
| 9 #include "base/android/jni_android.h" |
| 10 #include "base/android/jni_string.h" |
| 11 #include "base/android/scoped_java_ref.h" |
| 12 #include "base/bind.h" |
| 13 #include "base/macros.h" |
| 14 #include "base/memory/ref_counted.h" |
| 15 #include "base/message_loop/message_loop_proxy.h" |
| 16 #include "base/threading/thread.h" |
| 17 #include "components/cronet/android/cronet_upload_data_stream_adapter.h" |
| 18 #include "jni/UploadDataStreamHandler_jni.h" |
| 19 #include "net/base/io_buffer.h" |
| 20 #include "net/base/net_errors.h" |
| 21 #include "net/base/upload_data_stream.h" |
| 22 |
| 23 namespace cronet { |
| 24 |
| 25 namespace { |
| 26 |
| 27 static const size_t kReadBufferSize = 32768; |
| 28 |
| 29 /** |
| 30 * This class sets up the JNI for Java tests to invoke methods on the native |
| 31 * CronetUploadDataStreamAdapter. |
| 32 */ |
| 33 class UploadDataStreamHandler { |
| 34 public: |
| 35 UploadDataStreamHandler(CronetUploadDataStreamAdapter* adapter, |
| 36 JNIEnv* env, |
| 37 jobject jupload_data_stream_handler); |
| 38 |
| 39 ~UploadDataStreamHandler(); |
| 40 |
| 41 // Destroys |network_thread_| created by this class. |
| 42 void Destroy(); |
| 43 |
| 44 // Posts a task to |network_thread_| to call the corresponding method of |
| 45 // CronetUploadDataStreamAdapter on |adapter_|. |
| 46 |
| 47 void Init(); |
| 48 void Read(); |
| 49 void Reset(); |
| 50 |
| 51 // Posts a task to |network_thread_| to check whether init complete callback |
| 52 // has been invoked by net::UploadDataStream, and notifies the Java side of |
| 53 // the result. |
| 54 void CheckInitCallbackNotInvoked(); |
| 55 // Posts a task to |network_thread_| to check whether read complete callback |
| 56 // has been invoked by net::UploadDataStream, and notifies the Java side of |
| 57 // the result. |
| 58 void CheckReadCallbackNotInvoked(); |
| 59 |
| 60 private: |
| 61 // Complete callbacks that are passed to the |adapter_|. |
| 62 void OnInitCompleted(int res); |
| 63 void OnReadCompleted(int res); |
| 64 |
| 65 // Helper methods that run corresponding task on |network_thread_|. |
| 66 |
| 67 void InitOnNetworkThread(); |
| 68 void ReadOnNetworkThread(); |
| 69 void ResetOnNetworkThread(); |
| 70 void CheckInitCallbackNotInvokedOnNetworkThread(); |
| 71 void CheckReadCallbackNotInvokedOnNetworkThread(); |
| 72 |
| 73 // Notify the Java UploadDataStreamHandler that read has completed. |
| 74 void NotifyJavaReadCompleted(); |
| 75 |
| 76 // True if |OnInitCompleted| callback has been invoked. It is set to false |
| 77 // when init or reset is called again. Created on a Java thread, but are only |
| 78 // accessed from |network_thread_|. |
| 79 bool init_callback_invoked_; |
| 80 // True if |OnReadCompleted| callback has been invoked. It is set to false |
| 81 // when init or reset is called again. Created on a Java thread, but are only |
| 82 // accessed from |network_thread_|. |
| 83 bool read_callback_invoked_; |
| 84 // Indicates the number of bytes read. It is reset to 0 when init, reset, or |
| 85 // read is called again. Created on a Java thread, but are only accessed from |
| 86 // |network_thread_|. |
| 87 int bytes_read_; |
| 88 |
| 89 // Created and destroyed on the same Java thread. This is where methods of |
| 90 // CronetUploadDataStreamAdapter run on. |
| 91 scoped_ptr<base::Thread> network_thread_; |
| 92 // Created on a Java thread. Accessed only on |network_thread_|. |
| 93 scoped_ptr<CronetUploadDataStreamAdapter> adapter_; |
| 94 // Created and accessed only on |network_thread_|. |
| 95 scoped_refptr<net::IOBufferWithSize> read_buffer_; |
| 96 // A Java reference pointer for calling methods on the Java |
| 97 // UploadDataStreamHandler object. Initialized during construction. |
| 98 base::android::ScopedJavaGlobalRef<jobject> jupload_data_stream_handler_; |
| 99 |
| 100 DISALLOW_COPY_AND_ASSIGN(UploadDataStreamHandler); |
| 101 }; |
| 102 |
| 103 UploadDataStreamHandler::UploadDataStreamHandler( |
| 104 CronetUploadDataStreamAdapter* adapter, |
| 105 JNIEnv* env, |
| 106 jobject jupload_data_stream_handler) |
| 107 : init_callback_invoked_(false), |
| 108 read_callback_invoked_(false), |
| 109 bytes_read_(0), |
| 110 network_thread_(new base::Thread("network")), |
| 111 adapter_(adapter) { |
| 112 base::Thread::Options options; |
| 113 options.message_loop_type = base::MessageLoop::TYPE_IO; |
| 114 network_thread_->StartWithOptions(options); |
| 115 jupload_data_stream_handler_.Reset(env, jupload_data_stream_handler); |
| 116 } |
| 117 |
| 118 UploadDataStreamHandler::~UploadDataStreamHandler() { |
| 119 } |
| 120 |
| 121 void UploadDataStreamHandler::Destroy() { |
| 122 DCHECK(!network_thread_->task_runner()->BelongsToCurrentThread()); |
| 123 // Stick network_thread_ in a local, so |this| may be destroyed from the |
| 124 // network thread before the network thread is destroyed. |
| 125 scoped_ptr<base::Thread> network_thread = network_thread_.Pass(); |
| 126 network_thread->task_runner()->DeleteSoon(FROM_HERE, this); |
| 127 // Deleting thread stops it after all tasks are completed. |
| 128 network_thread.reset(); |
| 129 } |
| 130 |
| 131 void UploadDataStreamHandler::OnInitCompleted(int res) { |
| 132 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 133 init_callback_invoked_ = true; |
| 134 JNIEnv* env = base::android::AttachCurrentThread(); |
| 135 cronet::Java_UploadDataStreamHandler_onInitCompleted( |
| 136 env, jupload_data_stream_handler_.obj(), res); |
| 137 } |
| 138 |
| 139 void UploadDataStreamHandler::OnReadCompleted(int res) { |
| 140 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 141 read_callback_invoked_ = true; |
| 142 bytes_read_ = res; |
| 143 NotifyJavaReadCompleted(); |
| 144 } |
| 145 |
| 146 void UploadDataStreamHandler::Init() { |
| 147 DCHECK(!network_thread_->task_runner()->BelongsToCurrentThread()); |
| 148 network_thread_->task_runner()->PostTask( |
| 149 FROM_HERE, base::Bind(&UploadDataStreamHandler::InitOnNetworkThread, |
| 150 base::Unretained(this))); |
| 151 } |
| 152 |
| 153 void UploadDataStreamHandler::Read() { |
| 154 DCHECK(!network_thread_->task_runner()->BelongsToCurrentThread()); |
| 155 network_thread_->task_runner()->PostTask( |
| 156 FROM_HERE, base::Bind(&UploadDataStreamHandler::ReadOnNetworkThread, |
| 157 base::Unretained(this))); |
| 158 } |
| 159 |
| 160 void UploadDataStreamHandler::Reset() { |
| 161 DCHECK(!network_thread_->task_runner()->BelongsToCurrentThread()); |
| 162 network_thread_->task_runner()->PostTask( |
| 163 FROM_HERE, base::Bind(&UploadDataStreamHandler::ResetOnNetworkThread, |
| 164 base::Unretained(this))); |
| 165 } |
| 166 |
| 167 void UploadDataStreamHandler::CheckInitCallbackNotInvoked() { |
| 168 DCHECK(!network_thread_->task_runner()->BelongsToCurrentThread()); |
| 169 network_thread_->task_runner()->PostTask( |
| 170 FROM_HERE, |
| 171 base::Bind( |
| 172 &UploadDataStreamHandler::CheckInitCallbackNotInvokedOnNetworkThread, |
| 173 base::Unretained(this))); |
| 174 } |
| 175 |
| 176 void UploadDataStreamHandler::CheckReadCallbackNotInvoked() { |
| 177 DCHECK(!network_thread_->task_runner()->BelongsToCurrentThread()); |
| 178 network_thread_->task_runner()->PostTask( |
| 179 FROM_HERE, |
| 180 base::Bind( |
| 181 &UploadDataStreamHandler::CheckReadCallbackNotInvokedOnNetworkThread, |
| 182 base::Unretained(this))); |
| 183 } |
| 184 |
| 185 void UploadDataStreamHandler::InitOnNetworkThread() { |
| 186 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 187 init_callback_invoked_ = false; |
| 188 read_buffer_ = nullptr; |
| 189 bytes_read_ = 0; |
| 190 int res = adapter_->Init(base::Bind(&UploadDataStreamHandler::OnInitCompleted, |
| 191 base::Unretained(this))); |
| 192 JNIEnv* env = base::android::AttachCurrentThread(); |
| 193 cronet::Java_UploadDataStreamHandler_onInitCalled( |
| 194 env, jupload_data_stream_handler_.obj(), res); |
| 195 |
| 196 if (res == net::OK) { |
| 197 cronet::Java_UploadDataStreamHandler_onInitCompleted( |
| 198 env, jupload_data_stream_handler_.obj(), res); |
| 199 } |
| 200 } |
| 201 |
| 202 void UploadDataStreamHandler::ReadOnNetworkThread() { |
| 203 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 204 read_callback_invoked_ = false; |
| 205 if (!read_buffer_.get()) |
| 206 read_buffer_ = new net::IOBufferWithSize(kReadBufferSize); |
| 207 |
| 208 int bytes_read = |
| 209 adapter_->Read(read_buffer_.get(), kReadBufferSize, |
| 210 base::Bind(&UploadDataStreamHandler::OnReadCompleted, |
| 211 base::Unretained(this))); |
| 212 if (bytes_read == net::OK) { |
| 213 bytes_read_ = bytes_read; |
| 214 NotifyJavaReadCompleted(); |
| 215 } |
| 216 } |
| 217 |
| 218 void UploadDataStreamHandler::ResetOnNetworkThread() { |
| 219 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 220 init_callback_invoked_ = false; |
| 221 read_callback_invoked_ = false; |
| 222 read_buffer_ = nullptr; |
| 223 bytes_read_ = 0; |
| 224 adapter_->Reset(); |
| 225 JNIEnv* env = base::android::AttachCurrentThread(); |
| 226 cronet::Java_UploadDataStreamHandler_onResetCompleted( |
| 227 env, jupload_data_stream_handler_.obj()); |
| 228 } |
| 229 |
| 230 void UploadDataStreamHandler::CheckInitCallbackNotInvokedOnNetworkThread() { |
| 231 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 232 JNIEnv* env = base::android::AttachCurrentThread(); |
| 233 cronet::Java_UploadDataStreamHandler_onCheckInitCallbackNotInvoked( |
| 234 env, jupload_data_stream_handler_.obj(), init_callback_invoked_ == false); |
| 235 } |
| 236 |
| 237 void UploadDataStreamHandler::CheckReadCallbackNotInvokedOnNetworkThread() { |
| 238 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 239 JNIEnv* env = base::android::AttachCurrentThread(); |
| 240 cronet::Java_UploadDataStreamHandler_onCheckReadCallbackNotInvoked( |
| 241 env, jupload_data_stream_handler_.obj(), read_callback_invoked_ == false); |
| 242 } |
| 243 |
| 244 void UploadDataStreamHandler::NotifyJavaReadCompleted() { |
| 245 DCHECK(network_thread_->task_runner()->BelongsToCurrentThread()); |
| 246 JNIEnv* env = base::android::AttachCurrentThread(); |
| 247 std::string data_read = ""; |
| 248 if (read_buffer_.get() && bytes_read_ > 0) |
| 249 data_read = std::string(read_buffer_->data(), bytes_read_); |
| 250 cronet::Java_UploadDataStreamHandler_onReadCompleted( |
| 251 env, jupload_data_stream_handler_.obj(), bytes_read_, |
| 252 base::android::ConvertUTF8ToJavaString(env, data_read).Release()); |
| 253 } |
| 254 |
| 255 } // namespace |
| 256 |
| 257 static void Init(JNIEnv* env, |
| 258 jclass jcaller, |
| 259 jlong jupload_data_stream_handler) { |
| 260 UploadDataStreamHandler* handler = |
| 261 reinterpret_cast<UploadDataStreamHandler*>(jupload_data_stream_handler); |
| 262 DCHECK(handler); |
| 263 handler->Init(); |
| 264 } |
| 265 |
| 266 static void Read(JNIEnv* env, |
| 267 jclass jcaller, |
| 268 jlong jupload_data_stream_handler) { |
| 269 UploadDataStreamHandler* handler = |
| 270 reinterpret_cast<UploadDataStreamHandler*>(jupload_data_stream_handler); |
| 271 DCHECK(handler); |
| 272 handler->Read(); |
| 273 } |
| 274 |
| 275 static void Reset(JNIEnv* env, |
| 276 jclass jcaller, |
| 277 jlong jupload_data_stream_handler) { |
| 278 UploadDataStreamHandler* handler = |
| 279 reinterpret_cast<UploadDataStreamHandler*>(jupload_data_stream_handler); |
| 280 DCHECK(handler); |
| 281 handler->Reset(); |
| 282 } |
| 283 |
| 284 static void CheckInitCallbackNotInvoked(JNIEnv* env, |
| 285 jclass jcaller, |
| 286 jlong jupload_data_stream_handler) { |
| 287 UploadDataStreamHandler* handler = |
| 288 reinterpret_cast<UploadDataStreamHandler*>(jupload_data_stream_handler); |
| 289 DCHECK(handler); |
| 290 handler->CheckInitCallbackNotInvoked(); |
| 291 } |
| 292 |
| 293 static void CheckReadCallbackNotInvoked(JNIEnv* env, |
| 294 jclass jcaller, |
| 295 jlong jupload_data_stream_handler) { |
| 296 UploadDataStreamHandler* handler = |
| 297 reinterpret_cast<UploadDataStreamHandler*>(jupload_data_stream_handler); |
| 298 DCHECK(handler); |
| 299 handler->CheckReadCallbackNotInvoked(); |
| 300 } |
| 301 |
| 302 static jlong CreateUploadDataStreamHandler(JNIEnv* env, |
| 303 jobject jupload_data_stream_handler, |
| 304 jlong jupload_data_stream_adapter) { |
| 305 CronetUploadDataStreamAdapter* adapter = |
| 306 reinterpret_cast<CronetUploadDataStreamAdapter*>( |
| 307 jupload_data_stream_adapter); |
| 308 UploadDataStreamHandler* handler = |
| 309 new UploadDataStreamHandler(adapter, env, jupload_data_stream_handler); |
| 310 return reinterpret_cast<jlong>(handler); |
| 311 } |
| 312 |
| 313 static void Destroy(JNIEnv* env, |
| 314 jclass jcaller, |
| 315 jlong jupload_data_stream_handler) { |
| 316 UploadDataStreamHandler* handler = |
| 317 reinterpret_cast<UploadDataStreamHandler*>(jupload_data_stream_handler); |
| 318 DCHECK(handler); |
| 319 handler->Destroy(); |
| 320 } |
| 321 |
| 322 bool UploadDataStreamHandlerRegisterJni(JNIEnv* env) { |
| 323 return RegisterNativesImpl(env); |
| 324 } |
| 325 |
| 326 } // namespace cronet |
| OLD | NEW |