blob: adf2376c12d6a4b7e3480daaa72e74bffbc94e13 [file] [log] [blame]
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001/*
Wink Saville17465432010-09-21 09:15:35 -07002 * Copyright (C) 2010 The Android Open Source Project
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07003 *
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
Aaron Huanga523b442019-10-02 23:37:02 +080019import android.annotation.NonNull;
20import android.annotation.Nullable;
Artur Satayev0e45d782019-12-10 17:47:52 +000021import android.compat.annotation.UnsupportedAppUsage;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070022import android.os.Parcel;
23import android.os.Parcelable;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -070024import android.text.TextUtils;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070025
Chiachang Wang0fcb9872021-02-05 17:33:53 +080026import com.android.net.module.util.ProxyUtils;
27
Robert Greenwalt98f45832010-09-03 13:02:05 -070028import java.net.InetSocketAddress;
Jason Monk1e3df5d2014-04-25 15:00:09 -040029import java.net.URLConnection;
30import java.util.List;
Elliott Hughes55478822013-08-02 10:00:44 -070031import java.util.Locale;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070032
33/**
Jason Monk1e3df5d2014-04-25 15:00:09 -040034 * Describes a proxy configuration.
35 *
Narayan Kamath439fe7b2014-11-27 18:17:35 +000036 * 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.
Jason Monk1e3df5d2014-04-25 15:00:09 -040039 *
Lorenzo Colittib612fb42021-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}.
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070043 */
Jason Monk1e3df5d2014-04-25 15:00:09 -040044public class ProxyInfo implements Parcelable {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070045
Irina Dumitrescu3a838842018-12-05 16:19:47 +000046 private final String mHost;
47 private final int mPort;
48 private final String mExclusionList;
49 private final String[] mParsedExclusionList;
Aaron Huang25ef1712021-06-08 13:11:45 +080050 // Uri.EMPTY if none.
51 @NonNull
Irina Dumitrescu3a838842018-12-05 16:19:47 +000052 private final Uri mPacFileUrl;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070053
Jason Monk1e3df5d2014-04-25 15:00:09 -040054 /**
55 *@hide
56 */
Jason Monk43324ee2013-07-03 17:04:33 -040057 public static final String LOCAL_EXCL_LIST = "";
Jason Monk1e3df5d2014-04-25 15:00:09 -040058 /**
59 *@hide
60 */
Jason Monkaf9ded02013-08-23 19:21:25 -040061 public static final int LOCAL_PORT = -1;
Jason Monk1e3df5d2014-04-25 15:00:09 -040062 /**
63 *@hide
64 */
Jason Monk43324ee2013-07-03 17:04:33 -040065 public static final String LOCAL_HOST = "localhost";
66
Jason Monk1e3df5d2014-04-25 15:00:09 -040067 /**
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) {
Jason Monk60a0e162014-05-09 15:16:06 -040094 return new ProxyInfo(pacUri);
Jason Monk1e3df5d2014-04-25 15:00:09 -040095 }
96
97 /**
Aaron Huanga523b442019-10-02 23:37:02 +080098 * 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 /**
Jason Monk1e3df5d2014-04-25 15:00:09 -0400107 * Create a ProxyProperties that points at a HTTP Proxy.
108 * @hide
109 */
Mathew Inwoodf34f05c2018-08-08 14:44:44 +0100110 @UnsupportedAppUsage
Jason Monk1e3df5d2014-04-25 15:00:09 -0400111 public ProxyInfo(String host, int port, String exclList) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700112 mHost = host;
113 mPort = port;
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000114 mExclusionList = exclList;
115 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk60a0e162014-05-09 15:16:06 -0400116 mPacFileUrl = Uri.EMPTY;
117 }
118
119 /**
120 * Create a ProxyProperties that points at a PAC URL.
121 * @hide
122 */
Aaron Huanga523b442019-10-02 23:37:02 +0800123 public ProxyInfo(@NonNull Uri pacFileUrl) {
Jason Monk60a0e162014-05-09 15:16:06 -0400124 mHost = LOCAL_HOST;
125 mPort = LOCAL_PORT;
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000126 mExclusionList = LOCAL_EXCL_LIST;
127 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk60a0e162014-05-09 15:16:06 -0400128 if (pacFileUrl == null) {
129 throw new NullPointerException();
130 }
131 mPacFileUrl = pacFileUrl;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700132 }
133
Jason Monk1e3df5d2014-04-25 15:00:09 -0400134 /**
Aaron Huangb2ad4a92021-01-18 15:28:01 +0800135 * Only used in PacProxyService after Local Proxy is bound.
Jason Monk1e3df5d2014-04-25 15:00:09 -0400136 * @hide
137 */
Aaron Huanga523b442019-10-02 23:37:02 +0800138 public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {
Jason Monkaf9ded02013-08-23 19:21:25 -0400139 mHost = LOCAL_HOST;
140 mPort = localProxyPort;
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000141 mExclusionList = LOCAL_EXCL_LIST;
142 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk60a0e162014-05-09 15:16:06 -0400143 if (pacFileUrl == null) {
144 throw new NullPointerException();
145 }
Jason Monkaf9ded02013-08-23 19:21:25 -0400146 mPacFileUrl = pacFileUrl;
147 }
148
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000149 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
Jason Monk1e3df5d2014-04-25 15:00:09 -0400157 private ProxyInfo(String host, int port, String exclList, String[] parsedExclList) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700158 mHost = host;
159 mPort = port;
160 mExclusionList = exclList;
161 mParsedExclusionList = parsedExclList;
Jason Monk60a0e162014-05-09 15:16:06 -0400162 mPacFileUrl = Uri.EMPTY;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700163 }
164
Jason Monk1e3df5d2014-04-25 15:00:09 -0400165 /**
Aaron Huanga523b442019-10-02 23:37:02 +0800166 * A copy constructor to hold proxy properties.
Jason Monk1e3df5d2014-04-25 15:00:09 -0400167 */
Aaron Huanga523b442019-10-02 23:37:02 +0800168 public ProxyInfo(@Nullable ProxyInfo source) {
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700169 if (source != null) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700170 mHost = source.getHost();
171 mPort = source.getPort();
Jason Monk1e3df5d2014-04-25 15:00:09 -0400172 mPacFileUrl = source.mPacFileUrl;
173 mExclusionList = source.getExclusionListAsString();
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700174 mParsedExclusionList = source.mParsedExclusionList;
Sreeram Ramachandran6e24ec72014-05-14 14:45:00 -0700175 } else {
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000176 mHost = null;
177 mPort = 0;
178 mExclusionList = null;
179 mParsedExclusionList = null;
Sreeram Ramachandran6e24ec72014-05-14 14:45:00 -0700180 mPacFileUrl = Uri.EMPTY;
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700181 }
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700182 }
183
Jason Monk1e3df5d2014-04-25 15:00:09 -0400184 /**
185 * @hide
186 */
Robert Greenwalt98f45832010-09-03 13:02:05 -0700187 public InetSocketAddress getSocketAddress() {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700188 InetSocketAddress inetSocketAddress = null;
189 try {
190 inetSocketAddress = new InetSocketAddress(mHost, mPort);
191 } catch (IllegalArgumentException e) { }
192 return inetSocketAddress;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700193 }
Andrew Stadlere55ada72010-08-31 14:28:58 -0700194
Jason Monk1e3df5d2014-04-25 15:00:09 -0400195 /**
196 * Returns the URL of the current PAC script or null if there is
197 * no PAC script.
198 */
199 public Uri getPacFileUrl() {
Jason Monk60a0e162014-05-09 15:16:06 -0400200 return mPacFileUrl;
Jason Monk43324ee2013-07-03 17:04:33 -0400201 }
202
Jason Monk1e3df5d2014-04-25 15:00:09 -0400203 /**
204 * When configured to use a Direct Proxy this returns the host
205 * of the proxy.
206 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700207 public String getHost() {
208 return mHost;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700209 }
210
Jason Monk1e3df5d2014-04-25 15:00:09 -0400211 /**
212 * When configured to use a Direct Proxy this returns the port
213 * of the proxy
214 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700215 public int getPort() {
216 return mPort;
217 }
218
Jason Monk1e3df5d2014-04-25 15:00:09 -0400219 /**
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 */
Aaron Huanga523b442019-10-02 23:37:02 +0800231 @Nullable
Jason Monk1e3df5d2014-04-25 15:00:09 -0400232 public String getExclusionListAsString() {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700233 return mExclusionList;
234 }
Andrew Stadlere55ada72010-08-31 14:28:58 -0700235
Jason Monk1e3df5d2014-04-25 15:00:09 -0400236 /**
Aaron Huanga523b442019-10-02 23:37:02 +0800237 * Return true if the pattern of proxy is valid, otherwise return false.
Jason Monk1e3df5d2014-04-25 15:00:09 -0400238 */
Raj Mamadgi08e512b2013-11-11 13:52:58 -0800239 public boolean isValid() {
Jason Monk60a0e162014-05-09 15:16:06 -0400240 if (!Uri.EMPTY.equals(mPacFileUrl)) return true;
Chiachang Wang0fcb9872021-02-05 17:33:53 +0800241 return ProxyUtils.PROXY_VALID == ProxyUtils.validate(mHost == null ? "" : mHost,
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000242 mPort == 0 ? "" : Integer.toString(mPort),
243 mExclusionList == null ? "" : mExclusionList);
Raj Mamadgi08e512b2013-11-11 13:52:58 -0800244 }
245
Jason Monk1e3df5d2014-04-25 15:00:09 -0400246 /**
247 * @hide
248 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700249 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;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700259 }
260
Aaron Huang25ef1712021-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
Wink Saville7d857902010-08-27 11:15:18 -0700269 @Override
270 public String toString() {
271 StringBuilder sb = new StringBuilder();
Jason Monk60a0e162014-05-09 15:16:06 -0400272 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monk43324ee2013-07-03 17:04:33 -0400273 sb.append("PAC Script: ");
274 sb.append(mPacFileUrl);
Paul Jensen12131352014-12-10 15:12:18 -0500275 }
276 if (mHost != null) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700277 sb.append("[");
278 sb.append(mHost);
279 sb.append("] ");
280 sb.append(Integer.toString(mPort));
Robert Greenwalte422ad92010-09-01 09:12:38 -0700281 if (mExclusionList != null) {
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000282 sb.append(" xl=").append(mExclusionList);
Robert Greenwalte422ad92010-09-01 09:12:38 -0700283 }
Wink Savillea7d56572011-09-21 11:05:43 -0700284 } else {
285 sb.append("[ProxyProperties.mHost == null]");
Robert Greenwalte422ad92010-09-01 09:12:38 -0700286 }
Wink Saville7d857902010-08-27 11:15:18 -0700287 return sb.toString();
288 }
289
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700290 @Override
Roman Kalukiewicz1f69a5e2020-10-14 15:59:06 -0700291 public boolean equals(@Nullable Object o) {
Jason Monk1e3df5d2014-04-25 15:00:09 -0400292 if (!(o instanceof ProxyInfo)) return false;
293 ProxyInfo p = (ProxyInfo)o;
Jason Monk43324ee2013-07-03 17:04:33 -0400294 // If PAC URL is present in either then they must be equal.
295 // Other parameters will only be for fall back.
Jason Monk60a0e162014-05-09 15:16:06 -0400296 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monk445cea82013-10-10 14:02:51 -0400297 return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort;
Jason Monk43324ee2013-07-03 17:04:33 -0400298 }
Jason Monk60a0e162014-05-09 15:16:06 -0400299 if (!Uri.EMPTY.equals(p.mPacFileUrl)) {
Jason Monk43324ee2013-07-03 17:04:33 -0400300 return false;
301 }
Jason Monk60a0e162014-05-09 15:16:06 -0400302 if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) {
303 return false;
304 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700305 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
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700314 /**
315 * Implement the Parcelable interface
316 * @hide
317 */
318 public int describeContents() {
319 return 0;
320 }
321
John Wang3e567d52011-04-04 12:35:42 -0700322 @Override
323 /*
324 * generate hashcode based on significant fields
325 */
326 public int hashCode() {
327 return ((null == mHost) ? 0 : mHost.hashCode())
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000328 + ((null == mExclusionList) ? 0 : mExclusionList.hashCode())
329 + mPort;
John Wang3e567d52011-04-04 12:35:42 -0700330 }
331
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700332 /**
333 * Implement the Parcelable interface.
334 * @hide
335 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700336 public void writeToParcel(Parcel dest, int flags) {
Jason Monk60a0e162014-05-09 15:16:06 -0400337 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monk43324ee2013-07-03 17:04:33 -0400338 dest.writeByte((byte)1);
Jason Monk60a0e162014-05-09 15:16:06 -0400339 mPacFileUrl.writeToParcel(dest, 0);
Jason Monk445cea82013-10-10 14:02:51 -0400340 dest.writeInt(mPort);
Jason Monk43324ee2013-07-03 17:04:33 -0400341 return;
342 } else {
343 dest.writeByte((byte)0);
344 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700345 if (mHost != null) {
Irfan Sheriff30bdeb32010-09-26 14:54:54 -0700346 dest.writeByte((byte)1);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700347 dest.writeString(mHost);
348 dest.writeInt(mPort);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700349 } else {
350 dest.writeByte((byte)0);
351 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700352 dest.writeString(mExclusionList);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700353 dest.writeStringArray(mParsedExclusionList);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700354 }
355
Jeff Sharkey9286f912019-02-28 12:06:45 -0700356 public static final @android.annotation.NonNull Creator<ProxyInfo> CREATOR =
Jason Monk1e3df5d2014-04-25 15:00:09 -0400357 new Creator<ProxyInfo>() {
358 public ProxyInfo createFromParcel(Parcel in) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700359 String host = null;
360 int port = 0;
Jason Monk43324ee2013-07-03 17:04:33 -0400361 if (in.readByte() != 0) {
Jason Monk60a0e162014-05-09 15:16:06 -0400362 Uri url = Uri.CREATOR.createFromParcel(in);
Jason Monk445cea82013-10-10 14:02:51 -0400363 int localPort = in.readInt();
Jason Monk1e3df5d2014-04-25 15:00:09 -0400364 return new ProxyInfo(url, localPort);
Jason Monk43324ee2013-07-03 17:04:33 -0400365 }
366 if (in.readByte() != 0) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700367 host = in.readString();
368 port = in.readInt();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700369 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700370 String exclList = in.readString();
lucaslincee43542021-01-25 11:01:57 +0800371 String[] parsedExclList = in.createStringArray();
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000372 ProxyInfo proxyProperties = new ProxyInfo(host, port, exclList, parsedExclList);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700373 return proxyProperties;
374 }
375
Jason Monk1e3df5d2014-04-25 15:00:09 -0400376 public ProxyInfo[] newArray(int size) {
377 return new ProxyInfo[size];
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700378 }
379 };
Andrew Stadlere55ada72010-08-31 14:28:58 -0700380}