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