Skip to content

Commit d783dfe

Browse files
committed
fix: internet walled check logic
Signed-off-by: alperozturk <alper_ozturk@proton.me>
1 parent 3ea4f90 commit d783dfe

File tree

1 file changed

+74
-65
lines changed

1 file changed

+74
-65
lines changed

app/src/main/java/com/nextcloud/client/network/ConnectivityServiceImpl.java

Lines changed: 74 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424

2525
import org.apache.commons.httpclient.HttpStatus;
2626

27+
import java.util.concurrent.ExecutorService;
28+
import java.util.concurrent.Executors;
29+
2730
import androidx.annotation.NonNull;
28-
import androidx.core.net.ConnectivityManagerCompat;
2931
import kotlin.jvm.functions.Function1;
3032

3133
class ConnectivityServiceImpl implements ConnectivityService {
@@ -38,6 +40,7 @@ class ConnectivityServiceImpl implements ConnectivityService {
3840
private final ClientFactory clientFactory;
3941
private final GetRequestBuilder requestBuilder;
4042
private final WalledCheckCache walledCheckCache;
43+
private final ExecutorService executor = Executors.newSingleThreadExecutor();
4144
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
4245

4346
static class GetRequestBuilder implements Function1<String, GetMethod> {
@@ -61,22 +64,28 @@ public GetMethod invoke(String url) {
6164

6265
@Override
6366
public void isNetworkAndServerAvailable(@NonNull GenericCallback<Boolean> callback) {
64-
new Thread(() -> {
65-
Network activeNetwork = platformConnectivityManager.getActiveNetwork();
66-
NetworkCapabilities networkCapabilities = platformConnectivityManager.getNetworkCapabilities(activeNetwork);
67-
boolean hasInternet = networkCapabilities != null && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
68-
69-
boolean result;
70-
if (hasInternet) {
71-
result = !isInternetWalled();
72-
} else {
73-
result = false;
74-
}
75-
76-
mainThreadHandler.post(() -> callback.onComplete(result));
77-
}).start();
67+
executor.submit(() -> {
68+
boolean isAvailable = !isInternetWalled();
69+
mainThreadHandler.post(() -> callback.onComplete(isAvailable));
70+
});
7871
}
7972

73+
/**
74+
* Checks whether the device is currently connected to a network
75+
* that has verified Internet access.
76+
*
77+
* <p>This method performs multiple levels of validation:
78+
* <ul>
79+
* <li>Ensures there is an active network connection.</li>
80+
* <li>Retrieves and checks network capabilities.</li>
81+
* <li>Verifies that the active network provides and has validated Internet access.</li>
82+
* <li>Confirms that the network uses a supported transport type
83+
* (Wi-Fi, Cellular, Ethernet, VPN, etc.).</li>
84+
* </ul>
85+
*
86+
* @return {@code true} if the device is connected to the Internet via a valid transport type;
87+
* {@code false} otherwise.
88+
*/
8089
@Override
8190
public boolean isConnected() {
8291
Network nw = platformConnectivityManager.getActiveNetwork();
@@ -89,18 +98,28 @@ public boolean isConnected() {
8998
return false;
9099
}
91100

92-
if (actNw.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ||
93-
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
94-
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
95-
actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
96-
actNw.hasTransport(NetworkCapabilities.TRANSPORT_VPN) ||
97-
actNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) ||
98-
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
99-
return true;
101+
// Verify that the network both claims to provide Internet
102+
// and has been validated (i.e., Internet is actually reachable).
103+
if (actNw.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && actNw.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
104+
105+
// Check if the active network uses one of the recognized transport types.
106+
if (actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
107+
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
108+
actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
109+
actNw.hasTransport(NetworkCapabilities.TRANSPORT_VPN) ||
110+
actNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) ||
111+
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
112+
113+
// Connected through a valid, verified network transport.
114+
return true;
115+
}
116+
117+
// If still nothing matched check Android 12 (API 31, "S") and above via USB network transport.
118+
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
119+
actNw.hasTransport(NetworkCapabilities.TRANSPORT_USB);
100120
}
101121

102-
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
103-
actNw.hasTransport(NetworkCapabilities.TRANSPORT_USB);
122+
return false;
104123
}
105124

106125
@Override
@@ -110,31 +129,36 @@ public boolean isInternetWalled() {
110129
return cachedValue;
111130
}
112131

113-
Server server = accountManager.getUser().getServer();
114-
String baseServerAddress = server.getUri().toString();
115-
116-
boolean result = false;
117-
if (isConnected() && !baseServerAddress.isEmpty()) {
118-
try {
119-
GetMethod get = requestBuilder.invoke(baseServerAddress + CONNECTIVITY_CHECK_ROUTE);
120-
PlainClient client = clientFactory.createPlainClient();
121-
122-
int status = get.execute(client);
123-
124-
// Content-Length is not available when using chunked transfer encoding, so check for -1 as well
125-
result = !(status == HttpStatus.SC_NO_CONTENT && get.getResponseContentLength() <= 0);
126-
get.releaseConnection();
127-
if (result) {
128-
Log_OC.w(TAG, "isInternetWalled(): Failed to GET " + CONNECTIVITY_CHECK_ROUTE + "," +
129-
" assuming connectivity is impaired");
130-
}
131-
} catch (Exception e) {
132-
Log_OC.e(TAG, "Exception while checking internet walled state" + e);
133-
}
132+
final Server server = accountManager.getUser().getServer();
133+
final String baseServerAddress = server.getUri().toString();
134+
135+
if (!isConnected() || baseServerAddress.isEmpty()) {
136+
walledCheckCache.setValue(true);
137+
return true;
134138
}
135139

136-
walledCheckCache.setValue(result);
137-
return result;
140+
final GetMethod get = requestBuilder.invoke(baseServerAddress + CONNECTIVITY_CHECK_ROUTE);
141+
try {
142+
final PlainClient client = clientFactory.createPlainClient();
143+
int status = get.execute(client);
144+
145+
boolean isWalled = !(status == HttpStatus.SC_NO_CONTENT && get.getResponseContentLength() <= 0);
146+
147+
if (isWalled) {
148+
Log_OC.w(TAG, "isInternetWalled(): Failed to GET " + CONNECTIVITY_CHECK_ROUTE +
149+
", assuming connectivity is impaired");
150+
}
151+
152+
// Cache and return result
153+
walledCheckCache.setValue(isWalled);
154+
return isWalled;
155+
} catch (Exception e) {
156+
Log_OC.e(TAG, "Exception while checking internet walled state", e);
157+
walledCheckCache.setValue(true);
158+
return true;
159+
} finally {
160+
get.releaseConnection();
161+
}
138162
}
139163

140164
@Override
@@ -146,27 +170,12 @@ public Connectivity getConnectivity() {
146170

147171
NetworkCapabilities nc = platformConnectivityManager.getNetworkCapabilities(nw);
148172
boolean isConnected = isConnected();
149-
boolean isMetered = isNetworkMetered();
150-
boolean isWifi = nc != null &&
173+
boolean isMetered = (nc != null) && !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
174+
boolean isWifi = (nc != null) &&
151175
(nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
152176
nc.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
153177
nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE));
154178

155179
return new Connectivity(isConnected, isMetered, isWifi, null);
156180
}
157-
158-
private boolean isNetworkMetered() {
159-
final Network network = platformConnectivityManager.getActiveNetwork();
160-
try {
161-
NetworkCapabilities networkCapabilities = platformConnectivityManager.getNetworkCapabilities(network);
162-
if (networkCapabilities != null) {
163-
return !networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
164-
} else {
165-
return ConnectivityManagerCompat.isActiveNetworkMetered(platformConnectivityManager);
166-
}
167-
} catch (RuntimeException e) {
168-
Log_OC.e(TAG, "Exception when checking network capabilities", e);
169-
return false;
170-
}
171-
}
172181
}

0 commit comments

Comments
 (0)