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

Side by Side Diff: components/cronet/android/java/src/org/chromium/net/CronetUrlRequest.java

Issue 586143002: Initial implementation of Cronet Async API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 package org.chromium.net; 5 package org.chromium.net;
6 6
7 import android.util.Log;
8
9 import org.chromium.base.CalledByNative;
10 import org.chromium.base.JNINamespace;
11
12 import java.net.URL;
13 import java.nio.ByteBuffer;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.concurrent.Executor;
19
7 /** 20 /**
8 * UrlRequest using Chromium HTTP stack implementation. 21 * UrlRequest using Chromium HTTP stack implementation.
9 */ 22 */
23 @JNINamespace("cronet")
10 public class CronetUrlRequest implements UrlRequest { 24 public class CronetUrlRequest implements UrlRequest {
Charles 2014/09/20 00:47:34 Final?
mef 2014/09/22 17:12:13 Done.
25 /**
26 * Native adapter object, owned by UrlRequest.
27 */
28 private long mUrlRequestAdapter;
29 private final CronetUrlRequestContext mRequestContext;
30 private final String mUrl;
31 private final int mPriority;
32 private final UrlRequestListener mListener;
33 private final Executor mExecutor;
34 private ResponseInfo mResponseInfo;
35 private boolean mCanceled = false;
36
37 class NativeResponseInfo implements ResponseInfo {
Charles 2014/09/20 00:47:34 Final
mef 2014/09/22 17:12:13 Done.
38 @Override
39 public URL getUrl() {
40 return null;
41 }
42
43 @Override
44 public URL[] getUrlChain() {
45 return null;
46 }
47
48 @Override
49 public int getHttpStatusCode() {
50 return 0;
51 }
52
53 @Override
54 public Map<String, List<String>> getAllHeaders() {
55 return null;
56 }
57
58 @Override
59 public boolean wasCached() {
60 return false;
61 }
62
63 @Override
64 public boolean wasFetchedOverSPDY() {
Charles 2014/09/20 00:47:34 I actually prefer getting the negotiated protocol
mef 2014/09/22 17:12:12 sgtm
65 return false;
66 }
67
68 @Override
69 public boolean wasFetchedOverQUIC() {
70 return false;
71 }
72 };
73
74 CronetUrlRequest(CronetUrlRequestContext requestContext,
75 String url, int priority,
76 UrlRequestListener listener,
77 Executor executor) {
78 if (requestContext == null) {
79 throw new NullPointerException("Context is required");
80 }
81 if (url == null) {
82 throw new NullPointerException("URL is required");
83 }
84 if (listener == null) {
85 throw new NullPointerException("Listener is required");
86 }
87 if (executor == null) {
88 throw new NullPointerException("Executor is required");
89 }
90
91 mRequestContext = requestContext;
92 mUrl = url;
93 mPriority = convertRequestPriority(priority);
94 mUrlRequestAdapter = nativeCreateRequestAdapter(
95 mRequestContext.getCronetUrlRequestContextAdapter(),
Charles 2014/09/20 00:47:34 These params all fit on one line
mef 2014/09/22 17:12:13 Acknowledged.
mef 2014/09/23 18:42:14 Actually, they don't fit into 80 chars, which is o
96 mUrl,
97 mPriority);
98 mListener = listener;
99 mExecutor = executor;
100 }
101
11 @Override 102 @Override
12 public void setHttpMethod(String method) { 103 public void setHttpMethod(String method) {
13 104 if (method == null) {
105 throw new NullPointerException("method is required");
106 }
107 nativeSetHttpMethod(mUrlRequestAdapter, method);
14 } 108 }
15 109
16 @Override 110 @Override
17 public void addHeader(String header, String value) { 111 public void addHeader(String header, String value) {
18 112 if (header == null || value == null) {
113 throw new NullPointerException("Invalid header");
114 }
115 nativeAddHeader(mUrlRequestAdapter, header, value);
19 } 116 }
20 117
21 @Override 118 @Override
22 public void start(UrlRequestListener listener) { 119 public void start() {
Charles 2014/09/20 00:47:33 These methods should have threading policy attache
mef 2014/09/22 17:12:12 Is there some way to formally declare threading po
Charles 2014/09/22 21:22:54 There is, but it's not standard and the compiler d
23 120 nativeStart(mUrlRequestAdapter);
24 } 121 }
25 122
26 @Override 123 @Override
27 public void cancel() { 124 public void cancel() {
28 125 mCanceled = true;
126 nativeDestroyRequestAdapter(mUrlRequestAdapter);
29 } 127 }
30 128
31 @Override 129 @Override
32 public boolean isCanceled() { 130 public boolean isCanceled() {
33 return false; 131 return mCanceled;
34 } 132 }
35 133
36 @Override 134 @Override
37 public void pause() { 135 public void pause() {
38 136
39 } 137 }
40 138
41 @Override 139 @Override
42 public boolean isPaused() { 140 public boolean isPaused() {
43 return false; 141 return false;
44 } 142 }
45 143
46 @Override 144 @Override
47 public void resume() { 145 public void resume() {
48 146
49 } 147 }
148
149 private static int convertRequestPriority(int priority) {
150 switch (priority) {
151 case REQUEST_PRIORITY_IDLE:
152 return ChromiumUrlRequestPriority.IDLE;
153 case REQUEST_PRIORITY_LOWEST:
154 return ChromiumUrlRequestPriority.LOWEST;
155 case REQUEST_PRIORITY_LOW:
156 return ChromiumUrlRequestPriority.LOW;
157 case REQUEST_PRIORITY_MEDIUM:
158 return ChromiumUrlRequestPriority.MEDIUM;
159 case REQUEST_PRIORITY_HIGHEST:
160 return ChromiumUrlRequestPriority.HIGHEST;
161 default:
162 return ChromiumUrlRequestPriority.MEDIUM;
163 }
164 }
165
166 private void prepareResponseInfo() {
167
168 }
169
170
171 // Private methods called by native library.
172
173 /**
174 * If @CalledByNative method throws an exception, request gets cancelled
175 * and exception could be retrieved from request using getException().
176 */
177 private void onCalledByNativeException(Exception e) {
Charles 2014/09/20 00:47:34 Needs @CalledByNative annotation
mef 2014/09/22 17:12:12 It is not called by native, it merely handles exce
178 UrlRequestException requestError = new UrlRequestException(
179 "CalledByNative method has thrown an exception", e);
180 Log.e(CronetUrlRequestContext.LOG_TAG,
181 "Exception in CalledByNative method", e);
182 try {
183 mListener.onError(this, requestError);
184 cancel();
185 } catch (Exception cancel_exception) {
Charles 2014/09/20 00:47:33 Use java style naming of exception
mef 2014/09/22 17:12:13 Done.
186 Log.e(CronetUrlRequestContext.LOG_TAG,
187 "Exception trying to cancel request", cancel_exception);
188 }
189 }
190
191 /**
192 * Called before following redirects. The redirect will automatically be
193 * followed, unless the request is paused or cancelled during this
194 * callback. If the redirect response has a body, it will be ignored.
195 * This will only be called between start and onResponseStarted.
196 *
197 * @param info Response information.
198 * @param newLocation Location where request is redirected.
199 */
200 @SuppressWarnings("unused")
201 @CalledByNative
202 private void onRedirect(final String newLocation) {
203 prepareResponseInfo();
204 Runnable task = new Runnable() {
205 public void run() {
206 try {
207 mListener.onRedirect(CronetUrlRequest.this, mResponseInfo,
208 new URL(newLocation));
209 if (!isCanceled())
210 nativeFollowDeferredRedirect(mUrlRequestAdapter);
211 } catch (Exception e) {
212 onCalledByNativeException(e);
213 }
214 }
215 };
216 mExecutor.execute(task);
217 }
218
219 /**
220 * Called when the final set of headers, after all redirects,
221 * is received. Can only be called once for each request.
222 *
223 * @param info Response information.
224 */
225 @SuppressWarnings("unused")
226 @CalledByNative
227 private void onResponseStarted() {
228 prepareResponseInfo();
229 Runnable task = new Runnable() {
230 public void run() {
231 try {
232 mListener.onResponseStarted(CronetUrlRequest.this,
233 mResponseInfo);
234 if (!isCanceled())
235 nativeReceiveData(mUrlRequestAdapter);
236 } catch (Exception e) {
237 onCalledByNativeException(e);
238 }
239 }
240 };
241 mExecutor.execute(task);
242 }
243
244 /**
245 * Called whenever data is received. The ByteBuffer remains
246 * valid only for the duration of the callback. Or if the callback
247 * pauses the request, it remains valid until the request is resumed.
248 * Cancelling the request also invalidates the buffer.
249 *
250 * @param byteBuffer Received data.
251 */
252 @SuppressWarnings("unused")
253 @CalledByNative
254 private void onDataReceived(final ByteBuffer byteBuffer) {
255 Runnable task = new Runnable() {
Charles 2014/09/20 00:47:34 Is there any way to avoid allocating this every ti
mef 2014/09/22 17:12:12 I guess I can keep onDataReceivedRunnable as a mem
Charles 2014/09/22 21:22:53 That would work. On 2014/09/22 17:12:12, mef wrot
mef 2014/09/23 18:42:14 Done.
256 public void run() {
257 try {
258 mListener.onDataReceived(CronetUrlRequest.this, byteBuffer);
259 if (!isCanceled())
260 nativeReceiveData(mUrlRequestAdapter);
261 } catch (Exception e) {
262 onCalledByNativeException(e);
263 }
264 }
265 };
266 mExecutor.execute(task);
267 }
268
269 /**
270 * Called when request is complete, no callbacks will be called afterwards.
271 */
272 @SuppressWarnings("unused")
273 @CalledByNative
274 private void onComplete() {
275 Runnable task = new Runnable() {
276 public void run() {
277 try {
278 mListener.onComplete(CronetUrlRequest.this);
279 nativeDestroyRequestAdapter(mUrlRequestAdapter);
280 } catch (Exception e) {
281 onCalledByNativeException(e);
282 }
283 }
284 };
285 mExecutor.execute(task);
286 }
287
288 /**
289 * Called when error has occured, no callbacks will be called afterwards.
290 */
291 @SuppressWarnings("unused")
292 @CalledByNative
293 private void onError(int error) {
294 Runnable task = new Runnable() {
295 public void run() {
296 try {
297 UrlRequestException requestError = new UrlRequestException(
298 "Exception in CronetUrlRequest ", null);
299 mListener.onError(CronetUrlRequest.this, requestError);
300 nativeDestroyRequestAdapter(mUrlRequestAdapter);
301 } catch (Exception e) {
302 onCalledByNativeException(e);
Charles 2014/09/20 00:47:34 Given that this is happening on the other thread,
mef 2014/09/22 17:12:12 Good question. What should happen if listener thro
Charles 2014/09/22 21:22:53 I think the current behavior is correct, except th
mef 2014/09/23 18:42:14 Done.
303 }
304 }
305 };
306 mExecutor.execute(task);
mef 2014/09/22 17:12:13 Should we execute it inside of try...catch to hand
307 }
308
309 /**
310 * Appends header |name| with value |value| to |headersMap|.
311 */
312 @SuppressWarnings("unused")
313 @CalledByNative
314 private void onAppendResponseHeader(ResponseHeadersMap headersMap,
315 String name, String value) {
316 try {
317 if (!headersMap.containsKey(name)) {
318 headersMap.put(name, new ArrayList<String>());
319 }
320 headersMap.get(name).add(value);
321 } catch (Exception e) {
322 onCalledByNativeException(e);
323 }
324 }
325
326 // Native methods are implemented in cronet_url_request.cc.
327
328 private native long nativeCreateRequestAdapter(
329 long urlRequestContextAdapter, String url, int priority);
330
331 private native void nativeAddHeader(long urlRequestAdapter, String name,
332 String value);
333
334 private native void nativeSetHttpMethod(long urlRequestAdapter,
335 String method);
336
337 private native void nativeStart(long urlRequestAdapter);
338
339 private native void nativeCancel(long urlRequestAdapter);
340
341 private native void nativeDestroyRequestAdapter(long urlRequestAdapter);
342
343 private native void nativeFollowDeferredRedirect(long urlRequestAdapter);
344
345 private native void nativeReceiveData(long urlRequestAdapter);
346
347 // TODO(mef): Remove unused methods (if any).
348
349 private native int nativeGetErrorCode(long urlRequestAdapter);
350
351 private native int nativeGetHttpStatusCode(long urlRequestAdapter);
352
353 private native String nativeGetErrorString(long urlRequestAdapter);
354
355 private native String nativeGetContentType(long urlRequestAdapter);
356
357 private native long nativeGetContentLength(long urlRequestAdapter);
358
359 private native String nativeGetHeader(long urlRequestAdapter, String name);
360
361 private native void nativeGetAllHeaders(long urlRequestAdapter,
362 ResponseHeadersMap headers);
363
364 private native String nativeGetNegotiatedProtocol(long urlRequestAdapter);
365
366 // Explicit class to work around JNI-generator generics confusion.
367 private class ResponseHeadersMap extends HashMap<String, List<String>> {
368 }
369
370
50 } 371 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698