19ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk/*
29ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Copyright (C) 2013 The Android Open Source Project
39ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
49ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
59ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * you may not use this file except in compliance with the License.
69ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * You may obtain a copy of the License at
79ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
89ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
99ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Unless required by applicable law or agreed to in writing, software
119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * See the License for the specific language governing permissions and
149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * limitations under the License.
159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk */
16602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
17602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkpackage android.net;
18602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
19602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.RemoteException;
20602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.ServiceManager;
21a48ad8bd858d6ffe77838a282dbf71e01967957cWink Savilleimport android.util.Log;
22602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
23602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport com.android.net.IProxyService;
24602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport com.google.android.collect.Lists;
25602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
26602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.io.IOException;
27602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.InetSocketAddress;
28602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.MalformedURLException;
29602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.Proxy;
30602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.Proxy.Type;
31602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.ProxySelector;
32602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.SocketAddress;
33602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.URI;
34602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.util.List;
35602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
36602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk/**
37602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * @hide
38602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk */
39602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkpublic class PacProxySelector extends ProxySelector {
40a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville    private static final String TAG = "PacProxySelector";
41602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    public static final String PROXY_SERVICE = "com.android.net.IProxyService";
42602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    private IProxyService mProxyService;
439ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    private final List<Proxy> mDefaultList;
44602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
45602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    public PacProxySelector() {
46602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        mProxyService = IProxyService.Stub.asInterface(
47602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                ServiceManager.getService(PROXY_SERVICE));
48a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville        if (mProxyService == null) {
49a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville            // Added because of b10267814 where mako is restarting.
509ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            Log.e(TAG, "PacManager: no proxy service");
51a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville        }
529ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY);
53602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    }
54602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
55602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    @Override
56602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    public List<Proxy> select(URI uri) {
57a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville        if (mProxyService == null) {
589ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            mProxyService = IProxyService.Stub.asInterface(
599ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                    ServiceManager.getService(PROXY_SERVICE));
609ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
619ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        if (mProxyService == null) {
62a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville            Log.e(TAG, "select: no proxy service return NO_PROXY");
63a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville            return Lists.newArrayList(java.net.Proxy.NO_PROXY);
64a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville        }
65602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        String response = null;
66602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        String urlString;
67602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        try {
68602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            urlString = uri.toURL().toString();
69602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        } catch (MalformedURLException e) {
70602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            urlString = uri.getHost();
71602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        }
72602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        try {
73602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            response = mProxyService.resolvePacFile(uri.getHost(), urlString);
74602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        } catch (RemoteException e) {
75602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            e.printStackTrace();
76602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        }
779ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        if (response == null) {
789ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            return mDefaultList;
799ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        }
80602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
81602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        return parseResponse(response);
82602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    }
83602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
84602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    private static List<Proxy> parseResponse(String response) {
85602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        String[] split = response.split(";");
86602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        List<Proxy> ret = Lists.newArrayList();
87602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        for (String s : split) {
88602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            String trimmed = s.trim();
89602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            if (trimmed.equals("DIRECT")) {
90602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                ret.add(java.net.Proxy.NO_PROXY);
91602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            } else if (trimmed.startsWith("PROXY ")) {
92602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                String[] hostPort = trimmed.substring(6).split(":");
93602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                String host = hostPort[0];
94602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                int port;
95602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                try {
96602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                    port = Integer.parseInt(hostPort[1]);
97602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                } catch (Exception e) {
98602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                    port = 8080;
99602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk                }
100179d6e8e2067c380d3c1f7a1a26877b81a9240cbJason Monk                ret.add(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved(host, port)));
101602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            }
102602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        }
103602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        if (ret.size() == 0) {
104602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk            ret.add(java.net.Proxy.NO_PROXY);
105602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        }
106602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk        return ret;
107602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    }
108602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
109602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    @Override
110602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    public void connectFailed(URI uri, SocketAddress address, IOException failure) {
111602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
112602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk    }
113602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk
114602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk}
115