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