mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-07-25 15:34:49 +01:00
Convert provisioning and certificate endpoints to WebSocket and finalize attachments.
This commit is contained in:
+3
-3
@@ -26,10 +26,10 @@ import org.thoughtcrime.securesms.testing.runSync
|
||||
import org.thoughtcrime.securesms.testing.success
|
||||
import org.whispersystems.signalservice.api.SignalServiceDataStore
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||
import org.whispersystems.signalservice.api.attachment.AttachmentApi
|
||||
import org.whispersystems.signalservice.api.keys.KeysApi
|
||||
import org.whispersystems.signalservice.api.message.MessageApi
|
||||
import org.whispersystems.signalservice.api.push.TrustStore
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalCdsiUrl
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration
|
||||
@@ -123,14 +123,14 @@ class InstrumentationApplicationDependencyProvider(val application: Application,
|
||||
}
|
||||
|
||||
override fun provideSignalServiceMessageSender(
|
||||
authWebSocket: SignalWebSocket.AuthenticatedWebSocket,
|
||||
protocolStore: SignalServiceDataStore,
|
||||
pushServiceSocket: PushServiceSocket,
|
||||
attachmentApi: AttachmentApi,
|
||||
messageApi: MessageApi,
|
||||
keysApi: KeysApi
|
||||
): SignalServiceMessageSender {
|
||||
if (signalServiceMessageSender == null) {
|
||||
signalServiceMessageSender = spyk(objToCopy = default.provideSignalServiceMessageSender(authWebSocket, protocolStore, pushServiceSocket, messageApi, keysApi))
|
||||
signalServiceMessageSender = spyk(objToCopy = default.provideSignalServiceMessageSender(protocolStore, pushServiceSocket, attachmentApi, messageApi, keysApi))
|
||||
}
|
||||
return signalServiceMessageSender!!
|
||||
}
|
||||
|
||||
+2
-2
@@ -206,8 +206,8 @@ class ChangeNumberRepository(
|
||||
|
||||
for (certificateType in certificateTypes) {
|
||||
val certificate: ByteArray? = when (certificateType) {
|
||||
CertificateType.ACI_AND_E164 -> accountManager.senderCertificate
|
||||
CertificateType.ACI_ONLY -> accountManager.senderCertificateForPhoneNumberPrivacy
|
||||
CertificateType.ACI_AND_E164 -> SignalNetwork.certificate.getSenderCertificate().successOrThrow()
|
||||
CertificateType.ACI_ONLY -> SignalNetwork.certificate.getSenderCertificateForPhoneNumberPrivacy().successOrThrow()
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
|
||||
|
||||
@@ -47,11 +47,13 @@ import org.whispersystems.signalservice.api.archive.ArchiveApi
|
||||
import org.whispersystems.signalservice.api.attachment.AttachmentApi
|
||||
import org.whispersystems.signalservice.api.calling.CallingApi
|
||||
import org.whispersystems.signalservice.api.cds.CdsApi
|
||||
import org.whispersystems.signalservice.api.certificate.CertificateApi
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
|
||||
import org.whispersystems.signalservice.api.keys.KeysApi
|
||||
import org.whispersystems.signalservice.api.link.LinkDeviceApi
|
||||
import org.whispersystems.signalservice.api.message.MessageApi
|
||||
import org.whispersystems.signalservice.api.payments.PaymentsApi
|
||||
import org.whispersystems.signalservice.api.provisioning.ProvisioningApi
|
||||
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
|
||||
import org.whispersystems.signalservice.api.registration.RegistrationApi
|
||||
import org.whispersystems.signalservice.api.services.DonationsService
|
||||
@@ -334,6 +336,12 @@ object AppDependencies {
|
||||
val messageApi: MessageApi
|
||||
get() = networkModule.messageApi
|
||||
|
||||
val provisioningApi: ProvisioningApi
|
||||
get() = networkModule.provisioningApi
|
||||
|
||||
val certificateApi: CertificateApi
|
||||
get() = networkModule.certificateApi
|
||||
|
||||
@JvmStatic
|
||||
val okHttpClient: OkHttpClient
|
||||
get() = networkModule.okHttpClient
|
||||
@@ -362,7 +370,7 @@ object AppDependencies {
|
||||
fun providePushServiceSocket(signalServiceConfiguration: SignalServiceConfiguration, groupsV2Operations: GroupsV2Operations): PushServiceSocket
|
||||
fun provideGroupsV2Operations(signalServiceConfiguration: SignalServiceConfiguration): GroupsV2Operations
|
||||
fun provideSignalServiceAccountManager(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, accountApi: AccountApi, pushServiceSocket: PushServiceSocket, groupsV2Operations: GroupsV2Operations): SignalServiceAccountManager
|
||||
fun provideSignalServiceMessageSender(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, protocolStore: SignalServiceDataStore, pushServiceSocket: PushServiceSocket, messageApi: MessageApi, keysApi: KeysApi): SignalServiceMessageSender
|
||||
fun provideSignalServiceMessageSender(protocolStore: SignalServiceDataStore, pushServiceSocket: PushServiceSocket, attachmentApi: AttachmentApi, messageApi: MessageApi, keysApi: KeysApi): SignalServiceMessageSender
|
||||
fun provideSignalServiceMessageReceiver(pushServiceSocket: PushServiceSocket): SignalServiceMessageReceiver
|
||||
fun provideSignalServiceNetworkAccess(): SignalServiceNetworkAccess
|
||||
fun provideRecipientCache(): LiveRecipientCache
|
||||
@@ -411,5 +419,7 @@ object AppDependencies {
|
||||
fun provideCdsApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): CdsApi
|
||||
fun provideRateLimitChallengeApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): RateLimitChallengeApi
|
||||
fun provideMessageApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): MessageApi
|
||||
fun provideProvisioningApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): ProvisioningApi
|
||||
fun provideCertificateApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): CertificateApi
|
||||
}
|
||||
}
|
||||
|
||||
+15
-3
@@ -86,12 +86,14 @@ import org.whispersystems.signalservice.api.archive.ArchiveApi;
|
||||
import org.whispersystems.signalservice.api.attachment.AttachmentApi;
|
||||
import org.whispersystems.signalservice.api.calling.CallingApi;
|
||||
import org.whispersystems.signalservice.api.cds.CdsApi;
|
||||
import org.whispersystems.signalservice.api.certificate.CertificateApi;
|
||||
import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.keys.KeysApi;
|
||||
import org.whispersystems.signalservice.api.link.LinkDeviceApi;
|
||||
import org.whispersystems.signalservice.api.message.MessageApi;
|
||||
import org.whispersystems.signalservice.api.payments.PaymentsApi;
|
||||
import org.whispersystems.signalservice.api.provisioning.ProvisioningApi;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi;
|
||||
@@ -151,15 +153,15 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull SignalServiceMessageSender provideSignalServiceMessageSender(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket,
|
||||
@NonNull SignalServiceDataStore protocolStore,
|
||||
public @NonNull SignalServiceMessageSender provideSignalServiceMessageSender(@NonNull SignalServiceDataStore protocolStore,
|
||||
@NonNull PushServiceSocket pushServiceSocket,
|
||||
@NonNull AttachmentApi attachmentApi,
|
||||
@NonNull MessageApi messageApi,
|
||||
@NonNull KeysApi keysApi) {
|
||||
return new SignalServiceMessageSender(pushServiceSocket,
|
||||
protocolStore,
|
||||
ReentrantSessionLock.INSTANCE,
|
||||
authWebSocket,
|
||||
attachmentApi,
|
||||
messageApi,
|
||||
keysApi,
|
||||
Optional.of(new SecurityEventListener(context)),
|
||||
@@ -535,6 +537,16 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
return new MessageApi(authWebSocket, unauthWebSocket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ProvisioningApi provideProvisioningApi(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket) {
|
||||
return new ProvisioningApi(authWebSocket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CertificateApi provideCertificateApi(@NonNull SignalWebSocket.AuthenticatedWebSocket authWebSocket) {
|
||||
return new CertificateApi(authWebSocket);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class DynamicCredentialsProvider implements CredentialsProvider {
|
||||
|
||||
|
||||
+11
-1
@@ -32,11 +32,13 @@ import org.whispersystems.signalservice.api.archive.ArchiveApi
|
||||
import org.whispersystems.signalservice.api.attachment.AttachmentApi
|
||||
import org.whispersystems.signalservice.api.calling.CallingApi
|
||||
import org.whispersystems.signalservice.api.cds.CdsApi
|
||||
import org.whispersystems.signalservice.api.certificate.CertificateApi
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
|
||||
import org.whispersystems.signalservice.api.keys.KeysApi
|
||||
import org.whispersystems.signalservice.api.link.LinkDeviceApi
|
||||
import org.whispersystems.signalservice.api.message.MessageApi
|
||||
import org.whispersystems.signalservice.api.payments.PaymentsApi
|
||||
import org.whispersystems.signalservice.api.provisioning.ProvisioningApi
|
||||
import org.whispersystems.signalservice.api.push.TrustStore
|
||||
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
|
||||
import org.whispersystems.signalservice.api.registration.RegistrationApi
|
||||
@@ -82,7 +84,7 @@ class NetworkDependenciesModule(
|
||||
val protocolStore: SignalServiceDataStoreImpl by _protocolStore
|
||||
|
||||
private val _signalServiceMessageSender = resettableLazy {
|
||||
provider.provideSignalServiceMessageSender(authWebSocket, protocolStore, pushServiceSocket, messageApi, keysApi)
|
||||
provider.provideSignalServiceMessageSender(protocolStore, pushServiceSocket, attachmentApi, messageApi, keysApi)
|
||||
}
|
||||
val signalServiceMessageSender: SignalServiceMessageSender by _signalServiceMessageSender
|
||||
|
||||
@@ -193,6 +195,14 @@ class NetworkDependenciesModule(
|
||||
provider.provideMessageApi(authWebSocket, unauthWebSocket)
|
||||
}
|
||||
|
||||
val provisioningApi: ProvisioningApi by lazy {
|
||||
provider.provideProvisioningApi(authWebSocket)
|
||||
}
|
||||
|
||||
val certificateApi: CertificateApi by lazy {
|
||||
provider.provideCertificateApi(authWebSocket)
|
||||
}
|
||||
|
||||
val okHttpClient: OkHttpClient by lazy {
|
||||
OkHttpClient.Builder()
|
||||
.addInterceptor(StandardUserAgentInterceptor())
|
||||
|
||||
@@ -4,13 +4,13 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.CertificateType;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork;
|
||||
import org.thoughtcrime.securesms.util.ExceptionHelper;
|
||||
import org.whispersystems.signalservice.api.NetworkResultUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
@@ -56,7 +56,6 @@ public final class RotateCertificateJob extends BaseJob {
|
||||
}
|
||||
|
||||
synchronized (RotateCertificateJob.class) {
|
||||
SignalServiceAccountManager accountManager = AppDependencies.getSignalServiceAccountManager();
|
||||
Collection<CertificateType> certificateTypes = SignalStore.phoneNumberPrivacy()
|
||||
.getAllCertificateTypes();
|
||||
|
||||
@@ -66,8 +65,8 @@ public final class RotateCertificateJob extends BaseJob {
|
||||
byte[] certificate;
|
||||
|
||||
switch (certificateType) {
|
||||
case ACI_AND_E164: certificate = accountManager.getSenderCertificate(); break;
|
||||
case ACI_ONLY : certificate = accountManager.getSenderCertificateForPhoneNumberPrivacy(); break;
|
||||
case ACI_AND_E164: certificate = NetworkResultUtil.toBasicLegacy(SignalNetwork.certificate().getSenderCertificate()); break;
|
||||
case ACI_ONLY : certificate = NetworkResultUtil.toBasicLegacy(SignalNetwork.certificate().getSenderCertificateForPhoneNumberPrivacy()); break;
|
||||
default : throw new AssertionError();
|
||||
}
|
||||
|
||||
@@ -80,7 +79,7 @@ public final class RotateCertificateJob extends BaseJob {
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetry(@NonNull Exception e) {
|
||||
return e instanceof PushNetworkException;
|
||||
return ExceptionHelper.isRetryableIOException(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,10 +11,12 @@ import org.whispersystems.signalservice.api.archive.ArchiveApi
|
||||
import org.whispersystems.signalservice.api.attachment.AttachmentApi
|
||||
import org.whispersystems.signalservice.api.calling.CallingApi
|
||||
import org.whispersystems.signalservice.api.cds.CdsApi
|
||||
import org.whispersystems.signalservice.api.certificate.CertificateApi
|
||||
import org.whispersystems.signalservice.api.keys.KeysApi
|
||||
import org.whispersystems.signalservice.api.link.LinkDeviceApi
|
||||
import org.whispersystems.signalservice.api.message.MessageApi
|
||||
import org.whispersystems.signalservice.api.payments.PaymentsApi
|
||||
import org.whispersystems.signalservice.api.provisioning.ProvisioningApi
|
||||
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
|
||||
import org.whispersystems.signalservice.api.storage.StorageServiceApi
|
||||
import org.whispersystems.signalservice.api.username.UsernameApi
|
||||
@@ -42,6 +44,11 @@ object SignalNetwork {
|
||||
val cdsApi: CdsApi
|
||||
get() = AppDependencies.cdsApi
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("certificate")
|
||||
val certificate: CertificateApi
|
||||
get() = AppDependencies.certificateApi
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("keys")
|
||||
val keys: KeysApi
|
||||
@@ -60,6 +67,9 @@ object SignalNetwork {
|
||||
val payments: PaymentsApi
|
||||
get() = AppDependencies.paymentsApi
|
||||
|
||||
val provisioning: ProvisioningApi
|
||||
get() = AppDependencies.provisioningApi
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("rateLimitChallenge")
|
||||
val rateLimitChallenge: RateLimitChallengeApi
|
||||
|
||||
+5
-6
@@ -19,8 +19,9 @@ import org.signal.registration.proto.RegistrationProvisionMessage
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.net.SignalNetwork
|
||||
import org.whispersystems.signalservice.api.NetworkResult
|
||||
import org.whispersystems.signalservice.api.registration.RestoreMethod
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod
|
||||
import java.io.IOException
|
||||
import kotlin.coroutines.coroutineContext
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -71,9 +72,8 @@ object QuickRegistrationRepository {
|
||||
return TransferAccountResult.FAILED
|
||||
}
|
||||
|
||||
AppDependencies
|
||||
.signalServiceAccountManager
|
||||
.registrationApi
|
||||
SignalNetwork
|
||||
.provisioning
|
||||
.sendReRegisterDeviceProvisioningMessage(
|
||||
ephemeralId,
|
||||
publicKey,
|
||||
@@ -147,8 +147,7 @@ object QuickRegistrationRepository {
|
||||
Log.d(TAG, "Waiting for restore method with token: ***${restoreMethodToken.takeLast(4)}")
|
||||
while (retries-- > 0 && result !is NetworkResult.Success && coroutineContext.isActive) {
|
||||
Log.d(TAG, "Waiting, remaining tries: $retries")
|
||||
val api = AppDependencies.registrationApi
|
||||
result = api.waitForRestoreMethod(restoreMethodToken)
|
||||
result = SignalNetwork.provisioning.waitForRestoreMethod(restoreMethodToken)
|
||||
Log.d(TAG, "Result: $result")
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.viewModel
|
||||
import org.whispersystems.signalservice.api.registration.RestoreMethod
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod
|
||||
|
||||
/**
|
||||
* Launched after scanning QR code from new device to start the transfer/reregistration process from
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.registrationv3.data.QuickRegistrationRepository
|
||||
import org.whispersystems.signalservice.api.registration.RestoreMethod
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod
|
||||
import java.util.UUID
|
||||
|
||||
class TransferAccountViewModel(reRegisterUri: String) : ViewModel() {
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import org.thoughtcrime.securesms.keyvalue.Completed
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.keyvalue.Skipped
|
||||
import org.thoughtcrime.securesms.registrationv3.data.QuickRegistrationRepository
|
||||
import org.whispersystems.signalservice.api.registration.RestoreMethod
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod
|
||||
|
||||
class RemoteRestoreViewModel(isOnlyRestoreOption: Boolean) : ViewModel() {
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.registration.data.network.RegisterAccountResult
|
||||
import org.whispersystems.signalservice.api.registration.ProvisioningSocket
|
||||
import org.whispersystems.signalservice.api.provisioning.ProvisioningSocket
|
||||
import org.whispersystems.signalservice.internal.crypto.SecondaryProvisioningCipher
|
||||
import java.io.Closeable
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.thoughtcrime.securesms.registrationv3.data.QuickRegistrationRepositor
|
||||
import org.thoughtcrime.securesms.registrationv3.ui.restore.RestoreMethod
|
||||
import org.thoughtcrime.securesms.registrationv3.ui.restore.StorageServiceRestore
|
||||
import org.thoughtcrime.securesms.restore.transferorrestore.BackupRestorationType
|
||||
import org.whispersystems.signalservice.api.registration.RestoreMethod as ApiRestoreMethod
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod as ApiRestoreMethod
|
||||
|
||||
/**
|
||||
* Shared view model for the restore flow.
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.registrationv3.ui.restore.RestoreMethod
|
||||
import org.thoughtcrime.securesms.registrationv3.ui.restore.SelectRestoreMethodScreen
|
||||
import org.thoughtcrime.securesms.restore.RestoreViewModel
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.whispersystems.signalservice.api.registration.RestoreMethod as ApiRestoreMethod
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod as ApiRestoreMethod
|
||||
|
||||
/**
|
||||
* Provide options to select restore/transfer operation during quick/post registration.
|
||||
|
||||
+11
-1
@@ -41,11 +41,13 @@ import org.whispersystems.signalservice.api.archive.ArchiveApi
|
||||
import org.whispersystems.signalservice.api.attachment.AttachmentApi
|
||||
import org.whispersystems.signalservice.api.calling.CallingApi
|
||||
import org.whispersystems.signalservice.api.cds.CdsApi
|
||||
import org.whispersystems.signalservice.api.certificate.CertificateApi
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations
|
||||
import org.whispersystems.signalservice.api.keys.KeysApi
|
||||
import org.whispersystems.signalservice.api.link.LinkDeviceApi
|
||||
import org.whispersystems.signalservice.api.message.MessageApi
|
||||
import org.whispersystems.signalservice.api.payments.PaymentsApi
|
||||
import org.whispersystems.signalservice.api.provisioning.ProvisioningApi
|
||||
import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi
|
||||
import org.whispersystems.signalservice.api.registration.RegistrationApi
|
||||
import org.whispersystems.signalservice.api.services.DonationsService
|
||||
@@ -71,9 +73,9 @@ class MockApplicationDependencyProvider : AppDependencies.Provider {
|
||||
}
|
||||
|
||||
override fun provideSignalServiceMessageSender(
|
||||
authWebSocket: SignalWebSocket.AuthenticatedWebSocket,
|
||||
protocolStore: SignalServiceDataStore,
|
||||
pushServiceSocket: PushServiceSocket,
|
||||
attachmentApi: AttachmentApi,
|
||||
messageApi: MessageApi,
|
||||
keysApi: KeysApi
|
||||
): SignalServiceMessageSender {
|
||||
@@ -276,4 +278,12 @@ class MockApplicationDependencyProvider : AppDependencies.Provider {
|
||||
override fun provideMessageApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): MessageApi {
|
||||
return mockk(relaxed = true)
|
||||
}
|
||||
|
||||
override fun provideProvisioningApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): ProvisioningApi {
|
||||
return mockk(relaxed = true)
|
||||
}
|
||||
|
||||
override fun provideCertificateApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket): CertificateApi {
|
||||
return mockk(relaxed = true)
|
||||
}
|
||||
}
|
||||
|
||||
-8
@@ -106,14 +106,6 @@ public class SignalServiceAccountManager {
|
||||
this.configuration = pushServiceSocket.getConfiguration();
|
||||
}
|
||||
|
||||
public byte[] getSenderCertificate() throws IOException {
|
||||
return this.pushServiceSocket.getSenderCertificate();
|
||||
}
|
||||
|
||||
public byte[] getSenderCertificateForPhoneNumberPrivacy() throws IOException {
|
||||
return this.pushServiceSocket.getUuidOnlySenderCertificate();
|
||||
}
|
||||
|
||||
public SecureValueRecoveryV2 getSecureValueRecoveryV2(String mrEnclave) {
|
||||
return new SecureValueRecoveryV2(configuration, mrEnclave, authWebSocket);
|
||||
}
|
||||
|
||||
+19
-36
@@ -21,6 +21,7 @@ import org.signal.libsignal.protocol.message.SenderKeyDistributionMessage;
|
||||
import org.signal.libsignal.protocol.state.PreKeyBundle;
|
||||
import org.signal.libsignal.protocol.state.SessionRecord;
|
||||
import org.signal.libsignal.zkgroup.groupsend.GroupSendFullToken;
|
||||
import org.whispersystems.signalservice.api.attachment.AttachmentApi;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.ContentHint;
|
||||
import org.whispersystems.signalservice.api.crypto.EnvelopeContent;
|
||||
@@ -77,14 +78,12 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
|
||||
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||
import org.whispersystems.signalservice.api.services.AttachmentService;
|
||||
import org.whispersystems.signalservice.api.util.AttachmentPointerUtil;
|
||||
import org.whispersystems.signalservice.api.util.CredentialsProvider;
|
||||
import org.whispersystems.signalservice.api.util.Preconditions;
|
||||
import org.whispersystems.signalservice.api.util.Uint64RangeException;
|
||||
import org.whispersystems.signalservice.api.util.Uint64Util;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketUnavailableException;
|
||||
import org.whispersystems.signalservice.internal.crypto.AttachmentDigest;
|
||||
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream;
|
||||
@@ -175,9 +174,9 @@ public class SignalServiceMessageSender {
|
||||
private final Optional<EventListener> eventListener;
|
||||
private final IdentityKeyPair localPniIdentity;
|
||||
|
||||
private final AttachmentService attachmentService;
|
||||
private final MessageApi messageApi;
|
||||
private final KeysApi keysApi;
|
||||
private final AttachmentApi attachmentApi;
|
||||
private final MessageApi messageApi;
|
||||
private final KeysApi keysApi;
|
||||
|
||||
private final Scheduler scheduler;
|
||||
private final long maxEnvelopeSize;
|
||||
@@ -185,7 +184,7 @@ public class SignalServiceMessageSender {
|
||||
public SignalServiceMessageSender(PushServiceSocket pushServiceSocket,
|
||||
SignalServiceDataStore store,
|
||||
SignalSessionLock sessionLock,
|
||||
SignalWebSocket.AuthenticatedWebSocket authWebSocket,
|
||||
AttachmentApi attachmentApi,
|
||||
MessageApi messageApi,
|
||||
KeysApi keysApi,
|
||||
Optional<EventListener> eventListener,
|
||||
@@ -194,19 +193,19 @@ public class SignalServiceMessageSender {
|
||||
{
|
||||
CredentialsProvider credentialsProvider = pushServiceSocket.getCredentialsProvider();
|
||||
|
||||
this.socket = pushServiceSocket;
|
||||
this.aciStore = store.aci();
|
||||
this.sessionLock = sessionLock;
|
||||
this.localAddress = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
|
||||
this.localDeviceId = credentialsProvider.getDeviceId();
|
||||
this.localPni = credentialsProvider.getPni();
|
||||
this.attachmentService = new AttachmentService(authWebSocket);
|
||||
this.messageApi = messageApi;
|
||||
this.eventListener = eventListener;
|
||||
this.maxEnvelopeSize = maxEnvelopeSize;
|
||||
this.localPniIdentity = store.pni().getIdentityKeyPair();
|
||||
this.scheduler = Schedulers.from(executor, false, false);
|
||||
this.keysApi = keysApi;
|
||||
this.socket = pushServiceSocket;
|
||||
this.aciStore = store.aci();
|
||||
this.sessionLock = sessionLock;
|
||||
this.localAddress = new SignalServiceAddress(credentialsProvider.getAci(), credentialsProvider.getE164());
|
||||
this.localDeviceId = credentialsProvider.getDeviceId();
|
||||
this.localPni = credentialsProvider.getPni();
|
||||
this.attachmentApi = attachmentApi;
|
||||
this.messageApi = messageApi;
|
||||
this.eventListener = eventListener;
|
||||
this.maxEnvelopeSize = maxEnvelopeSize;
|
||||
this.localPniIdentity = store.pni().getIdentityKeyPair();
|
||||
this.scheduler = Schedulers.from(executor, false, false);
|
||||
this.keysApi = keysApi;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -810,24 +809,8 @@ public class SignalServiceMessageSender {
|
||||
}
|
||||
|
||||
public ResumableUploadSpec getResumableUploadSpec() throws IOException {
|
||||
AttachmentUploadForm v4UploadAttributes = null;
|
||||
|
||||
Log.d(TAG, "Using pipe to retrieve attachment upload attributes...");
|
||||
try {
|
||||
v4UploadAttributes = new AttachmentService.AttachmentAttributesResponseProcessor<>(attachmentService.getAttachmentV4UploadAttributes().blockingGet()).getResultOrThrow();
|
||||
} catch (WebSocketUnavailableException e) {
|
||||
Log.w(TAG, "[getResumableUploadSpec] Pipe unavailable, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
|
||||
} catch (IOException e) {
|
||||
if (e instanceof RateLimitException) {
|
||||
throw e;
|
||||
}
|
||||
Log.w(TAG, "Failed to retrieve attachment upload attributes using pipe. Falling back...");
|
||||
}
|
||||
|
||||
if (v4UploadAttributes == null) {
|
||||
Log.d(TAG, "Not using pipe to retrieve attachment upload attributes...");
|
||||
v4UploadAttributes = socket.getAttachmentV4UploadAttributes();
|
||||
}
|
||||
AttachmentUploadForm v4UploadAttributes = NetworkResultUtil.toBasicLegacy(attachmentApi.getAttachmentV4UploadForm());
|
||||
|
||||
return socket.getResumableUploadSpec(v4UploadAttributes);
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.certificate
|
||||
|
||||
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.SenderCertificate
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
|
||||
|
||||
/**
|
||||
* Endpoints to get [SenderCertificate]s.
|
||||
*/
|
||||
class CertificateApi(private val authWebSocket: SignalWebSocket.AuthenticatedWebSocket) {
|
||||
|
||||
/**
|
||||
* GET /v1/certificate/delivery
|
||||
* - 200: Success
|
||||
*/
|
||||
fun getSenderCertificate(): NetworkResult<ByteArray> {
|
||||
val request = WebSocketRequestMessage.get("/v1/certificate/delivery")
|
||||
return NetworkResult.fromWebSocketRequest(authWebSocket, request, SenderCertificate::class)
|
||||
.map { it.certificate }
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /v1/certificate/delivery?includeE164=false
|
||||
* - 200: Success
|
||||
*/
|
||||
fun getSenderCertificateForPhoneNumberPrivacy(): NetworkResult<ByteArray> {
|
||||
val request = WebSocketRequestMessage.get("/v1/certificate/delivery?includeE164=false")
|
||||
return NetworkResult.fromWebSocketRequest(authWebSocket, request, SenderCertificate::class)
|
||||
.map { it.certificate }
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,6 +16,7 @@ import org.whispersystems.signalservice.api.backup.MediaRootBackupKey
|
||||
import org.whispersystems.signalservice.api.backup.MessageBackupKey
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo
|
||||
import org.whispersystems.signalservice.api.provisioning.ProvisioningMessage
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.ACI
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
@@ -24,7 +25,6 @@ import org.whispersystems.signalservice.internal.delete
|
||||
import org.whispersystems.signalservice.internal.get
|
||||
import org.whispersystems.signalservice.internal.push.DeviceInfoList
|
||||
import org.whispersystems.signalservice.internal.push.ProvisionMessage
|
||||
import org.whispersystems.signalservice.internal.push.ProvisioningMessage
|
||||
import org.whispersystems.signalservice.internal.push.ProvisioningVersion
|
||||
import org.whispersystems.signalservice.internal.put
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.provisioning
|
||||
|
||||
import org.signal.core.util.Base64
|
||||
import org.signal.core.util.urlEncode
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey
|
||||
import org.signal.registration.proto.RegistrationProvisionMessage
|
||||
import org.whispersystems.signalservice.api.NetworkResult
|
||||
import org.whispersystems.signalservice.api.registration.RestoreMethodBody
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.internal.crypto.PrimaryProvisioningCipher
|
||||
import org.whispersystems.signalservice.internal.get
|
||||
import org.whispersystems.signalservice.internal.put
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
* Linked and new device provisioning endpoints.
|
||||
*/
|
||||
class ProvisioningApi(private val authWebSocket: SignalWebSocket.AuthenticatedWebSocket) {
|
||||
|
||||
/**
|
||||
* Encrypts and sends the [registrationProvisionMessage] from the current primary (old device) to the new device over
|
||||
* the provisioning web socket identified by [deviceIdentifier].
|
||||
*
|
||||
* PUT /v1/provisioning/[deviceIdentifier]
|
||||
* - 204: Success
|
||||
* - 400: Message was too large
|
||||
* - 404: No provisioning socket for [deviceIdentifier]
|
||||
*/
|
||||
fun sendReRegisterDeviceProvisioningMessage(
|
||||
deviceIdentifier: String,
|
||||
deviceKey: ECPublicKey,
|
||||
registrationProvisionMessage: RegistrationProvisionMessage
|
||||
): NetworkResult<Unit> {
|
||||
val cipherText = PrimaryProvisioningCipher(deviceKey).encrypt(registrationProvisionMessage)
|
||||
|
||||
val request = WebSocketRequestMessage.put("/v1/provisioning/${deviceIdentifier.urlEncode()}", ProvisioningMessage(Base64.encodeWithPadding(cipherText)))
|
||||
return NetworkResult.fromWebSocketRequest(authWebSocket, request)
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the [RestoreMethod] to be set on the server by the new device. This is a long polling operation.
|
||||
*
|
||||
* GET /v1/devices/restore_account/[token]?timeout=[timeout]
|
||||
* - 200: A request was received for the given token
|
||||
* - 204: No request given yet, may repeat call to continue waiting
|
||||
* - 400: Invalid [token] or [timeout]
|
||||
* - 429: Rate limited
|
||||
*/
|
||||
fun waitForRestoreMethod(token: String, timeout: Int = 30): NetworkResult<RestoreMethod> {
|
||||
val request = WebSocketRequestMessage.get("/v1/devices/restore_account/${token.urlEncode()}?timeout=$timeout")
|
||||
|
||||
return NetworkResult.fromWebSocket(NetworkResult.LongPollingWebSocketConverter(RestoreMethodBody::class)) {
|
||||
authWebSocket.request(request, timeout.seconds)
|
||||
}.map {
|
||||
it.method ?: RestoreMethod.DECLINE
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.whispersystems.signalservice.internal.push;
|
||||
package org.whispersystems.signalservice.api.provisioning;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.registration
|
||||
package org.whispersystems.signalservice.api.provisioning
|
||||
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.registration
|
||||
package org.whispersystems.signalservice.api.provisioning
|
||||
|
||||
/**
|
||||
* Restore method chosen by user on new device after performing a quick-restore.
|
||||
+1
-28
@@ -5,12 +5,10 @@
|
||||
|
||||
package org.whispersystems.signalservice.api.registration
|
||||
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey
|
||||
import org.signal.registration.proto.RegistrationProvisionMessage
|
||||
import org.whispersystems.signalservice.api.NetworkResult
|
||||
import org.whispersystems.signalservice.api.account.AccountAttributes
|
||||
import org.whispersystems.signalservice.api.account.PreKeyCollection
|
||||
import org.whispersystems.signalservice.internal.crypto.PrimaryProvisioningCipher
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod
|
||||
import org.whispersystems.signalservice.internal.push.BackupV2AuthCheckResponse
|
||||
import org.whispersystems.signalservice.internal.push.BackupV3AuthCheckResponse
|
||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket
|
||||
@@ -127,22 +125,6 @@ class RegistrationApi(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts and sends the [RegistrationProvisionMessage] from the current primary (old device) to the new device over
|
||||
* the provisioning web socket identified by [deviceIdentifier].
|
||||
*/
|
||||
fun sendReRegisterDeviceProvisioningMessage(
|
||||
deviceIdentifier: String,
|
||||
deviceKey: ECPublicKey,
|
||||
registrationProvisionMessage: RegistrationProvisionMessage
|
||||
): NetworkResult<Unit> {
|
||||
val cipherText = PrimaryProvisioningCipher(deviceKey).encrypt(registrationProvisionMessage)
|
||||
|
||||
return NetworkResult.fromFetch {
|
||||
pushServiceSocket.sendProvisioningMessage(deviceIdentifier, cipherText)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set [RestoreMethod] enum on the server for use by the old device to update UX.
|
||||
*/
|
||||
@@ -151,13 +133,4 @@ class RegistrationApi(
|
||||
pushServiceSocket.setRestoreMethodChosen(token, RestoreMethodBody(method = method))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the [RestoreMethod] to be set on the server by the new device. This is a long polling operation.
|
||||
*/
|
||||
fun waitForRestoreMethod(token: String, timeout: Int = 30): NetworkResult<RestoreMethod> {
|
||||
return NetworkResult.fromFetch {
|
||||
pushServiceSocket.waitForRestoreMethodChosen(token, timeout).method ?: RestoreMethod.DECLINE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -7,6 +7,7 @@ package org.whispersystems.signalservice.api.registration
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import org.whispersystems.signalservice.api.provisioning.RestoreMethod
|
||||
|
||||
/**
|
||||
* Request and response body used to communicate a quick restore method selection during registration.
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package org.whispersystems.signalservice.api.services
|
||||
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.internal.ServiceResponse
|
||||
import org.whispersystems.signalservice.internal.ServiceResponseProcessor
|
||||
import org.whispersystems.signalservice.internal.push.AttachmentUploadForm
|
||||
import org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper
|
||||
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage
|
||||
import org.whispersystems.signalservice.internal.websocket.WebsocketResponse
|
||||
import java.security.SecureRandom
|
||||
|
||||
/**
|
||||
* Provide WebSocket based interface to attachment upload endpoints.
|
||||
*
|
||||
* Note: To be expanded to have REST fallback and other attachment related operations.
|
||||
*/
|
||||
class AttachmentService(private val authWebSocket: SignalWebSocket.AuthenticatedWebSocket) {
|
||||
fun getAttachmentV4UploadAttributes(): Single<ServiceResponse<AttachmentUploadForm>> {
|
||||
val requestMessage = WebSocketRequestMessage(
|
||||
id = SecureRandom().nextLong(),
|
||||
verb = "GET",
|
||||
path = "/v4/attachments/form/upload"
|
||||
)
|
||||
|
||||
return authWebSocket.request(requestMessage)
|
||||
.map { response: WebsocketResponse? -> DefaultResponseMapper.getDefault(AttachmentUploadForm::class.java).map(response) }
|
||||
.onErrorReturn { throwable: Throwable? -> ServiceResponse.forUnknownError(throwable) }
|
||||
}
|
||||
|
||||
class AttachmentAttributesResponseProcessor<T>(response: ServiceResponse<T>) : ServiceResponseProcessor<T>(response)
|
||||
}
|
||||
-44
@@ -185,19 +185,13 @@ public class PushServiceSocket {
|
||||
|
||||
private static final String DELETE_ACCOUNT_PATH = "/v1/accounts/me";
|
||||
|
||||
private static final String PROVISIONING_MESSAGE_PATH = "/v1/provisioning/%s";
|
||||
private static final String SET_RESTORE_METHOD_PATH = "/v1/devices/restore_account/%s";
|
||||
private static final String WAIT_RESTORE_METHOD_PATH = "/v1/devices/restore_account/%s?timeout=%s";
|
||||
|
||||
private static final String GROUP_MESSAGE_PATH = "/v1/messages/multi_recipient?ts=%s&online=%s&urgent=%s&story=%s";
|
||||
private static final String ATTACHMENT_V4_PATH = "/v4/attachments/form/upload";
|
||||
|
||||
private static final String PROFILE_PATH = "/v1/profile/%s";
|
||||
private static final String PROFILE_BATCH_CHECK_PATH = "/v1/profile/identity_check/batch";
|
||||
|
||||
private static final String SENDER_CERTIFICATE_PATH = "/v1/certificate/delivery";
|
||||
private static final String SENDER_CERTIFICATE_NO_E164_PATH = "/v1/certificate/delivery?includeE164=false";
|
||||
|
||||
private static final String ATTACHMENT_KEY_DOWNLOAD_PATH = "attachments/%s";
|
||||
private static final String ATTACHMENT_ID_DOWNLOAD_PATH = "attachments/%d";
|
||||
private static final String AVATAR_UPLOAD_PATH = "";
|
||||
@@ -242,11 +236,8 @@ public class PushServiceSocket {
|
||||
|
||||
private static final String ARCHIVE_MEDIA_DOWNLOAD_PATH = "backups/%s/%s";
|
||||
|
||||
private static final String SERVER_DELIVERED_TIMESTAMP_HEADER = "X-Signal-Timestamp";
|
||||
|
||||
private static final Map<String, String> NO_HEADERS = Collections.emptyMap();
|
||||
private static final ResponseCodeHandler NO_HANDLER = new EmptyResponseCodeHandler();
|
||||
private static final ResponseCodeHandler LONG_POLL_HANDLER = new LongPollingResponseCodeHandler();
|
||||
private static final ResponseCodeHandler UNOPINIONATED_HANDLER = new UnopinionatedResponseCodeHandler();
|
||||
private static final ResponseCodeHandler UNOPINIONATED_BINARY_ERROR_HANDLER = new UnopinionatedBinaryErrorResponseCodeHandler();
|
||||
|
||||
@@ -404,33 +395,10 @@ public class PushServiceSocket {
|
||||
makeServiceRequest(String.format(Locale.US, SET_RESTORE_METHOD_PATH, urlEncode(token)), "PUT", body, NO_HEADERS, UNOPINIONATED_HANDLER, SealedSenderAccess.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a long-polling endpoint that relies on the fact that our normal connection timeout is already 30s.
|
||||
*/
|
||||
public @Nonnull RestoreMethodBody waitForRestoreMethodChosen(@Nonnull String token, int timeoutSeconds) throws IOException {
|
||||
String response = makeServiceRequest(String.format(Locale.US, WAIT_RESTORE_METHOD_PATH, urlEncode(token), timeoutSeconds), "GET", null, NO_HEADERS, LONG_POLL_HANDLER, SealedSenderAccess.NONE);
|
||||
return JsonUtil.fromJsonResponse(response, RestoreMethodBody.class);
|
||||
}
|
||||
|
||||
public void sendProvisioningMessage(String destination, byte[] body) throws IOException {
|
||||
makeServiceRequest(String.format(PROVISIONING_MESSAGE_PATH, urlEncode(destination)), "PUT",
|
||||
JsonUtil.toJson(new ProvisioningMessage(Base64.encodeWithPadding(body))));
|
||||
}
|
||||
|
||||
public void requestPushChallenge(String sessionId, String gcmRegistrationId) throws IOException {
|
||||
patchVerificationSession(sessionId, gcmRegistrationId, null, null, null, null);
|
||||
}
|
||||
|
||||
public byte[] getSenderCertificate() throws IOException {
|
||||
String responseText = makeServiceRequest(SENDER_CERTIFICATE_PATH, "GET", null);
|
||||
return JsonUtil.fromJson(responseText, SenderCertificate.class).getCertificate();
|
||||
}
|
||||
|
||||
public byte[] getUuidOnlySenderCertificate() throws IOException {
|
||||
String responseText = makeServiceRequest(SENDER_CERTIFICATE_NO_E164_PATH, "GET", null);
|
||||
return JsonUtil.fromJson(responseText, SenderCertificate.class).getCertificate();
|
||||
}
|
||||
|
||||
public SendGroupMessageResponse sendGroupMessage(byte[] body, @Nonnull SealedSenderAccess sealedSenderAccess, long timestamp, boolean online, boolean urgent, boolean story)
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException
|
||||
{
|
||||
@@ -888,18 +856,6 @@ public class PushServiceSocket {
|
||||
}
|
||||
}
|
||||
|
||||
public AttachmentUploadForm getAttachmentV4UploadAttributes()
|
||||
throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException
|
||||
{
|
||||
String response = makeServiceRequest(ATTACHMENT_V4_PATH, "GET", null);
|
||||
try {
|
||||
return JsonUtil.fromJson(response, AttachmentUploadForm.class);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
throw new MalformedResponseException("Unable to parse entity", e);
|
||||
}
|
||||
}
|
||||
|
||||
public AttachmentDigest uploadGroupV2Avatar(byte[] avatarCipherText, AvatarUploadAttributes uploadAttributes)
|
||||
throws IOException
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user