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

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

Issue 1359343005: Update ResponseInfo to UrlResponseInfo with API review comments. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Pass the integration tests. Created 5 years, 2 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 import android.util.Pair;
9 8
10 import org.chromium.base.VisibleForTesting; 9 import org.chromium.base.VisibleForTesting;
11 import org.chromium.base.annotations.CalledByNative; 10 import org.chromium.base.annotations.CalledByNative;
12 import org.chromium.base.annotations.JNIAdditionalImport; 11 import org.chromium.base.annotations.JNIAdditionalImport;
13 import org.chromium.base.annotations.JNINamespace; 12 import org.chromium.base.annotations.JNINamespace;
14 import org.chromium.base.annotations.NativeClassQualifiedName; 13 import org.chromium.base.annotations.NativeClassQualifiedName;
15 14
16 import java.nio.ByteBuffer; 15 import java.nio.ByteBuffer;
16 import java.util.AbstractMap;
17 import java.util.ArrayList; 17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List; 18 import java.util.List;
20 import java.util.Map; 19 import java.util.Map;
21 import java.util.TreeMap;
22 import java.util.concurrent.Executor; 20 import java.util.concurrent.Executor;
23 import java.util.concurrent.RejectedExecutionException; 21 import java.util.concurrent.RejectedExecutionException;
24 22
25 /** 23 /**
26 * UrlRequest using Chromium HTTP stack implementation. Could be accessed from 24 * UrlRequest using Chromium HTTP stack implementation. Could be accessed from
27 * any thread on Executor. Cancel can be called from any thread. 25 * any thread on Executor. Cancel can be called from any thread.
28 * All @CallByNative methods are called on native network thread 26 * All @CallByNative methods are called on native network thread
29 * and post tasks with listener calls onto Executor. Upon return from listener 27 * and post tasks with listener calls onto Executor. Upon return from listener
30 * callback native request adapter is called on executive thread and posts 28 * callback native request adapter is called on executive thread and posts
31 * native tasks to native network thread. Because Cancel could be called from 29 * native tasks to native network thread. Because Cancel could be called from
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 private final List<String> mUrlChain = new ArrayList<String>(); 64 private final List<String> mUrlChain = new ArrayList<String>();
67 65
68 private final UrlRequestListener mListener; 66 private final UrlRequestListener mListener;
69 private final String mInitialUrl; 67 private final String mInitialUrl;
70 private final int mPriority; 68 private final int mPriority;
71 private String mInitialMethod; 69 private String mInitialMethod;
72 private final HeadersList mRequestHeaders = new HeadersList(); 70 private final HeadersList mRequestHeaders = new HeadersList();
73 71
74 private CronetUploadDataStream mUploadDataStream; 72 private CronetUploadDataStream mUploadDataStream;
75 73
76 private NativeResponseInfo mResponseInfo; 74 private UrlResponseInfo mResponseInfo;
77 75
78 /* 76 /*
79 * Listener callback is repeatedly called when each read is completed, so it 77 * Listener callback is repeatedly called when each read is completed, so it
80 * is cached as a member variable. 78 * is cached as a member variable.
81 */ 79 */
82 private OnReadCompletedRunnable mOnReadCompletedTask; 80 private OnReadCompletedRunnable mOnReadCompletedTask;
83 81
84 private Runnable mOnDestroyedCallbackForTests; 82 private Runnable mOnDestroyedCallbackForTests;
85 83
86 private static final class HeadersList extends ArrayList<Pair<String, String >> {} 84 private static final class HeadersList extends ArrayList<Map.Entry<String, S tring>> {}
87 85
88 private final class OnReadCompletedRunnable implements Runnable { 86 private final class OnReadCompletedRunnable implements Runnable {
89 ByteBuffer mByteBuffer; 87 ByteBuffer mByteBuffer;
90 88
91 @Override 89 @Override
92 public void run() { 90 public void run() {
93 if (isDone()) { 91 if (isDone()) {
94 return; 92 return;
95 } 93 }
96 try { 94 try {
97 synchronized (mUrlRequestAdapterLock) { 95 synchronized (mUrlRequestAdapterLock) {
98 if (mUrlRequestAdapter == 0) { 96 if (mUrlRequestAdapter == 0) {
99 return; 97 return;
100 } 98 }
101 mWaitingOnRead = true; 99 mWaitingOnRead = true;
102 } 100 }
103 // Null out mByteBuffer, out of paranoia. Has to be done before 101 // Null out mByteBuffer, out of paranoia. Has to be done before
104 // mListener call, to avoid any race when there are multiple 102 // mListener call, to avoid any race when there are multiple
105 // executor threads. 103 // executor threads.
106 ByteBuffer buffer = mByteBuffer; 104 ByteBuffer buffer = mByteBuffer;
107 mByteBuffer = null; 105 mByteBuffer = null;
108 mListener.onReadCompleted(CronetUrlRequest.this, 106 mListener.onReadCompleted(CronetUrlRequest.this,
109 mResponseInfo, buffer); 107 mResponseInfo, buffer);
110 } catch (Exception e) { 108 } catch (Exception e) {
111 onListenerException(e); 109 onListenerException(e);
112 } 110 }
113 } 111 }
114 } 112 }
115 113
116 private static final class NativeResponseInfo implements ResponseInfo { 114 private static final class ExtendedUrlResponseInfo implements ExtendedRespon seInfo {
117 private final String[] mResponseInfoUrlChain; 115 private final UrlResponseInfo mUrlResponseInfo;
118 private final int mHttpStatusCode;
119 private final String mHttpStatusText;
120 private final boolean mWasCached;
121 private final String mNegotiatedProtocol;
122 private final String mProxyServer;
123 private final HeadersList mAllHeaders = new HeadersList();
124 private Map<String, List<String>> mResponseHeaders;
125 private List<Pair<String, String>> mUnmodifiableAllHeaders;
126 116
127 NativeResponseInfo(String[] urlChain, int httpStatusCode, 117 ExtendedUrlResponseInfo(UrlResponseInfo urlResponseInfo) {
128 String httpStatusText, boolean wasCached, 118 mUrlResponseInfo = urlResponseInfo;
129 String negotiatedProtocol, String proxyServer) {
130 mResponseInfoUrlChain = urlChain;
131 mHttpStatusCode = httpStatusCode;
132 mHttpStatusText = httpStatusText;
133 mWasCached = wasCached;
134 mNegotiatedProtocol = negotiatedProtocol;
135 mProxyServer = proxyServer;
136 }
137
138 @Override
139 public String getUrl() {
140 return mResponseInfoUrlChain[mResponseInfoUrlChain.length - 1];
141 }
142
143 @Override
144 public String[] getUrlChain() {
145 return mResponseInfoUrlChain;
146 }
147
148 @Override
149 public int getHttpStatusCode() {
150 return mHttpStatusCode;
151 }
152
153 @Override
154 public String getHttpStatusText() {
155 return mHttpStatusText;
156 }
157
158 @Override
159 public List<Pair<String, String>> getAllHeadersAsList() {
160 if (mUnmodifiableAllHeaders == null) {
161 mUnmodifiableAllHeaders =
162 Collections.unmodifiableList(mAllHeaders);
163 }
164 return mUnmodifiableAllHeaders;
165 }
166
167 @Override
168 public Map<String, List<String>> getAllHeaders() {
169 if (mResponseHeaders != null) {
170 return mResponseHeaders;
171 }
172 Map<String, List<String>> map = new TreeMap<String, List<String>>(
173 String.CASE_INSENSITIVE_ORDER);
174 for (Pair<String, String> entry : mAllHeaders) {
175 List<String> values = new ArrayList<String>();
176 if (map.containsKey(entry.first)) {
177 values.addAll(map.get(entry.first));
178 }
179 values.add(entry.second);
180 map.put(entry.first, Collections.unmodifiableList(values));
181 }
182 mResponseHeaders = Collections.unmodifiableMap(map);
183 return mResponseHeaders;
184 }
185
186 @Override
187 public boolean wasCached() {
188 return mWasCached;
189 }
190
191 @Override
192 public String getNegotiatedProtocol() {
193 return mNegotiatedProtocol;
194 }
195
196 @Override
197 public String getProxyServer() {
198 return mProxyServer;
199 }
200 };
201
202 private static final class NativeExtendedResponseInfo implements ExtendedRes ponseInfo {
203 private final ResponseInfo mResponseInfo;
204 private final long mTotalReceivedBytes;
205
206 NativeExtendedResponseInfo(ResponseInfo responseInfo,
207 long totalReceivedBytes) {
208 mResponseInfo = responseInfo;
209 mTotalReceivedBytes = totalReceivedBytes;
210 } 119 }
211 120
212 @Override 121 @Override
213 public ResponseInfo getResponseInfo() { 122 public ResponseInfo getResponseInfo() {
214 return mResponseInfo; 123 return mUrlResponseInfo;
215 } 124 }
216 125
217 @Override 126 @Override
218 public long getTotalReceivedBytes() { 127 public long getTotalReceivedBytes() {
219 return mTotalReceivedBytes; 128 return mUrlResponseInfo.getReceivedBytesCount();
220 } 129 }
221 }; 130 };
222 131
223 CronetUrlRequest(CronetUrlRequestContext requestContext, 132 CronetUrlRequest(CronetUrlRequestContext requestContext,
224 long urlRequestContextAdapter, 133 long urlRequestContextAdapter,
225 String url, 134 String url,
226 int priority, 135 int priority,
227 UrlRequestListener listener, 136 UrlRequestListener listener,
228 Executor executor) { 137 Executor executor) {
229 if (url == null) { 138 if (url == null) {
(...skipping 25 matching lines...) Expand all
255 164
256 @Override 165 @Override
257 public void addHeader(String header, String value) { 166 public void addHeader(String header, String value) {
258 checkNotStarted(); 167 checkNotStarted();
259 if (header == null) { 168 if (header == null) {
260 throw new NullPointerException("Invalid header name."); 169 throw new NullPointerException("Invalid header name.");
261 } 170 }
262 if (value == null) { 171 if (value == null) {
263 throw new NullPointerException("Invalid header value."); 172 throw new NullPointerException("Invalid header value.");
264 } 173 }
265 mRequestHeaders.add(Pair.create(header, value)); 174 mRequestHeaders.add(new AbstractMap.SimpleImmutableEntry<String, String> (header, value));
266 } 175 }
267 176
268 @Override 177 @Override
269 public void setUploadDataProvider(UploadDataProvider uploadDataProvider, Exe cutor executor) { 178 public void setUploadDataProvider(UploadDataProvider uploadDataProvider, Exe cutor executor) {
270 if (uploadDataProvider == null) { 179 if (uploadDataProvider == null) {
271 throw new NullPointerException("Invalid UploadDataProvider."); 180 throw new NullPointerException("Invalid UploadDataProvider.");
272 } 181 }
273 if (mInitialMethod == null) { 182 if (mInitialMethod == null) {
274 mInitialMethod = "POST"; 183 mInitialMethod = "POST";
275 } 184 }
276 mUploadDataStream = new CronetUploadDataStream(uploadDataProvider, execu tor); 185 mUploadDataStream = new CronetUploadDataStream(uploadDataProvider, execu tor);
277 } 186 }
278 187
279 @Override 188 @Override
280 public void start() { 189 public void start() {
281 synchronized (mUrlRequestAdapterLock) { 190 synchronized (mUrlRequestAdapterLock) {
282 checkNotStarted(); 191 checkNotStarted();
283 192
284 try { 193 try {
285 mUrlRequestAdapter = nativeCreateRequestAdapter( 194 mUrlRequestAdapter = nativeCreateRequestAdapter(
286 mRequestContext.getUrlRequestContextAdapter(), mInitialU rl, mPriority); 195 mRequestContext.getUrlRequestContextAdapter(), mInitialU rl, mPriority);
287 mRequestContext.onRequestStarted(this); 196 mRequestContext.onRequestStarted(this);
288 if (mInitialMethod != null) { 197 if (mInitialMethod != null) {
289 if (!nativeSetHttpMethod(mUrlRequestAdapter, mInitialMethod) ) { 198 if (!nativeSetHttpMethod(mUrlRequestAdapter, mInitialMethod) ) {
290 throw new IllegalArgumentException("Invalid http method " + mInitialMethod); 199 throw new IllegalArgumentException("Invalid http method " + mInitialMethod);
291 } 200 }
292 } 201 }
293 202
294 boolean hasContentType = false; 203 boolean hasContentType = false;
295 for (Pair<String, String> header : mRequestHeaders) { 204 for (Map.Entry<String, String> header : mRequestHeaders) {
296 if (header.first.equalsIgnoreCase("Content-Type") 205 if (header.getKey().equalsIgnoreCase("Content-Type")
297 && !header.second.isEmpty()) { 206 && !header.getValue().isEmpty()) {
298 hasContentType = true; 207 hasContentType = true;
299 } 208 }
300 if (!nativeAddRequestHeader(mUrlRequestAdapter, header.first , header.second)) { 209 if (!nativeAddRequestHeader(
210 mUrlRequestAdapter, header.getKey(), header.getV alue())) {
xunjieli 2015/09/25 13:54:32 The more I looked at this, the more I think this i
mef 2015/09/25 15:58:27 Do you mean make 2 string arrays for keys and valu
xunjieli 2015/09/25 16:16:34 Since key and values are strings, We can use even
pauljensen 2015/09/25 18:30:16 So here's a great resource: https://docs.google.co
xunjieli 2015/09/25 18:39:13 Cool, thanks for the pointer.
301 destroyRequestAdapter(); 211 destroyRequestAdapter();
302 throw new IllegalArgumentException( 212 throw new IllegalArgumentException(
303 "Invalid header " + header.first + "=" + header. second); 213 "Invalid header " + header.getKey() + "=" + head er.getValue());
304 } 214 }
305 } 215 }
306 if (mUploadDataStream != null) { 216 if (mUploadDataStream != null) {
307 if (!hasContentType) { 217 if (!hasContentType) {
308 throw new IllegalArgumentException( 218 throw new IllegalArgumentException(
309 "Requests with upload data must have a Content-T ype."); 219 "Requests with upload data must have a Content-T ype.");
310 } 220 }
311 mUploadDataStream.attachToRequest(this, mUrlRequestAdapter); 221 mUploadDataStream.attachToRequest(this, mUrlRequestAdapter);
312 } 222 }
313 } catch (RuntimeException e) { 223 } catch (RuntimeException e) {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 return RequestPriority.LOW; 384 return RequestPriority.LOW;
475 case REQUEST_PRIORITY_MEDIUM: 385 case REQUEST_PRIORITY_MEDIUM:
476 return RequestPriority.MEDIUM; 386 return RequestPriority.MEDIUM;
477 case REQUEST_PRIORITY_HIGHEST: 387 case REQUEST_PRIORITY_HIGHEST:
478 return RequestPriority.HIGHEST; 388 return RequestPriority.HIGHEST;
479 default: 389 default:
480 return RequestPriority.MEDIUM; 390 return RequestPriority.MEDIUM;
481 } 391 }
482 } 392 }
483 393
484 private NativeResponseInfo prepareResponseInfoOnNetworkThread( 394 private UrlResponseInfo prepareResponseInfoOnNetworkThread(int httpStatusCod e) {
485 int httpStatusCode) {
486 long urlRequestAdapter; 395 long urlRequestAdapter;
487 synchronized (mUrlRequestAdapterLock) { 396 synchronized (mUrlRequestAdapterLock) {
488 if (mUrlRequestAdapter == 0) { 397 if (mUrlRequestAdapter == 0) {
489 return null; 398 return null;
490 } 399 }
491 // This method is running on network thread, so even if 400 // This method is running on network thread, so even if
492 // mUrlRequestAdapter is set to 0 from another thread the actual 401 // mUrlRequestAdapter is set to 0 from another thread the actual
493 // deletion of the adapter is posted to network thread, so it is 402 // deletion of the adapter is posted to network thread, so it is
494 // safe to preserve and use urlRequestAdapter outside the lock. 403 // safe to preserve and use urlRequestAdapter outside the lock.
495 urlRequestAdapter = mUrlRequestAdapter; 404 urlRequestAdapter = mUrlRequestAdapter;
496 } 405 }
497 NativeResponseInfo responseInfo = new NativeResponseInfo( 406 HeadersList headersList = new HeadersList();
498 mUrlChain.toArray(new String[mUrlChain.size()]), 407 nativePopulateResponseHeaders(urlRequestAdapter, headersList);
499 httpStatusCode, 408
500 nativeGetHttpStatusText(urlRequestAdapter), 409 UrlResponseInfo responseInfo = new UrlResponseInfo(new ArrayList<String> (mUrlChain),
410 httpStatusCode, nativeGetHttpStatusText(urlRequestAdapter), head ersList,
501 nativeGetWasCached(urlRequestAdapter), 411 nativeGetWasCached(urlRequestAdapter),
502 nativeGetNegotiatedProtocol(urlRequestAdapter), 412 nativeGetNegotiatedProtocol(urlRequestAdapter),
503 nativeGetProxyServer(urlRequestAdapter)); 413 nativeGetProxyServer(urlRequestAdapter));
504 nativePopulateResponseHeaders(urlRequestAdapter,
505 responseInfo.mAllHeaders);
506 return responseInfo; 414 return responseInfo;
507 } 415 }
508 416
509 private void checkNotStarted() { 417 private void checkNotStarted() {
510 synchronized (mUrlRequestAdapterLock) { 418 synchronized (mUrlRequestAdapterLock) {
511 if (mStarted || isDone()) { 419 if (mStarted || isDone()) {
512 throw new IllegalStateException("Request is already started."); 420 throw new IllegalStateException("Request is already started.");
513 } 421 }
514 } 422 }
515 } 423 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 * callback. If the redirect response has a body, it will be ignored. 507 * callback. If the redirect response has a body, it will be ignored.
600 * This will only be called between start and onResponseStarted. 508 * This will only be called between start and onResponseStarted.
601 * 509 *
602 * @param newLocation Location where request is redirected. 510 * @param newLocation Location where request is redirected.
603 * @param httpStatusCode from redirect response 511 * @param httpStatusCode from redirect response
604 */ 512 */
605 @SuppressWarnings("unused") 513 @SuppressWarnings("unused")
606 @CalledByNative 514 @CalledByNative
607 private void onReceivedRedirect(final String newLocation, 515 private void onReceivedRedirect(final String newLocation,
608 int httpStatusCode) { 516 int httpStatusCode) {
609 final NativeResponseInfo responseInfo = 517 final UrlResponseInfo responseInfo = prepareResponseInfoOnNetworkThread( httpStatusCode);
610 prepareResponseInfoOnNetworkThread(httpStatusCode);
611 // Have to do this after creating responseInfo. 518 // Have to do this after creating responseInfo.
612 mUrlChain.add(newLocation); 519 mUrlChain.add(newLocation);
613 520
614 Runnable task = new Runnable() { 521 Runnable task = new Runnable() {
615 public void run() { 522 public void run() {
616 synchronized (mUrlRequestAdapterLock) { 523 synchronized (mUrlRequestAdapterLock) {
617 if (isDone()) { 524 if (isDone()) {
618 return; 525 return;
619 } 526 }
620 mWaitingOnRedirect = true; 527 mWaitingOnRedirect = true;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 postTaskToExecutor(mOnReadCompletedTask); 601 postTaskToExecutor(mOnReadCompletedTask);
695 } 602 }
696 603
697 /** 604 /**
698 * Called when request is completed successfully, no callbacks will be 605 * Called when request is completed successfully, no callbacks will be
699 * called afterwards. 606 * called afterwards.
700 */ 607 */
701 @SuppressWarnings("unused") 608 @SuppressWarnings("unused")
702 @CalledByNative 609 @CalledByNative
703 private void onSucceeded(long totalReceivedBytes) { 610 private void onSucceeded(long totalReceivedBytes) {
704 final NativeExtendedResponseInfo extendedResponseInfo = 611 mResponseInfo.updateReceivedBytesCount(totalReceivedBytes);
705 new NativeExtendedResponseInfo(mResponseInfo, 612 final ExtendedUrlResponseInfo extendedResponseInfo =
706 totalReceivedBytes); 613 new ExtendedUrlResponseInfo(mResponseInfo);
707 Runnable task = new Runnable() { 614 Runnable task = new Runnable() {
708 public void run() { 615 public void run() {
709 synchronized (mUrlRequestAdapterLock) { 616 synchronized (mUrlRequestAdapterLock) {
710 if (isDone()) { 617 if (isDone()) {
711 return; 618 return;
712 } 619 }
713 // Destroy adapter first, so request context could be shut 620 // Destroy adapter first, so request context could be shut
714 // down from the listener. 621 // down from the listener.
715 destroyRequestAdapter(); 622 destroyRequestAdapter();
716 } 623 }
(...skipping 24 matching lines...) Expand all
741 failWithException(requestError); 648 failWithException(requestError);
742 } 649 }
743 650
744 /** 651 /**
745 * Appends header |name| with value |value| to |headersList|. 652 * Appends header |name| with value |value| to |headersList|.
746 */ 653 */
747 @SuppressWarnings("unused") 654 @SuppressWarnings("unused")
748 @CalledByNative 655 @CalledByNative
749 private void onAppendResponseHeader(HeadersList headersList, 656 private void onAppendResponseHeader(HeadersList headersList,
750 String name, String value) { 657 String name, String value) {
751 headersList.add(Pair.create(name, value)); 658 headersList.add(new AbstractMap.SimpleImmutableEntry<String, String>(nam e, value));
752 } 659 }
753 660
754 /** 661 /**
755 * Called by the native code when request status is fetched from the 662 * Called by the native code when request status is fetched from the
756 * native stack. 663 * native stack.
757 */ 664 */
758 @SuppressWarnings("unused") 665 @SuppressWarnings("unused")
759 @CalledByNative 666 @CalledByNative
760 private void onStatus(final UrlRequest.StatusListener listener, final int lo adState) { 667 private void onStatus(final UrlRequest.StatusListener listener, final int lo adState) {
761 Runnable task = new Runnable() { 668 Runnable task = new Runnable() {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 712
806 @NativeClassQualifiedName("CronetURLRequestAdapter") 713 @NativeClassQualifiedName("CronetURLRequestAdapter")
807 private native String nativeGetProxyServer(long nativePtr); 714 private native String nativeGetProxyServer(long nativePtr);
808 715
809 @NativeClassQualifiedName("CronetURLRequestAdapter") 716 @NativeClassQualifiedName("CronetURLRequestAdapter")
810 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener); 717 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene r listener);
811 718
812 @NativeClassQualifiedName("CronetURLRequestAdapter") 719 @NativeClassQualifiedName("CronetURLRequestAdapter")
813 private native boolean nativeGetWasCached(long nativePtr); 720 private native boolean nativeGetWasCached(long nativePtr);
814 } 721 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698