CaptivePortalLoginActivity.java revision 868f6243bc6021465938a7b764bef8fd001cb39c
1869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen/*
2869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * Copyright (C) 2014 The Android Open Source Project
3869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen *
4869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * Licensed under the Apache License, Version 2.0 (the "License");
5869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * you may not use this file except in compliance with the License.
6869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * You may obtain a copy of the License at
7869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen *
8869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen *      http://www.apache.org/licenses/LICENSE-2.0
9869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen *
10869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * Unless required by applicable law or agreed to in writing, software
11869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * distributed under the License is distributed on an "AS IS" BASIS,
12869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * See the License for the specific language governing permissions and
14869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen * limitations under the License.
15869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen */
16869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
17869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenpackage com.android.captiveportallogin;
18869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
19869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.app.Activity;
2088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport android.app.LoadedApk;
2188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport android.content.Context;
22869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.content.Intent;
23869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.graphics.Bitmap;
24869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.net.ConnectivityManager;
258df099df1516d23c113be3121635dcd34984a4a0Paul Jensenimport android.net.ConnectivityManager.NetworkCallback;
26869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.net.Network;
278df099df1516d23c113be3121635dcd34984a4a0Paul Jensenimport android.net.NetworkCapabilities;
288df099df1516d23c113be3121635dcd34984a4a0Paul Jensenimport android.net.NetworkRequest;
2988eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport android.net.Proxy;
3088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport android.net.Uri;
31fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensenimport android.net.http.SslError;
32869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.os.Bundle;
33869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.provider.Settings;
3488eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport android.util.ArrayMap;
3588eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport android.util.Log;
36869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.view.Menu;
37869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.view.MenuItem;
38fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensenimport android.webkit.SslErrorHandler;
39869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.webkit.WebChromeClient;
40869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.webkit.WebSettings;
41869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.webkit.WebView;
42869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport android.webkit.WebViewClient;
438f333f19222ac9415152e31f10e0df2b571b0b77Paul Jensenimport android.widget.ProgressBar;
445344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensenimport android.widget.TextView;
45869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
46869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport java.io.IOException;
47869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport java.net.HttpURLConnection;
48869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport java.net.MalformedURLException;
49869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport java.net.URL;
50869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenimport java.lang.InterruptedException;
5188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport java.lang.reflect.Field;
5288eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensenimport java.lang.reflect.Method;
53869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
54869868be653cb8eedd338e8347dfee1520d38cecPaul Jensenpublic class CaptivePortalLoginActivity extends Activity {
5588eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen    private static final String TAG = "CaptivePortalLogin";
56cd29cb66f92b008e8547f70b30223ce8dbc1fb86Lorenzo Colitti    private static final String DEFAULT_SERVER = "connectivitycheck.android.com";
57869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    private static final int SOCKET_TIMEOUT_MS = 10000;
58869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
5925a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen    private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS };
60869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
61869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    private URL mURL;
6225a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen    private Network mNetwork;
6371b645fe9cb8106dfcbf025a3fd7f58698c051bbPaul Jensen    private String mResponseToken;
648df099df1516d23c113be3121635dcd34984a4a0Paul Jensen    private NetworkCallback mNetworkCallback;
6525a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen    private ConnectivityManager mCm;
66869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
67869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    @Override
68869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    protected void onCreate(Bundle savedInstanceState) {
69869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        super.onCreate(savedInstanceState);
70869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
71869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        String server = Settings.Global.getString(getContentResolver(), "captive_portal_server");
72869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        if (server == null) server = DEFAULT_SERVER;
7325a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        mCm = ConnectivityManager.from(this);
74869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        try {
7571b645fe9cb8106dfcbf025a3fd7f58698c051bbPaul Jensen            mURL = new URL("http", server, "/generate_204");
7625a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        } catch (MalformedURLException e) {
7771b645fe9cb8106dfcbf025a3fd7f58698c051bbPaul Jensen            // System misconfigured, bail out in a way that at least provides network access.
7825a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            Log.e(TAG, "Invalid captive portal URL, server=" + server);
7925a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            done(Result.WANTED_AS_IS);
80869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        }
8125a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
8225a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        mResponseToken = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_TOKEN);
83869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
84e0bef71662d81caaaa0d7214fb0bef5d39996a69Paul Jensen        // Also initializes proxy system properties.
8525a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        mCm.bindProcessToNetwork(mNetwork);
8688eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen
8788eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        // Proxy system properties must be initialized before setContentView is called because
8888eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        // setContentView initializes the WebView logic which in turn reads the system properties.
8988eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        setContentView(R.layout.activity_captive_portal_login);
9088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen
9188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        getActionBar().setDisplayShowHomeEnabled(false);
9288eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen
938df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        // Exit app if Network disappears.
9425a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
958df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        if (networkCapabilities == null) {
968df099df1516d23c113be3121635dcd34984a4a0Paul Jensen            finish();
978df099df1516d23c113be3121635dcd34984a4a0Paul Jensen            return;
988df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        }
998df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        mNetworkCallback = new NetworkCallback() {
1008df099df1516d23c113be3121635dcd34984a4a0Paul Jensen            @Override
1018df099df1516d23c113be3121635dcd34984a4a0Paul Jensen            public void onLost(Network lostNetwork) {
10225a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                if (mNetwork.equals(lostNetwork)) done(Result.UNWANTED);
1038df099df1516d23c113be3121635dcd34984a4a0Paul Jensen            }
1048df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        };
1058df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        final NetworkRequest.Builder builder = new NetworkRequest.Builder();
1068df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        for (int transportType : networkCapabilities.getTransportTypes()) {
1078df099df1516d23c113be3121635dcd34984a4a0Paul Jensen            builder.addTransportType(transportType);
1088df099df1516d23c113be3121635dcd34984a4a0Paul Jensen        }
10925a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        mCm.registerNetworkCallback(builder.build(), mNetworkCallback);
110869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
11188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        final WebView myWebView = (WebView) findViewById(R.id.webview);
11288eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        myWebView.clearCache(true);
113869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        WebSettings webSettings = myWebView.getSettings();
114869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        webSettings.setJavaScriptEnabled(true);
115869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        myWebView.setWebViewClient(new MyWebViewClient());
116869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        myWebView.setWebChromeClient(new MyWebChromeClient());
11788eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        // Start initial page load so WebView finishes loading proxy settings.
11888eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        // Actual load of mUrl is initiated by MyWebViewClient.
11988eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        myWebView.loadData("", "text/html", null);
12088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen    }
12188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen
12288eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen    // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
12388eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen    private void setWebViewProxy() {
12488eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        LoadedApk loadedApk = getApplication().mLoadedApk;
12588eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        try {
12688eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            Field receiversField = LoadedApk.class.getDeclaredField("mReceivers");
12788eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            receiversField.setAccessible(true);
12888eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
12988eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            for (Object receiverMap : receivers.values()) {
13088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                for (Object rec : ((ArrayMap) receiverMap).keySet()) {
13188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                    Class clazz = rec.getClass();
13288eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                    if (clazz.getName().contains("ProxyChangeListener")) {
13388eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                        Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class,
13488eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                                Intent.class);
13588eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
13688eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                        onReceiveMethod.invoke(rec, getApplicationContext(), intent);
13788eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                        Log.v(TAG, "Prompting WebView proxy reload.");
13888eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                    }
13988eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                }
14088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            }
14188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        } catch (Exception e) {
14288eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            Log.e(TAG, "Exception while setting WebView proxy: " + e);
14388eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        }
144869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    }
145869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
14625a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen    private void done(Result result) {
14771b645fe9cb8106dfcbf025a3fd7f58698c051bbPaul Jensen        if (mNetworkCallback != null) {
14825a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            mCm.unregisterNetworkCallback(mNetworkCallback);
149868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen            mNetworkCallback = null;
15025a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        }
15125a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen        switch (result) {
15225a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            case DISMISSED:
15325a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                mCm.reportCaptivePortalDismissed(mNetwork, mResponseToken);
15425a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                break;
15525a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            case UNWANTED:
15625a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                mCm.ignoreNetworkWithCaptivePortal(mNetwork, mResponseToken);
15725a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                break;
15825a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            case WANTED_AS_IS:
15925a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                mCm.useNetworkWithCaptivePortal(mNetwork, mResponseToken);
16025a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                break;
16171b645fe9cb8106dfcbf025a3fd7f58698c051bbPaul Jensen        }
162869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        finish();
163869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    }
164869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
165869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    @Override
166869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    public boolean onCreateOptionsMenu(Menu menu) {
167869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        getMenuInflater().inflate(R.menu.captive_portal_login, menu);
168869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        return true;
169869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    }
170869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
171869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    @Override
172b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen    public void onBackPressed() {
173b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen        WebView myWebView = (WebView) findViewById(R.id.webview);
174b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen        if (myWebView.canGoBack()) {
175b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen            myWebView.goBack();
176b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen        } else {
177b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen            super.onBackPressed();
178b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen        }
179b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen    }
180b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen
181b6ea9ee6fe6fc205f4f8be593ca993d594e8d504Paul Jensen    @Override
182869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    public boolean onOptionsItemSelected(MenuItem item) {
183869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        int id = item.getItemId();
184869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        if (id == R.id.action_use_network) {
18525a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            done(Result.WANTED_AS_IS);
186869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen            return true;
187869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        }
188869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        if (id == R.id.action_do_not_use_network) {
18925a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen            done(Result.UNWANTED);
190869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen            return true;
191869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        }
192869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        return super.onOptionsItemSelected(item);
193869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    }
194869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
195868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen    @Override
196868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen    public void onDestroy() {
197868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen        super.onDestroy();
198868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen
199868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen        if (mNetworkCallback != null) {
200868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen            mCm.unregisterNetworkCallback(mNetworkCallback);
201868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen            mNetworkCallback = null;
202868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen        }
203868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen    }
204868f6243bc6021465938a7b764bef8fd001cb39cPaul Jensen
205869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    private void testForCaptivePortal() {
206869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        new Thread(new Runnable() {
207869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen            public void run() {
208869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                // Give time for captive portal to open.
209869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                try {
210869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    Thread.sleep(1000);
211869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                } catch (InterruptedException e) {
212869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                }
213869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                HttpURLConnection urlConnection = null;
214869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                int httpResponseCode = 500;
215869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                try {
216869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    urlConnection = (HttpURLConnection) mURL.openConnection();
217869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    urlConnection.setInstanceFollowRedirects(false);
218869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
219869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
220869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    urlConnection.setUseCaches(false);
221869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    urlConnection.getInputStream();
222869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    httpResponseCode = urlConnection.getResponseCode();
223869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                } catch (IOException e) {
224869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                } finally {
225869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                    if (urlConnection != null) urlConnection.disconnect();
226869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                }
227869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                if (httpResponseCode == 204) {
22825a217c0fbda9bbaf58ec08b91115e99f73b727fPaul Jensen                    done(Result.DISMISSED);
229869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen                }
230869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen            }
231869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        }).start();
232869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    }
233869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
234869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    private class MyWebViewClient extends WebViewClient {
2355344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen        private static final String INTERNAL_ASSETS = "file:///android_asset/";
23688eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen        private boolean firstPageLoad = true;
23788eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen
238869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        @Override
239869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        public void onPageStarted(WebView view, String url, Bitmap favicon) {
24088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            if (firstPageLoad) return;
241869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen            testForCaptivePortal();
242869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        }
243869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
244869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        @Override
245869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        public void onPageFinished(WebView view, String url) {
24688eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            if (firstPageLoad) {
24788eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                firstPageLoad = false;
24888eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                // Now that WebView has loaded at least one page we know it has read in the proxy
24988eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                // settings.  Now prompt the WebView read the Network-specific proxy settings.
25088eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                setWebViewProxy();
25188eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                // Load the real page.
25288eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                view.loadUrl(mURL.toString());
25388eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen                return;
25488eb0fa8eec7da1b7a3bd39f9d9844909911bc64Paul Jensen            }
2555344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen            // For internally generated pages, leave URL bar listing prior URL as this is the URL
2565344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen            // the page refers to.
2575344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen            if (!url.startsWith(INTERNAL_ASSETS)) {
2585344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen                final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
2595344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen                myUrlBar.setText(url);
2605344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen            }
261869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen            testForCaptivePortal();
262869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        }
263fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen
264fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen        // A web page consisting of a large broken lock icon to indicate SSL failure.
265fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen        final static String SSL_ERROR_HTML = "<!DOCTYPE html><html><head><style>" +
266fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen                "html { width:100%; height:100%; " +
267fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen                "       background:url(locked_page.png) center center no-repeat; }" +
268fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen                "</style></head><body></body></html>";
269fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen
270fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen        @Override
271fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
272fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen            Log.w(TAG, "SSL error; displaying broken lock icon.");
2735344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen            view.loadDataWithBaseURL(INTERNAL_ASSETS, SSL_ERROR_HTML, "text/HTML", "UTF-8", null);
274fc8022f8cfffded3d94baef3ba5e5ce936799b06Paul Jensen        }
275869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    }
276869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen
277869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    private class MyWebChromeClient extends WebChromeClient {
278869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        @Override
279869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        public void onProgressChanged(WebView view, int newProgress) {
2805344a4abdf239a19485a9c858b6cc3be96002eacPaul Jensen            final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
2818f333f19222ac9415152e31f10e0df2b571b0b77Paul Jensen            myProgressBar.setProgress(newProgress);
282869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen        }
283869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen    }
284869868be653cb8eedd338e8347dfee1520d38cecPaul Jensen}
285