1 // Copyright 2023 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 static org.chromium.net.impl.HttpEngineNativeProvider.EXT_API_LEVEL; 8 import static org.chromium.net.impl.HttpEngineNativeProvider.EXT_VERSION; 9 10 import android.net.http.HttpException; 11 12 import androidx.annotation.RequiresExtension; 13 14 import org.chromium.net.CronetException; 15 16 @RequiresExtension(extension = EXT_API_LEVEL, version = EXT_VERSION) 17 class CronetExceptionTranslationUtils { 18 @SuppressWarnings("unchecked") executeTranslatingCronetExceptions( CronetWork<T, E> work, Class<E> nonCronetException)19 public static <T, E extends Exception> T executeTranslatingCronetExceptions( 20 CronetWork<T, E> work, Class<E> nonCronetException) throws CronetException, E { 21 try { 22 return work.run(); 23 } catch (Exception e) { 24 if (isUncheckedAndroidCronetException(e)) { 25 throw translateUncheckedAndroidCronetException(e); 26 } else if (isCheckedAndroidCronetException(e)) { 27 throw translateCheckedAndroidCronetException(e); 28 } else if (nonCronetException.isInstance(e)) { 29 throw (E) e; 30 } else { 31 throw e; 32 } 33 } 34 } 35 isUncheckedAndroidCronetException(Exception e)36 public static boolean isUncheckedAndroidCronetException(Exception e) { 37 return (e instanceof android.net.http.InlineExecutionProhibitedException); 38 } 39 isCheckedAndroidCronetException(Exception e)40 public static boolean isCheckedAndroidCronetException(Exception e) { 41 return (e instanceof HttpException); 42 } 43 translateUncheckedAndroidCronetException(Exception e)44 public static RuntimeException translateUncheckedAndroidCronetException(Exception e) { 45 if (!isUncheckedAndroidCronetException(e)) { 46 throw new IllegalArgumentException("Not an Android Cronet exception", e); 47 } 48 49 if (e instanceof android.net.http.InlineExecutionProhibitedException) { 50 // InlineExecutionProhibitedException is final so we can't have our own flavor 51 org.chromium.net.InlineExecutionProhibitedException wrappedException = 52 new org.chromium.net.InlineExecutionProhibitedException(); 53 wrappedException.initCause(e); 54 return wrappedException; 55 } 56 57 throw new UnsupportedOperationException("Unchecked exception translation discrepancy", e); 58 } 59 translateCheckedAndroidCronetException(Exception e)60 public static CronetException translateCheckedAndroidCronetException(Exception e) { 61 if (!isCheckedAndroidCronetException(e)) { 62 throw new IllegalArgumentException("Not an Android Cronet exception", e); 63 } 64 65 if (e instanceof android.net.http.QuicException) { 66 return new AndroidQuicExceptionWrapper((android.net.http.QuicException) e); 67 } else if (e instanceof android.net.http.NetworkException) { 68 return new AndroidNetworkExceptionWrapper((android.net.http.NetworkException) e); 69 } else if (e instanceof android.net.http.CallbackException) { 70 return new AndroidCallbackExceptionWrapper((android.net.http.CallbackException) e); 71 } else if (e instanceof HttpException) { 72 return new AndroidHttpExceptionWrapper((HttpException) e); 73 } 74 75 throw new UnsupportedOperationException("Checked exception translation discrepancy", e); 76 } 77 78 interface CronetWork<T, E extends Exception> { run()79 T run() throws E; 80 } 81 CronetExceptionTranslationUtils()82 private CronetExceptionTranslationUtils() {} 83 } 84