1 /* 2 * Copyright (C) 2013 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 import android.os.ServiceManager; 20 import android.util.Log; 21 22 import com.android.net.IProxyService; 23 24 import com.google.android.collect.Lists; 25 26 import java.io.IOException; 27 import java.net.InetSocketAddress; 28 import java.net.MalformedURLException; 29 import java.net.Proxy; 30 import java.net.Proxy.Type; 31 import java.net.ProxySelector; 32 import java.net.SocketAddress; 33 import java.net.URI; 34 import java.net.URISyntaxException; 35 import java.util.List; 36 37 /** 38 * @hide 39 */ 40 public class PacProxySelector extends ProxySelector { 41 private static final String TAG = "PacProxySelector"; 42 public static final String PROXY_SERVICE = "com.android.net.IProxyService"; 43 private static final String SOCKS = "SOCKS "; 44 private static final String PROXY = "PROXY "; 45 46 private IProxyService mProxyService; 47 private final List<Proxy> mDefaultList; 48 PacProxySelector()49 public PacProxySelector() { 50 mProxyService = IProxyService.Stub.asInterface( 51 ServiceManager.getService(PROXY_SERVICE)); 52 if (mProxyService == null) { 53 // Added because of b10267814 where mako is restarting. 54 Log.e(TAG, "PacProxyService: no proxy service"); 55 } 56 mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY); 57 } 58 59 @Override select(URI uri)60 public List<Proxy> select(URI uri) { 61 if (mProxyService == null) { 62 mProxyService = IProxyService.Stub.asInterface( 63 ServiceManager.getService(PROXY_SERVICE)); 64 } 65 if (mProxyService == null) { 66 Log.e(TAG, "select: no proxy service return NO_PROXY"); 67 return Lists.newArrayList(java.net.Proxy.NO_PROXY); 68 } 69 String response = null; 70 String urlString; 71 try { 72 // Strip path and username/password from URI so it's not visible to PAC script. The 73 // path often contains credentials the app does not want exposed to a potentially 74 // malicious PAC script. 75 if (!"http".equalsIgnoreCase(uri.getScheme())) { 76 uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null); 77 } 78 urlString = uri.toURL().toString(); 79 } catch (URISyntaxException e) { 80 urlString = uri.getHost(); 81 } catch (MalformedURLException e) { 82 urlString = uri.getHost(); 83 } 84 try { 85 response = mProxyService.resolvePacFile(uri.getHost(), urlString); 86 } catch (Exception e) { 87 Log.e(TAG, "Error resolving PAC File", e); 88 } 89 if (response == null) { 90 return mDefaultList; 91 } 92 93 return parseResponse(response); 94 } 95 parseResponse(String response)96 private static List<Proxy> parseResponse(String response) { 97 String[] split = response.split(";"); 98 List<Proxy> ret = Lists.newArrayList(); 99 for (String s : split) { 100 String trimmed = s.trim(); 101 if (trimmed.equals("DIRECT")) { 102 ret.add(java.net.Proxy.NO_PROXY); 103 } else if (trimmed.startsWith(PROXY)) { 104 Proxy proxy = proxyFromHostPort(Type.HTTP, trimmed.substring(PROXY.length())); 105 if (proxy != null) { 106 ret.add(proxy); 107 } 108 } else if (trimmed.startsWith(SOCKS)) { 109 Proxy proxy = proxyFromHostPort(Type.SOCKS, trimmed.substring(SOCKS.length())); 110 if (proxy != null) { 111 ret.add(proxy); 112 } 113 } 114 } 115 if (ret.size() == 0) { 116 ret.add(java.net.Proxy.NO_PROXY); 117 } 118 return ret; 119 } 120 proxyFromHostPort(Proxy.Type type, String hostPortString)121 private static Proxy proxyFromHostPort(Proxy.Type type, String hostPortString) { 122 try { 123 String[] hostPort = hostPortString.split(":"); 124 String host = hostPort[0]; 125 int port = Integer.parseInt(hostPort[1]); 126 return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); 127 } catch (NumberFormatException|ArrayIndexOutOfBoundsException e) { 128 Log.d(TAG, "Unable to parse proxy " + hostPortString + " " + e); 129 return null; 130 } 131 } 132 133 @Override connectFailed(URI uri, SocketAddress address, IOException failure)134 public void connectFailed(URI uri, SocketAddress address, IOException failure) { 135 136 } 137 138 } 139