1 /* 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 17 package android.net; 18 19 20 import android.annotation.UnsupportedAppUsage; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.text.TextUtils; 24 25 import java.net.InetSocketAddress; 26 import java.net.URLConnection; 27 import java.util.List; 28 import java.util.Locale; 29 30 /** 31 * Describes a proxy configuration. 32 * 33 * Proxy configurations are already integrated within the {@code java.net} and 34 * Apache HTTP stack. So {@link URLConnection} and Apache's {@code HttpClient} will use 35 * them automatically. 36 * 37 * Other HTTP stacks will need to obtain the proxy info from 38 * {@link Proxy#PROXY_CHANGE_ACTION} broadcast as the extra {@link Proxy#EXTRA_PROXY_INFO}. 39 */ 40 public class ProxyInfo implements Parcelable { 41 42 private final String mHost; 43 private final int mPort; 44 private final String mExclusionList; 45 private final String[] mParsedExclusionList; 46 private final Uri mPacFileUrl; 47 48 /** 49 *@hide 50 */ 51 public static final String LOCAL_EXCL_LIST = ""; 52 /** 53 *@hide 54 */ 55 public static final int LOCAL_PORT = -1; 56 /** 57 *@hide 58 */ 59 public static final String LOCAL_HOST = "localhost"; 60 61 /** 62 * Constructs a {@link ProxyInfo} object that points at a Direct proxy 63 * on the specified host and port. 64 */ buildDirectProxy(String host, int port)65 public static ProxyInfo buildDirectProxy(String host, int port) { 66 return new ProxyInfo(host, port, null); 67 } 68 69 /** 70 * Constructs a {@link ProxyInfo} object that points at a Direct proxy 71 * on the specified host and port. 72 * 73 * The proxy will not be used to access any host in exclusion list, exclList. 74 * 75 * @param exclList Hosts to exclude using the proxy on connections for. These 76 * hosts can use wildcards such as *.example.com. 77 */ buildDirectProxy(String host, int port, List<String> exclList)78 public static ProxyInfo buildDirectProxy(String host, int port, List<String> exclList) { 79 String[] array = exclList.toArray(new String[exclList.size()]); 80 return new ProxyInfo(host, port, TextUtils.join(",", array), array); 81 } 82 83 /** 84 * Construct a {@link ProxyInfo} that will download and run the PAC script 85 * at the specified URL. 86 */ buildPacProxy(Uri pacUri)87 public static ProxyInfo buildPacProxy(Uri pacUri) { 88 return new ProxyInfo(pacUri); 89 } 90 91 /** 92 * Create a ProxyProperties that points at a HTTP Proxy. 93 * @hide 94 */ 95 @UnsupportedAppUsage ProxyInfo(String host, int port, String exclList)96 public ProxyInfo(String host, int port, String exclList) { 97 mHost = host; 98 mPort = port; 99 mExclusionList = exclList; 100 mParsedExclusionList = parseExclusionList(mExclusionList); 101 mPacFileUrl = Uri.EMPTY; 102 } 103 104 /** 105 * Create a ProxyProperties that points at a PAC URL. 106 * @hide 107 */ ProxyInfo(Uri pacFileUrl)108 public ProxyInfo(Uri pacFileUrl) { 109 mHost = LOCAL_HOST; 110 mPort = LOCAL_PORT; 111 mExclusionList = LOCAL_EXCL_LIST; 112 mParsedExclusionList = parseExclusionList(mExclusionList); 113 if (pacFileUrl == null) { 114 throw new NullPointerException(); 115 } 116 mPacFileUrl = pacFileUrl; 117 } 118 119 /** 120 * Create a ProxyProperties that points at a PAC URL. 121 * @hide 122 */ ProxyInfo(String pacFileUrl)123 public ProxyInfo(String pacFileUrl) { 124 mHost = LOCAL_HOST; 125 mPort = LOCAL_PORT; 126 mExclusionList = LOCAL_EXCL_LIST; 127 mParsedExclusionList = parseExclusionList(mExclusionList); 128 mPacFileUrl = Uri.parse(pacFileUrl); 129 } 130 131 /** 132 * Only used in PacManager after Local Proxy is bound. 133 * @hide 134 */ ProxyInfo(Uri pacFileUrl, int localProxyPort)135 public ProxyInfo(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 parseExclusionList(String exclusionList)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 ProxyInfo(String host, int port, String exclList, String[] parsedExclList)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 // copy constructor instead of clone 163 /** 164 * @hide 165 */ ProxyInfo(ProxyInfo source)166 public ProxyInfo(ProxyInfo source) { 167 if (source != null) { 168 mHost = source.getHost(); 169 mPort = source.getPort(); 170 mPacFileUrl = source.mPacFileUrl; 171 mExclusionList = source.getExclusionListAsString(); 172 mParsedExclusionList = source.mParsedExclusionList; 173 } else { 174 mHost = null; 175 mPort = 0; 176 mExclusionList = null; 177 mParsedExclusionList = null; 178 mPacFileUrl = Uri.EMPTY; 179 } 180 } 181 182 /** 183 * @hide 184 */ getSocketAddress()185 public InetSocketAddress getSocketAddress() { 186 InetSocketAddress inetSocketAddress = null; 187 try { 188 inetSocketAddress = new InetSocketAddress(mHost, mPort); 189 } catch (IllegalArgumentException e) { } 190 return inetSocketAddress; 191 } 192 193 /** 194 * Returns the URL of the current PAC script or null if there is 195 * no PAC script. 196 */ getPacFileUrl()197 public Uri getPacFileUrl() { 198 return mPacFileUrl; 199 } 200 201 /** 202 * When configured to use a Direct Proxy this returns the host 203 * of the proxy. 204 */ getHost()205 public String getHost() { 206 return mHost; 207 } 208 209 /** 210 * When configured to use a Direct Proxy this returns the port 211 * of the proxy 212 */ getPort()213 public int getPort() { 214 return mPort; 215 } 216 217 /** 218 * When configured to use a Direct Proxy this returns the list 219 * of hosts for which the proxy is ignored. 220 */ getExclusionList()221 public String[] getExclusionList() { 222 return mParsedExclusionList; 223 } 224 225 /** 226 * comma separated 227 * @hide 228 */ getExclusionListAsString()229 public String getExclusionListAsString() { 230 return mExclusionList; 231 } 232 233 /** 234 * @hide 235 */ isValid()236 public boolean isValid() { 237 if (!Uri.EMPTY.equals(mPacFileUrl)) return true; 238 return Proxy.PROXY_VALID == Proxy.validate(mHost == null ? "" : mHost, 239 mPort == 0 ? "" : Integer.toString(mPort), 240 mExclusionList == null ? "" : mExclusionList); 241 } 242 243 /** 244 * @hide 245 */ makeProxy()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 toString()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 equals(Object o)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 */ describeContents()307 public int describeContents() { 308 return 0; 309 } 310 311 @Override 312 /* 313 * generate hashcode based on significant fields 314 */ hashCode()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 */ writeToParcel(Parcel dest, int flags)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.readStringArray(); 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 } 370