diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppDependencies.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppDependencies.kt index 03d5b5bc6a..508598a19c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppDependencies.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/AppDependencies.kt @@ -446,7 +446,7 @@ object AppDependencies { fun provideProvisioningApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): ProvisioningApi fun provideCertificateApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): CertificateApi fun provideProfileApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket, pushServiceSocket: PushServiceSocket, clientZkProfileOperations: ClientZkProfileOperations): ProfileApi - fun provideRemoteConfigApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): RemoteConfigApi + fun provideRemoteConfigApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, pushServiceSocket: PushServiceSocket): RemoteConfigApi fun provideDonationsApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): DonationsApi } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java index 6e0cc26b33..cf7c01efec 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java @@ -564,8 +564,8 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider { } @Override - public @NonNull RemoteConfigApi provideRemoteConfigApi(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket) { - return new RemoteConfigApi(authWebSocket); + public @NonNull RemoteConfigApi provideRemoteConfigApi(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket, @NonNull PushServiceSocket pushServiceSocket) { + return new RemoteConfigApi(authWebSocket, pushServiceSocket); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/NetworkDependenciesModule.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/NetworkDependenciesModule.kt index 74cff95d79..42785200d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/NetworkDependenciesModule.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/NetworkDependenciesModule.kt @@ -211,7 +211,7 @@ class NetworkDependenciesModule( } val remoteConfigApi: RemoteConfigApi by lazy { - provider.provideRemoteConfigApi(authWebSocket) + provider.provideRemoteConfigApi(authWebSocket, pushServiceSocket) } val donationsApi: DonationsApi by lazy { diff --git a/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.kt b/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.kt index c6bc9e160f..e08f6a2112 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.kt @@ -293,7 +293,7 @@ class MockApplicationDependencyProvider : AppDependencies.Provider { return mockk(relaxed = true) } - override fun provideRemoteConfigApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): RemoteConfigApi { + override fun provideRemoteConfigApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, pushServiceSocket: PushServiceSocket): RemoteConfigApi { return mockk(relaxed = true) } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigApi.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigApi.kt index 08ba54e90c..a2d8b444a9 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigApi.kt +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigApi.kt @@ -8,6 +8,7 @@ package org.whispersystems.signalservice.api.remoteconfig import org.whispersystems.signalservice.api.NetworkResult import org.whispersystems.signalservice.api.websocket.SignalWebSocket import org.whispersystems.signalservice.internal.get +import org.whispersystems.signalservice.internal.push.PushServiceSocket import org.whispersystems.signalservice.internal.util.JsonUtil import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage import org.whispersystems.signalservice.internal.websocket.WebsocketResponse @@ -17,7 +18,7 @@ import org.whispersystems.signalservice.internal.websocket.WebsocketResponse * * Configuration values change over time, and the list should be refreshed periodically. */ -class RemoteConfigApi(val authWebSocket: SignalWebSocket.AuthenticatedWebSocket) { +class RemoteConfigApi(val authWebSocket: SignalWebSocket.AuthenticatedWebSocket, val pushServiceSocket: PushServiceSocket) { /** * Get remote config data from the server. @@ -28,6 +29,16 @@ class RemoteConfigApi(val authWebSocket: SignalWebSocket.AuthenticatedWebSocket) fun getRemoteConfig(): NetworkResult { val request = WebSocketRequestMessage.get("/v1/config") return NetworkResult.fromWebSocketRequest(signalWebSocket = authWebSocket, request = request, webSocketResponseConverter = RemoteConfigResultWebSocketResponseConverter()) + .fallback { + NetworkResult.fromFetch { + val response = pushServiceSocket.getRemoteConfig() + val transformed = response.config.associate { it.name to (it.value ?: it.isEnabled) } + RemoteConfigResult( + config = transformed, + serverEpochTimeMilliseconds = response.serverEpochTime.takeIf { it > 0 }?.times(1000) ?: System.currentTimeMillis() + ) + } + } } /** diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigResponse.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigResponse.java index a7c5cb5a83..1f28fc990a 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigResponse.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/remoteconfig/RemoteConfigResponse.java @@ -15,10 +15,17 @@ public class RemoteConfigResponse { @JsonProperty private List config; + @JsonProperty + private long serverEpochTime; + public List getConfig() { return config; } + public long getServerEpochTime() { + return serverEpochTime; + } + public static class Config { @JsonProperty private String name; diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index be29b95805..f5c07fc542 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -35,6 +35,7 @@ import org.whispersystems.signalservice.api.messages.calls.CallingResponse; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignedPreKeyEntity; import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException; +import org.whispersystems.signalservice.api.remoteconfig.RemoteConfigResponse; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; import org.whispersystems.signalservice.api.push.exceptions.ChallengeRequiredException; import org.whispersystems.signalservice.api.push.exceptions.ConflictException; @@ -533,6 +534,11 @@ public class PushServiceSocket { } } + public RemoteConfigResponse getRemoteConfig() throws IOException { + String response = makeServiceRequest("/v1/config", "GET", null); + return JsonUtil.fromJson(response, RemoteConfigResponse.class); + } + public void cancelInFlightRequests() { synchronized (connections) { Log.w(TAG, "Canceling: " + connections.size());