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
17package androidx.webkit.internal;
18
19import android.content.Context;
20import android.os.Build;
21import android.webkit.ValueCallback;
22import android.webkit.WebResourceRequest;
23import android.webkit.WebSettings;
24
25import androidx.webkit.ServiceWorkerClientCompat;
26import androidx.webkit.WebResourceRequestCompat;
27import androidx.webkit.WebViewClientCompat;
28import androidx.webkit.WebViewCompat;
29import androidx.webkit.WebViewFeature;
30import androidx.webkit.WebViewFeature.WebViewSupportFeature;
31
32import 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 */
38public 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
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     */
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     */
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     */
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
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     */
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