diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 51431ebfaf146..042481f1727ee 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -222,6 +222,13 @@ public class ConnectivityManager { */ public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL"; + /** + * Key for passing a user agent string to the captive portal login activity. + * {@hide} + */ + public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = + "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; + /** * Broadcast action to indicate the change of data activity status * (idle or active) on a network in a recent period. diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index bb8eb2cd07977..23a8655a3bb68 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -55,12 +55,15 @@ import java.lang.reflect.Method; import java.util.Random; public class CaptivePortalLoginActivity extends Activity { - private static final String TAG = "CaptivePortalLogin"; + private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName(); + private static final boolean DBG = true; + private static final int SOCKET_TIMEOUT_MS = 10000; private enum Result { DISMISSED, UNWANTED, WANTED_AS_IS }; - private URL mURL; + private URL mUrl; + private String mUserAgent; private Network mNetwork; private CaptivePortal mCaptivePortal; private NetworkCallback mNetworkCallback; @@ -72,17 +75,20 @@ public class CaptivePortalLoginActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCm = ConnectivityManager.from(this); - String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL); - if (url == null) url = mCm.getCaptivePortalServerUrl(); - try { - mURL = new URL(url); - } catch (MalformedURLException e) { - // System misconfigured, bail out in a way that at least provides network access. - Log.e(TAG, "Invalid captive portal URL, url=" + url); - done(Result.WANTED_AS_IS); - } mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK); mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL); + mUserAgent = getIntent().getParcelableExtra( + ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT); + mUrl = getUrl(); + if (mUrl == null) { + // getUrl() failed to parse the url provided in the intent: bail out in a way that + // at least provides network access. + done(Result.WANTED_AS_IS); + return; + } + if (DBG) { + Log.d(TAG, String.format("onCreate for %s", mUrl.toString())); + } // Also initializes proxy system properties. mCm.bindProcessToNetwork(mNetwork); @@ -149,6 +155,9 @@ public class CaptivePortalLoginActivity extends Activity { } private void done(Result result) { + if (DBG) { + Log.d(TAG, String.format("Result %s for %s", result.name(), mUrl.toString())); + } if (mNetworkCallback != null) { mCm.unregisterNetworkCallback(mNetworkCallback); mNetworkCallback = null; @@ -185,22 +194,31 @@ public class CaptivePortalLoginActivity extends Activity { @Override public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == R.id.action_use_network) { - done(Result.WANTED_AS_IS); - return true; + final Result result; + final String action; + final int id = item.getItemId(); + switch (id) { + case R.id.action_use_network: + result = Result.WANTED_AS_IS; + action = "USE_NETWORK"; + break; + case R.id.action_do_not_use_network: + result = Result.UNWANTED; + action = "DO_NOT_USE_NETWORK"; + break; + default: + return super.onOptionsItemSelected(item); } - if (id == R.id.action_do_not_use_network) { - done(Result.UNWANTED); - return true; + if (DBG) { + Log.d(TAG, String.format("onOptionsItemSelect %s for %s", action, mUrl.toString())); } - return super.onOptionsItemSelected(item); + done(result); + return true; } @Override public void onDestroy() { super.onDestroy(); - if (mNetworkCallback != null) { mCm.unregisterNetworkCallback(mNetworkCallback); mNetworkCallback = null; @@ -215,11 +233,29 @@ public class CaptivePortalLoginActivity extends Activity { } catch (InterruptedException e) { } } - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mURL.toString()))); + final String url = mUrl.toString(); + if (DBG) { + Log.d(TAG, "starting activity with intent ACTION_VIEW for " + url); + } + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); } } + private URL getUrl() { + String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL); + if (url == null) { + url = mCm.getCaptivePortalServerUrl(); + } + try { + return new URL(url); + } catch (MalformedURLException e) { + Log.e(TAG, "Invalid captive portal URL " + url); + } + return null; + } + private void testForCaptivePortal() { + // TODO: reuse NetworkMonitor facilities for consistent captive portal detection. new Thread(new Runnable() { public void run() { // Give time for captive portal to open. @@ -230,11 +266,14 @@ public class CaptivePortalLoginActivity extends Activity { HttpURLConnection urlConnection = null; int httpResponseCode = 500; try { - urlConnection = (HttpURLConnection) mURL.openConnection(); + urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl); urlConnection.setInstanceFollowRedirects(false); urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS); urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS); urlConnection.setUseCaches(false); + if (mUserAgent != null) { + urlConnection.setRequestProperty("User-Agent", mUserAgent); + } urlConnection.getInputStream(); httpResponseCode = urlConnection.getResponseCode(); } catch (IOException e) { @@ -292,7 +331,7 @@ public class CaptivePortalLoginActivity extends Activity { // settings. Now prompt the WebView read the Network-specific proxy settings. setWebViewProxy(); // Load the real page. - view.loadUrl(mURL.toString()); + view.loadUrl(mUrl.toString()); return; } else if (mPagesLoaded == 2) { // Prevent going back to empty first page. diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index 5e98859141697..9ffe2b78a0957 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -433,6 +433,8 @@ public class NetworkMonitor extends StateMachine { })); intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, mLastPortalProbeResult.detectUrl); + intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, + getCaptivePortalUserAgent(mContext)); intent.setFlags( Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, UserHandle.CURRENT);