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