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 androidx.webkit.WebViewRenderProcess; 20 21 import org.chromium.support_lib_boundary.WebViewRendererBoundaryInterface; 22 import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil; 23 import org.jspecify.annotations.NonNull; 24 25 import java.lang.ref.WeakReference; 26 import java.lang.reflect.InvocationHandler; 27 import java.util.WeakHashMap; 28 29 /** 30 * Implementation of {@link WebViewRenderProcess}. 31 * This class uses the framework's {@link android.webkit.WebViewRenderProcess} or the WebView APK to 32 * implement {@link WebViewRenderProcess} functionality. 33 */ 34 public class WebViewRenderProcessImpl extends WebViewRenderProcess { 35 private WebViewRendererBoundaryInterface mBoundaryInterface; 36 private WeakReference<android.webkit.WebViewRenderProcess> mFrameworkObject; 37 private static final WeakHashMap<android.webkit.WebViewRenderProcess, 38 WebViewRenderProcessImpl> sFrameworkMap = new WeakHashMap<>(); 39 WebViewRenderProcessImpl(@onNull WebViewRendererBoundaryInterface boundaryInterface)40 public WebViewRenderProcessImpl(@NonNull WebViewRendererBoundaryInterface boundaryInterface) { 41 mBoundaryInterface = boundaryInterface; 42 } 43 WebViewRenderProcessImpl( android.webkit.@onNull WebViewRenderProcess frameworkRenderer)44 public WebViewRenderProcessImpl( 45 android.webkit.@NonNull WebViewRenderProcess frameworkRenderer) { 46 mFrameworkObject = new WeakReference<>(frameworkRenderer); 47 } 48 49 /** 50 * Get a support library WebViewRenderProcess object that is 1:1 with the WebView object. 51 */ forInvocationHandler( @onNull InvocationHandler invocationHandler)52 public static @NonNull WebViewRenderProcessImpl forInvocationHandler( 53 @NonNull InvocationHandler invocationHandler) { 54 // Make a possibly temporary proxy object in order to call into WebView. 55 final WebViewRendererBoundaryInterface boundaryInterface = 56 BoundaryInterfaceReflectionUtil.castToSuppLibClass( 57 WebViewRendererBoundaryInterface.class, 58 invocationHandler); 59 60 // Ask WebView to either call us back to create the wrapper object, or 61 // to return a previously created wrapper object. 62 return (WebViewRenderProcessImpl) boundaryInterface.getOrCreatePeer( 63 () -> new WebViewRenderProcessImpl(boundaryInterface)); 64 } 65 66 /** 67 * Get a support library WebViewRenderProcess object that is 1:1 with the framework object. 68 */ forFrameworkObject( android.webkit.@onNull WebViewRenderProcess frameworkRenderer)69 public static @NonNull WebViewRenderProcessImpl forFrameworkObject( 70 android.webkit.@NonNull WebViewRenderProcess frameworkRenderer) { 71 WebViewRenderProcessImpl renderer = sFrameworkMap.get(frameworkRenderer); 72 if (renderer != null) { 73 return renderer; 74 } 75 renderer = new WebViewRenderProcessImpl(frameworkRenderer); 76 sFrameworkMap.put(frameworkRenderer, renderer); 77 return renderer; 78 } 79 80 @Override terminate()81 public boolean terminate() { 82 final ApiFeature.Q feature = WebViewFeatureInternal.WEB_VIEW_RENDERER_TERMINATE; 83 if (feature.isSupportedByFramework()) { 84 android.webkit.WebViewRenderProcess renderer = mFrameworkObject.get(); 85 return renderer != null && ApiHelperForQ.terminate(renderer); 86 } else if (feature.isSupportedByWebView()) { 87 return mBoundaryInterface.terminate(); 88 } else { 89 throw WebViewFeatureInternal.getUnsupportedOperationException(); 90 } 91 } 92 } 93