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

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

Issue 945843003: [Cronet] Do not call into native adapter after it is destroyed in ChromiumUrlRequest.java (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed Comments Created 5 years, 9 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; 7 import android.util.Log;
8 8
9 import org.apache.http.conn.ConnectTimeoutException; 9 import org.apache.http.conn.ConnectTimeoutException;
10 import org.chromium.base.CalledByNative; 10 import org.chromium.base.CalledByNative;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 private String mMethod; 43 private String mMethod;
44 private byte[] mUploadData; 44 private byte[] mUploadData;
45 private ReadableByteChannel mUploadChannel; 45 private ReadableByteChannel mUploadChannel;
46 private boolean mChunkedUpload; 46 private boolean mChunkedUpload;
47 private IOException mSinkException; 47 private IOException mSinkException;
48 private volatile boolean mStarted; 48 private volatile boolean mStarted;
49 private volatile boolean mCanceled; 49 private volatile boolean mCanceled;
50 private volatile boolean mRecycled; 50 private volatile boolean mRecycled;
51 private volatile boolean mFinished; 51 private volatile boolean mFinished;
52 private boolean mHeadersAvailable; 52 private boolean mHeadersAvailable;
53 private String mContentType;
54 private long mUploadContentLength; 53 private long mUploadContentLength;
55 private final HttpUrlRequestListener mListener; 54 private final HttpUrlRequestListener mListener;
56 private boolean mBufferFullResponse; 55 private boolean mBufferFullResponse;
57 private long mOffset; 56 private long mOffset;
58 private long mContentLength;
59 private long mContentLengthLimit; 57 private long mContentLengthLimit;
60 private boolean mCancelIfContentLengthOverLimit; 58 private boolean mCancelIfContentLengthOverLimit;
61 private boolean mContentLengthOverLimit; 59 private boolean mContentLengthOverLimit;
62 private boolean mSkippingToOffset; 60 private boolean mSkippingToOffset;
63 private long mSize; 61 private long mSize;
62
64 // Indicates whether redirects have been disabled. 63 // Indicates whether redirects have been disabled.
65 private boolean mDisableRedirects; 64 private boolean mDisableRedirects;
65
66 // Http status code. Default to 0. Populated in onResponseStarted().
67 private int mHttpStatusCode = 0;
68
69 // Http status text. Default to null. Populated in onResponseStarted().
70 private String mHttpStatusText;
71
72 // Content type. Default to null. Populated in onResponseStarted().
73 private String mContentType;
74
75 // Compressed content length as reported by the server. Populated in onRespo nseStarted().
76 private long mContentLength;
77
78 // Native error code. Default to no error. Populated in onRequestComplete().
79 private int mErrorCode = ChromiumUrlRequestError.SUCCESS;
80
81 // Native error string. Default to null. Populated in onRequestComplete().
82 private String mErrorString;
83
66 private final Object mLock = new Object(); 84 private final Object mLock = new Object();
67 85
68 public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext, 86 public ChromiumUrlRequest(ChromiumUrlRequestContext requestContext,
69 String url, int priority, Map<String, String> headers, 87 String url, int priority, Map<String, String> headers,
70 HttpUrlRequestListener listener) { 88 HttpUrlRequestListener listener) {
71 this(requestContext, url, priority, headers, 89 this(requestContext, url, priority, headers,
72 new ChunkedWritableByteChannel(), listener); 90 new ChunkedWritableByteChannel(), listener);
73 mBufferFullResponse = true; 91 mBufferFullResponse = true;
74 } 92 }
75 93
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 } 143 }
126 144
127 @Override 145 @Override
128 public void setContentLengthLimit(long limit, boolean cancelEarly) { 146 public void setContentLengthLimit(long limit, boolean cancelEarly) {
129 mContentLengthLimit = limit; 147 mContentLengthLimit = limit;
130 mCancelIfContentLengthOverLimit = cancelEarly; 148 mCancelIfContentLengthOverLimit = cancelEarly;
131 } 149 }
132 150
133 @Override 151 @Override
134 public int getHttpStatusCode() { 152 public int getHttpStatusCode() {
135 int httpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter);
136
137 // TODO(mef): Investigate the following: 153 // TODO(mef): Investigate the following:
138 // If we have been able to successfully resume a previously interrupted 154 // If we have been able to successfully resume a previously interrupted
139 // download, the status code will be 206, not 200. Since the rest of the 155 // download, the status code will be 206, not 200. Since the rest of the
140 // application is expecting 200 to indicate success, we need to fake it. 156 // application is expecting 200 to indicate success, we need to fake it.
141 if (httpStatusCode == 206) { 157 if (mHttpStatusCode == 206) {
142 httpStatusCode = 200; 158 return 200;
143 } 159 }
144 return httpStatusCode; 160 return mHttpStatusCode;
145 } 161 }
146 162
147 @Override 163 @Override
148 public String getHttpStatusText() { 164 public String getHttpStatusText() {
149 return nativeGetHttpStatusText(mUrlRequestAdapter); 165 return mHttpStatusText;
150 } 166 }
151 167
152 /** 168 /**
153 * Returns an exception if any, or null if the request was completed 169 * Returns an exception if any, or null if the request has not completed or
154 * successfully. 170 * completed successfully.
155 */ 171 */
156 @Override 172 @Override
157 public IOException getException() { 173 public IOException getException() {
158 if (mSinkException != null) { 174 if (mSinkException != null) {
159 return mSinkException; 175 return mSinkException;
160 } 176 }
161 177
162 validateNotRecycled(); 178 switch (mErrorCode) {
163
164 int errorCode = nativeGetErrorCode(mUrlRequestAdapter);
165 switch (errorCode) {
166 case ChromiumUrlRequestError.SUCCESS: 179 case ChromiumUrlRequestError.SUCCESS:
167 if (mContentLengthOverLimit) { 180 if (mContentLengthOverLimit) {
168 return new ResponseTooLargeException(); 181 return new ResponseTooLargeException();
169 } 182 }
170 return null; 183 return null;
171 case ChromiumUrlRequestError.UNKNOWN: 184 case ChromiumUrlRequestError.UNKNOWN:
172 return new IOException( 185 return new IOException(mErrorString);
173 nativeGetErrorString(mUrlRequestAdapter));
174 case ChromiumUrlRequestError.MALFORMED_URL: 186 case ChromiumUrlRequestError.MALFORMED_URL:
175 return new MalformedURLException("Malformed URL: " + mUrl); 187 return new MalformedURLException("Malformed URL: " + mUrl);
176 case ChromiumUrlRequestError.CONNECTION_TIMED_OUT: 188 case ChromiumUrlRequestError.CONNECTION_TIMED_OUT:
177 return new ConnectTimeoutException("Connection timed out"); 189 return new ConnectTimeoutException("Connection timed out");
178 case ChromiumUrlRequestError.UNKNOWN_HOST: 190 case ChromiumUrlRequestError.UNKNOWN_HOST:
179 String host; 191 String host;
180 try { 192 try {
181 host = new URL(mUrl).getHost(); 193 host = new URL(mUrl).getHost();
182 } catch (MalformedURLException e) { 194 } catch (MalformedURLException e) {
183 host = mUrl; 195 host = mUrl;
184 } 196 }
185 return new UnknownHostException("Unknown host: " + host); 197 return new UnknownHostException("Unknown host: " + host);
186 case ChromiumUrlRequestError.TOO_MANY_REDIRECTS: 198 case ChromiumUrlRequestError.TOO_MANY_REDIRECTS:
187 return new IOException("Request failed because there were too " 199 return new IOException("Request failed because there were too "
188 + "many redirects or redirects have been disabled"); 200 + "many redirects or redirects have been disabled");
189 default: 201 default:
190 throw new IllegalStateException( 202 throw new IllegalStateException(
191 "Unrecognized error code: " + errorCode); 203 "Unrecognized error code: " + mErrorCode);
192 } 204 }
193 } 205 }
194 206
195 @Override 207 @Override
196 public ByteBuffer getByteBuffer() { 208 public ByteBuffer getByteBuffer() {
197 return ((ChunkedWritableByteChannel) getSink()).getByteBuffer(); 209 return ((ChunkedWritableByteChannel) getSink()).getByteBuffer();
198 } 210 }
199 211
200 @Override 212 @Override
201 public byte[] getResponseAsBytes() { 213 public byte[] getResponseAsBytes() {
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 468
457 private void onContentLengthOverLimit() { 469 private void onContentLengthOverLimit() {
458 mContentLengthOverLimit = true; 470 mContentLengthOverLimit = true;
459 cancel(); 471 cancel();
460 } 472 }
461 473
462 /** 474 /**
463 * A callback invoked when the response has been fully consumed. 475 * A callback invoked when the response has been fully consumed.
464 */ 476 */
465 private void onRequestComplete() { 477 private void onRequestComplete() {
478 mErrorCode = nativeGetErrorCode(mUrlRequestAdapter);
479 mErrorString = nativeGetErrorString(mUrlRequestAdapter);
480 // When there is an error or redirects have been disabled,
481 // onResponseStarted is often not invoked.
482 // Populate status code and status text if that's the case.
483 if (mErrorCode != ChromiumUrlRequestError.SUCCESS) {
484 mHttpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter);
485 mHttpStatusText = nativeGetHttpStatusText(mUrlRequestAdapter);
486 }
466 mListener.onRequestComplete(this); 487 mListener.onRequestComplete(this);
467 } 488 }
468 489
469 private void validateNotRecycled() { 490 private void validateNotRecycled() {
470 if (mRecycled) { 491 if (mRecycled) {
471 throw new IllegalStateException("Accessing recycled request"); 492 throw new IllegalStateException("Accessing recycled request");
472 } 493 }
473 } 494 }
474 495
475 private void validateNotStarted() { 496 private void validateNotStarted() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 "Exception trying to cancel request", cancel_exception); 529 "Exception trying to cancel request", cancel_exception);
509 } 530 }
510 } 531 }
511 532
512 /** 533 /**
513 * A callback invoked when the first chunk of the response has arrived. 534 * A callback invoked when the first chunk of the response has arrived.
514 */ 535 */
515 @CalledByNative 536 @CalledByNative
516 private void onResponseStarted() { 537 private void onResponseStarted() {
517 try { 538 try {
539 mHttpStatusCode = nativeGetHttpStatusCode(mUrlRequestAdapter);
540 mHttpStatusText = nativeGetHttpStatusText(mUrlRequestAdapter);
518 mContentType = nativeGetContentType(mUrlRequestAdapter); 541 mContentType = nativeGetContentType(mUrlRequestAdapter);
519 mContentLength = nativeGetContentLength(mUrlRequestAdapter); 542 mContentLength = nativeGetContentLength(mUrlRequestAdapter);
520 mHeadersAvailable = true; 543 mHeadersAvailable = true;
521 544
522 if (mContentLengthLimit > 0 545 if (mContentLengthLimit > 0
523 && mContentLength > mContentLengthLimit 546 && mContentLength > mContentLengthLimit
524 && mCancelIfContentLengthOverLimit) { 547 && mCancelIfContentLengthOverLimit) {
525 onContentLengthOverLimit(); 548 onContentLengthOverLimit();
526 return; 549 return;
527 } 550 }
528 551
529 if (mBufferFullResponse && mContentLength != -1 552 if (mBufferFullResponse && mContentLength != -1
530 && !mContentLengthOverLimit) { 553 && !mContentLengthOverLimit) {
531 ((ChunkedWritableByteChannel) getSink()).setCapacity( 554 ((ChunkedWritableByteChannel) getSink()).setCapacity(
532 (int) mContentLength); 555 (int) mContentLength);
533 } 556 }
534 557
535 if (mOffset != 0) { 558 if (mOffset != 0) {
536 // The server may ignore the request for a byte range, in which 559 // The server may ignore the request for a byte range, in which
537 // case status code will be 200, instead of 206. Note that we 560 // case status code will be 200, instead of 206. Note that we
538 // cannot call getHttpStatusCode as it rewrites 206 into 200. 561 // cannot call getHttpStatusCode as it rewrites 206 into 200.
539 if (nativeGetHttpStatusCode(mUrlRequestAdapter) == 200) { 562 if (mHttpStatusCode == 200) {
540 // TODO(mef): Revisit this logic. 563 // TODO(mef): Revisit this logic.
541 if (mContentLength != -1) { 564 if (mContentLength != -1) {
542 mContentLength -= mOffset; 565 mContentLength -= mOffset;
543 } 566 }
544 mSkippingToOffset = true; 567 mSkippingToOffset = true;
545 } else { 568 } else {
546 mSize = mOffset; 569 mSize = mOffset;
547 } 570 }
548 } 571 }
549 mListener.onResponseStarted(this); 572 mListener.onResponseStarted(this);
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 private native void nativeGetAllHeaders(long urlRequestAdapter, 743 private native void nativeGetAllHeaders(long urlRequestAdapter,
721 ResponseHeadersMap headers); 744 ResponseHeadersMap headers);
722 745
723 private native String nativeGetNegotiatedProtocol(long urlRequestAdapter); 746 private native String nativeGetNegotiatedProtocol(long urlRequestAdapter);
724 747
725 // Explicit class to work around JNI-generator generics confusion. 748 // Explicit class to work around JNI-generator generics confusion.
726 private static class ResponseHeadersMap extends 749 private static class ResponseHeadersMap extends
727 HashMap<String, List<String>> { 750 HashMap<String, List<String>> {
728 } 751 }
729 } 752 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698