Commit 5adf37cf authored by Paul Jensen's avatar Paul Jensen Committed by Commit Bot

Listen to default network callbacks for Android Pie.

Listening for LinkProperties changes is required so we can detect if
private DNS is enabled. Register a default-network callback so
NetworkChangeNotifierAutoDetect on Android can listen for these
LinkProperties changes.  Use this default-network callback in place
of CONNECTIVITY_ACTION which is deprecated.

Bug: 885291, 774497
Change-Id: I0e6457f9cb970f1e010171af6c030638b1a667e6
Reviewed-on: https://chromium-review.googlesource.com/1243343
Commit-Queue: Paul Jensen <pauljensen@chromium.org>
Reviewed-by: default avatarCathy Li <chili@chromium.org>
Reviewed-by: default avatarMisha Efimov <mef@chromium.org>
Cr-Commit-Position: refs/heads/master@{#594739}
parent 951a1129
...@@ -71,7 +71,7 @@ public class PrefetchFlowTest implements WebServer.RequestHandler { ...@@ -71,7 +71,7 @@ public class PrefetchFlowTest implements WebServer.RequestHandler {
} }
@Override @Override
public NetworkState getCurrentNetworkState() { public NetworkState getCurrentNetworkState() {
return new NetworkState(true, ConnectivityManager.TYPE_WIFI, 0, null); return new NetworkState(true, ConnectivityManager.TYPE_WIFI, 0, null, false);
} }
} }
......
...@@ -56,6 +56,9 @@ class AndroidNetworkLibrary { ...@@ -56,6 +56,9 @@ class AndroidNetworkLibrary {
private static final String TAG = "AndroidNetworkLibrary"; private static final String TAG = "AndroidNetworkLibrary";
// Cached Method for LinkProperties.isPrivateDnsActive().
private static Method sIsPrivateDnsActiveMethod;
/** /**
* @return the mime type (if any) that is associated with the file * @return the mime type (if any) that is associated with the file
* extension. Returns null if no corresponding mime type exists. * extension. Returns null if no corresponding mime type exists.
...@@ -283,6 +286,27 @@ class AndroidNetworkLibrary { ...@@ -283,6 +286,27 @@ class AndroidNetworkLibrary {
} }
} }
/**
* @returns result of linkProperties.isPrivateDnsActive().
*/
static boolean isPrivateDnsActive(LinkProperties linkProperties) {
if (BuildInfo.isAtLeastP() && linkProperties != null) {
// TODO(pauljensen): When Android P SDK is available, remove reflection.
try {
// This could be racy if called on multiple threads, but races will
// end in the same result so it's not a problem.
if (sIsPrivateDnsActiveMethod == null) {
sIsPrivateDnsActiveMethod =
linkProperties.getClass().getMethod("isPrivateDnsActive");
}
return ((Boolean) sIsPrivateDnsActiveMethod.invoke(linkProperties)).booleanValue();
} catch (Exception e) {
Log.e(TAG, "Can not call LinkProperties.isPrivateDnsActive():", e);
}
}
return false;
}
/** /**
* Returns list of IP addresses of DNS servers. * Returns list of IP addresses of DNS servers.
* If private DNS is active, then returns a 1x1 array. * If private DNS is active, then returns a 1x1 array.
...@@ -304,19 +328,9 @@ class AndroidNetworkLibrary { ...@@ -304,19 +328,9 @@ class AndroidNetworkLibrary {
if (linkProperties == null) { if (linkProperties == null) {
return new byte[0][0]; return new byte[0][0];
} }
if (BuildInfo.isAtLeastP()) { if (isPrivateDnsActive(linkProperties)) {
// TODO(pauljensen): When Android P SDK is available, remove reflection.
try {
if (((Boolean) linkProperties.getClass()
.getMethod("isPrivateDnsActive")
.invoke(linkProperties))
.booleanValue()) {
return new byte[1][1]; return new byte[1][1];
} }
} catch (Exception e) {
Log.e(TAG, "Can not call LinkProperties.isPrivateDnsActive():", e);
}
}
List<InetAddress> dnsServersList = linkProperties.getDnsServers(); List<InetAddress> dnsServersList = linkProperties.getDnsServers();
byte[][] dnsServers = new byte[dnsServersList.size()][]; byte[][] dnsServers = new byte[dnsServersList.size()][];
for (int i = 0; i < dnsServersList.size(); i++) { for (int i = 0; i < dnsServersList.size(); i++) {
......
...@@ -21,6 +21,8 @@ import android.net.Network; ...@@ -21,6 +21,8 @@ import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.os.Build; import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.StrictMode; import android.os.StrictMode;
import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest; import android.support.test.annotation.UiThreadTest;
...@@ -35,6 +37,7 @@ import org.junit.Test; ...@@ -35,6 +37,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.ApplicationState; import org.chromium.base.ApplicationState;
import org.chromium.base.BuildInfo;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryLoader;
...@@ -187,14 +190,17 @@ public class NetworkChangeNotifierTest { ...@@ -187,14 +190,17 @@ public class NetworkChangeNotifierTest {
private boolean mActiveNetworkExists; private boolean mActiveNetworkExists;
private int mNetworkType; private int mNetworkType;
private int mNetworkSubtype; private int mNetworkSubtype;
private boolean mIsPrivateDnsActive;
private NetworkCallback mLastRegisteredNetworkCallback; private NetworkCallback mLastRegisteredNetworkCallback;
private NetworkCallback mLastRegisteredDefaultNetworkCallback;
@Override @Override
public NetworkState getNetworkState(WifiManagerDelegate wifiManagerDelegate) { public NetworkState getNetworkState(WifiManagerDelegate wifiManagerDelegate) {
return new NetworkState(mActiveNetworkExists, mNetworkType, mNetworkSubtype, return new NetworkState(mActiveNetworkExists, mNetworkType, mNetworkSubtype,
mNetworkType == ConnectivityManager.TYPE_WIFI mNetworkType == ConnectivityManager.TYPE_WIFI
? wifiManagerDelegate.getWifiSsid() ? wifiManagerDelegate.getWifiSsid()
: null); : null,
mIsPrivateDnsActive);
} }
@Override @Override
...@@ -246,10 +252,17 @@ public class NetworkChangeNotifierTest { ...@@ -246,10 +252,17 @@ public class NetworkChangeNotifierTest {
// Dummy implementation that also records the last registered callback. // Dummy implementation that also records the last registered callback.
@Override @Override
public void registerNetworkCallback( public void registerNetworkCallback(
NetworkRequest networkRequest, NetworkCallback networkCallback) { NetworkRequest networkRequest, NetworkCallback networkCallback, Handler handler) {
mLastRegisteredNetworkCallback = networkCallback; mLastRegisteredNetworkCallback = networkCallback;
} }
// Dummy implementation that also records the last registered callback.
@Override
public void registerDefaultNetworkCallback(
NetworkCallback networkCallback, Handler handler) {
mLastRegisteredDefaultNetworkCallback = networkCallback;
}
public void setActiveNetworkExists(boolean networkExists) { public void setActiveNetworkExists(boolean networkExists) {
mActiveNetworkExists = networkExists; mActiveNetworkExists = networkExists;
} }
...@@ -262,10 +275,18 @@ public class NetworkChangeNotifierTest { ...@@ -262,10 +275,18 @@ public class NetworkChangeNotifierTest {
mNetworkSubtype = networkSubtype; mNetworkSubtype = networkSubtype;
} }
public void setIsPrivateDnsActive(boolean isPrivateDnsActive) {
mIsPrivateDnsActive = isPrivateDnsActive;
}
public NetworkCallback getLastRegisteredNetworkCallback() { public NetworkCallback getLastRegisteredNetworkCallback() {
return mLastRegisteredNetworkCallback; return mLastRegisteredNetworkCallback;
} }
public NetworkCallback getDefaultNetworkCallback() {
return mLastRegisteredDefaultNetworkCallback;
}
/** /**
* Pretends a network connects. * Pretends a network connects.
* @param netId Network identifier * @param netId Network identifier
...@@ -413,6 +434,8 @@ public class NetworkChangeNotifierTest { ...@@ -413,6 +434,8 @@ public class NetworkChangeNotifierTest {
// Mock out to avoid unintended system interaction. // Mock out to avoid unintended system interaction.
@Override @Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
// Should not be used starting with Pie.
Assert.assertFalse(BuildInfo.isAtLeastP());
return null; return null;
} }
...@@ -581,6 +604,19 @@ public class NetworkChangeNotifierTest { ...@@ -581,6 +604,19 @@ public class NetworkChangeNotifierTest {
Assert.assertEquals(ConnectionSubtype.SUBTYPE_LTE, getCurrentConnectionSubtype()); Assert.assertEquals(ConnectionSubtype.SUBTYPE_LTE, getCurrentConnectionSubtype());
} }
/**
* Indicate to NetworkChangeNotifierAutoDetect that a connectivity change has occurred.
* Uses same signals that system would use.
*/
private void notifyConnectivityChange() {
if (BuildInfo.isAtLeastP()) {
mConnectivityDelegate.getDefaultNetworkCallback().onAvailable(null);
} else {
Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
}
}
/** /**
* Tests that when Chrome gets an intent indicating a change in network connectivity, it sends a * Tests that when Chrome gets an intent indicating a change in network connectivity, it sends a
* notification to Java observers. * notification to Java observers.
...@@ -598,31 +634,51 @@ public class NetworkChangeNotifierTest { ...@@ -598,31 +634,51 @@ public class NetworkChangeNotifierTest {
// We shouldn't be re-notified if the connection hasn't actually changed. // We shouldn't be re-notified if the connection hasn't actually changed.
NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver(); NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver();
NetworkChangeNotifier.addConnectionTypeObserver(observer); NetworkChangeNotifier.addConnectionTypeObserver(observer);
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); notifyConnectivityChange();
Assert.assertFalse(observer.hasReceivedNotification()); Assert.assertFalse(observer.hasReceivedNotification());
// We shouldn't be notified if we're connected to non-Wifi and the Wifi SSID changes. // We shouldn't be notified if we're connected to non-Wifi and the Wifi SSID changes.
mWifiDelegate.setWifiSSID("bar"); mWifiDelegate.setWifiSSID("bar");
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); notifyConnectivityChange();
Assert.assertFalse(observer.hasReceivedNotification()); Assert.assertFalse(observer.hasReceivedNotification());
// We should be notified when we change to Wifi. // We should be notified when we change to Wifi.
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI); mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); notifyConnectivityChange();
Assert.assertTrue(observer.hasReceivedNotification()); Assert.assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification(); observer.resetHasReceivedNotification();
// We should be notified when the Wifi SSID changes. // We should be notified when the Wifi SSID changes.
mWifiDelegate.setWifiSSID("foo"); mWifiDelegate.setWifiSSID("foo");
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); notifyConnectivityChange();
Assert.assertTrue(observer.hasReceivedNotification()); Assert.assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification(); observer.resetHasReceivedNotification();
// We shouldn't be re-notified if the Wifi SSID hasn't actually changed. // We shouldn't be re-notified if the Wifi SSID hasn't actually changed.
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent); notifyConnectivityChange();
Assert.assertFalse(observer.hasReceivedNotification()); Assert.assertFalse(observer.hasReceivedNotification());
// We should be notified if use of DNS-over-TLS changes.
if (BuildInfo.isAtLeastP()) {
// Verify notification for enabling.
mConnectivityDelegate.setIsPrivateDnsActive(true);
mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null);
Assert.assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification();
// Verify no notification for no change.
mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null);
Assert.assertFalse(observer.hasReceivedNotification());
// Verify notification for disbling.
mConnectivityDelegate.setIsPrivateDnsActive(false);
mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null);
Assert.assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification();
}
// Mimic that connectivity has been lost and ensure that Chrome notifies our observer. // Mimic that connectivity has been lost and ensure that Chrome notifies our observer.
mConnectivityDelegate.setActiveNetworkExists(false); mConnectivityDelegate.setActiveNetworkExists(false);
Intent noConnectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); if (BuildInfo.isAtLeastP()) {
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), noConnectivityIntent); mConnectivityDelegate.getDefaultNetworkCallback().onLost(null);
} else {
mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
}
Assert.assertTrue(observer.hasReceivedNotification()); Assert.assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification(); observer.resetHasReceivedNotification();
...@@ -730,7 +786,8 @@ public class NetworkChangeNotifierTest { ...@@ -730,7 +786,8 @@ public class NetworkChangeNotifierTest {
delegate.getDefaultNetwork(); delegate.getDefaultNetwork();
NetworkCallback networkCallback = new NetworkCallback(); NetworkCallback networkCallback = new NetworkCallback();
NetworkRequest networkRequest = new NetworkRequest.Builder().build(); NetworkRequest networkRequest = new NetworkRequest.Builder().build();
delegate.registerNetworkCallback(networkRequest, networkCallback); delegate.registerNetworkCallback(
networkRequest, networkCallback, new Handler(Looper.myLooper()));
delegate.unregisterNetworkCallback(networkCallback); delegate.unregisterNetworkCallback(networkCallback);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment