1 /*
2  * Copyright (C) 2023 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 android.adservices.utils;
18 
19 import android.content.Context;
20 import android.util.Log;
21 
22 import androidx.javascriptengine.JavaScriptSandbox;
23 
24 import com.android.adservices.shared.testing.SupportedByConditionRule;
25 
26 import java.util.Objects;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.TimeUnit;
29 import java.util.concurrent.TimeoutException;
30 
31 /**
32  * This class is only meant to be used in CTS tests. For unit tests use
33  * #com.android.adservices.common.WebViewSupportUtil.
34  */
35 public class CtsWebViewSupportUtil {
36 
37     private static final String TAG = "CtsWebViewSupportUtil";
38 
39     /**
40      * @return instance of SupportedByConditionRule which checks if Javascript Sandbox is available
41      */
createJSSandboxAvailableRule(Context context)42     public static SupportedByConditionRule createJSSandboxAvailableRule(Context context) {
43         Objects.requireNonNull(context);
44         return new SupportedByConditionRule(
45                 "JS Sandbox is not available", () -> isJSSandboxAvailable(context));
46     }
47 
48     /**
49      * @return instance of SupportedByConditionRule which checks if Javascript Sandbox supports WASM
50      *     for Fledge/Protected Audience
51      */
createWasmSupportAvailableRule(Context context)52     public static SupportedByConditionRule createWasmSupportAvailableRule(Context context) {
53         Objects.requireNonNull(context);
54         return new SupportedByConditionRule(
55                 "JS Sandbox does not support WASM", () -> isWasmSupportAvailable(context));
56     }
57 
58     /**
59      * @return instance of SupportedByConditionRule which checks if Javascript Sandbox supports
60      *     evaluate without transaction limit.
61      */
62     public static SupportedByConditionRule
createEvaluateWithoutTransactionLimitAvailableForFledgeRule(Context context)63             createEvaluateWithoutTransactionLimitAvailableForFledgeRule(Context context) {
64         Objects.requireNonNull(context);
65         return new SupportedByConditionRule(
66                 "JS Sandbox does not support evaluate without transaction limit",
67                 () -> isEvaluateWithoutTransactionLimitSupportAvailable(context));
68     }
69 
70     /**
71      * @return a boolean to indicate if Javascript sandbox is available.
72      */
isJSSandboxAvailable(Context context)73     public static boolean isJSSandboxAvailable(Context context) {
74         return checkFeatureInJavaScriptSandbox(
75                 context, JavaScriptSandbox.JS_FEATURE_ISOLATE_MAX_HEAP_SIZE);
76     }
77 
78     /**
79      * @return a boolean to indicate if Javascript sandbox supports WASM.
80      */
isWasmSupportAvailable(Context context)81     public static boolean isWasmSupportAvailable(Context context) {
82         return checkFeatureInJavaScriptSandbox(
83                 context, JavaScriptSandbox.JS_FEATURE_WASM_COMPILATION);
84     }
85 
86     /**
87      * @return a boolean to indicate if Javascript sandbox supports evaluate without transaction
88      *     limit.
89      */
isEvaluateWithoutTransactionLimitSupportAvailable(Context context)90     public static boolean isEvaluateWithoutTransactionLimitSupportAvailable(Context context) {
91         return checkFeatureInJavaScriptSandbox(
92                 context, JavaScriptSandbox.JS_FEATURE_EVALUATE_WITHOUT_TRANSACTION_LIMIT);
93     }
94 
checkFeatureInJavaScriptSandbox(Context context, String featureName)95     private static boolean checkFeatureInJavaScriptSandbox(Context context, String featureName) {
96         if (!JavaScriptSandbox.isSupported()) {
97             return false;
98         }
99         try {
100             JavaScriptSandbox javaScriptSandbox =
101                     JavaScriptSandbox.createConnectedInstanceAsync(context)
102                             .get(2, TimeUnit.SECONDS);
103             boolean result = javaScriptSandbox.isFeatureSupported(featureName);
104             javaScriptSandbox.close();
105             return result;
106         } catch (InterruptedException | ExecutionException | TimeoutException exception) {
107             Log.e(TAG, "Exception while trying to create JavaScriptSandbox", exception);
108         }
109         return false;
110     }
111 }
112