Handle additional schemes in captive portal
Handle SMS URL schemes, and show an error page for other schemes with an
option to bail out to browser.
Test: atest CaptivePortalLoginTests; change on top
Bug: 131401028
Change-Id: Ic56f2bc757bb47bdf2836783b7ca97f8ff9ecf45
diff --git a/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
old mode 100644
new mode 100755
index ff58ad9..1e45613
--- a/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -24,6 +24,7 @@
import android.app.AlertDialog;
import android.app.Application;
import android.app.admin.DevicePolicyManager;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
@@ -68,6 +69,7 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
import androidx.annotation.VisibleForTesting;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -619,13 +621,14 @@
}
final String continueMsg = getString(R.string.error_continue_via_browser);
- return " <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a><br>";
+ return " <a id=continue_link href=" + mBrowserBailOutToken + ">" + continueMsg
+ + "</a><br>";
}
- private String makeSslErrorPage() {
- final String warningMsg = getString(R.string.ssl_error_warning);
- final String exampleMsg = getString(R.string.ssl_error_example);
- final String certificateMsg = getString(R.string.ssl_error_view_certificate);
+ private String makeErrorPage(@StringRes int warningMsgRes, @StringRes int exampleMsgRes,
+ String extraLink) {
+ final String warningMsg = getString(warningMsgRes);
+ final String exampleMsg = getString(exampleMsgRes);
return String.join("\n",
makeHtmlTag(),
"<head>",
@@ -663,7 +666,7 @@
" text-decoration:none;",
" text-transform:uppercase;",
" }",
- " a.certificate {",
+ " a#cert_link {",
" margin-top:0px;",
" }",
" </style>",
@@ -673,16 +676,37 @@
" <div class=warn>" + warningMsg + "</div>",
" <div class=example>" + exampleMsg + "</div>",
getVpnMsgOrLinkToBrowser(),
- " <a class=certificate href=" + mCertificateOutToken + ">" + certificateMsg +
- "</a>",
+ extraLink,
"</body>",
"</html>");
}
+ private String makeCustomSchemeErrorPage() {
+ return makeErrorPage(R.string.custom_scheme_warning, R.string.custom_scheme_example,
+ "" /* extraLink */);
+ }
+
+ private String makeSslErrorPage() {
+ final String certificateMsg = getString(R.string.ssl_error_view_certificate);
+ return makeErrorPage(R.string.ssl_error_warning, R.string.ssl_error_example,
+ "<a id=cert_link href=" + mCertificateOutToken + ">" + certificateMsg
+ + "</a>");
+ }
+
@Override
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if (url.startsWith("tel:")) {
- startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
+ return startActivity(Intent.ACTION_DIAL, url);
+ } else if (url.startsWith("sms:")) {
+ return startActivity(Intent.ACTION_SENDTO, url);
+ } else if (!url.startsWith("http:")
+ && !url.startsWith("https:") && !url.startsWith(INTERNAL_ASSETS)) {
+ // If the page is not in a supported scheme (HTTP, HTTPS or internal page),
+ // show an error page that informs the user that the page is not supported. The
+ // user can bypass the warning and reopen the portal in browser if needed.
+ // This is done as it is unclear whether third party applications can properly
+ // handle multinetwork scenarios, if the scheme refers to a third party application.
+ loadCustomSchemeErrorPage(view);
return true;
}
if (url.contains(mCertificateOutToken) && mSslError != null) {
@@ -691,6 +715,24 @@
}
return false;
}
+
+ private boolean startActivity(String action, String uriData) {
+ final Intent intent = new Intent(action, Uri.parse(uriData));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ CaptivePortalLoginActivity.this.startActivity(intent);
+ return true;
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found to handle captive portal intent", e);
+ return false;
+ }
+ }
+
+ protected void loadCustomSchemeErrorPage(WebView view) {
+ final String errorPage = makeCustomSchemeErrorPage();
+ view.loadDataWithBaseURL(INTERNAL_ASSETS, errorPage, "text/HTML", "UTF-8", null);
+ }
+
private void showSslAlertDialog(SslErrorHandler handler, SslError error, String title) {
final LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
final View sslWarningView = factory.inflate(R.layout.ssl_warning, null);