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

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

Issue 458633002: Merge UrlRequest.java into ChromiumUrlRequest.java (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move methods around. Created 6 years, 4 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 | Annotate | Revision Log
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 org.apache.http.conn.ConnectTimeoutException;
8 import org.chromium.base.CalledByNative;
9 import org.chromium.base.JNINamespace;
10
7 import java.io.IOException; 11 import java.io.IOException;
12 import java.net.MalformedURLException;
13 import java.net.URL;
14 import java.net.UnknownHostException;
8 import java.nio.ByteBuffer; 15 import java.nio.ByteBuffer;
16 import java.nio.channels.ReadableByteChannel;
9 import java.nio.channels.WritableByteChannel; 17 import java.nio.channels.WritableByteChannel;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
10 import java.util.Map; 21 import java.util.Map;
22 import java.util.Map.Entry;
11 23
12 /** 24 /**
13 * Network request using the native http stack implementation. 25 * Network request using the native http stack implementation.
14 */ 26 */
15 public class ChromiumUrlRequest extends UrlRequest implements HttpUrlRequest { 27 @JNINamespace("cronet")
28 public class ChromiumUrlRequest implements HttpUrlRequest {
29 /**
30 * Native adapter object, owned by UrlRequest.
31 */
32 private long mUrlRequestAdapter;
33 private final ChromiumUrlRequestContext mRequestContext;
34 private final String mUrl;
35 private final int mPriority;
36 private final Map<String, String> mHeaders;
37 private final WritableByteChannel mSink;
38 private Map<String, String> mAdditionalHeaders;
39 private String mUploadContentType;
40 private String mMethod;
41 private byte[] mUploadData;
42 private ReadableByteChannel mUploadChannel;
43 private WritableByteChannel mOutputChannel;
44 private IOException mSinkException;
45 private volatile boolean mStarted;
46 private volatile boolean mCanceled;
47 private volatile boolean mRecycled;
48 private volatile boolean mFinished;
49 private boolean mHeadersAvailable;
50 private String mContentType;
51 private long mUploadContentLength;
52 private final HttpUrlRequestListener mListener;
53 private boolean mBufferFullResponse;
54 private long mOffset;
55 private long mContentLength;
56 private long mContentLengthLimit;
57 private boolean mCancelIfContentLengthOverLimit;
58 private boolean mContentLengthOverLimit;
59 private boolean mSkippingToOffset;
60 private long mSize;
61 private final Object mLock;
16 62
17 private final HttpUrlRequestListener mListener; 63 public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext,
18
19 private boolean mBufferFullResponse;
20
21 private long mOffset;
22
23 private long mContentLength;
24
25 private long mContentLengthLimit;
26
27 private boolean mCancelIfContentLengthOverLimit;
28
29 private boolean mContentLengthOverLimit;
30
31 private boolean mSkippingToOffset;
32
33 private long mSize;
34
35 public ChromiumUrlRequest(UrlRequestContext requestContext,
36 String url, int priority, Map<String, String> headers, 64 String url, int priority, Map<String, String> headers,
37 HttpUrlRequestListener listener) { 65 HttpUrlRequestListener listener) {
38 this(requestContext, url, priority, headers, 66 this(requestContext, url, priority, headers,
39 new ChunkedWritableByteChannel(), listener); 67 new ChunkedWritableByteChannel(), listener);
40 mBufferFullResponse = true; 68 mBufferFullResponse = true;
41 } 69 }
42 70
43 public ChromiumUrlRequest(UrlRequestContext requestContext, 71 /**
72 * Constructor.
73 *
74 * @param requestContext The context.
75 * @param url The URL.
76 * @param priority Request priority, e.g. {@link #REQUEST_PRIORITY_MEDIUM}.
77 * @param headers HTTP headers.
78 * @param sink The output channel into which downloaded content will be
79 * written.
80 */
81 public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext,
44 String url, int priority, Map<String, String> headers, 82 String url, int priority, Map<String, String> headers,
45 WritableByteChannel sink, HttpUrlRequestListener listener) { 83 WritableByteChannel sink, HttpUrlRequestListener listener) {
46 super(requestContext, url, convertRequestPriority(priority), headers, 84 if (requestContext == null) {
47 sink); 85 throw new NullPointerException("Context is required");
86 }
87 if (url == null) {
88 throw new NullPointerException("URL is required");
89 }
90 mRequestContext = requestContext;
91 mUrl = url;
92 mPriority = convertRequestPriority(priority);
93 mHeaders = headers;
94 mSink = sink;
95 mLock = new Object();
96 mUrlRequestAdapter = nativeCreateRequestAdapter(
97 mRequestContext.getChromiumUrlRequestContextAdapter(),
98 mUrl,
99 mPriority);
mmenke 2014/08/13 15:33:50 Hrm...Not sure about the android style guide, but
mef 2014/08/13 18:52:41 Acknowledged.
48 mListener = listener; 100 mListener = listener;
49 } 101 }
50 102
51 private static int convertRequestPriority(int priority) {
52 switch (priority) {
53 case HttpUrlRequest.REQUEST_PRIORITY_IDLE:
54 return UrlRequestPriority.IDLE;
55 case HttpUrlRequest.REQUEST_PRIORITY_LOWEST:
56 return UrlRequestPriority.LOWEST;
57 case HttpUrlRequest.REQUEST_PRIORITY_LOW:
58 return UrlRequestPriority.LOW;
59 case HttpUrlRequest.REQUEST_PRIORITY_MEDIUM:
60 return UrlRequestPriority.MEDIUM;
61 case HttpUrlRequest.REQUEST_PRIORITY_HIGHEST:
62 return UrlRequestPriority.HIGHEST;
63 default:
64 return UrlRequestPriority.MEDIUM;
65 }
66 }
67
68 @Override 103 @Override
69 public void setOffset(long offset) { 104 public void setOffset(long offset) {
70 mOffset = offset; 105 mOffset = offset;
71 if (offset != 0) { 106 if (offset != 0) {
72 addHeader("Range", "bytes=" + offset + "-"); 107 addHeader("Range", "bytes=" + offset + "-");
73 } 108 }
74 } 109 }
75 110
111 /**
112 * Content length as reported by the server. May be -1 or incorrect if the
113 * server returns the wrong number, which happens even with Google servers.
mmenke 2014/08/13 15:33:50 This doesn't seem quite right. Maybe "The compres
mmenke 2014/08/13 15:33:51 Should we add Javadoc style comments here? @retur
mef 2014/08/13 18:52:41 Done.
mef 2014/08/13 18:52:41 I think so? I think that ideally (or possibly abso
114 */
76 @Override 115 @Override
77 public long getContentLength() { 116 public long getContentLength() {
78 return mContentLength; 117 return mContentLength;
79 } 118 }
80 119
81 @Override 120 @Override
82 public void setContentLengthLimit(long limit, boolean cancelEarly) { 121 public void setContentLengthLimit(long limit, boolean cancelEarly) {
83 mContentLengthLimit = limit; 122 mContentLengthLimit = limit;
84 mCancelIfContentLengthOverLimit = cancelEarly; 123 mCancelIfContentLengthOverLimit = cancelEarly;
85 } 124 }
86 125
87 @Override 126 @Override
127 public int getHttpStatusCode() {
128 int httpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter);
129
130 // TODO(mef): Investigate the following:
131 // If we have been able to successfully resume a previously interrupted
132 // download,
133 // the status code will be 206, not 200. Since the rest of the
134 // application is
135 // expecting 200 to indicate success, we need to fake it.
136 if (httpStatusCode == 206) {
137 httpStatusCode = 200;
138 }
139 return httpStatusCode;
140 }
141
142 /**
143 * Returns an exception if any, or null if the request was completed
144 * successfully.
145 */
146 @Override
147 public IOException getException() {
148 if (mSinkException != null) {
149 return mSinkException;
150 }
151
152 validateNotRecycled();
153
154 int errorCode = nativeGetErrorCode(mUrlRequestAdapter);
155 switch (errorCode) {
156 case ChromiumUrlRequestError.SUCCESS:
157 if (mContentLengthOverLimit) {
158 return new ResponseTooLargeException();
159 }
160 return null;
161 case ChromiumUrlRequestError.UNKNOWN:
162 return new IOException(
163 nativeGetErrorString(mUrlRequestAdapter));
164 case ChromiumUrlRequestError.MALFORMED_URL:
165 return new MalformedURLException("Malformed URL: " + mUrl);
166 case ChromiumUrlRequestError.CONNECTION_TIMED_OUT:
167 return new ConnectTimeoutException("Connection timed out");
168 case ChromiumUrlRequestError.UNKNOWN_HOST:
169 String host;
170 try {
171 host = new URL(mUrl).getHost();
172 } catch (MalformedURLException e) {
173 host = mUrl;
174 }
175 return new UnknownHostException("Unknown host: " + host);
176 default:
177 throw new IllegalStateException(
178 "Unrecognized error code: " + errorCode);
179 }
180 }
181
182 @Override
183 public ByteBuffer getByteBuffer() {
184 return ((ChunkedWritableByteChannel)getSink()).getByteBuffer();
185 }
186
187 @Override
188 public byte[] getResponseAsBytes() {
189 return ((ChunkedWritableByteChannel)getSink()).getBytes();
190 }
191
192 /**
193 * Adds a request header.
194 */
195 public void addHeader(String header, String value) {
mmenke 2014/08/13 15:33:50 Should this be synchronized? Heck, should all set
mef 2014/08/13 18:52:41 Acknowledged. I'd prefer to change it in separate
196 validateNotStarted();
197 if (mAdditionalHeaders == null) {
198 mAdditionalHeaders = new HashMap<String, String>();
199 }
200 mAdditionalHeaders.put(header, value);
201 }
202
203 /**
204 * Sets data to upload as part of a POST request.
205 *
206 * @param contentType MIME type of the post content or null if this is not a
mmenke 2014/08/13 15:33:49 nit: post -> POST
mef 2014/08/13 18:52:41 Done.
207 * POST.
208 * @param data The content that needs to be uploaded if this is a POST
209 * request.
210 */
211 public void setUploadData(String contentType, byte[] data) {
212 synchronized (mLock) {
213 validateNotStarted();
214 mUploadContentType = contentType;
215 mUploadData = data;
216 mUploadChannel = null;
217 }
218 }
219
220 /**
221 * Sets a readable byte channel to upload as part of a POST request.
222 *
223 * @param contentType MIME type of the post content or null if this is not a
mmenke 2014/08/13 15:33:49 nit POST?
mef 2014/08/13 18:52:41 Done.
224 * POST request.
225 * @param channel The channel to read to read upload data from if this is a
226 * POST request.
227 * @param contentLength The length of data to upload.
228 */
229 public void setUploadChannel(String contentType,
230 ReadableByteChannel channel, long contentLength) {
231 synchronized (mLock) {
232 validateNotStarted();
233 mUploadContentType = contentType;
234 mUploadChannel = channel;
235 mUploadContentLength = contentLength;
236 mUploadData = null;
237 }
238 }
239
240 public void setHttpMethod(String method) {
241 validateNotStarted();
242 if (!("PUT".equals(method) || "POST".equals(method))) {
243 throw new IllegalArgumentException("Only PUT or POST are allowed.");
244 }
245 mMethod = method;
246 }
247
248 public WritableByteChannel getSink() {
249 return mSink;
250 }
251
252 public void start() {
253 synchronized (mLock) {
254 if (mCanceled) {
255 return;
256 }
257
258 validateNotStarted();
259 validateNotRecycled();
260
261 mStarted = true;
262
263 String method = mMethod;
264 if (method == null &&
265 ((mUploadData != null && mUploadData.length > 0) ||
266 mUploadChannel != null)) {
267 // Default to POST if there is data to upload but no method was
268 // specified.
269 method = "POST";
270 }
271
272 if (method != null) {
273 nativeSetMethod(mUrlRequestAdapter, method);
274 }
275
276 if (mHeaders != null && !mHeaders.isEmpty()) {
277 for (Entry<String, String> entry : mHeaders.entrySet()) {
278 nativeAddHeader(mUrlRequestAdapter, entry.getKey(),
279 entry.getValue());
280 }
mmenke 2014/08/13 15:33:51 indent +2
mef 2014/08/13 18:52:41 Done.
281 }
282
283 if (mAdditionalHeaders != null) {
284 for (Entry<String, String> entry :
285 mAdditionalHeaders.entrySet()) {
286 nativeAddHeader(mUrlRequestAdapter, entry.getKey(),
287 entry.getValue());
mmenke 2014/08/13 15:33:50 Is is really correct indentation? It looks wrong.
mef 2014/08/13 18:52:41 Yeah, I'm not sure, I think continuation line is i
288 }
mmenke 2014/08/13 15:33:50 indent +2
mef 2014/08/13 18:52:41 Done.
289 }
290
291 if (mUploadData != null && mUploadData.length > 0) {
292 nativeSetUploadData(mUrlRequestAdapter, mUploadContentType,
293 mUploadData);
294 } else if (mUploadChannel != null) {
295 nativeSetUploadChannel(mUrlRequestAdapter, mUploadContentType,
296 mUploadContentLength);
297 }
298
299 nativeStart(mUrlRequestAdapter);
300 }
301 }
302
303 public void cancel() {
304 synchronized (mLock) {
305 if (mCanceled) {
306 return;
307 }
308
309 mCanceled = true;
310
311 if (!mRecycled) {
312 nativeCancel(mUrlRequestAdapter);
313 }
314 }
315 }
316
317 public boolean isCanceled() {
318 synchronized (mLock) {
319 return mCanceled;
320 }
321 }
322
323 public boolean isRecycled() {
324 synchronized (mLock) {
325 return mRecycled;
326 }
327 }
328
329 public String getContentType() {
330 return mContentType;
331 }
332
333 public String getHeader(String name) {
334 validateHeadersAvailable();
335 return nativeGetHeader(mUrlRequestAdapter, name);
336 }
337
338 // All response headers.
339 public Map<String, List<String>> getAllHeaders() {
340 validateHeadersAvailable();
341 ResponseHeadersMap result = new ResponseHeadersMap();
342 nativeGetAllHeaders(mUrlRequestAdapter, result);
343 return result;
344 }
345
346 public String getUrl() {
347 return mUrl;
348 }
349
350 /**
351 * A callback invoked when the first chunk of the response has arrived.
352 */
353 @CalledByNative
88 protected void onResponseStarted() { 354 protected void onResponseStarted() {
89 super.onResponseStarted(); 355 mContentType = nativeGetContentType(mUrlRequestAdapter);
90 356 mContentLength = nativeGetContentLength(mUrlRequestAdapter);
91 mContentLength = super.getContentLength(); 357 mHeadersAvailable = true;
358
92 if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit 359 if (mContentLengthLimit > 0 && mContentLength > mContentLengthLimit
93 && mCancelIfContentLengthOverLimit) { 360 && mCancelIfContentLengthOverLimit) {
94 onContentLengthOverLimit(); 361 onContentLengthOverLimit();
95 return; 362 return;
96 } 363 }
97 364
98 if (mBufferFullResponse && mContentLength != -1 365 if (mBufferFullResponse && mContentLength != -1
99 && !mContentLengthOverLimit) { 366 && !mContentLengthOverLimit) {
100 ((ChunkedWritableByteChannel)getSink()).setCapacity( 367 ((ChunkedWritableByteChannel)getSink()).setCapacity(
101 (int)mContentLength); 368 (int)mContentLength);
102 } 369 }
103 370
104 if (mOffset != 0) { 371 if (mOffset != 0) {
105 // The server may ignore the request for a byte range. 372 // The server may ignore the request for a byte range.
106 if (super.getHttpStatusCode() == 200) { 373 if (getHttpStatusCode() == 200) {
Charles 2014/08/14 18:23:50 This breaks range requests. Lower down in the file
mef 2014/08/14 20:58:02 Done.
Charles 2014/08/14 21:33:27 This is still broken - the server will return 20 T
107 if (mContentLength != -1) { 374 if (mContentLength != -1) {
108 mContentLength -= mOffset; 375 mContentLength -= mOffset;
mmenke 2014/08/13 15:33:50 This just seems bizarre...But fixing it is beyond
mef 2014/08/13 18:52:41 Ack. Added TODO.
109 } 376 }
110 mSkippingToOffset = true; 377 mSkippingToOffset = true;
111 } else { 378 } else {
112 mSize = mOffset; 379 mSize = mOffset;
113 } 380 }
114 } 381 }
115 mListener.onResponseStarted(this); 382 mListener.onResponseStarted(this);
116 } 383 }
117 384
118 @Override 385 /**
386 * Consumes a portion of the response.
387 *
388 * @param byteBuffer The ByteBuffer to append. Must be a direct buffer, and
389 * no references to it may be retained after the method ends, as
390 * it wraps code managed on the native heap.
391 */
392 @CalledByNative
119 protected void onBytesRead(ByteBuffer buffer) { 393 protected void onBytesRead(ByteBuffer buffer) {
120 if (mContentLengthOverLimit) { 394 if (mContentLengthOverLimit) {
121 return; 395 return;
122 } 396 }
123 397
124 int size = buffer.remaining(); 398 int size = buffer.remaining();
125 mSize += size; 399 mSize += size;
126 if (mSkippingToOffset) { 400 if (mSkippingToOffset) {
127 if (mSize <= mOffset) { 401 if (mSize <= mOffset) {
128 return; 402 return;
129 } else { 403 } else {
130 mSkippingToOffset = false; 404 mSkippingToOffset = false;
131 buffer.position((int)(mOffset - (mSize - size))); 405 buffer.position((int)(mOffset - (mSize - size)));
132 } 406 }
133 } 407 }
134 408
135 if (mContentLengthLimit != 0 && mSize > mContentLengthLimit) { 409 boolean contentLengthOverLimit =
410 (mContentLengthLimit != 0 && mSize > mContentLengthLimit);
411 if (contentLengthOverLimit) {
136 buffer.limit(size - (int)(mSize - mContentLengthLimit)); 412 buffer.limit(size - (int)(mSize - mContentLengthLimit));
137 super.onBytesRead(buffer);
138 onContentLengthOverLimit();
139 return;
140 } 413 }
141 414
142 super.onBytesRead(buffer); 415 try {
416 while (buffer.hasRemaining()) {
417 mSink.write(buffer);
418 }
419 } catch (IOException e) {
420 mSinkException = e;
421 cancel();
422 }
423 if (contentLengthOverLimit) {
424 onContentLengthOverLimit();
425 }
426 }
427
428 private static int convertRequestPriority(int priority) {
429 switch (priority) {
430 case HttpUrlRequest.REQUEST_PRIORITY_IDLE:
431 return ChromiumUrlRequestPriority.IDLE;
432 case HttpUrlRequest.REQUEST_PRIORITY_LOWEST:
433 return ChromiumUrlRequestPriority.LOWEST;
434 case HttpUrlRequest.REQUEST_PRIORITY_LOW:
435 return ChromiumUrlRequestPriority.LOW;
436 case HttpUrlRequest.REQUEST_PRIORITY_MEDIUM:
437 return ChromiumUrlRequestPriority.MEDIUM;
438 case HttpUrlRequest.REQUEST_PRIORITY_HIGHEST:
439 return ChromiumUrlRequestPriority.HIGHEST;
440 default:
441 return ChromiumUrlRequestPriority.MEDIUM;
442 }
143 } 443 }
144 444
145 private void onContentLengthOverLimit() { 445 private void onContentLengthOverLimit() {
146 mContentLengthOverLimit = true; 446 mContentLengthOverLimit = true;
147 cancel(); 447 cancel();
148 } 448 }
149 449
150 @Override 450 /**
451 * A callback invoked when the response has been fully consumed.
452 */
151 protected void onRequestComplete() { 453 protected void onRequestComplete() {
152 mListener.onRequestComplete(this); 454 mListener.onRequestComplete(this);
153 } 455 }
154 456
155 @Override 457 private void validateNotRecycled() {
156 public int getHttpStatusCode() { 458 if (mRecycled) {
157 int httpStatusCode = super.getHttpStatusCode(); 459 throw new IllegalStateException("Accessing recycled request");
158
159 // TODO(mef): Investigate the following:
160 // If we have been able to successfully resume a previously interrupted
161 // download,
162 // the status code will be 206, not 200. Since the rest of the
163 // application is
164 // expecting 200 to indicate success, we need to fake it.
165 if (httpStatusCode == 206) {
166 httpStatusCode = 200;
167 } 460 }
168 return httpStatusCode;
169 } 461 }
170 462
171 @Override 463 private void validateNotStarted() {
172 public IOException getException() { 464 if (mStarted) {
173 IOException ex = super.getException(); 465 throw new IllegalStateException("Request already started");
174 if (ex == null && mContentLengthOverLimit) {
175 ex = new ResponseTooLargeException();
176 } 466 }
177 return ex;
178 } 467 }
179 468
180 @Override 469 private void validateHeadersAvailable() {
181 public ByteBuffer getByteBuffer() { 470 if (!mHeadersAvailable) {
182 return ((ChunkedWritableByteChannel)getSink()).getByteBuffer(); 471 throw new IllegalStateException("Response headers not available");
472 }
183 } 473 }
184 474
185 @Override 475 /**
186 public byte[] getResponseAsBytes() { 476 * Notifies the listener, releases native data structures.
187 return ((ChunkedWritableByteChannel)getSink()).getBytes(); 477 */
478 @SuppressWarnings("unused")
479 @CalledByNative
480 private void finish() {
481 synchronized (mLock) {
482 mFinished = true;
483
484 if (mRecycled) {
485 return;
486 }
487 try {
488 mSink.close();
489 } catch (IOException e) {
490 // Ignore
491 }
492 onRequestComplete();
493 nativeDestroyRequestAdapter(mUrlRequestAdapter);
494 mUrlRequestAdapter = 0;
495 mRecycled = true;
496 }
497 }
498
499 /**
500 * Appends header |name| with value |value| to |headersMap|.
501 */
502 @SuppressWarnings("unused")
503 @CalledByNative
504 private void onAppendResponseHeader(ResponseHeadersMap headersMap,
505 String name, String value) {
506 if (!headersMap.containsKey(name)) {
507 headersMap.put(name, new ArrayList<String>());
508 }
509 headersMap.get(name).add(value);
510 }
511
512 /**
513 * Reads a sequence of bytes from upload channel into the given buffer.
514 * @param dest The buffer into which bytes are to be transferred.
515 * @return Returns number of bytes read (could be 0) or -1 and closes
516 * the channel if error occured.
517 */
518 @SuppressWarnings("unused")
519 @CalledByNative
520 private int readFromUploadChannel(ByteBuffer dest) {
521 if (mUploadChannel == null || !mUploadChannel.isOpen())
522 return -1;
523 try {
524 int result = mUploadChannel.read(dest);
525 if (result < 0) {
526 mUploadChannel.close();
527 return 0;
528 }
529 return result;
530 } catch (IOException e) {
531 mSinkException = e;
532 try {
533 mUploadChannel.close();
534 } catch (IOException ignored) {
535 // Ignore this exception.
536 }
537 cancel();
538 return -1;
539 }
540 }
541
542 // Native methods are implemented in chromium_url_request.cc.
543
544 private native long nativeCreateRequestAdapter(
545 long ChromiumUrlRequestContextAdapter, String url, int priority);
546
547 private native void nativeAddHeader(long urlRequestAdapter, String name,
548 String value);
549
550 private native void nativeSetMethod(long urlRequestAdapter, String method);
551
552 private native void nativeSetUploadData(long urlRequestAdapter,
553 String contentType, byte[] content);
554
555 private native void nativeSetUploadChannel(long urlRequestAdapter,
556 String contentType, long contentLength);
557
558 private native void nativeStart(long urlRequestAdapter);
559
560 private native void nativeCancel(long urlRequestAdapter);
561
562 private native void nativeDestroyRequestAdapter(long urlRequestAdapter);
563
564 private native int nativeGetErrorCode(long urlRequestAdapter);
565
566 private native int nativeGetHttpStatusCode(long urlRequestAdapter);
567
568 private native String nativeGetErrorString(long urlRequestAdapter);
569
570 private native String nativeGetContentType(long urlRequestAdapter);
571
572 private native long nativeGetContentLength(long urlRequestAdapter);
573
574 private native String nativeGetHeader(long urlRequestAdapter, String name);
575
576 private native void nativeGetAllHeaders(long urlRequestAdapter,
577 ResponseHeadersMap headers);
578
579 // Explicit class to work around JNI-generator generics confusion.
580 private class ResponseHeadersMap extends HashMap<String, List<String>> {
188 } 581 }
189 } 582 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698