OLD | NEW |
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 Loading... |
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 { | |
117 private final String[] mResponseInfoUrlChain; | |
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 | |
127 NativeResponseInfo(String[] urlChain, int httpStatusCode, | |
128 String httpStatusText, boolean wasCached, | |
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 } | |
211 | |
212 @Override | |
213 public ResponseInfo getResponseInfo() { | |
214 return mResponseInfo; | |
215 } | |
216 | |
217 @Override | |
218 public long getTotalReceivedBytes() { | |
219 return mTotalReceivedBytes; | |
220 } | |
221 }; | |
222 | |
223 CronetUrlRequest(CronetUrlRequestContext requestContext, | 114 CronetUrlRequest(CronetUrlRequestContext requestContext, |
224 long urlRequestContextAdapter, | 115 long urlRequestContextAdapter, |
225 String url, | 116 String url, |
226 int priority, | 117 int priority, |
227 UrlRequestListener listener, | 118 UrlRequestListener listener, |
228 Executor executor) { | 119 Executor executor) { |
229 if (url == null) { | 120 if (url == null) { |
230 throw new NullPointerException("URL is required"); | 121 throw new NullPointerException("URL is required"); |
231 } | 122 } |
232 if (listener == null) { | 123 if (listener == null) { |
(...skipping 22 matching lines...) Expand all Loading... |
255 | 146 |
256 @Override | 147 @Override |
257 public void addHeader(String header, String value) { | 148 public void addHeader(String header, String value) { |
258 checkNotStarted(); | 149 checkNotStarted(); |
259 if (header == null) { | 150 if (header == null) { |
260 throw new NullPointerException("Invalid header name."); | 151 throw new NullPointerException("Invalid header name."); |
261 } | 152 } |
262 if (value == null) { | 153 if (value == null) { |
263 throw new NullPointerException("Invalid header value."); | 154 throw new NullPointerException("Invalid header value."); |
264 } | 155 } |
265 mRequestHeaders.add(Pair.create(header, value)); | 156 mRequestHeaders.add(new AbstractMap.SimpleImmutableEntry<String, String>
(header, value)); |
266 } | 157 } |
267 | 158 |
268 @Override | 159 @Override |
269 public void setUploadDataProvider(UploadDataProvider uploadDataProvider, Exe
cutor executor) { | 160 public void setUploadDataProvider(UploadDataProvider uploadDataProvider, Exe
cutor executor) { |
270 if (uploadDataProvider == null) { | 161 if (uploadDataProvider == null) { |
271 throw new NullPointerException("Invalid UploadDataProvider."); | 162 throw new NullPointerException("Invalid UploadDataProvider."); |
272 } | 163 } |
273 if (mInitialMethod == null) { | 164 if (mInitialMethod == null) { |
274 mInitialMethod = "POST"; | 165 mInitialMethod = "POST"; |
275 } | 166 } |
276 mUploadDataStream = new CronetUploadDataStream(uploadDataProvider, execu
tor); | 167 mUploadDataStream = new CronetUploadDataStream(uploadDataProvider, execu
tor); |
277 } | 168 } |
278 | 169 |
279 @Override | 170 @Override |
280 public void start() { | 171 public void start() { |
281 synchronized (mUrlRequestAdapterLock) { | 172 synchronized (mUrlRequestAdapterLock) { |
282 checkNotStarted(); | 173 checkNotStarted(); |
283 | 174 |
284 try { | 175 try { |
285 mUrlRequestAdapter = nativeCreateRequestAdapter( | 176 mUrlRequestAdapter = nativeCreateRequestAdapter( |
286 mRequestContext.getUrlRequestContextAdapter(), mInitialU
rl, mPriority); | 177 mRequestContext.getUrlRequestContextAdapter(), mInitialU
rl, mPriority); |
287 mRequestContext.onRequestStarted(this); | 178 mRequestContext.onRequestStarted(this); |
288 if (mInitialMethod != null) { | 179 if (mInitialMethod != null) { |
289 if (!nativeSetHttpMethod(mUrlRequestAdapter, mInitialMethod)
) { | 180 if (!nativeSetHttpMethod(mUrlRequestAdapter, mInitialMethod)
) { |
290 throw new IllegalArgumentException("Invalid http method
" + mInitialMethod); | 181 throw new IllegalArgumentException("Invalid http method
" + mInitialMethod); |
291 } | 182 } |
292 } | 183 } |
293 | 184 |
294 boolean hasContentType = false; | 185 boolean hasContentType = false; |
295 for (Pair<String, String> header : mRequestHeaders) { | 186 for (Map.Entry<String, String> header : mRequestHeaders) { |
296 if (header.first.equalsIgnoreCase("Content-Type") | 187 if (header.getKey().equalsIgnoreCase("Content-Type") |
297 && !header.second.isEmpty()) { | 188 && !header.getValue().isEmpty()) { |
298 hasContentType = true; | 189 hasContentType = true; |
299 } | 190 } |
300 if (!nativeAddRequestHeader(mUrlRequestAdapter, header.first
, header.second)) { | 191 if (!nativeAddRequestHeader( |
| 192 mUrlRequestAdapter, header.getKey(), header.getV
alue())) { |
301 destroyRequestAdapter(); | 193 destroyRequestAdapter(); |
302 throw new IllegalArgumentException( | 194 throw new IllegalArgumentException( |
303 "Invalid header " + header.first + "=" + header.
second); | 195 "Invalid header " + header.getKey() + "=" + head
er.getValue()); |
304 } | 196 } |
305 } | 197 } |
306 if (mUploadDataStream != null) { | 198 if (mUploadDataStream != null) { |
307 if (!hasContentType) { | 199 if (!hasContentType) { |
308 throw new IllegalArgumentException( | 200 throw new IllegalArgumentException( |
309 "Requests with upload data must have a Content-T
ype."); | 201 "Requests with upload data must have a Content-T
ype."); |
310 } | 202 } |
311 mUploadDataStream.attachToRequest(this, mUrlRequestAdapter); | 203 mUploadDataStream.attachToRequest(this, mUrlRequestAdapter); |
312 } | 204 } |
313 } catch (RuntimeException e) { | 205 } catch (RuntimeException e) { |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 return RequestPriority.LOW; | 366 return RequestPriority.LOW; |
475 case Builder.REQUEST_PRIORITY_MEDIUM: | 367 case Builder.REQUEST_PRIORITY_MEDIUM: |
476 return RequestPriority.MEDIUM; | 368 return RequestPriority.MEDIUM; |
477 case Builder.REQUEST_PRIORITY_HIGHEST: | 369 case Builder.REQUEST_PRIORITY_HIGHEST: |
478 return RequestPriority.HIGHEST; | 370 return RequestPriority.HIGHEST; |
479 default: | 371 default: |
480 return RequestPriority.MEDIUM; | 372 return RequestPriority.MEDIUM; |
481 } | 373 } |
482 } | 374 } |
483 | 375 |
484 private NativeResponseInfo prepareResponseInfoOnNetworkThread( | 376 private UrlResponseInfo prepareResponseInfoOnNetworkThread(int httpStatusCod
e) { |
485 int httpStatusCode) { | |
486 long urlRequestAdapter; | 377 long urlRequestAdapter; |
487 synchronized (mUrlRequestAdapterLock) { | 378 synchronized (mUrlRequestAdapterLock) { |
488 if (mUrlRequestAdapter == 0) { | 379 if (mUrlRequestAdapter == 0) { |
489 return null; | 380 return null; |
490 } | 381 } |
491 // This method is running on network thread, so even if | 382 // This method is running on network thread, so even if |
492 // mUrlRequestAdapter is set to 0 from another thread the actual | 383 // mUrlRequestAdapter is set to 0 from another thread the actual |
493 // deletion of the adapter is posted to network thread, so it is | 384 // deletion of the adapter is posted to network thread, so it is |
494 // safe to preserve and use urlRequestAdapter outside the lock. | 385 // safe to preserve and use urlRequestAdapter outside the lock. |
495 urlRequestAdapter = mUrlRequestAdapter; | 386 urlRequestAdapter = mUrlRequestAdapter; |
496 } | 387 } |
497 NativeResponseInfo responseInfo = new NativeResponseInfo( | 388 HeadersList headersList = new HeadersList(); |
498 mUrlChain.toArray(new String[mUrlChain.size()]), | 389 nativePopulateResponseHeaders(urlRequestAdapter, headersList); |
499 httpStatusCode, | 390 |
500 nativeGetHttpStatusText(urlRequestAdapter), | 391 UrlResponseInfo responseInfo = new UrlResponseInfo(new ArrayList<String>
(mUrlChain), |
| 392 httpStatusCode, nativeGetHttpStatusText(urlRequestAdapter), head
ersList, |
501 nativeGetWasCached(urlRequestAdapter), | 393 nativeGetWasCached(urlRequestAdapter), |
502 nativeGetNegotiatedProtocol(urlRequestAdapter), | 394 nativeGetNegotiatedProtocol(urlRequestAdapter), |
503 nativeGetProxyServer(urlRequestAdapter)); | 395 nativeGetProxyServer(urlRequestAdapter)); |
504 nativePopulateResponseHeaders(urlRequestAdapter, | |
505 responseInfo.mAllHeaders); | |
506 return responseInfo; | 396 return responseInfo; |
507 } | 397 } |
508 | 398 |
509 private void checkNotStarted() { | 399 private void checkNotStarted() { |
510 synchronized (mUrlRequestAdapterLock) { | 400 synchronized (mUrlRequestAdapterLock) { |
511 if (mStarted || isDone()) { | 401 if (mStarted || isDone()) { |
512 throw new IllegalStateException("Request is already started."); | 402 throw new IllegalStateException("Request is already started."); |
513 } | 403 } |
514 } | 404 } |
515 } | 405 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 * callback. If the redirect response has a body, it will be ignored. | 489 * callback. If the redirect response has a body, it will be ignored. |
600 * This will only be called between start and onResponseStarted. | 490 * This will only be called between start and onResponseStarted. |
601 * | 491 * |
602 * @param newLocation Location where request is redirected. | 492 * @param newLocation Location where request is redirected. |
603 * @param httpStatusCode from redirect response | 493 * @param httpStatusCode from redirect response |
604 */ | 494 */ |
605 @SuppressWarnings("unused") | 495 @SuppressWarnings("unused") |
606 @CalledByNative | 496 @CalledByNative |
607 private void onReceivedRedirect(final String newLocation, | 497 private void onReceivedRedirect(final String newLocation, |
608 int httpStatusCode) { | 498 int httpStatusCode) { |
609 final NativeResponseInfo responseInfo = | 499 final UrlResponseInfo responseInfo = prepareResponseInfoOnNetworkThread(
httpStatusCode); |
610 prepareResponseInfoOnNetworkThread(httpStatusCode); | |
611 // Have to do this after creating responseInfo. | 500 // Have to do this after creating responseInfo. |
612 mUrlChain.add(newLocation); | 501 mUrlChain.add(newLocation); |
613 | 502 |
614 Runnable task = new Runnable() { | 503 Runnable task = new Runnable() { |
615 public void run() { | 504 public void run() { |
616 synchronized (mUrlRequestAdapterLock) { | 505 synchronized (mUrlRequestAdapterLock) { |
617 if (isDone()) { | 506 if (isDone()) { |
618 return; | 507 return; |
619 } | 508 } |
620 mWaitingOnRedirect = true; | 509 mWaitingOnRedirect = true; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 postTaskToExecutor(mOnReadCompletedTask); | 583 postTaskToExecutor(mOnReadCompletedTask); |
695 } | 584 } |
696 | 585 |
697 /** | 586 /** |
698 * Called when request is completed successfully, no callbacks will be | 587 * Called when request is completed successfully, no callbacks will be |
699 * called afterwards. | 588 * called afterwards. |
700 */ | 589 */ |
701 @SuppressWarnings("unused") | 590 @SuppressWarnings("unused") |
702 @CalledByNative | 591 @CalledByNative |
703 private void onSucceeded(long totalReceivedBytes) { | 592 private void onSucceeded(long totalReceivedBytes) { |
704 final NativeExtendedResponseInfo extendedResponseInfo = | 593 mResponseInfo.setReceivedBytesCount(totalReceivedBytes); |
705 new NativeExtendedResponseInfo(mResponseInfo, | |
706 totalReceivedBytes); | |
707 Runnable task = new Runnable() { | 594 Runnable task = new Runnable() { |
708 public void run() { | 595 public void run() { |
709 synchronized (mUrlRequestAdapterLock) { | 596 synchronized (mUrlRequestAdapterLock) { |
710 if (isDone()) { | 597 if (isDone()) { |
711 return; | 598 return; |
712 } | 599 } |
713 // Destroy adapter first, so request context could be shut | 600 // Destroy adapter first, so request context could be shut |
714 // down from the listener. | 601 // down from the listener. |
715 destroyRequestAdapter(); | 602 destroyRequestAdapter(); |
716 } | 603 } |
717 try { | 604 try { |
718 mListener.onSucceeded(CronetUrlRequest.this, | 605 mListener.onSucceeded(CronetUrlRequest.this, mResponseInfo); |
719 extendedResponseInfo); | |
720 } catch (Exception e) { | 606 } catch (Exception e) { |
721 Log.e(CronetUrlRequestContext.LOG_TAG, | 607 Log.e(CronetUrlRequestContext.LOG_TAG, |
722 "Exception in onComplete method", e); | 608 "Exception in onComplete method", e); |
723 } | 609 } |
724 } | 610 } |
725 }; | 611 }; |
726 postTaskToExecutor(task); | 612 postTaskToExecutor(task); |
727 } | 613 } |
728 | 614 |
729 /** | 615 /** |
(...skipping 11 matching lines...) Expand all Loading... |
741 failWithException(requestError); | 627 failWithException(requestError); |
742 } | 628 } |
743 | 629 |
744 /** | 630 /** |
745 * Appends header |name| with value |value| to |headersList|. | 631 * Appends header |name| with value |value| to |headersList|. |
746 */ | 632 */ |
747 @SuppressWarnings("unused") | 633 @SuppressWarnings("unused") |
748 @CalledByNative | 634 @CalledByNative |
749 private void onAppendResponseHeader(HeadersList headersList, | 635 private void onAppendResponseHeader(HeadersList headersList, |
750 String name, String value) { | 636 String name, String value) { |
751 headersList.add(Pair.create(name, value)); | 637 headersList.add(new AbstractMap.SimpleImmutableEntry<String, String>(nam
e, value)); |
752 } | 638 } |
753 | 639 |
754 /** | 640 /** |
755 * Called by the native code when request status is fetched from the | 641 * Called by the native code when request status is fetched from the |
756 * native stack. | 642 * native stack. |
757 */ | 643 */ |
758 @SuppressWarnings("unused") | 644 @SuppressWarnings("unused") |
759 @CalledByNative | 645 @CalledByNative |
760 private void onStatus(final UrlRequest.StatusListener listener, final int lo
adState) { | 646 private void onStatus(final UrlRequest.StatusListener listener, final int lo
adState) { |
761 Runnable task = new Runnable() { | 647 Runnable task = new Runnable() { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 | 691 |
806 @NativeClassQualifiedName("CronetURLRequestAdapter") | 692 @NativeClassQualifiedName("CronetURLRequestAdapter") |
807 private native String nativeGetProxyServer(long nativePtr); | 693 private native String nativeGetProxyServer(long nativePtr); |
808 | 694 |
809 @NativeClassQualifiedName("CronetURLRequestAdapter") | 695 @NativeClassQualifiedName("CronetURLRequestAdapter") |
810 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene
r listener); | 696 private native void nativeGetStatus(long nativePtr, UrlRequest.StatusListene
r listener); |
811 | 697 |
812 @NativeClassQualifiedName("CronetURLRequestAdapter") | 698 @NativeClassQualifiedName("CronetURLRequestAdapter") |
813 private native boolean nativeGetWasCached(long nativePtr); | 699 private native boolean nativeGetWasCached(long nativePtr); |
814 } | 700 } |
OLD | NEW |