1 /*
2  * Copyright 2022 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.net.Uri;
20 import android.os.Build;
21 import android.os.Handler;
22 import android.webkit.WebMessage;
23 import android.webkit.WebMessagePort;
24 import android.webkit.WebResourceError;
25 import android.webkit.WebSettings;
26 import android.webkit.WebView;
27 
28 import androidx.annotation.RequiresApi;
29 import androidx.webkit.WebMessageCompat;
30 import androidx.webkit.WebMessagePortCompat;
31 import androidx.webkit.WebViewCompat;
32 
33 import org.jspecify.annotations.NonNull;
34 import org.jspecify.annotations.Nullable;
35 
36 /**
37  * Utility class to use new APIs that were added in M (API level 23).
38  * These need to exist in a separate class so that Android framework can successfully verify
39  * classes without encountering the new APIs.
40  */
41 @RequiresApi(Build.VERSION_CODES.M)
42 public class ApiHelperForM {
ApiHelperForM()43     private ApiHelperForM() {
44     }
45 
46     /**
47      * @see WebMessagePort#postMessage(WebMessage)
48      */
postMessage(@onNull WebMessagePort webMessagePort, @NonNull WebMessage webMessage)49     public static void postMessage(@NonNull WebMessagePort webMessagePort,
50             @NonNull WebMessage webMessage) {
51         webMessagePort.postMessage(webMessage);
52     }
53 
54     /**
55      * @see WebMessagePort#close()
56      */
close(@onNull WebMessagePort webMessagePort)57     public static void close(@NonNull WebMessagePort webMessagePort) {
58         webMessagePort.close();
59     }
60 
61     /**
62      * Wraps the passed callback in the framework callback type to isolate new types in this class.
63      * @see WebMessagePort#setWebMessageCallback(WebMessagePort.WebMessageCallback)
64      */
setWebMessageCallback(@onNull WebMessagePort frameworksImpl, WebMessagePortCompat.@NonNull WebMessageCallbackCompat callback)65     public static void setWebMessageCallback(@NonNull WebMessagePort frameworksImpl,
66             WebMessagePortCompat.@NonNull WebMessageCallbackCompat callback) {
67         frameworksImpl.setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
68             @Override
69             public void onMessage(WebMessagePort port, WebMessage message) {
70                 callback.onMessage(new WebMessagePortImpl(port),
71                         WebMessagePortImpl.frameworkMessageToCompat(message));
72             }
73         });
74     }
75 
76     /**
77      * Calls
78      * {@link WebMessagePort#setWebMessageCallback(WebMessagePort.WebMessageCallback, Handler)}
79      * Wraps the passed callback in the framework callback type to isolate new types in this class.
80      */
setWebMessageCallback(@onNull WebMessagePort frameworksImpl, WebMessagePortCompat.@NonNull WebMessageCallbackCompat callback, @Nullable Handler handler)81     public static void setWebMessageCallback(@NonNull WebMessagePort frameworksImpl,
82             WebMessagePortCompat.@NonNull WebMessageCallbackCompat callback,
83             @Nullable Handler handler) {
84         frameworksImpl.setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
85             @Override
86             public void onMessage(WebMessagePort port, WebMessage message) {
87                 callback.onMessage(new WebMessagePortImpl(port),
88                         WebMessagePortImpl.frameworkMessageToCompat(message));
89             }
90         }, handler);
91     }
92 
93     /**
94      * @see WebMessage#WebMessage(String, WebMessagePort[])}  WebMessage
95      */
createWebMessage(@onNull WebMessageCompat message)96     public static @NonNull WebMessage createWebMessage(@NonNull WebMessageCompat message) {
97         return new WebMessage(message.getData(),
98                 WebMessagePortImpl.compatToPorts(message.getPorts()));
99     }
100 
101     /**
102      * @see WebMessageCompat#WebMessageCompat(String, WebMessagePortCompat[])
103      */
createWebMessageCompat(@onNull WebMessage webMessage)104     public static @NonNull WebMessageCompat createWebMessageCompat(@NonNull WebMessage webMessage) {
105         return new WebMessageCompat(webMessage.getData(),
106                 WebMessagePortImpl.portsToCompat(webMessage.getPorts()));
107     }
108 
109     /**
110      * @see WebResourceError#getErrorCode()
111      */
getErrorCode(@onNull WebResourceError webResourceError)112     public static int getErrorCode(@NonNull WebResourceError webResourceError) {
113         return webResourceError.getErrorCode();
114     }
115 
116 
117     /**
118      * @see WebResourceError#getDescription()
119      */
getDescription(@onNull WebResourceError webResourceError)120     public static @NonNull CharSequence getDescription(@NonNull WebResourceError webResourceError) {
121         return webResourceError.getDescription();
122     }
123 
124     /**
125      * @see WebSettings#setOffscreenPreRaster(boolean)
126      */
setOffscreenPreRaster(@onNull WebSettings webSettings, boolean b)127     public static void setOffscreenPreRaster(@NonNull WebSettings webSettings, boolean b) {
128         webSettings.setOffscreenPreRaster(b);
129     }
130 
131     /**
132      * @see WebSettings#getOffscreenPreRaster()
133      */
getOffscreenPreRaster(@onNull WebSettings webSettings)134     public static boolean getOffscreenPreRaster(@NonNull WebSettings webSettings) {
135         return webSettings.getOffscreenPreRaster();
136     }
137 
138     /**
139      * Wraps the passed callback in the framework callback type to isolate new types in this class.
140      * @see WebView#postVisualStateCallback(long, WebView.VisualStateCallback)
141      */
postVisualStateCallback(@onNull WebView webView, long requestId, final WebViewCompat.@NonNull VisualStateCallback callback)142     public static void postVisualStateCallback(@NonNull WebView webView, long requestId,
143             final WebViewCompat.@NonNull VisualStateCallback callback) {
144         webView.postVisualStateCallback(requestId, new WebView.VisualStateCallback() {
145             @Override
146             public void onComplete(long l) {
147                 callback.onComplete(l);
148             }
149         });
150     }
151 
152     /**
153      * @see WebView#postWebMessage(WebMessage, Uri)
154      */
postWebMessage(@onNull WebView webView, @NonNull WebMessage message, @NonNull Uri targetOrigin)155     public static void postWebMessage(@NonNull WebView webView, @NonNull WebMessage message,
156             @NonNull Uri targetOrigin) {
157         webView.postWebMessage(message, targetOrigin);
158     }
159 
160     /**
161      * @see WebView#createWebMessageChannel()
162      */
createWebMessageChannel(@onNull WebView webView)163     public static WebMessagePort @NonNull [] createWebMessageChannel(@NonNull WebView webView) {
164         return webView.createWebMessageChannel();
165     }
166 }
167