1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.webkit.internal; 18 19 import android.annotation.SuppressLint; 20 import android.webkit.WebResourceError; 21 22 import androidx.annotation.NonNull; 23 import androidx.annotation.RequiresApi; 24 import androidx.webkit.WebResourceErrorCompat; 25 import androidx.webkit.WebViewFeature; 26 27 import org.chromium.support_lib_boundary.WebResourceErrorBoundaryInterface; 28 import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil; 29 30 import java.lang.reflect.InvocationHandler; 31 import java.lang.reflect.Proxy; 32 33 /** 34 * Implementation of {@link WebResourceErrorCompat}. 35 * This class uses either the framework, the WebView APK, or both, to implement 36 * {@link WebResourceErrorCompat} functionality. 37 * 38 */ 39 public class WebResourceErrorImpl extends WebResourceErrorCompat { 40 /** 41 * Frameworks implementation - do not use this directly, instead use 42 * {@link #getFrameworksImpl()} to ensure this variable has been instantiated correctly. 43 */ 44 private WebResourceError mFrameworksImpl; 45 46 /** 47 * Support library glue implementation - do not use this directly, instead use 48 * {@link #getBoundaryInterface()} to ensure this variable has been instantiated correctly. 49 */ 50 private WebResourceErrorBoundaryInterface mBoundaryInterface; 51 52 public WebResourceErrorImpl(@NonNull InvocationHandler invocationHandler) { 53 mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass( 54 WebResourceErrorBoundaryInterface.class, invocationHandler); 55 } 56 57 public WebResourceErrorImpl(@NonNull WebResourceError error) { 58 mFrameworksImpl = error; 59 } 60 61 @RequiresApi(23) 62 private WebResourceError getFrameworksImpl() { 63 if (mFrameworksImpl == null) { 64 mFrameworksImpl = WebViewGlueCommunicator.getCompatConverter().convertWebResourceError( 65 Proxy.getInvocationHandler(mBoundaryInterface)); 66 } 67 return mFrameworksImpl; 68 } 69 70 private WebResourceErrorBoundaryInterface getBoundaryInterface() { 71 if (mBoundaryInterface == null) { 72 mBoundaryInterface = BoundaryInterfaceReflectionUtil.castToSuppLibClass( 73 WebResourceErrorBoundaryInterface.class, 74 WebViewGlueCommunicator.getCompatConverter().convertWebResourceError( 75 mFrameworksImpl)); 76 } 77 return mBoundaryInterface; 78 } 79 80 @SuppressLint("NewApi") 81 @Override 82 public int getErrorCode() { 83 final WebViewFeatureInternal feature = 84 WebViewFeatureInternal.getFeature(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE); 85 if (feature.isSupportedByFramework()) { 86 return getFrameworksImpl().getErrorCode(); 87 } else if (feature.isSupportedByWebView()) { 88 return getBoundaryInterface().getErrorCode(); 89 } else { 90 throw WebViewFeatureInternal.getUnsupportedOperationException(); 91 } 92 } 93 94 @SuppressLint("NewApi") 95 @Override 96 public CharSequence getDescription() { 97 final WebViewFeatureInternal feature = WebViewFeatureInternal.getFeature( 98 WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION); 99 if (feature.isSupportedByFramework()) { 100 return getFrameworksImpl().getDescription(); 101 } else if (feature.isSupportedByWebView()) { 102 return getBoundaryInterface().getDescription(); 103 } 104 throw WebViewFeatureInternal.getUnsupportedOperationException(); 105 } 106 } 107