blob: 0deda371f6b9e4d795abb378852e19290f4e7b54 [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;
50 private final Uri mPacFileUrl;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070051
Jason Monk1e3df5d2014-04-25 15:00:09 -040052 /**
53 *@hide
54 */
Jason Monk43324ee2013-07-03 17:04:33 -040055 public static final String LOCAL_EXCL_LIST = "";
Jason Monk1e3df5d2014-04-25 15:00:09 -040056 /**
57 *@hide
58 */
Jason Monkaf9ded02013-08-23 19:21:25 -040059 public static final int LOCAL_PORT = -1;
Jason Monk1e3df5d2014-04-25 15:00:09 -040060 /**
61 *@hide
62 */
Jason Monk43324ee2013-07-03 17:04:33 -040063 public static final String LOCAL_HOST = "localhost";
64
Jason Monk1e3df5d2014-04-25 15:00:09 -040065 /**
66 * Constructs a {@link ProxyInfo} object that points at a Direct proxy
67 * on the specified host and port.
68 */
69 public static ProxyInfo buildDirectProxy(String host, int port) {
70 return new ProxyInfo(host, port, null);
71 }
72
73 /**
74 * Constructs a {@link ProxyInfo} object that points at a Direct proxy
75 * on the specified host and port.
76 *
77 * The proxy will not be used to access any host in exclusion list, exclList.
78 *
79 * @param exclList Hosts to exclude using the proxy on connections for. These
80 * hosts can use wildcards such as *.example.com.
81 */
82 public static ProxyInfo buildDirectProxy(String host, int port, List<String> exclList) {
83 String[] array = exclList.toArray(new String[exclList.size()]);
84 return new ProxyInfo(host, port, TextUtils.join(",", array), array);
85 }
86
87 /**
88 * Construct a {@link ProxyInfo} that will download and run the PAC script
89 * at the specified URL.
90 */
91 public static ProxyInfo buildPacProxy(Uri pacUri) {
Jason Monk60a0e162014-05-09 15:16:06 -040092 return new ProxyInfo(pacUri);
Jason Monk1e3df5d2014-04-25 15:00:09 -040093 }
94
95 /**
Aaron Huanga523b442019-10-02 23:37:02 +080096 * Construct a {@link ProxyInfo} object that will download and run the PAC script at the
97 * specified URL and port.
98 */
99 @NonNull
100 public static ProxyInfo buildPacProxy(@NonNull Uri pacUrl, int port) {
101 return new ProxyInfo(pacUrl, port);
102 }
103
104 /**
Jason Monk1e3df5d2014-04-25 15:00:09 -0400105 * Create a ProxyProperties that points at a HTTP Proxy.
106 * @hide
107 */
Mathew Inwoodf34f05c2018-08-08 14:44:44 +0100108 @UnsupportedAppUsage
Jason Monk1e3df5d2014-04-25 15:00:09 -0400109 public ProxyInfo(String host, int port, String exclList) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700110 mHost = host;
111 mPort = port;
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000112 mExclusionList = exclList;
113 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk60a0e162014-05-09 15:16:06 -0400114 mPacFileUrl = Uri.EMPTY;
115 }
116
117 /**
118 * Create a ProxyProperties that points at a PAC URL.
119 * @hide
120 */
Aaron Huanga523b442019-10-02 23:37:02 +0800121 public ProxyInfo(@NonNull Uri pacFileUrl) {
Jason Monk60a0e162014-05-09 15:16:06 -0400122 mHost = LOCAL_HOST;
123 mPort = LOCAL_PORT;
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000124 mExclusionList = LOCAL_EXCL_LIST;
125 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk60a0e162014-05-09 15:16:06 -0400126 if (pacFileUrl == null) {
127 throw new NullPointerException();
128 }
129 mPacFileUrl = pacFileUrl;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700130 }
131
Jason Monk1e3df5d2014-04-25 15:00:09 -0400132 /**
Aaron Huangb2ad4a92021-01-18 15:28:01 +0800133 * Only used in PacProxyService after Local Proxy is bound.
Jason Monk1e3df5d2014-04-25 15:00:09 -0400134 * @hide
135 */
Aaron Huanga523b442019-10-02 23:37:02 +0800136 public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {
Jason Monkaf9ded02013-08-23 19:21:25 -0400137 mHost = LOCAL_HOST;
138 mPort = localProxyPort;
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000139 mExclusionList = LOCAL_EXCL_LIST;
140 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk60a0e162014-05-09 15:16:06 -0400141 if (pacFileUrl == null) {
142 throw new NullPointerException();
143 }
Jason Monkaf9ded02013-08-23 19:21:25 -0400144 mPacFileUrl = pacFileUrl;
145 }
146
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000147 private static String[] parseExclusionList(String exclusionList) {
148 if (exclusionList == null) {
149 return new String[0];
150 } else {
151 return exclusionList.toLowerCase(Locale.ROOT).split(",");
152 }
153 }
154
Jason Monk1e3df5d2014-04-25 15:00:09 -0400155 private ProxyInfo(String host, int port, String exclList, String[] parsedExclList) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700156 mHost = host;
157 mPort = port;
158 mExclusionList = exclList;
159 mParsedExclusionList = parsedExclList;
Jason Monk60a0e162014-05-09 15:16:06 -0400160 mPacFileUrl = Uri.EMPTY;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700161 }
162
Jason Monk1e3df5d2014-04-25 15:00:09 -0400163 /**
Aaron Huanga523b442019-10-02 23:37:02 +0800164 * A copy constructor to hold proxy properties.
Jason Monk1e3df5d2014-04-25 15:00:09 -0400165 */
Aaron Huanga523b442019-10-02 23:37:02 +0800166 public ProxyInfo(@Nullable ProxyInfo source) {
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700167 if (source != null) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700168 mHost = source.getHost();
169 mPort = source.getPort();
Jason Monk1e3df5d2014-04-25 15:00:09 -0400170 mPacFileUrl = source.mPacFileUrl;
171 mExclusionList = source.getExclusionListAsString();
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700172 mParsedExclusionList = source.mParsedExclusionList;
Sreeram Ramachandran6e24ec72014-05-14 14:45:00 -0700173 } else {
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000174 mHost = null;
175 mPort = 0;
176 mExclusionList = null;
177 mParsedExclusionList = null;
Sreeram Ramachandran6e24ec72014-05-14 14:45:00 -0700178 mPacFileUrl = Uri.EMPTY;
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700179 }
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700180 }
181
Jason Monk1e3df5d2014-04-25 15:00:09 -0400182 /**
183 * @hide
184 */
Robert Greenwalt98f45832010-09-03 13:02:05 -0700185 public InetSocketAddress getSocketAddress() {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700186 InetSocketAddress inetSocketAddress = null;
187 try {
188 inetSocketAddress = new InetSocketAddress(mHost, mPort);
189 } catch (IllegalArgumentException e) { }
190 return inetSocketAddress;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700191 }
Andrew Stadlere55ada72010-08-31 14:28:58 -0700192
Jason Monk1e3df5d2014-04-25 15:00:09 -0400193 /**
194 * Returns the URL of the current PAC script or null if there is
195 * no PAC script.
196 */
197 public Uri getPacFileUrl() {
Jason Monk60a0e162014-05-09 15:16:06 -0400198 return mPacFileUrl;
Jason Monk43324ee2013-07-03 17:04:33 -0400199 }
200
Jason Monk1e3df5d2014-04-25 15:00:09 -0400201 /**
202 * When configured to use a Direct Proxy this returns the host
203 * of the proxy.
204 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700205 public String getHost() {
206 return mHost;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700207 }
208
Jason Monk1e3df5d2014-04-25 15:00:09 -0400209 /**
210 * When configured to use a Direct Proxy this returns the port
211 * of the proxy
212 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700213 public int getPort() {
214 return mPort;
215 }
216
Jason Monk1e3df5d2014-04-25 15:00:09 -0400217 /**
218 * When configured to use a Direct Proxy this returns the list
219 * of hosts for which the proxy is ignored.
220 */
221 public String[] getExclusionList() {
222 return mParsedExclusionList;
223 }
224
225 /**
226 * comma separated
227 * @hide
228 */
Aaron Huanga523b442019-10-02 23:37:02 +0800229 @Nullable
Jason Monk1e3df5d2014-04-25 15:00:09 -0400230 public String getExclusionListAsString() {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700231 return mExclusionList;
232 }
Andrew Stadlere55ada72010-08-31 14:28:58 -0700233
Jason Monk1e3df5d2014-04-25 15:00:09 -0400234 /**
Aaron Huanga523b442019-10-02 23:37:02 +0800235 * Return true if the pattern of proxy is valid, otherwise return false.
Jason Monk1e3df5d2014-04-25 15:00:09 -0400236 */
Raj Mamadgi08e512b2013-11-11 13:52:58 -0800237 public boolean isValid() {
Jason Monk60a0e162014-05-09 15:16:06 -0400238 if (!Uri.EMPTY.equals(mPacFileUrl)) return true;
Chiachang Wang0fcb9872021-02-05 17:33:53 +0800239 return ProxyUtils.PROXY_VALID == ProxyUtils.validate(mHost == null ? "" : mHost,
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000240 mPort == 0 ? "" : Integer.toString(mPort),
241 mExclusionList == null ? "" : mExclusionList);
Raj Mamadgi08e512b2013-11-11 13:52:58 -0800242 }
243
Jason Monk1e3df5d2014-04-25 15:00:09 -0400244 /**
245 * @hide
246 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700247 public java.net.Proxy makeProxy() {
248 java.net.Proxy proxy = java.net.Proxy.NO_PROXY;
249 if (mHost != null) {
250 try {
251 InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort);
252 proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress);
253 } catch (IllegalArgumentException e) {
254 }
255 }
256 return proxy;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700257 }
258
Wink Saville7d857902010-08-27 11:15:18 -0700259 @Override
260 public String toString() {
261 StringBuilder sb = new StringBuilder();
Jason Monk60a0e162014-05-09 15:16:06 -0400262 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monk43324ee2013-07-03 17:04:33 -0400263 sb.append("PAC Script: ");
264 sb.append(mPacFileUrl);
Paul Jensen12131352014-12-10 15:12:18 -0500265 }
266 if (mHost != null) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700267 sb.append("[");
268 sb.append(mHost);
269 sb.append("] ");
270 sb.append(Integer.toString(mPort));
Robert Greenwalte422ad92010-09-01 09:12:38 -0700271 if (mExclusionList != null) {
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000272 sb.append(" xl=").append(mExclusionList);
Robert Greenwalte422ad92010-09-01 09:12:38 -0700273 }
Wink Savillea7d56572011-09-21 11:05:43 -0700274 } else {
275 sb.append("[ProxyProperties.mHost == null]");
Robert Greenwalte422ad92010-09-01 09:12:38 -0700276 }
Wink Saville7d857902010-08-27 11:15:18 -0700277 return sb.toString();
278 }
279
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700280 @Override
Roman Kalukiewicz1f69a5e2020-10-14 15:59:06 -0700281 public boolean equals(@Nullable Object o) {
Jason Monk1e3df5d2014-04-25 15:00:09 -0400282 if (!(o instanceof ProxyInfo)) return false;
283 ProxyInfo p = (ProxyInfo)o;
Jason Monk43324ee2013-07-03 17:04:33 -0400284 // If PAC URL is present in either then they must be equal.
285 // Other parameters will only be for fall back.
Jason Monk60a0e162014-05-09 15:16:06 -0400286 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monk445cea82013-10-10 14:02:51 -0400287 return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort;
Jason Monk43324ee2013-07-03 17:04:33 -0400288 }
Jason Monk60a0e162014-05-09 15:16:06 -0400289 if (!Uri.EMPTY.equals(p.mPacFileUrl)) {
Jason Monk43324ee2013-07-03 17:04:33 -0400290 return false;
291 }
Jason Monk60a0e162014-05-09 15:16:06 -0400292 if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) {
293 return false;
294 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700295 if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) {
296 return false;
297 }
298 if (mHost != null && p.mHost == null) return false;
299 if (mHost == null && p.mHost != null) return false;
300 if (mPort != p.mPort) return false;
301 return true;
302 }
303
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700304 /**
305 * Implement the Parcelable interface
306 * @hide
307 */
308 public int describeContents() {
309 return 0;
310 }
311
John Wang3e567d52011-04-04 12:35:42 -0700312 @Override
313 /*
314 * generate hashcode based on significant fields
315 */
316 public int hashCode() {
317 return ((null == mHost) ? 0 : mHost.hashCode())
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000318 + ((null == mExclusionList) ? 0 : mExclusionList.hashCode())
319 + mPort;
John Wang3e567d52011-04-04 12:35:42 -0700320 }
321
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700322 /**
323 * Implement the Parcelable interface.
324 * @hide
325 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700326 public void writeToParcel(Parcel dest, int flags) {
Jason Monk60a0e162014-05-09 15:16:06 -0400327 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monk43324ee2013-07-03 17:04:33 -0400328 dest.writeByte((byte)1);
Jason Monk60a0e162014-05-09 15:16:06 -0400329 mPacFileUrl.writeToParcel(dest, 0);
Jason Monk445cea82013-10-10 14:02:51 -0400330 dest.writeInt(mPort);
Jason Monk43324ee2013-07-03 17:04:33 -0400331 return;
332 } else {
333 dest.writeByte((byte)0);
334 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700335 if (mHost != null) {
Irfan Sheriff30bdeb32010-09-26 14:54:54 -0700336 dest.writeByte((byte)1);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700337 dest.writeString(mHost);
338 dest.writeInt(mPort);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700339 } else {
340 dest.writeByte((byte)0);
341 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700342 dest.writeString(mExclusionList);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700343 dest.writeStringArray(mParsedExclusionList);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700344 }
345
Jeff Sharkey9286f912019-02-28 12:06:45 -0700346 public static final @android.annotation.NonNull Creator<ProxyInfo> CREATOR =
Jason Monk1e3df5d2014-04-25 15:00:09 -0400347 new Creator<ProxyInfo>() {
348 public ProxyInfo createFromParcel(Parcel in) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700349 String host = null;
350 int port = 0;
Jason Monk43324ee2013-07-03 17:04:33 -0400351 if (in.readByte() != 0) {
Jason Monk60a0e162014-05-09 15:16:06 -0400352 Uri url = Uri.CREATOR.createFromParcel(in);
Jason Monk445cea82013-10-10 14:02:51 -0400353 int localPort = in.readInt();
Jason Monk1e3df5d2014-04-25 15:00:09 -0400354 return new ProxyInfo(url, localPort);
Jason Monk43324ee2013-07-03 17:04:33 -0400355 }
356 if (in.readByte() != 0) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700357 host = in.readString();
358 port = in.readInt();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700359 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700360 String exclList = in.readString();
lucaslincee43542021-01-25 11:01:57 +0800361 String[] parsedExclList = in.createStringArray();
Irina Dumitrescu3a838842018-12-05 16:19:47 +0000362 ProxyInfo proxyProperties = new ProxyInfo(host, port, exclList, parsedExclList);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700363 return proxyProperties;
364 }
365
Jason Monk1e3df5d2014-04-25 15:00:09 -0400366 public ProxyInfo[] newArray(int size) {
367 return new ProxyInfo[size];
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700368 }
369 };
Andrew Stadlere55ada72010-08-31 14:28:58 -0700370}