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