diff options
| author | Remi NGUYEN VAN <reminv@google.com> | 2021-03-02 19:52:58 +0000 |
|---|---|---|
| committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-03-02 19:52:58 +0000 |
| commit | b6c5e099b5d95ce455fa1f9f5ef5dee46d1e89a5 (patch) | |
| tree | 770e19a24ce167bc3f3535a602b6bc5bae0447a3 /core/java/android | |
| parent | b3bc93fbcfef5e4a650d32b61379f0419524905e (diff) | |
| parent | ae171d864d14c7ffbc90a2c0f0b0f2310e58de87 (diff) | |
Merge "Move Proxy, PacProxySelector out of Connectivity" am: ae171d864d
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1598157
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: Id81273b33752ff353dfebdd2cd3faf43429f1a29
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/net/PacProxySelector.java | 138 | ||||
| -rw-r--r-- | core/java/android/net/Proxy.java | 248 |
2 files changed, 386 insertions, 0 deletions
diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java new file mode 100644 index 000000000000..326943a27d4e --- /dev/null +++ b/core/java/android/net/PacProxySelector.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.ServiceManager; +import android.util.Log; + +import com.android.net.IProxyService; + +import com.google.android.collect.Lists; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.Proxy.Type; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +/** + * @hide + */ +public class PacProxySelector extends ProxySelector { + private static final String TAG = "PacProxySelector"; + public static final String PROXY_SERVICE = "com.android.net.IProxyService"; + private static final String SOCKS = "SOCKS "; + private static final String PROXY = "PROXY "; + + private IProxyService mProxyService; + private final List<Proxy> mDefaultList; + + public PacProxySelector() { + mProxyService = IProxyService.Stub.asInterface( + ServiceManager.getService(PROXY_SERVICE)); + if (mProxyService == null) { + // Added because of b10267814 where mako is restarting. + Log.e(TAG, "PacProxyInstaller: no proxy service"); + } + mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY); + } + + @Override + public List<Proxy> select(URI uri) { + if (mProxyService == null) { + mProxyService = IProxyService.Stub.asInterface( + ServiceManager.getService(PROXY_SERVICE)); + } + if (mProxyService == null) { + Log.e(TAG, "select: no proxy service return NO_PROXY"); + return Lists.newArrayList(java.net.Proxy.NO_PROXY); + } + String response = null; + String urlString; + try { + // Strip path and username/password from URI so it's not visible to PAC script. The + // path often contains credentials the app does not want exposed to a potentially + // malicious PAC script. + if (!"http".equalsIgnoreCase(uri.getScheme())) { + uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null); + } + urlString = uri.toURL().toString(); + } catch (URISyntaxException e) { + urlString = uri.getHost(); + } catch (MalformedURLException e) { + urlString = uri.getHost(); + } + try { + response = mProxyService.resolvePacFile(uri.getHost(), urlString); + } catch (Exception e) { + Log.e(TAG, "Error resolving PAC File", e); + } + if (response == null) { + return mDefaultList; + } + + return parseResponse(response); + } + + private static List<Proxy> parseResponse(String response) { + String[] split = response.split(";"); + List<Proxy> ret = Lists.newArrayList(); + for (String s : split) { + String trimmed = s.trim(); + if (trimmed.equals("DIRECT")) { + ret.add(java.net.Proxy.NO_PROXY); + } else if (trimmed.startsWith(PROXY)) { + Proxy proxy = proxyFromHostPort(Type.HTTP, trimmed.substring(PROXY.length())); + if (proxy != null) { + ret.add(proxy); + } + } else if (trimmed.startsWith(SOCKS)) { + Proxy proxy = proxyFromHostPort(Type.SOCKS, trimmed.substring(SOCKS.length())); + if (proxy != null) { + ret.add(proxy); + } + } + } + if (ret.size() == 0) { + ret.add(java.net.Proxy.NO_PROXY); + } + return ret; + } + + private static Proxy proxyFromHostPort(Proxy.Type type, String hostPortString) { + try { + String[] hostPort = hostPortString.split(":"); + String host = hostPort[0]; + int port = Integer.parseInt(hostPort[1]); + return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); + } catch (NumberFormatException|ArrayIndexOutOfBoundsException e) { + Log.d(TAG, "Unable to parse proxy " + hostPortString + " " + e); + return null; + } + } + + @Override + public void connectFailed(URI uri, SocketAddress address, IOException failure) { + + } + +} diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java new file mode 100644 index 000000000000..77c8a4f4579b --- /dev/null +++ b/core/java/android/net/Proxy.java @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.Nullable; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; + +import com.android.net.module.util.ProxyUtils; + +import java.net.InetSocketAddress; +import java.net.ProxySelector; +import java.net.URI; +import java.util.List; + +/** + * A convenience class for accessing the user and default proxy + * settings. + */ +public final class Proxy { + + private static final String TAG = "Proxy"; + + private static final ProxySelector sDefaultProxySelector; + + /** + * Used to notify an app that's caching the proxy that either the default + * connection has changed or any connection's proxy has changed. The new + * proxy should be queried using {@link ConnectivityManager#getDefaultProxy()}. + * + * <p class="note">This is a protected intent that can only be sent by the system + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; + /** + * Intent extra included with {@link #PROXY_CHANGE_ACTION} intents. + * It describes the new proxy being used (as a {@link ProxyInfo} object). + * @deprecated Because {@code PROXY_CHANGE_ACTION} is sent whenever the proxy + * for any network on the system changes, applications should always use + * {@link ConnectivityManager#getDefaultProxy()} or + * {@link ConnectivityManager#getLinkProperties(Network)}.{@link LinkProperties#getHttpProxy()} + * to get the proxy for the Network(s) they are using. + */ + @Deprecated + public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; + + private static ConnectivityManager sConnectivityManager = null; + + static { + sDefaultProxySelector = ProxySelector.getDefault(); + } + + /** + * Return the proxy object to be used for the URL given as parameter. + * @param ctx A Context used to get the settings for the proxy host. + * @param url A URL to be accessed. Used to evaluate exclusion list. + * @return Proxy (java.net) object containing the host name. If the + * user did not set a hostname it returns the default host. + * A null value means that no host is to be used. + * {@hide} + */ + @UnsupportedAppUsage + public static final java.net.Proxy getProxy(Context ctx, String url) { + String host = ""; + if ((url != null) && !isLocalHost(host)) { + URI uri = URI.create(url); + ProxySelector proxySelector = ProxySelector.getDefault(); + + List<java.net.Proxy> proxyList = proxySelector.select(uri); + + if (proxyList.size() > 0) { + return proxyList.get(0); + } + } + return java.net.Proxy.NO_PROXY; + } + + + /** + * Return the proxy host set by the user. + * @param ctx A Context used to get the settings for the proxy host. + * @return String containing the host name. If the user did not set a host + * name it returns the default host. A null value means that no + * host is to be used. + * @deprecated Use standard java vm proxy values to find the host, port + * and exclusion list. This call ignores the exclusion list. + */ + @Deprecated + public static final String getHost(Context ctx) { + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return null; + try { + return ((InetSocketAddress)(proxy.address())).getHostName(); + } catch (Exception e) { + return null; + } + } + + /** + * Return the proxy port set by the user. + * @param ctx A Context used to get the settings for the proxy port. + * @return The port number to use or -1 if no proxy is to be used. + * @deprecated Use standard java vm proxy values to find the host, port + * and exclusion list. This call ignores the exclusion list. + */ + @Deprecated + public static final int getPort(Context ctx) { + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return -1; + try { + return ((InetSocketAddress)(proxy.address())).getPort(); + } catch (Exception e) { + return -1; + } + } + + /** + * Return the default proxy host specified by the carrier. + * @return String containing the host name or null if there is no proxy for + * this carrier. + * @deprecated Use standard java vm proxy values to find the host, port and + * exclusion list. This call ignores the exclusion list and no + * longer reports only mobile-data apn-based proxy values. + */ + @Deprecated + public static final String getDefaultHost() { + String host = System.getProperty("http.proxyHost"); + if (TextUtils.isEmpty(host)) return null; + return host; + } + + /** + * Return the default proxy port specified by the carrier. + * @return The port number to be used with the proxy host or -1 if there is + * no proxy for this carrier. + * @deprecated Use standard java vm proxy values to find the host, port and + * exclusion list. This call ignores the exclusion list and no + * longer reports only mobile-data apn-based proxy values. + */ + @Deprecated + public static final int getDefaultPort() { + if (getDefaultHost() == null) return -1; + try { + return Integer.parseInt(System.getProperty("http.proxyPort")); + } catch (NumberFormatException e) { + return -1; + } + } + + private static final boolean isLocalHost(String host) { + if (host == null) { + return false; + } + try { + if (host != null) { + if (host.equalsIgnoreCase("localhost")) { + return true; + } + if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) { + return true; + } + } + } catch (IllegalArgumentException iex) { + } + return false; + } + + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Deprecated + public static void setHttpProxySystemProperty(ProxyInfo p) { + setHttpProxyConfiguration(p); + } + + /** + * Set HTTP proxy configuration for the process to match the provided ProxyInfo. + * + * If the provided ProxyInfo is null, the proxy configuration will be cleared. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static void setHttpProxyConfiguration(@Nullable ProxyInfo p) { + String host = null; + String port = null; + String exclList = null; + Uri pacFileUrl = Uri.EMPTY; + if (p != null) { + host = p.getHost(); + port = Integer.toString(p.getPort()); + exclList = ProxyUtils.exclusionListAsString(p.getExclusionList()); + pacFileUrl = p.getPacFileUrl(); + } + setHttpProxyConfiguration(host, port, exclList, pacFileUrl); + } + + /** @hide */ + public static void setHttpProxyConfiguration(String host, String port, String exclList, + Uri pacFileUrl) { + if (exclList != null) exclList = exclList.replace(",", "|"); + if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); + if (host != null) { + System.setProperty("http.proxyHost", host); + System.setProperty("https.proxyHost", host); + } else { + System.clearProperty("http.proxyHost"); + System.clearProperty("https.proxyHost"); + } + if (port != null) { + System.setProperty("http.proxyPort", port); + System.setProperty("https.proxyPort", port); + } else { + System.clearProperty("http.proxyPort"); + System.clearProperty("https.proxyPort"); + } + if (exclList != null) { + System.setProperty("http.nonProxyHosts", exclList); + System.setProperty("https.nonProxyHosts", exclList); + } else { + System.clearProperty("http.nonProxyHosts"); + System.clearProperty("https.nonProxyHosts"); + } + if (!Uri.EMPTY.equals(pacFileUrl)) { + ProxySelector.setDefault(new PacProxySelector()); + } else { + ProxySelector.setDefault(sDefaultProxySelector); + } + } +} |
