| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.chrome.browser.ssl; |
| |
| import android.annotation.TargetApi; |
| import android.content.Context; |
| import android.net.ConnectivityManager; |
| import android.net.Network; |
| import android.os.Build; |
| |
| import org.chromium.base.ContextUtils; |
| import org.chromium.base.annotations.CalledByNative; |
| import org.chromium.base.annotations.JNINamespace; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| /** Helper class for captive portal related methods on Android. */ |
| @JNINamespace("chrome::android") |
| public class CaptivePortalHelper { |
| private static final String DEFAULT_PORTAL_CHECK_URL = |
| "http://connectivitycheck.gstatic.com/generate_204"; |
| |
| public static void setCaptivePortalCertificateForTesting(String spkiHash) { |
| nativeSetCaptivePortalCertificateForTesting(spkiHash); |
| } |
| |
| public static void setOSReportsCaptivePortalForTesting(boolean osReportsCaptivePortal) { |
| nativeSetOSReportsCaptivePortalForTesting(osReportsCaptivePortal); |
| } |
| |
| @CalledByNative |
| private static String getCaptivePortalServerUrl() { |
| // Since Android N MR2 it is possible that a captive portal was detected with a |
| // different URL than getCaptivePortalServerUrl(). By default, Android uses the URL from |
| // getCaptivePortalServerUrl() first, but there are also two additional fallback HTTP |
| // URLs to probe if the first HTTP probe does not find anything. Using the default URL |
| // is acceptable as the return value is only used by the captive portal interstitial. |
| try { |
| Context context = ContextUtils.getApplicationContext(); |
| ConnectivityManager connectivityManager = |
| (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); |
| Method getCaptivePortalServerUrlMethod = |
| connectivityManager.getClass().getMethod("getCaptivePortalServerUrl"); |
| return (String) getCaptivePortalServerUrlMethod.invoke(connectivityManager); |
| } catch (NoSuchMethodException e) { |
| // To avoid crashing, return the default portal check URL on Android. |
| return DEFAULT_PORTAL_CHECK_URL; |
| } catch (IllegalAccessException e) { |
| return DEFAULT_PORTAL_CHECK_URL; |
| } catch (InvocationTargetException e) { |
| return DEFAULT_PORTAL_CHECK_URL; |
| } |
| } |
| |
| @TargetApi(Build.VERSION_CODES.M) |
| @CalledByNative |
| private static void reportNetworkConnectivity() { |
| // Call reportNetworkConnectivity on all networks, including the current network. |
| Context context = ContextUtils.getApplicationContext(); |
| ConnectivityManager connectivityManager = |
| (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); |
| |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| for (Network network : connectivityManager.getAllNetworks()) { |
| // Try both true and false for |hasConnectivity|, that's what reportBadNetwork does. |
| // See |
| // https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/net/ConnectivityManager.java#L2463 |
| // for details. |
| connectivityManager.reportNetworkConnectivity(network, true); |
| connectivityManager.reportNetworkConnectivity(network, false); |
| } |
| return; |
| } |
| |
| try { |
| Class<?> networkClass = Class.forName("android.net.Network"); |
| Method reportNetworkConnectivityMethod = |
| connectivityManager.getClass().getMethod("reportNetworkConnectivity", |
| Class.forName("android.net.Network"), boolean.class); |
| Method getAllNetworksMethod = |
| connectivityManager.getClass().getMethod("getAllNetworks"); |
| |
| for (Object obj : (Object[]) getAllNetworksMethod.invoke(connectivityManager)) { |
| // Try both true and false for |hasConnectivity|, as above. |
| reportNetworkConnectivityMethod.invoke( |
| connectivityManager, new Object[] {networkClass.cast(obj), true}); |
| reportNetworkConnectivityMethod.invoke( |
| connectivityManager, new Object[] {networkClass.cast(obj), false}); |
| } |
| } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException |
| | ClassNotFoundException e) { |
| // Ignore and do nothing. |
| } |
| } |
| |
| private CaptivePortalHelper() {} |
| |
| private static native void nativeSetCaptivePortalCertificateForTesting(String spkiHash); |
| |
| private static native void nativeSetOSReportsCaptivePortalForTesting( |
| boolean osReportsCaptivePortal); |
| } |