1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.net.impl; 6 7 import android.net.http.BidirectionalStream; 8 import android.net.http.HeaderBlock; 9 import android.net.http.HttpException; 10 import android.net.http.NetworkQualityRttListener; 11 import android.net.http.NetworkQualityThroughputListener; 12 import android.net.http.RequestFinishedInfo; 13 import android.net.http.UploadDataProvider; 14 import android.net.http.UploadDataSink; 15 import android.net.http.UrlRequest; 16 import android.net.http.UrlResponseInfo; 17 18 import java.io.IOException; 19 import java.nio.ByteBuffer; 20 import java.time.Instant; 21 import java.util.concurrent.Executor; 22 23 /** 24 * This class contains wrapper classes for all Cronet API callback/listener classes. These classes 25 * only permit callbacks that the version of the client API is known to support. For example, if 26 * version 2 of the API adds a callback onFoo() but the client API this class is implementing is 27 * version 1, these wrapper classes should not call {@code mWrappedCallback.onFoo()} and should 28 * instead silently drop the callback. 29 * 30 * When adding any callback wrapping here, be sure you add the proper version check. Only callbacks 31 * supported in all versions of the API should forgo a version check. 32 */ 33 public class VersionSafeCallbacks { 34 /** 35 * Wrap a {@link UrlRequest.Callback} in a version safe manner. 36 */ 37 public static final class UrlRequestCallback implements UrlRequest.Callback { 38 private final UrlRequest.Callback mWrappedCallback; 39 UrlRequestCallback(UrlRequest.Callback callback)40 public UrlRequestCallback(UrlRequest.Callback callback) { 41 mWrappedCallback = callback; 42 } 43 44 @Override onRedirectReceived( UrlRequest request, UrlResponseInfo info, String newLocationUrl)45 public void onRedirectReceived( 46 UrlRequest request, UrlResponseInfo info, String newLocationUrl) throws Exception { 47 mWrappedCallback.onRedirectReceived(request, info, newLocationUrl); 48 } 49 50 @Override onResponseStarted(UrlRequest request, UrlResponseInfo info)51 public void onResponseStarted(UrlRequest request, UrlResponseInfo info) throws Exception { 52 mWrappedCallback.onResponseStarted(request, info); 53 } 54 55 @Override onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer)56 public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) 57 throws Exception { 58 mWrappedCallback.onReadCompleted(request, info, byteBuffer); 59 } 60 61 @Override onSucceeded(UrlRequest request, UrlResponseInfo info)62 public void onSucceeded(UrlRequest request, UrlResponseInfo info) { 63 mWrappedCallback.onSucceeded(request, info); 64 } 65 66 @Override onFailed(UrlRequest request, UrlResponseInfo info, HttpException error)67 public void onFailed(UrlRequest request, UrlResponseInfo info, HttpException error) { 68 mWrappedCallback.onFailed(request, info, error); 69 } 70 71 @Override onCanceled(UrlRequest request, UrlResponseInfo info)72 public void onCanceled(UrlRequest request, UrlResponseInfo info) { 73 mWrappedCallback.onCanceled(request, info); 74 } 75 } 76 77 /** 78 * Wrap a {@link UrlRequest.StatusListener} in a version safe manner. 79 */ 80 public static final class UrlRequestStatusListener implements UrlRequest.StatusListener { 81 private final UrlRequest.StatusListener mWrappedListener; 82 UrlRequestStatusListener(UrlRequest.StatusListener listener)83 public UrlRequestStatusListener(UrlRequest.StatusListener listener) { 84 mWrappedListener = listener; 85 } 86 87 @Override onStatus(int status)88 public void onStatus(int status) { 89 mWrappedListener.onStatus(status); 90 } 91 } 92 93 /** 94 * Wrap a {@link BidirectionalStream.Callback} in a version safe manner. 95 */ 96 public static final class BidirectionalStreamCallback implements BidirectionalStream.Callback { 97 private final BidirectionalStream.Callback mWrappedCallback; 98 BidirectionalStreamCallback(BidirectionalStream.Callback callback)99 public BidirectionalStreamCallback(BidirectionalStream.Callback callback) { 100 mWrappedCallback = callback; 101 } 102 103 @Override onStreamReady(BidirectionalStream stream)104 public void onStreamReady(BidirectionalStream stream) { 105 mWrappedCallback.onStreamReady(stream); 106 } 107 108 @Override onResponseHeadersReceived(BidirectionalStream stream, UrlResponseInfo info)109 public void onResponseHeadersReceived(BidirectionalStream stream, UrlResponseInfo info) { 110 mWrappedCallback.onResponseHeadersReceived(stream, info); 111 } 112 113 @Override onReadCompleted(BidirectionalStream stream, UrlResponseInfo info, ByteBuffer buffer, boolean endOfStream)114 public void onReadCompleted(BidirectionalStream stream, UrlResponseInfo info, 115 ByteBuffer buffer, boolean endOfStream) { 116 mWrappedCallback.onReadCompleted(stream, info, buffer, endOfStream); 117 } 118 119 @Override onWriteCompleted(BidirectionalStream stream, UrlResponseInfo info, ByteBuffer buffer, boolean endOfStream)120 public void onWriteCompleted(BidirectionalStream stream, UrlResponseInfo info, 121 ByteBuffer buffer, boolean endOfStream) { 122 mWrappedCallback.onWriteCompleted(stream, info, buffer, endOfStream); 123 } 124 125 @Override onResponseTrailersReceived(BidirectionalStream stream, UrlResponseInfo info, HeaderBlock trailers)126 public void onResponseTrailersReceived(BidirectionalStream stream, UrlResponseInfo info, 127 HeaderBlock trailers) { 128 mWrappedCallback.onResponseTrailersReceived(stream, info, trailers); 129 } 130 131 @Override onSucceeded(BidirectionalStream stream, UrlResponseInfo info)132 public void onSucceeded(BidirectionalStream stream, UrlResponseInfo info) { 133 mWrappedCallback.onSucceeded(stream, info); 134 } 135 136 @Override onFailed( BidirectionalStream stream, UrlResponseInfo info, HttpException error)137 public void onFailed( 138 BidirectionalStream stream, UrlResponseInfo info, HttpException error) { 139 mWrappedCallback.onFailed(stream, info, error); 140 } 141 142 @Override onCanceled(BidirectionalStream stream, UrlResponseInfo info)143 public void onCanceled(BidirectionalStream stream, UrlResponseInfo info) { 144 mWrappedCallback.onCanceled(stream, info); 145 } 146 } 147 148 /** 149 * Wrap a {@link UploadDataProvider} in a version safe manner. 150 */ 151 public static final class UploadDataProviderWrapper extends UploadDataProvider { 152 private final UploadDataProvider mWrappedProvider; 153 UploadDataProviderWrapper(UploadDataProvider provider)154 public UploadDataProviderWrapper(UploadDataProvider provider) { 155 mWrappedProvider = provider; 156 } 157 158 @Override getLength()159 public long getLength() throws IOException { 160 return mWrappedProvider.getLength(); 161 } 162 163 @Override read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer)164 public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) throws IOException { 165 mWrappedProvider.read(uploadDataSink, byteBuffer); 166 } 167 168 @Override rewind(UploadDataSink uploadDataSink)169 public void rewind(UploadDataSink uploadDataSink) throws IOException { 170 mWrappedProvider.rewind(uploadDataSink); 171 } 172 173 @Override close()174 public void close() throws IOException { 175 mWrappedProvider.close(); 176 } 177 } 178 179 /** 180 * Wrap a {@link RequestFinishedInfo.Listener} in a version safe manner. 181 */ 182 public static final class RequestFinishedInfoListener extends RequestFinishedInfo.Listener { 183 private final RequestFinishedInfo.Listener mWrappedListener; 184 RequestFinishedInfoListener(RequestFinishedInfo.Listener listener)185 public RequestFinishedInfoListener(RequestFinishedInfo.Listener listener) { 186 super(listener.getExecutor()); 187 mWrappedListener = listener; 188 } 189 190 @Override onRequestFinished(RequestFinishedInfo requestInfo)191 public void onRequestFinished(RequestFinishedInfo requestInfo) { 192 mWrappedListener.onRequestFinished(requestInfo); 193 } 194 195 @Override getExecutor()196 public Executor getExecutor() { 197 return mWrappedListener.getExecutor(); 198 } 199 } 200 201 /** 202 * Wrap a {@link NetworkQualityRttListener} in a version safe manner. 203 * NOTE(pauljensen): Delegates equals() and hashCode() to wrapped listener to 204 * facilitate looking up by wrapped listener in an ArrayList.indexOf(). 205 */ 206 public static final class NetworkQualityRttListenerWrapper extends NetworkQualityRttListener { 207 private final NetworkQualityRttListener mWrappedListener; 208 NetworkQualityRttListenerWrapper(NetworkQualityRttListener listener)209 public NetworkQualityRttListenerWrapper(NetworkQualityRttListener listener) { 210 super(listener.getExecutor()); 211 mWrappedListener = listener; 212 } 213 214 @Override onRttObservation(int rttMs, Instant observationInstant, int source)215 public void onRttObservation(int rttMs, Instant observationInstant, int source) { 216 mWrappedListener.onRttObservation(rttMs, observationInstant, source); 217 } 218 219 @Override getExecutor()220 public Executor getExecutor() { 221 return mWrappedListener.getExecutor(); 222 } 223 224 @Override hashCode()225 public int hashCode() { 226 return mWrappedListener.hashCode(); 227 } 228 229 @Override equals(Object o)230 public boolean equals(Object o) { 231 if (o == null || !(o instanceof NetworkQualityRttListenerWrapper)) { 232 return false; 233 } 234 return mWrappedListener.equals(((NetworkQualityRttListenerWrapper) o).mWrappedListener); 235 } 236 } 237 238 /** 239 * Wrap a {@link NetworkQualityThroughputListener} in a version safe manner. 240 * NOTE(pauljensen): Delegates equals() and hashCode() to wrapped listener to 241 * facilitate looking up by wrapped listener in an ArrayList.indexOf(). 242 */ 243 public static final class NetworkQualityThroughputListenerWrapper 244 extends NetworkQualityThroughputListener { 245 private final NetworkQualityThroughputListener mWrappedListener; 246 NetworkQualityThroughputListenerWrapper(NetworkQualityThroughputListener listener)247 public NetworkQualityThroughputListenerWrapper(NetworkQualityThroughputListener listener) { 248 super(listener.getExecutor()); 249 mWrappedListener = listener; 250 } 251 252 @Override onThroughputObservation(int throughputKbps, Instant observationInstant, int source)253 public void onThroughputObservation(int throughputKbps, Instant observationInstant, int source) { 254 mWrappedListener.onThroughputObservation(throughputKbps, observationInstant, source); 255 } 256 257 @Override getExecutor()258 public Executor getExecutor() { 259 return mWrappedListener.getExecutor(); 260 } 261 262 @Override hashCode()263 public int hashCode() { 264 return mWrappedListener.hashCode(); 265 } 266 267 @Override equals(Object o)268 public boolean equals(Object o) { 269 if (o == null || !(o instanceof NetworkQualityThroughputListenerWrapper)) { 270 return false; 271 } 272 return mWrappedListener.equals( 273 ((NetworkQualityThroughputListenerWrapper) o).mWrappedListener); 274 } 275 } 276 } 277