Loading core/java/android/provider/Settings.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -8182,6 +8182,15 @@ public final class Settings { */ */ public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url"; public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url"; /** * A "|" separated list of URLs used for captive portal detection in addition to the * fallback HTTP url associated with the CAPTIVE_PORTAL_FALLBACK_URL settings. * * @hide */ public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls"; /** /** * Whether to use HTTPS for network validation. This is enabled by default and the setting * Whether to use HTTPS for network validation. This is enabled by default and the setting * needs to be set to 0 to disable it. This setting is a misnomer because captive portals * needs to be set to 0 to disable it. This setting is a misnomer because captive portals Loading services/core/java/com/android/server/connectivity/NetworkMonitor.java +58 −19 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ import java.net.InetAddress; import java.net.MalformedURLException; import java.net.MalformedURLException; import java.net.URL; import java.net.URL; import java.net.UnknownHostException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Random; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch; Loading @@ -90,6 +91,8 @@ public class NetworkMonitor extends StateMachine { private static final String DEFAULT_HTTP_URL = private static final String DEFAULT_HTTP_URL = "http://connectivitycheck.gstatic.com/generate_204"; "http://connectivitycheck.gstatic.com/generate_204"; private static final String DEFAULT_FALLBACK_URL = "http://www.google.com/gen_204"; private static final String DEFAULT_FALLBACK_URL = "http://www.google.com/gen_204"; private static final String DEFAULT_OTHER_FALLBACK_URLS = "http://play.googleapis.com/generate_204"; private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) " private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/52.0.2743.82 Safari/537.36"; + "Chrome/52.0.2743.82 Safari/537.36"; Loading Loading @@ -263,7 +266,8 @@ public class NetworkMonitor extends StateMachine { private final String mCaptivePortalUserAgent; private final String mCaptivePortalUserAgent; private final URL mCaptivePortalHttpsUrl; private final URL mCaptivePortalHttpsUrl; private final URL mCaptivePortalHttpUrl; private final URL mCaptivePortalHttpUrl; private final URL mCaptivePortalFallbackUrl; private final URL[] mCaptivePortalFallbackUrls; private int mNextFallbackUrlIndex = 0; public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) { NetworkRequest defaultRequest) { Loading Loading @@ -302,7 +306,7 @@ public class NetworkMonitor extends StateMachine { mCaptivePortalUserAgent = getCaptivePortalUserAgent(context); mCaptivePortalUserAgent = getCaptivePortalUserAgent(context); mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context)); mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context)); mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context)); mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context)); mCaptivePortalFallbackUrl = makeURL(getCaptivePortalFallbackUrl(context)); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(context); start(); start(); } } Loading Loading @@ -450,7 +454,7 @@ public class NetworkMonitor extends StateMachine { intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, mLastPortalProbeResult.detectUrl); mLastPortalProbeResult.detectUrl); intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, getCaptivePortalUserAgent(mContext)); mCaptivePortalUserAgent); intent.setFlags( intent.setFlags( Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, UserHandle.CURRENT); mContext.startActivityAsUser(intent, UserHandle.CURRENT); Loading @@ -474,7 +478,11 @@ public class NetworkMonitor extends StateMachine { */ */ @VisibleForTesting @VisibleForTesting public static final class CaptivePortalProbeResult { public static final class CaptivePortalProbeResult { static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(599); static final int SUCCESS_CODE = 204; static final int FAILED_CODE = 599; static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE); static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE); private final int mHttpResponseCode; // HTTP response code returned from Internet probe. private final int mHttpResponseCode; // HTTP response code returned from Internet probe. final String redirectUrl; // Redirect destination returned from Internet probe. final String redirectUrl; // Redirect destination returned from Internet probe. Loading @@ -492,9 +500,16 @@ public class NetworkMonitor extends StateMachine { this(httpResponseCode, null, null); this(httpResponseCode, null, null); } } boolean isSuccessful() { return mHttpResponseCode == 204; } boolean isSuccessful() { return mHttpResponseCode == SUCCESS_CODE; } boolean isPortal() { boolean isPortal() { return !isSuccessful() && mHttpResponseCode >= 200 && mHttpResponseCode <= 399; return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399); } boolean isFailed() { return !isSuccessful() && !isPortal(); } } } } Loading Loading @@ -666,9 +681,24 @@ public class NetworkMonitor extends StateMachine { return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL); return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL); } } private static String getCaptivePortalFallbackUrl(Context context) { private URL[] makeCaptivePortalFallbackUrls(Context context) { return getSetting(context, String separator = "|"; String firstUrl = getSetting(context, Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL); Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL); String joinedUrls = firstUrl + separator + getSetting(context, Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, DEFAULT_OTHER_FALLBACK_URLS); List<URL> urls = new ArrayList<>(); for (String s : joinedUrls.split(separator)) { URL u = makeURL(s); if (u == null) { continue; } urls.add(u); } if (urls.isEmpty()) { Log.e(TAG, String.format("could not create any url from %s", joinedUrls)); } return urls.toArray(new URL[urls.size()]); } } private static String getCaptivePortalUserAgent(Context context) { private static String getCaptivePortalUserAgent(Context context) { Loading @@ -680,17 +710,25 @@ public class NetworkMonitor extends StateMachine { return value != null ? value : defaultValue; return value != null ? value : defaultValue; } } private URL nextFallbackUrl() { if (mCaptivePortalFallbackUrls.length == 0) { return null; } int idx = Math.abs(mNextFallbackUrlIndex) % mCaptivePortalFallbackUrls.length; mNextFallbackUrlIndex += new Random().nextInt(); // randomely change url without memory. return mCaptivePortalFallbackUrls[idx]; } @VisibleForTesting @VisibleForTesting protected CaptivePortalProbeResult isCaptivePortal() { protected CaptivePortalProbeResult isCaptivePortal() { if (!mIsCaptivePortalCheckEnabled) { if (!mIsCaptivePortalCheckEnabled) { validationLog("Validation disabled."); validationLog("Validation disabled."); return new CaptivePortalProbeResult(204); return CaptivePortalProbeResult.SUCCESS; } } URL pacUrl = null; URL pacUrl = null; URL httpsUrl = mCaptivePortalHttpsUrl; URL httpsUrl = mCaptivePortalHttpsUrl; URL httpUrl = mCaptivePortalHttpUrl; URL httpUrl = mCaptivePortalHttpUrl; URL fallbackUrl = mCaptivePortalFallbackUrl; // On networks with a PAC instead of fetching a URL that should result in a 204 // On networks with a PAC instead of fetching a URL that should result in a 204 // response, we instead simply fetch the PAC script. This is done for a few reasons: // response, we instead simply fetch the PAC script. This is done for a few reasons: Loading Loading @@ -727,7 +765,7 @@ public class NetworkMonitor extends StateMachine { if (pacUrl != null) { if (pacUrl != null) { result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC); result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC); } else if (mUseHttps) { } else if (mUseHttps) { result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl); result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl); } else { } else { result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); } } Loading Loading @@ -789,7 +827,7 @@ public class NetworkMonitor extends StateMachine { @VisibleForTesting @VisibleForTesting protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) { protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) { HttpURLConnection urlConnection = null; HttpURLConnection urlConnection = null; int httpResponseCode = 599; int httpResponseCode = CaptivePortalProbeResult.FAILED_CODE; String redirectUrl = null; String redirectUrl = null; final Stopwatch probeTimer = new Stopwatch().start(); final Stopwatch probeTimer = new Stopwatch().start(); try { try { Loading Loading @@ -827,7 +865,7 @@ public class NetworkMonitor extends StateMachine { if (probeType == ValidationProbeEvent.PROBE_PAC) { if (probeType == ValidationProbeEvent.PROBE_PAC) { validationLog( validationLog( probeType, url, "PAC fetch 200 response interpreted as 204 response."); probeType, url, "PAC fetch 200 response interpreted as 204 response."); httpResponseCode = 204; httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE; } else if (urlConnection.getContentLengthLong() == 0) { } else if (urlConnection.getContentLengthLong() == 0) { // Consider 200 response with "Content-length=0" to not be a captive portal. // Consider 200 response with "Content-length=0" to not be a captive portal. // There's no point in considering this a captive portal as the user cannot // There's no point in considering this a captive portal as the user cannot Loading @@ -835,20 +873,20 @@ public class NetworkMonitor extends StateMachine { // See http://b/9972012. // See http://b/9972012. validationLog(probeType, url, validationLog(probeType, url, "200 response with Content-length=0 interpreted as 204 response."); "200 response with Content-length=0 interpreted as 204 response."); httpResponseCode = 204; httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE; } else if (urlConnection.getContentLengthLong() == -1) { } else if (urlConnection.getContentLengthLong() == -1) { // When no Content-length (default value == -1), attempt to read a byte from the // When no Content-length (default value == -1), attempt to read a byte from the // response. Do not use available() as it is unreliable. See http://b/33498325. // response. Do not use available() as it is unreliable. See http://b/33498325. if (urlConnection.getInputStream().read() == -1) { if (urlConnection.getInputStream().read() == -1) { validationLog( validationLog( probeType, url, "Empty 200 response interpreted as 204 response."); probeType, url, "Empty 200 response interpreted as 204 response."); httpResponseCode = 204; httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE; } } } } } } } catch (IOException e) { } catch (IOException e) { validationLog(probeType, url, "Probably not a portal: exception " + e); validationLog(probeType, url, "Probe failed with exception " + e); if (httpResponseCode == 599) { if (httpResponseCode == CaptivePortalProbeResult.FAILED_CODE) { // TODO: Ping gateway and DNS server and log results. // TODO: Ping gateway and DNS server and log results. } } } finally { } finally { Loading @@ -861,7 +899,7 @@ public class NetworkMonitor extends StateMachine { } } private CaptivePortalProbeResult sendParallelHttpProbes( private CaptivePortalProbeResult sendParallelHttpProbes( ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) { ProxyInfo proxy, URL httpsUrl, URL httpUrl) { // Number of probes to wait for. If a probe completes with a conclusive answer // Number of probes to wait for. If a probe completes with a conclusive answer // it shortcuts the latch immediately by forcing the count to 0. // it shortcuts the latch immediately by forcing the count to 0. final CountDownLatch latch = new CountDownLatch(2); final CountDownLatch latch = new CountDownLatch(2); Loading Loading @@ -920,7 +958,8 @@ public class NetworkMonitor extends StateMachine { if (httpsResult.isPortal() || httpsResult.isSuccessful()) { if (httpsResult.isPortal() || httpsResult.isSuccessful()) { return httpsResult; return httpsResult; } } // If a fallback url is specified, use a fallback probe to try again portal detection. // If a fallback url exists, use a fallback probe to try again portal detection. URL fallbackUrl = nextFallbackUrl(); if (fallbackUrl != null) { if (fallbackUrl != null) { CaptivePortalProbeResult result = CaptivePortalProbeResult result = sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK); sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK); Loading Loading
core/java/android/provider/Settings.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -8182,6 +8182,15 @@ public final class Settings { */ */ public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url"; public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url"; /** * A "|" separated list of URLs used for captive portal detection in addition to the * fallback HTTP url associated with the CAPTIVE_PORTAL_FALLBACK_URL settings. * * @hide */ public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls"; /** /** * Whether to use HTTPS for network validation. This is enabled by default and the setting * Whether to use HTTPS for network validation. This is enabled by default and the setting * needs to be set to 0 to disable it. This setting is a misnomer because captive portals * needs to be set to 0 to disable it. This setting is a misnomer because captive portals Loading
services/core/java/com/android/server/connectivity/NetworkMonitor.java +58 −19 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ import java.net.InetAddress; import java.net.MalformedURLException; import java.net.MalformedURLException; import java.net.URL; import java.net.URL; import java.net.UnknownHostException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Random; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch; Loading @@ -90,6 +91,8 @@ public class NetworkMonitor extends StateMachine { private static final String DEFAULT_HTTP_URL = private static final String DEFAULT_HTTP_URL = "http://connectivitycheck.gstatic.com/generate_204"; "http://connectivitycheck.gstatic.com/generate_204"; private static final String DEFAULT_FALLBACK_URL = "http://www.google.com/gen_204"; private static final String DEFAULT_FALLBACK_URL = "http://www.google.com/gen_204"; private static final String DEFAULT_OTHER_FALLBACK_URLS = "http://play.googleapis.com/generate_204"; private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) " private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/52.0.2743.82 Safari/537.36"; + "Chrome/52.0.2743.82 Safari/537.36"; Loading Loading @@ -263,7 +266,8 @@ public class NetworkMonitor extends StateMachine { private final String mCaptivePortalUserAgent; private final String mCaptivePortalUserAgent; private final URL mCaptivePortalHttpsUrl; private final URL mCaptivePortalHttpsUrl; private final URL mCaptivePortalHttpUrl; private final URL mCaptivePortalHttpUrl; private final URL mCaptivePortalFallbackUrl; private final URL[] mCaptivePortalFallbackUrls; private int mNextFallbackUrlIndex = 0; public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo, NetworkRequest defaultRequest) { NetworkRequest defaultRequest) { Loading Loading @@ -302,7 +306,7 @@ public class NetworkMonitor extends StateMachine { mCaptivePortalUserAgent = getCaptivePortalUserAgent(context); mCaptivePortalUserAgent = getCaptivePortalUserAgent(context); mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context)); mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context)); mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context)); mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context)); mCaptivePortalFallbackUrl = makeURL(getCaptivePortalFallbackUrl(context)); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(context); start(); start(); } } Loading Loading @@ -450,7 +454,7 @@ public class NetworkMonitor extends StateMachine { intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, mLastPortalProbeResult.detectUrl); mLastPortalProbeResult.detectUrl); intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT, getCaptivePortalUserAgent(mContext)); mCaptivePortalUserAgent); intent.setFlags( intent.setFlags( Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, UserHandle.CURRENT); mContext.startActivityAsUser(intent, UserHandle.CURRENT); Loading @@ -474,7 +478,11 @@ public class NetworkMonitor extends StateMachine { */ */ @VisibleForTesting @VisibleForTesting public static final class CaptivePortalProbeResult { public static final class CaptivePortalProbeResult { static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(599); static final int SUCCESS_CODE = 204; static final int FAILED_CODE = 599; static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE); static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE); private final int mHttpResponseCode; // HTTP response code returned from Internet probe. private final int mHttpResponseCode; // HTTP response code returned from Internet probe. final String redirectUrl; // Redirect destination returned from Internet probe. final String redirectUrl; // Redirect destination returned from Internet probe. Loading @@ -492,9 +500,16 @@ public class NetworkMonitor extends StateMachine { this(httpResponseCode, null, null); this(httpResponseCode, null, null); } } boolean isSuccessful() { return mHttpResponseCode == 204; } boolean isSuccessful() { return mHttpResponseCode == SUCCESS_CODE; } boolean isPortal() { boolean isPortal() { return !isSuccessful() && mHttpResponseCode >= 200 && mHttpResponseCode <= 399; return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399); } boolean isFailed() { return !isSuccessful() && !isPortal(); } } } } Loading Loading @@ -666,9 +681,24 @@ public class NetworkMonitor extends StateMachine { return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL); return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL); } } private static String getCaptivePortalFallbackUrl(Context context) { private URL[] makeCaptivePortalFallbackUrls(Context context) { return getSetting(context, String separator = "|"; String firstUrl = getSetting(context, Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL); Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL); String joinedUrls = firstUrl + separator + getSetting(context, Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, DEFAULT_OTHER_FALLBACK_URLS); List<URL> urls = new ArrayList<>(); for (String s : joinedUrls.split(separator)) { URL u = makeURL(s); if (u == null) { continue; } urls.add(u); } if (urls.isEmpty()) { Log.e(TAG, String.format("could not create any url from %s", joinedUrls)); } return urls.toArray(new URL[urls.size()]); } } private static String getCaptivePortalUserAgent(Context context) { private static String getCaptivePortalUserAgent(Context context) { Loading @@ -680,17 +710,25 @@ public class NetworkMonitor extends StateMachine { return value != null ? value : defaultValue; return value != null ? value : defaultValue; } } private URL nextFallbackUrl() { if (mCaptivePortalFallbackUrls.length == 0) { return null; } int idx = Math.abs(mNextFallbackUrlIndex) % mCaptivePortalFallbackUrls.length; mNextFallbackUrlIndex += new Random().nextInt(); // randomely change url without memory. return mCaptivePortalFallbackUrls[idx]; } @VisibleForTesting @VisibleForTesting protected CaptivePortalProbeResult isCaptivePortal() { protected CaptivePortalProbeResult isCaptivePortal() { if (!mIsCaptivePortalCheckEnabled) { if (!mIsCaptivePortalCheckEnabled) { validationLog("Validation disabled."); validationLog("Validation disabled."); return new CaptivePortalProbeResult(204); return CaptivePortalProbeResult.SUCCESS; } } URL pacUrl = null; URL pacUrl = null; URL httpsUrl = mCaptivePortalHttpsUrl; URL httpsUrl = mCaptivePortalHttpsUrl; URL httpUrl = mCaptivePortalHttpUrl; URL httpUrl = mCaptivePortalHttpUrl; URL fallbackUrl = mCaptivePortalFallbackUrl; // On networks with a PAC instead of fetching a URL that should result in a 204 // On networks with a PAC instead of fetching a URL that should result in a 204 // response, we instead simply fetch the PAC script. This is done for a few reasons: // response, we instead simply fetch the PAC script. This is done for a few reasons: Loading Loading @@ -727,7 +765,7 @@ public class NetworkMonitor extends StateMachine { if (pacUrl != null) { if (pacUrl != null) { result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC); result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC); } else if (mUseHttps) { } else if (mUseHttps) { result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl); result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl); } else { } else { result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); } } Loading Loading @@ -789,7 +827,7 @@ public class NetworkMonitor extends StateMachine { @VisibleForTesting @VisibleForTesting protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) { protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) { HttpURLConnection urlConnection = null; HttpURLConnection urlConnection = null; int httpResponseCode = 599; int httpResponseCode = CaptivePortalProbeResult.FAILED_CODE; String redirectUrl = null; String redirectUrl = null; final Stopwatch probeTimer = new Stopwatch().start(); final Stopwatch probeTimer = new Stopwatch().start(); try { try { Loading Loading @@ -827,7 +865,7 @@ public class NetworkMonitor extends StateMachine { if (probeType == ValidationProbeEvent.PROBE_PAC) { if (probeType == ValidationProbeEvent.PROBE_PAC) { validationLog( validationLog( probeType, url, "PAC fetch 200 response interpreted as 204 response."); probeType, url, "PAC fetch 200 response interpreted as 204 response."); httpResponseCode = 204; httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE; } else if (urlConnection.getContentLengthLong() == 0) { } else if (urlConnection.getContentLengthLong() == 0) { // Consider 200 response with "Content-length=0" to not be a captive portal. // Consider 200 response with "Content-length=0" to not be a captive portal. // There's no point in considering this a captive portal as the user cannot // There's no point in considering this a captive portal as the user cannot Loading @@ -835,20 +873,20 @@ public class NetworkMonitor extends StateMachine { // See http://b/9972012. // See http://b/9972012. validationLog(probeType, url, validationLog(probeType, url, "200 response with Content-length=0 interpreted as 204 response."); "200 response with Content-length=0 interpreted as 204 response."); httpResponseCode = 204; httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE; } else if (urlConnection.getContentLengthLong() == -1) { } else if (urlConnection.getContentLengthLong() == -1) { // When no Content-length (default value == -1), attempt to read a byte from the // When no Content-length (default value == -1), attempt to read a byte from the // response. Do not use available() as it is unreliable. See http://b/33498325. // response. Do not use available() as it is unreliable. See http://b/33498325. if (urlConnection.getInputStream().read() == -1) { if (urlConnection.getInputStream().read() == -1) { validationLog( validationLog( probeType, url, "Empty 200 response interpreted as 204 response."); probeType, url, "Empty 200 response interpreted as 204 response."); httpResponseCode = 204; httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE; } } } } } } } catch (IOException e) { } catch (IOException e) { validationLog(probeType, url, "Probably not a portal: exception " + e); validationLog(probeType, url, "Probe failed with exception " + e); if (httpResponseCode == 599) { if (httpResponseCode == CaptivePortalProbeResult.FAILED_CODE) { // TODO: Ping gateway and DNS server and log results. // TODO: Ping gateway and DNS server and log results. } } } finally { } finally { Loading @@ -861,7 +899,7 @@ public class NetworkMonitor extends StateMachine { } } private CaptivePortalProbeResult sendParallelHttpProbes( private CaptivePortalProbeResult sendParallelHttpProbes( ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) { ProxyInfo proxy, URL httpsUrl, URL httpUrl) { // Number of probes to wait for. If a probe completes with a conclusive answer // Number of probes to wait for. If a probe completes with a conclusive answer // it shortcuts the latch immediately by forcing the count to 0. // it shortcuts the latch immediately by forcing the count to 0. final CountDownLatch latch = new CountDownLatch(2); final CountDownLatch latch = new CountDownLatch(2); Loading Loading @@ -920,7 +958,8 @@ public class NetworkMonitor extends StateMachine { if (httpsResult.isPortal() || httpsResult.isSuccessful()) { if (httpsResult.isPortal() || httpsResult.isSuccessful()) { return httpsResult; return httpsResult; } } // If a fallback url is specified, use a fallback probe to try again portal detection. // If a fallback url exists, use a fallback probe to try again portal detection. URL fallbackUrl = nextFallbackUrl(); if (fallbackUrl != null) { if (fallbackUrl != null) { CaptivePortalProbeResult result = CaptivePortalProbeResult result = sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK); sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK); Loading