blob: adf2376c12d6a4b7e3480daaa72e74bffbc94e13 [file] [log] [blame]
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +09001/*
2 * Copyright (C) 2010 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 android.net;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.compat.annotation.UnsupportedAppUsage;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.text.TextUtils;
25
Chiachang Wangf1512902021-02-05 17:33:53 +080026import com.android.net.module.util.ProxyUtils;
27
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +090028import java.net.InetSocketAddress;
29import java.net.URLConnection;
30import java.util.List;
31import java.util.Locale;
32
33/**
34 * Describes a proxy configuration.
35 *
36 * Proxy configurations are already integrated within the {@code java.net} and
37 * Apache HTTP stack. So {@link URLConnection} and Apache's {@code HttpClient} will use
38 * them automatically.
39 *
Lorenzo Colitti9c0095c2021-03-18 13:07:37 +090040 * Other HTTP stacks will need to obtain the proxy info by watching for the
41 * {@link Proxy#PROXY_CHANGE_ACTION} broadcast and calling methods such as
42 * {@link android.net.ConnectivityManager#getDefaultProxy}.
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +090043 */
44public class ProxyInfo implements Parcelable {
45
46 private final String mHost;
47 private final int mPort;
48 private final String mExclusionList;
49 private final String[] mParsedExclusionList;
Aaron Huang9fe47be2021-06-08 13:11:45 +080050 // Uri.EMPTY if none.
51 @NonNull
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +090052 private final Uri mPacFileUrl;
53
54 /**
55 *@hide
56 */
57 public static final String LOCAL_EXCL_LIST = "";
58 /**
59 *@hide
60 */
61 public static final int LOCAL_PORT = -1;
62 /**
63 *@hide
64 */
65 public static final String LOCAL_HOST = "localhost";
66
67 /**
68 * Constructs a {@link ProxyInfo} object that points at a Direct proxy
69 * on the specified host and port.
70 */
71 public static ProxyInfo buildDirectProxy(String host, int port) {
72 return new ProxyInfo(host, port, null);
73 }
74
75 /**
76 * Constructs a {@link ProxyInfo} object that points at a Direct proxy
77 * on the specified host and port.
78 *
79 * The proxy will not be used to access any host in exclusion list, exclList.
80 *
81 * @param exclList Hosts to exclude using the proxy on connections for. These
82 * hosts can use wildcards such as *.example.com.
83 */
84 public static ProxyInfo buildDirectProxy(String host, int port, List<String> exclList) {
85 String[] array = exclList.toArray(new String[exclList.size()]);
86 return new ProxyInfo(host, port, TextUtils.join(",", array), array);
87 }
88
89 /**
90 * Construct a {@link ProxyInfo} that will download and run the PAC script
91 * at the specified URL.
92 */
93 public static ProxyInfo buildPacProxy(Uri pacUri) {
94 return new ProxyInfo(pacUri);
95 }
96
97 /**
98 * Construct a {@link ProxyInfo} object that will download and run the PAC script at the
99 * specified URL and port.
100 */
101 @NonNull
102 public static ProxyInfo buildPacProxy(@NonNull Uri pacUrl, int port) {
103 return new ProxyInfo(pacUrl, port);
104 }
105
106 /**
107 * Create a ProxyProperties that points at a HTTP Proxy.
108 * @hide
109 */
110 @UnsupportedAppUsage
111 public ProxyInfo(String host, int port, String exclList) {
112 mHost = host;
113 mPort = port;
114 mExclusionList = exclList;
115 mParsedExclusionList = parseExclusionList(mExclusionList);
116 mPacFileUrl = Uri.EMPTY;
117 }
118
119 /**
120 * Create a ProxyProperties that points at a PAC URL.
121 * @hide
122 */
123 public ProxyInfo(@NonNull Uri pacFileUrl) {
124 mHost = LOCAL_HOST;
125 mPort = LOCAL_PORT;
126 mExclusionList = LOCAL_EXCL_LIST;
127 mParsedExclusionList = parseExclusionList(mExclusionList);
128 if (pacFileUrl == null) {
129 throw new NullPointerException();
130 }
131 mPacFileUrl = pacFileUrl;
132 }
133
134 /**
Aaron Huanged0fe3e2021-01-18 15:28:01 +0800135 * Only used in PacProxyService after Local Proxy is bound.
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +0900136 * @hide
137 */
138 public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {
139 mHost = LOCAL_HOST;
140 mPort = localProxyPort;
141 mExclusionList = LOCAL_EXCL_LIST;
142 mParsedExclusionList = parseExclusionList(mExclusionList);
143 if (pacFileUrl == null) {
144 throw new NullPointerException();
145 }
146 mPacFileUrl = pacFileUrl;
147 }
148
149 private static String[] parseExclusionList(String exclusionList) {
150 if (exclusionList == null) {
151 return new String[0];
152 } else {
153 return exclusionList.toLowerCase(Locale.ROOT).split(",");
154 }
155 }
156
157 private ProxyInfo(String host, int port, String exclList, String[] parsedExclList) {
158 mHost = host;
159 mPort = port;
160 mExclusionList = exclList;
161 mParsedExclusionList = parsedExclList;
162 mPacFileUrl = Uri.EMPTY;
163 }
164
165 /**
166 * A copy constructor to hold proxy properties.
167 */
168 public ProxyInfo(@Nullable ProxyInfo source) {
169 if (source != null) {
170 mHost = source.getHost();
171 mPort = source.getPort();
172 mPacFileUrl = source.mPacFileUrl;
173 mExclusionList = source.getExclusionListAsString();
174 mParsedExclusionList = source.mParsedExclusionList;
175 } else {
176 mHost = null;
177 mPort = 0;
178 mExclusionList = null;
179 mParsedExclusionList = null;
180 mPacFileUrl = Uri.EMPTY;
181 }
182 }
183
184 /**
185 * @hide
186 */
187 public InetSocketAddress getSocketAddress() {
188 InetSocketAddress inetSocketAddress = null;
189 try {
190 inetSocketAddress = new InetSocketAddress(mHost, mPort);
191 } catch (IllegalArgumentException e) { }
192 return inetSocketAddress;
193 }
194
195 /**
196 * Returns the URL of the current PAC script or null if there is
197 * no PAC script.
198 */
199 public Uri getPacFileUrl() {
200 return mPacFileUrl;
201 }
202
203 /**
204 * When configured to use a Direct Proxy this returns the host
205 * of the proxy.
206 */
207 public String getHost() {
208 return mHost;
209 }
210
211 /**
212 * When configured to use a Direct Proxy this returns the port
213 * of the proxy
214 */
215 public int getPort() {
216 return mPort;
217 }
218
219 /**
220 * When configured to use a Direct Proxy this returns the list
221 * of hosts for which the proxy is ignored.
222 */
223 public String[] getExclusionList() {
224 return mParsedExclusionList;
225 }
226
227 /**
228 * comma separated
229 * @hide
230 */
231 @Nullable
232 public String getExclusionListAsString() {
233 return mExclusionList;
234 }
235
236 /**
237 * Return true if the pattern of proxy is valid, otherwise return false.
238 */
239 public boolean isValid() {
240 if (!Uri.EMPTY.equals(mPacFileUrl)) return true;
Chiachang Wangf1512902021-02-05 17:33:53 +0800241 return ProxyUtils.PROXY_VALID == ProxyUtils.validate(mHost == null ? "" : mHost,
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +0900242 mPort == 0 ? "" : Integer.toString(mPort),
243 mExclusionList == null ? "" : mExclusionList);
244 }
245
246 /**
247 * @hide
248 */
249 public java.net.Proxy makeProxy() {
250 java.net.Proxy proxy = java.net.Proxy.NO_PROXY;
251 if (mHost != null) {
252 try {
253 InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort);
254 proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress);
255 } catch (IllegalArgumentException e) {
256 }
257 }
258 return proxy;
259 }
260
Aaron Huang9fe47be2021-06-08 13:11:45 +0800261 /**
262 * @hide
263 * @return whether this proxy uses a Proxy Auto Configuration URL.
264 */
265 public boolean isPacProxy() {
266 return !Uri.EMPTY.equals(mPacFileUrl);
267 }
268
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +0900269 @Override
270 public String toString() {
271 StringBuilder sb = new StringBuilder();
272 if (!Uri.EMPTY.equals(mPacFileUrl)) {
273 sb.append("PAC Script: ");
274 sb.append(mPacFileUrl);
275 }
276 if (mHost != null) {
277 sb.append("[");
278 sb.append(mHost);
279 sb.append("] ");
280 sb.append(Integer.toString(mPort));
281 if (mExclusionList != null) {
282 sb.append(" xl=").append(mExclusionList);
283 }
284 } else {
285 sb.append("[ProxyProperties.mHost == null]");
286 }
287 return sb.toString();
288 }
289
290 @Override
Roman Kalukiewicz0b6f2902020-10-14 15:59:06 -0700291 public boolean equals(@Nullable Object o) {
Remi NGUYEN VANfbbccbc2021-01-15 18:08:24 +0900292 if (!(o instanceof ProxyInfo)) return false;
293 ProxyInfo p = (ProxyInfo)o;
294 // If PAC URL is present in either then they must be equal.
295 // Other parameters will only be for fall back.
296 if (!Uri.EMPTY.equals(mPacFileUrl)) {
297 return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort;
298 }
299 if (!Uri.EMPTY.equals(p.mPacFileUrl)) {
300 return false;
301 }
302 if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) {
303 return false;
304 }
305 if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) {
306 return false;
307 }
308 if (mHost != null && p.mHost == null) return false;
309 if (mHost == null && p.mHost != null) return false;
310 if (mPort != p.mPort) return false;
311 return true;
312 }
313
314 /**
315 * Implement the Parcelable interface
316 * @hide
317 */
318 public int describeContents() {
319 return 0;
320 }
321
322 @Override
323 /*
324 * generate hashcode based on significant fields
325 */
326 public int hashCode() {
327 return ((null == mHost) ? 0 : mHost.hashCode())
328 + ((null == mExclusionList) ? 0 : mExclusionList.hashCode())
329 + mPort;
330 }
331
332 /**
333 * Implement the Parcelable interface.
334 * @hide
335 */
336 public void writeToParcel(Parcel dest, int flags) {
337 if (!Uri.EMPTY.equals(mPacFileUrl)) {
338 dest.writeByte((byte)1);
339 mPacFileUrl.writeToParcel(dest, 0);
340 dest.writeInt(mPort);
341 return;
342 } else {
343 dest.writeByte((byte)0);
344 }
345 if (mHost != null) {
346 dest.writeByte((byte)1);
347 dest.writeString(mHost);
348 dest.writeInt(mPort);
349 } else {
350 dest.writeByte((byte)0);
351 }
352 dest.writeString(mExclusionList);
353 dest.writeStringArray(mParsedExclusionList);
354 }
355
356 public static final @android.annotation.NonNull Creator<ProxyInfo> CREATOR =
357 new Creator<ProxyInfo>() {
358 public ProxyInfo createFromParcel(Parcel in) {
359 String host = null;
360 int port = 0;
361 if (in.readByte() != 0) {
362 Uri url = Uri.CREATOR.createFromParcel(in);
363 int localPort = in.readInt();
364 return new ProxyInfo(url, localPort);
365 }
366 if (in.readByte() != 0) {
367 host = in.readString();
368 port = in.readInt();
369 }
370 String exclList = in.readString();
371 String[] parsedExclList = in.createStringArray();
372 ProxyInfo proxyProperties = new ProxyInfo(host, port, exclList, parsedExclList);
373 return proxyProperties;
374 }
375
376 public ProxyInfo[] newArray(int size) {
377 return new ProxyInfo[size];
378 }
379 };
380}