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;
18 
19 import android.webkit.SafeBrowsingResponse;
20 
21 import androidx.annotation.NonNull;
22 import androidx.annotation.RequiresApi;
23 import androidx.annotation.RequiresFeature;
24 import androidx.webkit.internal.WebViewFeatureInternal;
25 
26 import org.chromium.support_lib_boundary.SafeBrowsingResponseBoundaryInterface;
27 import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
28 
29 import java.lang.reflect.InvocationHandler;
30 
31 /**
32  * Compatibility version of {@link SafeBrowsingResponse}.
33  */
34 public abstract class SafeBrowsingResponseCompat {
35     /**
36      * Display the default interstitial.
37      *
38      * @param allowReporting {@code true} if the interstitial should show a reporting checkbox.
39      */
40     @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL,
41             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
showInterstitial(boolean allowReporting)42     public abstract void showInterstitial(boolean allowReporting);
43 
44     /**
45      * Act as if the user clicked "visit this unsafe site."
46      *
47      * @param report {@code true} to enable Safe Browsing reporting.
48      */
49     @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED,
50             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
proceed(boolean report)51     public abstract void proceed(boolean report);
52 
53     /**
54      * Act as if the user clicked "back to safety."
55      *
56      * @param report {@code true} to enable Safe Browsing reporting.
57      */
58     @RequiresFeature(name = WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY,
59             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
backToSafety(boolean report)60     public abstract void backToSafety(boolean report);
61 
62     /**
63      * This class cannot be created by applications. The support library should instantiate this
64      * with {@link #fromInvocationHandler} or {@link #fromSafeBrowsingResponse}.
65      */
SafeBrowsingResponseCompat()66     private SafeBrowsingResponseCompat() {
67     }
68 
69     /**
70      * Conversion helper to create a SafeBrowsingResponseCompat which delegates calls to {@param
71      * handler}. The InvocationHandler must be created by {@link
72      * BoundaryInterfaceReflectionUtil#createInvocationHandlerFor} using {@link
73      * SafeBrowsingResponseBoundaryInterface}.
74      *
75      * @param handler The InvocationHandler that chromium passed in the callback.
76      */
77     @NonNull
fromInvocationHandler( @onNull InvocationHandler handler)78     /* package */ static SafeBrowsingResponseCompat fromInvocationHandler(
79             @NonNull InvocationHandler handler) {
80         final SafeBrowsingResponseBoundaryInterface responseDelegate =
81                 BoundaryInterfaceReflectionUtil.castToSuppLibClass(
82                         SafeBrowsingResponseBoundaryInterface.class, handler);
83         return new SafeBrowsingResponseCompat() {
84             @Override
85             public void showInterstitial(boolean allowReporting) {
86                 final WebViewFeatureInternal webViewFeature =
87                         WebViewFeatureInternal.getFeature(
88                                 WebViewFeature.SAFE_BROWSING_RESPONSE_SHOW_INTERSTITIAL);
89                 if (!webViewFeature.isSupportedByWebView()) {
90                     throw WebViewFeatureInternal.getUnsupportedOperationException();
91                 }
92                 responseDelegate.showInterstitial(allowReporting);
93             }
94 
95             @Override
96             public void proceed(boolean report) {
97                 final WebViewFeatureInternal webViewFeature =
98                         WebViewFeatureInternal.getFeature(
99                                 WebViewFeature.SAFE_BROWSING_RESPONSE_PROCEED);
100                 if (!webViewFeature.isSupportedByWebView()) {
101                     throw WebViewFeatureInternal.getUnsupportedOperationException();
102                 }
103                 responseDelegate.proceed(report);
104             }
105 
106             @Override
107             public void backToSafety(boolean report) {
108                 final WebViewFeatureInternal webViewFeature =
109                         WebViewFeatureInternal.getFeature(
110                                 WebViewFeature.SAFE_BROWSING_RESPONSE_BACK_TO_SAFETY);
111                 if (!webViewFeature.isSupportedByWebView()) {
112                     throw WebViewFeatureInternal.getUnsupportedOperationException();
113                 }
114                 responseDelegate.backToSafety(report);
115             }
116         };
117     }
118 
119     /**
120      * Conversion helper to create a SafeBrowsingResponseCompat which delegates calls to {@param
121      * response}.
122      *
123      * @param response The SafeBrowsingResponse that chromium passed in the callback.
124      */
125     @NonNull
126     @RequiresApi(27)
127     /* package */ static SafeBrowsingResponseCompat fromSafeBrowsingResponse(
128             @NonNull final SafeBrowsingResponse response) {
129         // Frameworks support is implied by the API level.
130         return new SafeBrowsingResponseCompat() {
131             @Override
132             public void showInterstitial(boolean allowReporting) {
133                 response.showInterstitial(allowReporting);
134             }
135 
136             @Override
137             public void proceed(boolean report) {
138                 response.proceed(report);
139             }
140 
141             @Override
142             public void backToSafety(boolean report) {
143                 response.backToSafety(report);
144             }
145         };
146     }
147 }
148