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 androidx.annotation.AnyThread;
20 import androidx.annotation.RequiresFeature;
21 import androidx.annotation.RestrictTo;
22 import androidx.webkit.internal.ProxyControllerImpl;
23 
24 import org.jspecify.annotations.NonNull;
25 
26 import java.util.concurrent.Executor;
27 
28 /**
29  * Manages setting and clearing a process-specific override for the Android system-wide proxy
30  * settings that govern network requests made by {@link android.webkit.WebView}.
31  * <p>
32  * WebView may make network requests in order to fetch content that is not otherwise read from
33  * the file system or provided directly by application code. In this case by default the
34  * system-wide Android network proxy settings are used to redirect requests to appropriate proxy
35  * servers.
36  * <p>
37  * In the rare case that it is necessary for an application to explicitly specify its proxy
38  * configuration, this API may be used to explicitly specify the proxy rules that govern WebView
39  * initiated network requests.
40  *
41  * <p>
42  * Example usage:
43  * <pre class="prettyprint">
44  * ProxyConfig proxyConfig = new ProxyConfig.Builder().addProxyRule("myproxy.com")
45  *                                                    .addBypassRule("www.excluded.*")
46  *                                                    .build();
47  * Executor executor = ...
48  * Runnable listener = ...
49  * ProxyController.getInstance().setProxyOverride(proxyConfig, executor, listener);
50  * ...
51  * ProxyController.getInstance().clearProxyOverride(executor, listener);
52  * </pre>
53  */
54 @AnyThread
55 public abstract class ProxyController {
56     /**
57      */
58     @RestrictTo(RestrictTo.Scope.LIBRARY)
ProxyController()59     public ProxyController() {}
60 
61     /**
62      * Returns the {@link ProxyController} instance.
63      *
64      * <p>
65      * This method should only be called if {@link WebViewFeature#isFeatureSupported(String)}
66      * returns {@code true} for {@link WebViewFeature#PROXY_OVERRIDE}.
67      */
68     @RequiresFeature(name = WebViewFeature.PROXY_OVERRIDE,
69             enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
getInstance()70     public static @NonNull ProxyController getInstance() {
71         if (!WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {
72             throw new UnsupportedOperationException("Proxy override not supported");
73         }
74         return LAZY_HOLDER.INSTANCE;
75     }
76 
77     private static class LAZY_HOLDER {
78         static final ProxyController INSTANCE = new ProxyControllerImpl();
79     }
80 
81     /**
82      * Sets {@link ProxyConfig} which will be used by all WebViews in the app. URLs that match
83      * patterns in the bypass list will not be directed to any proxy. Instead, the request will be
84      * made directly to the origin specified by the URL. Network connections are not guaranteed to
85      * immediately use the new proxy setting; wait for the listener before loading a page. This
86      * listener will be called in the provided executor.
87      *
88      * <p class="note"><b>Note:</b> calling setProxyOverride will cause any existing system wide
89      * setting to be ignored.
90      *
91      * @param proxyConfig Proxy config to be applied
92      * @param executor Executor for the listener to be executed in
93      * @param listener Listener called when the proxy setting change has been applied
94      *
95      * @throws IllegalArgumentException If the proxyConfig is invalid
96      */
setProxyOverride(@onNull ProxyConfig proxyConfig, @NonNull Executor executor, @NonNull Runnable listener)97     public abstract void setProxyOverride(@NonNull ProxyConfig proxyConfig,
98             @NonNull Executor executor, @NonNull Runnable listener);
99 
100     /**
101      * Clears the proxy settings. Network connections are not guaranteed to immediately use the
102      * new proxy setting; wait for the listener before loading a page. This listener will be called
103      * in the provided executor.
104      *
105      * @param executor Executor for the listener to be executed in
106      * @param listener Listener called when the proxy setting change has been applied
107      */
clearProxyOverride(@onNull Executor executor, @NonNull Runnable listener)108     public abstract void clearProxyOverride(@NonNull Executor executor,
109             @NonNull Runnable listener);
110 }
111