Merge "Prepare CaptivePortalLogin for system_current"
This commit is contained in:
27
packages/CaptivePortalLogin/Android.bp
Normal file
27
packages/CaptivePortalLogin/Android.bp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Copyright (C) 2019 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
android_app {
|
||||||
|
name: "CaptivePortalLogin",
|
||||||
|
srcs: ["src/**/*.java"],
|
||||||
|
platform_apis: true,
|
||||||
|
certificate: "platform",
|
||||||
|
static_libs: [
|
||||||
|
"android-support-v4",
|
||||||
|
"metrics-constants-protos",
|
||||||
|
],
|
||||||
|
manifest: "AndroidManifest.xml",
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
LOCAL_PATH:= $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
|
|
||||||
LOCAL_MODULE_TAGS := optional
|
|
||||||
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
|
|
||||||
|
|
||||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
|
||||||
|
|
||||||
LOCAL_PACKAGE_NAME := CaptivePortalLogin
|
|
||||||
LOCAL_PRIVATE_PLATFORM_APIS := true
|
|
||||||
LOCAL_CERTIFICATE := platform
|
|
||||||
|
|
||||||
include $(BUILD_PACKAGE)
|
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
|
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
|
||||||
<uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
|
<uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2018 The Android Open Source Project
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/ssl_error_msg"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
|
||||||
android:layout_marginStart="20dip"
|
|
||||||
android:layout_marginEnd="20dip"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:layout_marginBottom="4dip"
|
|
||||||
android:layout_marginTop="4dip" />
|
|
||||||
|
|
||||||
@@ -78,7 +78,18 @@
|
|||||||
android:id="@+id/certificate_layout"
|
android:id="@+id/certificate_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_marginBottom="16dip" >
|
android:layout_marginBottom="16dip" >
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ssl_error_msg"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:layout_marginStart="20dip"
|
||||||
|
android:layout_marginEnd="20dip"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginBottom="4dip"
|
||||||
|
android:layout_marginTop="16dip" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.LoadedApk;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -37,8 +37,9 @@ import android.net.captiveportal.CaptivePortalProbeSpec;
|
|||||||
import android.net.http.SslCertificate;
|
import android.net.http.SslCertificate;
|
||||||
import android.net.http.SslError;
|
import android.net.http.SslError;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.os.Build;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.SystemProperties;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
@@ -95,6 +96,7 @@ public class CaptivePortalLoginActivity extends Activity {
|
|||||||
private CaptivePortal mCaptivePortal;
|
private CaptivePortal mCaptivePortal;
|
||||||
private NetworkCallback mNetworkCallback;
|
private NetworkCallback mNetworkCallback;
|
||||||
private ConnectivityManager mCm;
|
private ConnectivityManager mCm;
|
||||||
|
private WifiManager mWifiManager;
|
||||||
private boolean mLaunchBrowser = false;
|
private boolean mLaunchBrowser = false;
|
||||||
private MyWebViewClient mWebViewClient;
|
private MyWebViewClient mWebViewClient;
|
||||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
@@ -108,7 +110,8 @@ public class CaptivePortalLoginActivity extends Activity {
|
|||||||
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
|
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
|
||||||
logMetricsEvent(MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
|
logMetricsEvent(MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
|
||||||
|
|
||||||
mCm = ConnectivityManager.from(this);
|
mCm = getSystemService(ConnectivityManager.class);
|
||||||
|
mWifiManager = getSystemService(WifiManager.class);
|
||||||
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
|
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
|
||||||
mUserAgent =
|
mUserAgent =
|
||||||
getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
|
getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
|
||||||
@@ -150,7 +153,6 @@ public class CaptivePortalLoginActivity extends Activity {
|
|||||||
// Also initializes proxy system properties.
|
// Also initializes proxy system properties.
|
||||||
mNetwork = mNetwork.getPrivateDnsBypassingCopy();
|
mNetwork = mNetwork.getPrivateDnsBypassingCopy();
|
||||||
mCm.bindProcessToNetwork(mNetwork);
|
mCm.bindProcessToNetwork(mNetwork);
|
||||||
mCm.setProcessDefaultNetworkForHostResolution(mNetwork);
|
|
||||||
|
|
||||||
// Proxy system properties must be initialized before setContentView is called because
|
// Proxy system properties must be initialized before setContentView is called because
|
||||||
// setContentView initializes the WebView logic which in turn reads the system properties.
|
// setContentView initializes the WebView logic which in turn reads the system properties.
|
||||||
@@ -189,9 +191,12 @@ public class CaptivePortalLoginActivity extends Activity {
|
|||||||
|
|
||||||
// Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
|
// Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
|
||||||
private void setWebViewProxy() {
|
private void setWebViewProxy() {
|
||||||
LoadedApk loadedApk = getApplication().mLoadedApk;
|
// TODO: migrate to androidx WebView proxy setting API as soon as it is finalized
|
||||||
try {
|
try {
|
||||||
Field receiversField = LoadedApk.class.getDeclaredField("mReceivers");
|
final Field loadedApkField = Application.class.getDeclaredField("mLoadedApk");
|
||||||
|
final Class<?> loadedApkClass = loadedApkField.getType();
|
||||||
|
final Object loadedApk = loadedApkField.get(getApplication());
|
||||||
|
Field receiversField = loadedApkClass.getDeclaredField("mReceivers");
|
||||||
receiversField.setAccessible(true);
|
receiversField.setAccessible(true);
|
||||||
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
|
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
|
||||||
for (Object receiverMap : receivers.values()) {
|
for (Object receiverMap : receivers.values()) {
|
||||||
@@ -332,7 +337,11 @@ public class CaptivePortalLoginActivity extends Activity {
|
|||||||
|
|
||||||
private static String sanitizeURL(URL url) {
|
private static String sanitizeURL(URL url) {
|
||||||
// In non-Debug build, only show host to avoid leaking private info.
|
// In non-Debug build, only show host to avoid leaking private info.
|
||||||
return Build.IS_DEBUGGABLE ? Objects.toString(url) : host(url);
|
return isDebuggable() ? Objects.toString(url) : host(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDebuggable() {
|
||||||
|
return SystemProperties.getInt("ro.debuggable", 0) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testForCaptivePortal() {
|
private void testForCaptivePortal() {
|
||||||
@@ -585,19 +594,18 @@ public class CaptivePortalLoginActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setViewSecurityCertificate(LinearLayout certificateLayout, SslError error) {
|
private void setViewSecurityCertificate(LinearLayout certificateLayout, SslError error) {
|
||||||
|
((TextView) certificateLayout.findViewById(R.id.ssl_error_msg))
|
||||||
|
.setText(sslErrorMessage(error));
|
||||||
SslCertificate cert = error.getCertificate();
|
SslCertificate cert = error.getCertificate();
|
||||||
|
// TODO: call the method directly once inflateCertificateView is @SystemApi
|
||||||
View certificateView = cert.inflateCertificateView(CaptivePortalLoginActivity.this);
|
try {
|
||||||
final LinearLayout placeholder = (LinearLayout) certificateView
|
final View certificateView = (View) SslCertificate.class.getMethod(
|
||||||
.findViewById(com.android.internal.R.id.placeholder);
|
"inflateCertificateView", Context.class)
|
||||||
LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
|
.invoke(cert, CaptivePortalLoginActivity.this);
|
||||||
|
certificateLayout.addView(certificateView);
|
||||||
TextView textView = (TextView) factory.inflate(
|
} catch (ReflectiveOperationException | SecurityException e) {
|
||||||
R.layout.ssl_error_msg, placeholder, false);
|
Log.e(TAG, "Could not create certificate view", e);
|
||||||
textView.setText(sslErrorMessage(error));
|
}
|
||||||
placeholder.addView(textView);
|
|
||||||
|
|
||||||
certificateLayout.addView(certificateView);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,11 +626,30 @@ public class CaptivePortalLoginActivity extends Activity {
|
|||||||
|
|
||||||
private String getHeaderTitle() {
|
private String getHeaderTitle() {
|
||||||
NetworkCapabilities nc = mCm.getNetworkCapabilities(mNetwork);
|
NetworkCapabilities nc = mCm.getNetworkCapabilities(mNetwork);
|
||||||
if (nc == null || TextUtils.isEmpty(nc.getSSID())
|
final String ssid = getSsid();
|
||||||
|| !nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
|
if (TextUtils.isEmpty(ssid)
|
||||||
|
|| nc == null || !nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
|
||||||
return getString(R.string.action_bar_label);
|
return getString(R.string.action_bar_label);
|
||||||
}
|
}
|
||||||
return getString(R.string.action_bar_title, WifiInfo.removeDoubleQuotes(nc.getSSID()));
|
return getString(R.string.action_bar_title, ssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove once SSID is obtained from NetworkCapabilities
|
||||||
|
private String getSsid() {
|
||||||
|
if (mWifiManager == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
|
||||||
|
return removeDoubleQuotes(wifiInfo.getSSID());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String removeDoubleQuotes(String string) {
|
||||||
|
if (string == null) return null;
|
||||||
|
final int length = string.length();
|
||||||
|
if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
|
||||||
|
return string.substring(1, length - 1);
|
||||||
|
}
|
||||||
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getHeaderSubtitle(URL url) {
|
private String getHeaderSubtitle(URL url) {
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ public class NetworkMonitor extends StateMachine {
|
|||||||
private static final boolean DBG = true;
|
private static final boolean DBG = true;
|
||||||
private static final boolean VDBG = false;
|
private static final boolean VDBG = false;
|
||||||
private static final boolean VDBG_STALL = Log.isLoggable(TAG, Log.DEBUG);
|
private static final boolean VDBG_STALL = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
// TODO: use another permission for CaptivePortalLoginActivity once it has its own certificate
|
||||||
|
private static final String PERMISSION_NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS";
|
||||||
// Default configuration values for captive portal detection probes.
|
// Default configuration values for captive portal detection probes.
|
||||||
// TODO: append a random length parameter to the default HTTPS url.
|
// TODO: append a random length parameter to the default HTTPS url.
|
||||||
// TODO: randomize browser version ids in the default User-Agent String.
|
// TODO: randomize browser version ids in the default User-Agent String.
|
||||||
@@ -682,7 +684,7 @@ public class NetworkMonitor extends StateMachine {
|
|||||||
public void appResponse(int response) {
|
public void appResponse(int response) {
|
||||||
if (response == APP_RETURN_WANTED_AS_IS) {
|
if (response == APP_RETURN_WANTED_AS_IS) {
|
||||||
mContext.enforceCallingPermission(
|
mContext.enforceCallingPermission(
|
||||||
android.Manifest.permission.CONNECTIVITY_INTERNAL,
|
PERMISSION_NETWORK_SETTINGS,
|
||||||
"CaptivePortal");
|
"CaptivePortal");
|
||||||
}
|
}
|
||||||
sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
|
sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
|
||||||
@@ -692,7 +694,7 @@ public class NetworkMonitor extends StateMachine {
|
|||||||
public void logEvent(int eventId, String packageName)
|
public void logEvent(int eventId, String packageName)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
mContext.enforceCallingPermission(
|
mContext.enforceCallingPermission(
|
||||||
android.Manifest.permission.CONNECTIVITY_INTERNAL,
|
PERMISSION_NETWORK_SETTINGS,
|
||||||
"CaptivePortal");
|
"CaptivePortal");
|
||||||
mCallback.logCaptivePortalLoginEvent(eventId, packageName);
|
mCallback.logCaptivePortalLoginEvent(eventId, packageName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,3 +17,24 @@ java_library_static {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java_library_static {
|
||||||
|
name: "metrics-constants-protos",
|
||||||
|
host_supported: true,
|
||||||
|
proto: {
|
||||||
|
type: "nano",
|
||||||
|
},
|
||||||
|
srcs: ["src/metrics_constants.proto"],
|
||||||
|
no_framework_libs: true,
|
||||||
|
sdk_version: "system_current",
|
||||||
|
// Pin java_version until jarjar is certified to support later versions. http://b/72703434
|
||||||
|
java_version: "1.8",
|
||||||
|
target: {
|
||||||
|
android: {
|
||||||
|
jarjar_rules: "jarjar-rules.txt",
|
||||||
|
},
|
||||||
|
host: {
|
||||||
|
static_libs: ["libprotobuf-java-nano"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user