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 androidx.annotation.VisibleForTesting;
20 import androidx.webkit.ProxyConfig;
21 import androidx.webkit.ProxyConfig.ProxyRule;
22 import androidx.webkit.ProxyController;
23 
24 import org.chromium.support_lib_boundary.ProxyControllerBoundaryInterface;
25 import org.jspecify.annotations.NonNull;
26 
27 import java.util.List;
28 import java.util.concurrent.Executor;
29 
30 /**
31  * Implementation of {@link ProxyController}.
32  */
33 public class ProxyControllerImpl extends ProxyController {
34     private ProxyControllerBoundaryInterface mBoundaryInterface;
35 
36     @Override
setProxyOverride(@onNull ProxyConfig proxyConfig, @NonNull Executor executor, @NonNull Runnable listener)37     public void setProxyOverride(@NonNull ProxyConfig proxyConfig, @NonNull Executor executor,
38             @NonNull Runnable listener) {
39         ApiFeature.NoFramework proxyOverride = WebViewFeatureInternal.PROXY_OVERRIDE;
40         ApiFeature.NoFramework reverseBypass = WebViewFeatureInternal.PROXY_OVERRIDE_REVERSE_BYPASS;
41 
42         // A 2D String array representation is required by reflection
43         String[][] proxyRuleArray = proxyRulesToStringArray(proxyConfig.getProxyRules());
44         String[] bypassRuleArray = proxyConfig.getBypassRules().toArray(new String[0]);
45 
46         if (proxyOverride.isSupportedByWebView() && !proxyConfig.isReverseBypassEnabled()) {
47             getBoundaryInterface().setProxyOverride(
48                     proxyRuleArray, bypassRuleArray, listener, executor);
49         } else if (proxyOverride.isSupportedByWebView() && reverseBypass.isSupportedByWebView()) {
50             getBoundaryInterface().setProxyOverride(
51                     proxyRuleArray,
52                     bypassRuleArray,
53                     listener,
54                     executor,
55                     proxyConfig.isReverseBypassEnabled());
56         } else {
57             throw WebViewFeatureInternal.getUnsupportedOperationException();
58         }
59     }
60 
61     @Override
clearProxyOverride(@onNull Executor executor, @NonNull Runnable listener)62     public void clearProxyOverride(@NonNull Executor executor, @NonNull Runnable listener) {
63         ApiFeature.NoFramework feature = WebViewFeatureInternal.PROXY_OVERRIDE;
64         if (feature.isSupportedByWebView()) {
65             getBoundaryInterface().clearProxyOverride(listener, executor);
66         } else {
67             throw WebViewFeatureInternal.getUnsupportedOperationException();
68         }
69     }
70 
71     /**
72      * Converts a ProxyRule List into a String array.
73      */
74     @VisibleForTesting
proxyRulesToStringArray( @onNull List<ProxyRule> proxyRuleList)75     public static String @NonNull [][] proxyRulesToStringArray(
76             @NonNull List<ProxyRule> proxyRuleList) {
77         String[][] proxyRuleArray = new String[proxyRuleList.size()][2];
78         for (int i = 0; i < proxyRuleList.size(); i++) {
79             proxyRuleArray[i][0] = proxyRuleList.get(i).getSchemeFilter();
80             proxyRuleArray[i][1] = proxyRuleList.get(i).getUrl();
81         }
82         return proxyRuleArray;
83     }
84 
getBoundaryInterface()85     private ProxyControllerBoundaryInterface getBoundaryInterface() {
86         if (mBoundaryInterface == null) {
87             mBoundaryInterface = WebViewGlueCommunicator.getFactory().getProxyController();
88         }
89         return mBoundaryInterface;
90     }
91 }
92