blob: 229db0d717cd8e890740eeb7645df929361cffa7 [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 Huangfb8581a2019-10-02 23:37:02 +080019import android.annotation.NonNull;
20import android.annotation.Nullable;
Artur Satayev9c2add62019-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 Wangab9f0172021-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 Monk4d5e20f2014-04-25 15:00:09 -040029import java.net.URLConnection;
30import java.util.List;
Elliott Hughes4e347592013-08-02 10:00:44 -070031import java.util.Locale;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070032
33/**
Jason Monk4d5e20f2014-04-25 15:00:09 -040034 * Describes a proxy configuration.
35 *
Narayan Kamath9a87ca52014-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 Monk4d5e20f2014-04-25 15:00:09 -040039 *
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}.
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070042 */
Jason Monk4d5e20f2014-04-25 15:00:09 -040043public class ProxyInfo implements Parcelable {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070044
Irina Dumitrescu8767f412018-12-05 16:19:47 +000045 private final String mHost;
46 private final int mPort;
47 private final String mExclusionList;
48 private final String[] mParsedExclusionList;
49 private final Uri mPacFileUrl;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070050
Jason Monk4d5e20f2014-04-25 15:00:09 -040051 /**
52 *@hide
53 */
Jason Monka5bf2842013-07-03 17:04:33 -040054 public static final String LOCAL_EXCL_LIST = "";
Jason Monk4d5e20f2014-04-25 15:00:09 -040055 /**
56 *@hide
57 */
Jason Monk0a9cc502013-08-23 19:21:25 -040058 public static final int LOCAL_PORT = -1;
Jason Monk4d5e20f2014-04-25 15:00:09 -040059 /**
60 *@hide
61 */
Jason Monka5bf2842013-07-03 17:04:33 -040062 public static final String LOCAL_HOST = "localhost";
63
Jason Monk4d5e20f2014-04-25 15:00:09 -040064 /**
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) {
Jason Monk19c65612014-05-09 15:16:06 -040091 return new ProxyInfo(pacUri);
Jason Monk4d5e20f2014-04-25 15:00:09 -040092 }
93
94 /**
Aaron Huangfb8581a2019-10-02 23:37:02 +080095 * 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 /**
Jason Monk4d5e20f2014-04-25 15:00:09 -0400104 * Create a ProxyProperties that points at a HTTP Proxy.
105 * @hide
106 */
Mathew Inwood58574792018-08-08 14:44:44 +0100107 @UnsupportedAppUsage
Jason Monk4d5e20f2014-04-25 15:00:09 -0400108 public ProxyInfo(String host, int port, String exclList) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700109 mHost = host;
110 mPort = port;
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000111 mExclusionList = exclList;
112 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk19c65612014-05-09 15:16:06 -0400113 mPacFileUrl = Uri.EMPTY;
114 }
115
116 /**
117 * Create a ProxyProperties that points at a PAC URL.
118 * @hide
119 */
Aaron Huangfb8581a2019-10-02 23:37:02 +0800120 public ProxyInfo(@NonNull Uri pacFileUrl) {
Jason Monk19c65612014-05-09 15:16:06 -0400121 mHost = LOCAL_HOST;
122 mPort = LOCAL_PORT;
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000123 mExclusionList = LOCAL_EXCL_LIST;
124 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk19c65612014-05-09 15:16:06 -0400125 if (pacFileUrl == null) {
126 throw new NullPointerException();
127 }
128 mPacFileUrl = pacFileUrl;
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700129 }
130
Jason Monk4d5e20f2014-04-25 15:00:09 -0400131 /**
Aaron Huangcc525022020-11-13 23:55:09 +0800132 * Only used in PacProxyInstaller after Local Proxy is bound.
Jason Monk4d5e20f2014-04-25 15:00:09 -0400133 * @hide
134 */
Aaron Huangfb8581a2019-10-02 23:37:02 +0800135 public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {
Jason Monk0a9cc502013-08-23 19:21:25 -0400136 mHost = LOCAL_HOST;
137 mPort = localProxyPort;
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000138 mExclusionList = LOCAL_EXCL_LIST;
139 mParsedExclusionList = parseExclusionList(mExclusionList);
Jason Monk19c65612014-05-09 15:16:06 -0400140 if (pacFileUrl == null) {
141 throw new NullPointerException();
142 }
Jason Monk0a9cc502013-08-23 19:21:25 -0400143 mPacFileUrl = pacFileUrl;
144 }
145
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000146 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
Jason Monk4d5e20f2014-04-25 15:00:09 -0400154 private ProxyInfo(String host, int port, String exclList, String[] parsedExclList) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700155 mHost = host;
156 mPort = port;
157 mExclusionList = exclList;
158 mParsedExclusionList = parsedExclList;
Jason Monk19c65612014-05-09 15:16:06 -0400159 mPacFileUrl = Uri.EMPTY;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700160 }
161
Jason Monk4d5e20f2014-04-25 15:00:09 -0400162 /**
Aaron Huangfb8581a2019-10-02 23:37:02 +0800163 * A copy constructor to hold proxy properties.
Jason Monk4d5e20f2014-04-25 15:00:09 -0400164 */
Aaron Huangfb8581a2019-10-02 23:37:02 +0800165 public ProxyInfo(@Nullable ProxyInfo source) {
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700166 if (source != null) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700167 mHost = source.getHost();
168 mPort = source.getPort();
Jason Monk4d5e20f2014-04-25 15:00:09 -0400169 mPacFileUrl = source.mPacFileUrl;
170 mExclusionList = source.getExclusionListAsString();
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700171 mParsedExclusionList = source.mParsedExclusionList;
Sreeram Ramachandran44a242a2014-05-14 14:45:00 -0700172 } else {
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000173 mHost = null;
174 mPort = 0;
175 mExclusionList = null;
176 mParsedExclusionList = null;
Sreeram Ramachandran44a242a2014-05-14 14:45:00 -0700177 mPacFileUrl = Uri.EMPTY;
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700178 }
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700179 }
180
Jason Monk4d5e20f2014-04-25 15:00:09 -0400181 /**
182 * @hide
183 */
Robert Greenwalt98f45832010-09-03 13:02:05 -0700184 public InetSocketAddress getSocketAddress() {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700185 InetSocketAddress inetSocketAddress = null;
186 try {
187 inetSocketAddress = new InetSocketAddress(mHost, mPort);
188 } catch (IllegalArgumentException e) { }
189 return inetSocketAddress;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700190 }
Andrew Stadlere55ada72010-08-31 14:28:58 -0700191
Jason Monk4d5e20f2014-04-25 15:00:09 -0400192 /**
193 * Returns the URL of the current PAC script or null if there is
194 * no PAC script.
195 */
196 public Uri getPacFileUrl() {
Jason Monk19c65612014-05-09 15:16:06 -0400197 return mPacFileUrl;
Jason Monka5bf2842013-07-03 17:04:33 -0400198 }
199
Jason Monk4d5e20f2014-04-25 15:00:09 -0400200 /**
201 * When configured to use a Direct Proxy this returns the host
202 * of the proxy.
203 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700204 public String getHost() {
205 return mHost;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700206 }
207
Jason Monk4d5e20f2014-04-25 15:00:09 -0400208 /**
209 * When configured to use a Direct Proxy this returns the port
210 * of the proxy
211 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700212 public int getPort() {
213 return mPort;
214 }
215
Jason Monk4d5e20f2014-04-25 15:00:09 -0400216 /**
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 */
Aaron Huangfb8581a2019-10-02 23:37:02 +0800228 @Nullable
Jason Monk4d5e20f2014-04-25 15:00:09 -0400229 public String getExclusionListAsString() {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700230 return mExclusionList;
231 }
Andrew Stadlere55ada72010-08-31 14:28:58 -0700232
Jason Monk4d5e20f2014-04-25 15:00:09 -0400233 /**
Aaron Huangfb8581a2019-10-02 23:37:02 +0800234 * Return true if the pattern of proxy is valid, otherwise return false.
Jason Monk4d5e20f2014-04-25 15:00:09 -0400235 */
Raj Mamadgif3df1622013-11-11 13:52:58 -0800236 public boolean isValid() {
Jason Monk19c65612014-05-09 15:16:06 -0400237 if (!Uri.EMPTY.equals(mPacFileUrl)) return true;
Chiachang Wangab9f0172021-02-05 17:33:53 +0800238 return ProxyUtils.PROXY_VALID == ProxyUtils.validate(mHost == null ? "" : mHost,
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000239 mPort == 0 ? "" : Integer.toString(mPort),
240 mExclusionList == null ? "" : mExclusionList);
Raj Mamadgif3df1622013-11-11 13:52:58 -0800241 }
242
Jason Monk4d5e20f2014-04-25 15:00:09 -0400243 /**
244 * @hide
245 */
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700246 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;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700256 }
257
Wink Saville7d857902010-08-27 11:15:18 -0700258 @Override
259 public String toString() {
260 StringBuilder sb = new StringBuilder();
Jason Monk19c65612014-05-09 15:16:06 -0400261 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monka5bf2842013-07-03 17:04:33 -0400262 sb.append("PAC Script: ");
263 sb.append(mPacFileUrl);
Paul Jensenc0618a62014-12-10 15:12:18 -0500264 }
265 if (mHost != null) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700266 sb.append("[");
267 sb.append(mHost);
268 sb.append("] ");
269 sb.append(Integer.toString(mPort));
Robert Greenwalte422ad92010-09-01 09:12:38 -0700270 if (mExclusionList != null) {
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000271 sb.append(" xl=").append(mExclusionList);
Robert Greenwalte422ad92010-09-01 09:12:38 -0700272 }
Wink Savillea7d56572011-09-21 11:05:43 -0700273 } else {
274 sb.append("[ProxyProperties.mHost == null]");
Robert Greenwalte422ad92010-09-01 09:12:38 -0700275 }
Wink Saville7d857902010-08-27 11:15:18 -0700276 return sb.toString();
277 }
278
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700279 @Override
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -0700280 public boolean equals(@Nullable Object o) {
Jason Monk4d5e20f2014-04-25 15:00:09 -0400281 if (!(o instanceof ProxyInfo)) return false;
282 ProxyInfo p = (ProxyInfo)o;
Jason Monka5bf2842013-07-03 17:04:33 -0400283 // If PAC URL is present in either then they must be equal.
284 // Other parameters will only be for fall back.
Jason Monk19c65612014-05-09 15:16:06 -0400285 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monka69f1b02013-10-10 14:02:51 -0400286 return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort;
Jason Monka5bf2842013-07-03 17:04:33 -0400287 }
Jason Monk19c65612014-05-09 15:16:06 -0400288 if (!Uri.EMPTY.equals(p.mPacFileUrl)) {
Jason Monka5bf2842013-07-03 17:04:33 -0400289 return false;
290 }
Jason Monk19c65612014-05-09 15:16:06 -0400291 if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) {
292 return false;
293 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700294 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
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700303 /**
304 * Implement the Parcelable interface
305 * @hide
306 */
307 public int describeContents() {
308 return 0;
309 }
310
John Wang3e567d52011-04-04 12:35:42 -0700311 @Override
312 /*
313 * generate hashcode based on significant fields
314 */
315 public int hashCode() {
316 return ((null == mHost) ? 0 : mHost.hashCode())
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000317 + ((null == mExclusionList) ? 0 : mExclusionList.hashCode())
318 + mPort;
John Wang3e567d52011-04-04 12:35:42 -0700319 }
320
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700321 /**
322 * Implement the Parcelable interface.
323 * @hide
324 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700325 public void writeToParcel(Parcel dest, int flags) {
Jason Monk19c65612014-05-09 15:16:06 -0400326 if (!Uri.EMPTY.equals(mPacFileUrl)) {
Jason Monka5bf2842013-07-03 17:04:33 -0400327 dest.writeByte((byte)1);
Jason Monk19c65612014-05-09 15:16:06 -0400328 mPacFileUrl.writeToParcel(dest, 0);
Jason Monka69f1b02013-10-10 14:02:51 -0400329 dest.writeInt(mPort);
Jason Monka5bf2842013-07-03 17:04:33 -0400330 return;
331 } else {
332 dest.writeByte((byte)0);
333 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700334 if (mHost != null) {
Irfan Sheriff30bdeb32010-09-26 14:54:54 -0700335 dest.writeByte((byte)1);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700336 dest.writeString(mHost);
337 dest.writeInt(mPort);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700338 } else {
339 dest.writeByte((byte)0);
340 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700341 dest.writeString(mExclusionList);
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700342 dest.writeStringArray(mParsedExclusionList);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700343 }
344
Jeff Sharkeyf8525282019-02-28 12:06:45 -0700345 public static final @android.annotation.NonNull Creator<ProxyInfo> CREATOR =
Jason Monk4d5e20f2014-04-25 15:00:09 -0400346 new Creator<ProxyInfo>() {
347 public ProxyInfo createFromParcel(Parcel in) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700348 String host = null;
349 int port = 0;
Jason Monka5bf2842013-07-03 17:04:33 -0400350 if (in.readByte() != 0) {
Jason Monk19c65612014-05-09 15:16:06 -0400351 Uri url = Uri.CREATOR.createFromParcel(in);
Jason Monka69f1b02013-10-10 14:02:51 -0400352 int localPort = in.readInt();
Jason Monk4d5e20f2014-04-25 15:00:09 -0400353 return new ProxyInfo(url, localPort);
Jason Monka5bf2842013-07-03 17:04:33 -0400354 }
355 if (in.readByte() != 0) {
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700356 host = in.readString();
357 port = in.readInt();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700358 }
Robert Greenwaltc3c5f862010-10-11 16:00:27 -0700359 String exclList = in.readString();
lucaslin20f95d42021-01-25 11:01:57 +0800360 String[] parsedExclList = in.createStringArray();
Irina Dumitrescu8767f412018-12-05 16:19:47 +0000361 ProxyInfo proxyProperties = new ProxyInfo(host, port, exclList, parsedExclList);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700362 return proxyProperties;
363 }
364
Jason Monk4d5e20f2014-04-25 15:00:09 -0400365 public ProxyInfo[] newArray(int size) {
366 return new ProxyInfo[size];
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700367 }
368 };
Andrew Stadlere55ada72010-08-31 14:28:58 -0700369}