Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: components/cronet/android/cronet_upload_data_stream.cc

Issue 849903002: [Cronet] Upload support for async APIs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Misha's comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "components/cronet/android/cronet_upload_data_stream.h"
pauljensen 2015/02/12 17:15:39 nit: Would seem like this file would be better nam
xunjieli 2015/02/12 20:56:27 Done. SGTM
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/callback_helpers.h"
14 #include "base/location.h"
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/message_loop/message_loop_proxy.h"
20 #include "base/single_thread_task_runner.h"
21 #include "components/cronet/android/cronet_upload_data_stream_adapter.h"
22 #include "components/cronet/android/cronet_url_request_adapter.h"
23 #include "jni/CronetUploadDataStream_jni.h"
24 #include "net/base/io_buffer.h"
25 #include "net/base/upload_data_stream.h"
26
27 using base::android::ConvertUTF8ToJavaString;
28
29 namespace cronet {
30
31 namespace {
32
33 // The Delegate holds onto a reference to the IOBuffer that is currently being
34 // written to in Java, so may not be deleted until any read operation in Java
35 // has completed.
36 //
37 // The Delegate is owned by the Java CronetUploadDataStream, and also owns a
38 // reference to it. The Delegate is only destroyed after the URLRequest
39 // destroys the adapter and the CronetUploadDataStream has no operation pending,
40 // at which point it also releases its reference to the CronetUploadDataStream.
41 //
42 // Failures don't go through the delegate, but directly to the Java request
43 // object, since normally reads aren't allowed to fail during an upload.
44 class CronetUploadDataStreamDelegate
45 : public CronetUploadDataStreamAdapter::Delegate {
46 public:
47 CronetUploadDataStreamDelegate(JNIEnv* env, jobject jupload_data_stream);
48 ~CronetUploadDataStreamDelegate() override {}
49
50 // CronetUploadDataStreamAdapter::Delegate implementation. Called on network
51 // thread.
52 void InitializeOnNetworkThread(
53 base::WeakPtr<CronetUploadDataStreamAdapter> adapter) override;
54 void Read(net::IOBuffer* buffer, int buf_len) override;
55 void Rewind() override;
56 void OnAdapterDestroyed() override;
57
58 // Callbacks from Java, called on some Java thread.
59 void OnReadSucceeded(int bytes_read, bool final_chunk);
60 void OnRewindSucceeded();
61
62 private:
63 // Initialized on construction, effectively constant.
64 base::android::ScopedJavaGlobalRef<jobject> jupload_data_stream_;
65
66 // These are initialized in InitializeOnNetworkThread, so are safe to access
67 // during Java callbacks, which all happen after initialization.
68 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
69 base::WeakPtr<CronetUploadDataStreamAdapter> adapter_;
70
71 // Used to keep the read buffer alive until the callback from Java has been
72 // received.
73 scoped_refptr<net::IOBuffer> buffer_;
74
75 DISALLOW_COPY_AND_ASSIGN(CronetUploadDataStreamDelegate);
76 };
77
78 CronetUploadDataStreamDelegate::CronetUploadDataStreamDelegate(
79 JNIEnv* env,
80 jobject jupload_data_stream) {
81 jupload_data_stream_.Reset(env, jupload_data_stream);
82 }
83
84 void CronetUploadDataStreamDelegate::InitializeOnNetworkThread(
85 base::WeakPtr<CronetUploadDataStreamAdapter> adapter) {
86 DCHECK(!adapter_);
87 DCHECK(!network_task_runner_.get());
88
89 adapter_ = adapter;
90 network_task_runner_ = base::MessageLoopProxy::current();
91 DCHECK(network_task_runner_);
92 }
93
94 void CronetUploadDataStreamDelegate::Read(net::IOBuffer* buffer, int buf_len) {
95 DCHECK(adapter_);
96 DCHECK(network_task_runner_);
97 DCHECK(network_task_runner_->BelongsToCurrentThread());
98 DCHECK_GT(buf_len, 0);
99 DCHECK(!buffer_.get());
100 buffer_ = buffer;
101
102 // TODO(mmenke): Consider preserving the java buffer across reads, when the
103 // IOBuffer's data pointer and its length are unchanged.
104 JNIEnv* env = base::android::AttachCurrentThread();
105 base::android::ScopedJavaLocalRef<jobject> java_buffer(
106 env, env->NewDirectByteBuffer(buffer->data(), buf_len));
107 Java_CronetUploadDataStream_readData(env, jupload_data_stream_.obj(),
108 java_buffer.obj());
109 }
110
111 void CronetUploadDataStreamDelegate::Rewind() {
112 DCHECK(adapter_);
113 DCHECK(network_task_runner_->BelongsToCurrentThread());
114
115 JNIEnv* env = base::android::AttachCurrentThread();
116 Java_CronetUploadDataStream_rewind(env, jupload_data_stream_.obj());
117 }
118
119 void CronetUploadDataStreamDelegate::OnAdapterDestroyed() {
120 DCHECK(adapter_);
121 DCHECK(network_task_runner_->BelongsToCurrentThread());
122
123 JNIEnv* env = base::android::AttachCurrentThread();
124 Java_CronetUploadDataStream_onAdapterDestroyed(env,
125 jupload_data_stream_.obj());
126 }
127
128 void CronetUploadDataStreamDelegate::OnReadSucceeded(int bytes_read,
129 bool final_chunk) {
130 DCHECK(!network_task_runner_->BelongsToCurrentThread());
131 DCHECK(bytes_read > 0 || (final_chunk && bytes_read == 0));
132
133 buffer_ = nullptr;
134 DCHECK(network_task_runner_->PostTask(
135 FROM_HERE, base::Bind(&CronetUploadDataStreamAdapter::OnReadSuccess,
136 adapter_, bytes_read, final_chunk)));
137 }
138
139 void CronetUploadDataStreamDelegate::OnRewindSucceeded() {
140 DCHECK(!network_task_runner_->BelongsToCurrentThread());
141
142 network_task_runner_->PostTask(
143 FROM_HERE,
144 base::Bind(&CronetUploadDataStreamAdapter::OnRewindSuccess, adapter_));
145 }
146
147 } // namespace
148
149 // Explicitly register static JNI functions.
150 bool CronetUploadDataStreamRegisterJni(JNIEnv* env) {
151 return RegisterNativesImpl(env);
152 }
153
154 static jlong AttachUploadDataToRequest(JNIEnv* env,
155 jobject jupload_data_stream,
156 jlong jcronet_url_request_adapter,
157 jlong jlength) {
158 CronetURLRequestAdapter* request_adapter =
159 reinterpret_cast<CronetURLRequestAdapter*>(jcronet_url_request_adapter);
160 DCHECK(request_adapter != nullptr);
161
162 CronetUploadDataStreamDelegate* delegate =
163 new CronetUploadDataStreamDelegate(env, jupload_data_stream);
164
165 scoped_ptr<CronetUploadDataStreamAdapter> upload_adapter(
166 new CronetUploadDataStreamAdapter(delegate, jlength));
167
168 request_adapter->SetUpload(upload_adapter.Pass());
169
170 return reinterpret_cast<jlong>(delegate);
171 }
172
173 static jlong CreateDelegateForTesting(JNIEnv* env,
174 jobject jupload_data_stream) {
175 CronetUploadDataStreamDelegate* delegate =
176 new CronetUploadDataStreamDelegate(env, jupload_data_stream);
177 return reinterpret_cast<jlong>(delegate);
178 }
179
180 static jlong CreateAdapterForTesting(JNIEnv* env,
181 jobject jupload_data_stream,
182 jlong jlength,
183 jlong jdelegate) {
184 CronetUploadDataStreamDelegate* delegate =
185 reinterpret_cast<CronetUploadDataStreamDelegate*>(jdelegate);
186 CronetUploadDataStreamAdapter* upload_adapter =
187 new CronetUploadDataStreamAdapter(delegate, jlength);
188 return reinterpret_cast<jlong>(upload_adapter);
189 }
190
191 static void OnReadSucceeded(JNIEnv* env,
192 jobject jcaller,
193 jlong jupload_data_stream_delegate,
194 jint bytes_read,
195 jboolean final_chunk) {
196 CronetUploadDataStreamDelegate* delegate =
197 reinterpret_cast<CronetUploadDataStreamDelegate*>(
198 jupload_data_stream_delegate);
pauljensen 2015/02/12 17:15:39 I'm no JNI expert, but did you consider using @Nat
xunjieli 2015/02/12 20:56:27 Done. Good to know. That's very convenient!
199 DCHECK(delegate != nullptr);
200
201 delegate->OnReadSucceeded(bytes_read, final_chunk);
202 }
203
204 static void OnRewindSucceeded(JNIEnv* env,
205 jobject jcaller,
206 jlong jupload_data_stream_delegate) {
207 CronetUploadDataStreamDelegate* delegate =
208 reinterpret_cast<CronetUploadDataStreamDelegate*>(
209 jupload_data_stream_delegate);
210 DCHECK(delegate != nullptr);
211
212 delegate->OnRewindSucceeded();
213 }
214
215 static void DestroyDelegate(JNIEnv* env,
216 jclass jcronet_url_request_adapter,
217 jlong jupload_data_stream_delegate) {
218 CronetUploadDataStreamDelegate* delegate =
219 reinterpret_cast<CronetUploadDataStreamDelegate*>(
220 jupload_data_stream_delegate);
221 DCHECK(delegate != nullptr);
222 delete delegate;
223 }
224
225 } // namespace cronet
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698