Merge "CaptivePortalLogin ignores some ssl errors." into oc-dr1-dev

This commit is contained in:
Lorenzo Colitti
2017-07-16 07:38:12 +00:00
committed by Android (Google) Code Review

View File

@@ -30,6 +30,7 @@ import android.net.NetworkRequest;
import android.net.Proxy; import android.net.Proxy;
import android.net.Uri; import android.net.Uri;
import android.net.http.SslError; import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.util.ArrayMap; import android.util.ArrayMap;
@@ -56,6 +57,7 @@ import java.net.URL;
import java.lang.InterruptedException; import java.lang.InterruptedException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Objects;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -285,6 +287,18 @@ public class CaptivePortalLoginActivity extends Activity {
return null; return null;
} }
private static String host(URL url) {
if (url == null) {
return null;
}
return url.getHost();
}
private static String sanitizeURL(URL url) {
// In non-Debug build, only show host to avoid leaking private info.
return Build.IS_DEBUGGABLE ? Objects.toString(url) : host(url);
}
private void testForCaptivePortal() { private void testForCaptivePortal() {
// TODO: reuse NetworkMonitor facilities for consistent captive portal detection. // TODO: reuse NetworkMonitor facilities for consistent captive portal detection.
new Thread(new Runnable() { new Thread(new Runnable() {
@@ -338,6 +352,8 @@ public class CaptivePortalLoginActivity extends Activity {
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
getResources().getDisplayMetrics()); getResources().getDisplayMetrics());
private int mPagesLoaded; private int mPagesLoaded;
// the host of the page that this webview is currently loading. Can be null when undefined.
private String mHostname;
// If we haven't finished cleaning up the history, don't allow going back. // If we haven't finished cleaning up the history, don't allow going back.
public boolean allowBack() { public boolean allowBack() {
@@ -345,8 +361,8 @@ public class CaptivePortalLoginActivity extends Activity {
} }
@Override @Override
public void onPageStarted(WebView view, String url, Bitmap favicon) { public void onPageStarted(WebView view, String urlString, Bitmap favicon) {
if (url.contains(mBrowserBailOutToken)) { if (urlString.contains(mBrowserBailOutToken)) {
mLaunchBrowser = true; mLaunchBrowser = true;
done(Result.WANTED_AS_IS); done(Result.WANTED_AS_IS);
return; return;
@@ -354,11 +370,17 @@ public class CaptivePortalLoginActivity extends Activity {
// The first page load is used only to cause the WebView to // The first page load is used only to cause the WebView to
// fetch the proxy settings. Don't update the URL bar, and // fetch the proxy settings. Don't update the URL bar, and
// don't check if the captive portal is still there. // don't check if the captive portal is still there.
if (mPagesLoaded == 0) return; if (mPagesLoaded == 0) {
return;
}
final URL url = makeURL(urlString);
Log.d(TAG, "onPageSarted: " + sanitizeURL(url));
mHostname = host(url);
// For internally generated pages, leave URL bar listing prior URL as this is the URL // For internally generated pages, leave URL bar listing prior URL as this is the URL
// the page refers to. // the page refers to.
if (!url.startsWith(INTERNAL_ASSETS)) { if (!urlString.startsWith(INTERNAL_ASSETS)) {
getActionBar().setSubtitle(getHeaderSubtitle(url)); String subtitle = (url != null) ? getHeaderSubtitle(url) : urlString;
getActionBar().setSubtitle(subtitle);
} }
getProgressBar().setVisibility(View.VISIBLE); getProgressBar().setVisibility(View.VISIBLE);
testForCaptivePortal(); testForCaptivePortal();
@@ -400,15 +422,18 @@ public class CaptivePortalLoginActivity extends Activity {
@Override @Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
logMetricsEvent(MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR); final URL url = makeURL(error.getUrl());
Log.w(TAG, "SSL error (error: " + error.getPrimaryError() + " host: " + final String host = host(url);
// Only show host to avoid leaking private info. Log.d(TAG, String.format("SSL error: %s, url: %s, certificate: %s",
Uri.parse(error.getUrl()).getHost() + " certificate: " + error.getPrimaryError(), sanitizeURL(url), error.getCertificate()));
error.getCertificate() + "); displaying SSL warning."); if (url == null || !Objects.equals(host, mHostname)) {
final String sslErrorPage = makeSslErrorPage(); // Ignore ssl errors for resources coming from a different hostname than the page
if (VDBG) { // that we are currently loading, and only cancel the request.
Log.d(TAG, sslErrorPage); handler.cancel();
return;
} }
logMetricsEvent(MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR);
final String sslErrorPage = makeSslErrorPage();
view.loadDataWithBaseURL(INTERNAL_ASSETS, sslErrorPage, "text/HTML", "UTF-8", null); view.loadDataWithBaseURL(INTERNAL_ASSETS, sslErrorPage, "text/HTML", "UTF-8", null);
} }
@@ -493,16 +518,13 @@ public class CaptivePortalLoginActivity extends Activity {
return getString(R.string.action_bar_label); return getString(R.string.action_bar_label);
} }
private String getHeaderSubtitle(String urlString) { private String getHeaderSubtitle(URL url) {
URL url = makeURL(urlString); String host = host(url);
if (url == null) {
return urlString;
}
final String https = "https"; final String https = "https";
if (https.equals(url.getProtocol())) { if (https.equals(url.getProtocol())) {
return https + "://" + url.getHost(); return https + "://" + host;
} }
return url.getHost(); return host;
} }
private void logMetricsEvent(int event) { private void logMetricsEvent(int event) {