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.content.Context;
20 import android.os.Build;
21 import android.webkit.ValueCallback;
22 import android.webkit.WebResourceRequest;
23 import android.webkit.WebSettings;
24 
25 import androidx.webkit.ServiceWorkerClientCompat;
26 import androidx.webkit.WebResourceRequestCompat;
27 import androidx.webkit.WebViewClientCompat;
28 import androidx.webkit.WebViewCompat;
29 import androidx.webkit.WebViewFeature;
30 import androidx.webkit.WebViewFeature.WebViewSupportFeature;
31 
32 import java.util.List;
33 
34 /**
35  * Enum representing a WebView feature, this provides functionality for determining whether a
36  * feature is supported by the current framework and/or WebView APK.
37  */
38 public enum WebViewFeatureInternal {
39     /**
40      * This feature covers
41      * {@link androidx.webkit.WebViewCompat#postVisualStateCallback(android.webkit.WebView, long,
42      * androidx.webkit.WebViewCompat.VisualStateCallback)}, and
43      * {@link WebViewClientCompat#onPageCommitVisible(android.webkit.WebView, String)}.
44      */
45     VISUAL_STATE_CALLBACK_FEATURE(WebViewFeature.VISUAL_STATE_CALLBACK, Build.VERSION_CODES.M),
46 
47     /**
48      * This feature covers
49      * {@link androidx.webkit.WebSettingsCompat#getOffscreenPreRaster(WebSettings)}, and
50      * {@link androidx.webkit.WebSettingsCompat#setOffscreenPreRaster(WebSettings, boolean)}.
51      */
52     OFF_SCREEN_PRERASTER(WebViewFeature.OFF_SCREEN_PRERASTER, Build.VERSION_CODES.M),
53 
54     /**
55      * This feature covers
56      * {@link androidx.webkit.WebSettingsCompat#getSafeBrowsingEnabled(WebSettings)}, and
57      * {@link androidx.webkit.WebSettingsCompat#setSafeBrowsingEnabled(WebSettings, boolean)}.
58      */
59     SAFE_BROWSING_ENABLE(WebViewFeature.SAFE_BROWSING_ENABLE, Build.VERSION_CODES.O),
60 
61     /**
62      * This feature covers
63      * {@link androidx.webkit.WebSettingsCompat#getDisabledActionModeMenuItems(WebSettings)}, and
64      * {@link androidx.webkit.WebSettingsCompat#setDisabledActionModeMenuItems(WebSettings, int)}.
65      */
66     DISABLED_ACTION_MODE_MENU_ITEMS(WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
67                                     Build.VERSION_CODES.N),
68 
69     /**
70      * This feature covers
71      * {@link androidx.webkit.WebViewCompat#startSafeBrowsing(Context, ValueCallback)}.
72      */
73     START_SAFE_BROWSING(WebViewFeature.START_SAFE_BROWSING, Build.VERSION_CODES.O_MR1),
74 
75     /**
76      * This feature covers
77      * {@link androidx.webkit.WebViewCompat#setSafeBrowsingWhitelist(List, ValueCallback)}.
78      */
79     SAFE_BROWSING_WHITELIST(WebViewFeature.SAFE_BROWSING_WHITELIST, Build.VERSION_CODES.O_MR1),
80 
81     /**
82      * This feature covers
83      * {@link WebViewCompat#getSafeBrowsingPrivacyPolicyUrl()}.
84      */
85     SAFE_BROWSING_PRIVACY_POLICY_URL(WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL,
86             Build.VERSION_CODES.O_MR1),
87 
88     /**
89      * This feature covers
90      * {@link androidx.webkit.ServiceWorkerControllerCompat#getInstance()}.
91      */
92     SERVICE_WORKER_BASIC_USAGE(WebViewFeature.SERVICE_WORKER_BASIC_USAGE, Build.VERSION_CODES.N),
93 
94     /**
95      * This feature covers
96      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getCacheMode()}, and
97      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setCacheMode(int)}.
98      */
99     SERVICE_WORKER_CACHE_MODE(WebViewFeature.SERVICE_WORKER_CACHE_MODE, Build.VERSION_CODES.N),
100 
101     /**
102      * This feature covers
103      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getAllowContentAccess()}, and
104      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setAllowContentAccess(boolean)}.
105      */
106     SERVICE_WORKER_CONTENT_ACCESS(WebViewFeature.SERVICE_WORKER_CONTENT_ACCESS,
107             Build.VERSION_CODES.N),
108 
109     /**
110      * This feature covers
111      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getAllowFileAccess()}, and
112      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setAllowFileAccess(boolean)}.
113      */
114     SERVICE_WORKER_FILE_ACCESS(WebViewFeature.SERVICE_WORKER_FILE_ACCESS, Build.VERSION_CODES.N),
115 
116     /**
117      * This feature covers
118      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#getBlockNetworkLoads()}, and
119      * {@link androidx.webkit.ServiceWorkerWebSettingsCompat#setBlockNetworkLoads(boolean)}.
120      */
121     SERVICE_WORKER_BLOCK_NETWORK_LOADS(WebViewFeature.SERVICE_WORKER_BLOCK_NETWORK_LOADS,
122             Build.VERSION_CODES.N),
123 
124     /**
125      * This feature covers
126      * {@link ServiceWorkerClientCompat#shouldInterceptRequest(WebResourceRequest)}.
127      */
128     SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST(WebViewFeature.SERVICE_WORKER_SHOULD_INTERCEPT_REQUEST,
129             Build.VERSION_CODES.N),
130 
131     /**
132      * This feature covers
133      * {@link WebViewClientCompat#onReceivedError(android.webkit.WebView, WebResourceRequest,
134      * WebResourceErrorCompat)}.
135      */
136     RECEIVE_WEB_RESOURCE_ERROR(WebViewFeature.RECEIVE_WEB_RESOURCE_ERROR, Build.VERSION_CODES.M),
137 
138     /**
139      * This feature covers
140      * {@link WebViewClientCompat#onReceivedHttpError(android.webkit.WebView, WebResourceRequest,
141      * WebResourceResponse)}.
142      */
143     RECEIVE_HTTP_ERROR(WebViewFeature.RECEIVE_HTTP_ERROR, Build.VERSION_CODES.M),
144 
145     /**
146      * This feature covers
147      * {@link WebViewClientCompat#shouldOverrideUrlLoading(android.webkit.WebView,
148      * WebResourceRequest)}.
149      */
150     SHOULD_OVERRIDE_WITH_REDIRECTS(WebViewFeature.SHOULD_OVERRIDE_WITH_REDIRECTS,
151             Build.VERSION_CODES.N),
152 
153     /**
154      * This feature covers
155      * {@link WebViewClientCompat#onSafeBrowsingHit(android.webkit.WebView,
156      * WebResourceRequest, int, SafeBrowsingResponseCompat)}.
157      */
158     SAFE_BROWSING_HIT(WebViewFeature.SAFE_BROWSING_HIT, Build.VERSION_CODES.O_MR1),
159 
160     /**
161      * This feature covers
162      * {@link WebResourceRequestCompat#isRedirect(WebResourceRequest)}.
163      */
164     WEB_RESOURCE_REQUEST_IS_REDIRECT(WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT,
165             Build.VERSION_CODES.N),
166 
167     /**
168      * This feature covers
169      * {@link WebResourceErrorCompat#getDescription()}.
170      */
171     WEB_RESOURCE_ERROR_GET_DESCRIPTION(WebViewFeature.WEB_RESOURCE_ERROR_GET_DESCRIPTION,
172             Build.VERSION_CODES.M),
173 
174     /**
175      * This feature covers
176      * {@link WebResourceErrorCompat#getErrorCode()}.
177      */
178     WEB_RESOURCE_ERROR_GET_CODE(WebViewFeature.WEB_RESOURCE_ERROR_GET_CODE,
179             Build.VERSION_CODES.M),
180 
181     /**
182      * This feature covers
183      * {@link SafeBrowsingResponseCompat#backToSafety(boolean)}.
184      */
185     SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY(WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
186             Build.VERSION_CODES.O_MR1),
187 
188     /**
189      * This feature covers
190      * {@link SafeBrowsingResponseCompat#proceed(boolean)}.
191      */
192     SAFE_BROWSING_RESPONSE_PROCEED(WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED,
193             Build.VERSION_CODES.O_MR1),
194 
195     /**
196      * This feature covers
197      * {@link SafeBrowsingResponseCompat#showInterstitial(boolean)}.
198      */
199     SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL(
200             WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL,
201             Build.VERSION_CODES.O_MR1);
202 
203     private final String mFeatureValue;
204     private final int mOsVersion;
205 
WebViewFeatureInternal(@ebViewSupportFeature String featureValue, int osVersion)206     WebViewFeatureInternal(@WebViewSupportFeature String featureValue, int osVersion) {
207         mFeatureValue = featureValue;
208         mOsVersion = osVersion;
209     }
210 
211     /**
212      * Return the {@link WebViewFeatureInternal} corresponding to {@param feature}.
213      */
getFeature(@ebViewSupportFeature String feature)214     public static WebViewFeatureInternal getFeature(@WebViewSupportFeature String feature) {
215         for (WebViewFeatureInternal internalFeature : WebViewFeatureInternal.values()) {
216             if (internalFeature.mFeatureValue.equals(feature)) return internalFeature;
217         }
218         throw new RuntimeException("Unknown feature " + feature);
219     }
220 
221     /**
222      * Return whether this {@link WebViewFeature} is supported by the framework of the current
223      * device.
224      */
isSupportedByFramework()225     public boolean isSupportedByFramework() {
226         return Build.VERSION.SDK_INT >= mOsVersion;
227     }
228 
229     /**
230      * Return whether this {@link WebViewFeature} is supported by the current WebView APK.
231      */
isSupportedByWebView()232     public boolean isSupportedByWebView() {
233         String[] webviewFeatures = LAZY_HOLDER.WEBVIEW_APK_FEATURES;
234         for (String webviewFeature : webviewFeatures) {
235             if (webviewFeature.equals(mFeatureValue)) return true;
236         }
237         return false;
238     }
239 
240     private static class LAZY_HOLDER {
241         static final String[] WEBVIEW_APK_FEATURES =
242                 WebViewGlueCommunicator.getFactory().getWebViewFeatures();
243     }
244 
245 
getWebViewApkFeaturesForTesting()246     public static String[] getWebViewApkFeaturesForTesting() {
247         return LAZY_HOLDER.WEBVIEW_APK_FEATURES;
248     }
249 
250     /**
251      * Utility method for throwing an exception explaining that the feature the app trying to use
252      * isn't supported.
253      */
getUnsupportedOperationException()254     public static UnsupportedOperationException getUnsupportedOperationException() {
255         return new UnsupportedOperationException("This method is not supported by the current "
256                 + "version of the framework and the current WebView APK");
257     }
258 }
259