Consolidate S3 requests into one interface.
This commit is contained in:
parent
bb963f9210
commit
ecc358ef40
10 changed files with 109 additions and 177 deletions
|
@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor;
|
|||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.payments.Payments;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceTrustStore;
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
|
||||
import org.thoughtcrime.securesms.revealable.ViewOnceMessageManager;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
|
@ -50,8 +51,20 @@ import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
|||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.SignalWebSocket;
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
|
||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||
import org.whispersystems.signalservice.api.services.DonationsService;
|
||||
import org.whispersystems.signalservice.api.util.Tls12SocketFactory;
|
||||
import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
|
@ -97,6 +110,7 @@ public class ApplicationDependencies {
|
|||
private static volatile SignalCallManager signalCallManager;
|
||||
private static volatile ShakeToReport shakeToReport;
|
||||
private static volatile OkHttpClient okHttpClient;
|
||||
private static volatile OkHttpClient signalOkHttpClient;
|
||||
private static volatile PendingRetryReceiptManager pendingRetryReceiptManager;
|
||||
private static volatile PendingRetryReceiptCache pendingRetryReceiptCache;
|
||||
private static volatile SignalWebSocket signalWebSocket;
|
||||
|
@ -509,6 +523,32 @@ public class ApplicationDependencies {
|
|||
return okHttpClient;
|
||||
}
|
||||
|
||||
public static @NonNull OkHttpClient getSignalOkHttpClient() {
|
||||
if (signalOkHttpClient == null) {
|
||||
synchronized (LOCK) {
|
||||
if (signalOkHttpClient == null) {
|
||||
try {
|
||||
OkHttpClient baseClient = ApplicationDependencies.getOkHttpClient();
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
TrustStore trustStore = new SignalServiceTrustStore(ApplicationDependencies.getApplication());
|
||||
TrustManager[] trustManagers = BlacklistingTrustManager.createFor(trustStore);
|
||||
|
||||
sslContext.init(null, trustManagers, null);
|
||||
|
||||
signalOkHttpClient = baseClient.newBuilder()
|
||||
.sslSocketFactory(new Tls12SocketFactory(sslContext.getSocketFactory()), (X509TrustManager) trustManagers[0])
|
||||
.connectionSpecs(Util.immutableList(ConnectionSpec.RESTRICTED_TLS))
|
||||
.build();
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return signalOkHttpClient;
|
||||
}
|
||||
|
||||
public static @NonNull AppForegroundObserver getAppForegroundObserver() {
|
||||
return appForegroundObserver;
|
||||
}
|
||||
|
|
|
@ -1,42 +1,22 @@
|
|||
package org.thoughtcrime.securesms.emoji
|
||||
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.s3.S3
|
||||
import java.io.IOException
|
||||
|
||||
private const val VERSION_URL = "https://updates.signal.org/dynamic/android/emoji/version_v3.txt"
|
||||
private const val BASE_STATIC_BUCKET_URL = "https://updates.signal.org/static/android/emoji"
|
||||
private const val BASE_STATIC_BUCKET_URI = "${S3.STATIC_PATH}/android/emoji"
|
||||
|
||||
/**
|
||||
* Responsible for communicating with S3 to download Emoji related objects.
|
||||
*/
|
||||
object EmojiRemote {
|
||||
|
||||
private const val TAG = "EmojiRemote"
|
||||
|
||||
private val okHttpClient = ApplicationDependencies.getOkHttpClient()
|
||||
private const val VERSION_URI = "${S3.DYNAMIC_PATH}/android/emoji/version_v3.txt"
|
||||
|
||||
@JvmStatic
|
||||
@Throws(IOException::class)
|
||||
fun getVersion(): Int {
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url(VERSION_URL)
|
||||
.build()
|
||||
|
||||
try {
|
||||
okHttpClient.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException()
|
||||
}
|
||||
|
||||
return response.body()?.bytes()?.let { String(it).trim().toIntOrNull() } ?: throw IOException()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw e
|
||||
}
|
||||
return S3.getLong(VERSION_URI).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,23 +24,7 @@ object EmojiRemote {
|
|||
*/
|
||||
@JvmStatic
|
||||
fun getMd5(emojiRequest: EmojiRequest): ByteArray? {
|
||||
val request = Request.Builder()
|
||||
.head()
|
||||
.url(emojiRequest.url)
|
||||
.build()
|
||||
|
||||
try {
|
||||
okHttpClient.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException()
|
||||
}
|
||||
|
||||
return response.header("ETag")?.toByteArray()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Could not retrieve md5", e)
|
||||
return null
|
||||
}
|
||||
return S3.getObjectMD5(emojiRequest.uri)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,21 +32,16 @@ object EmojiRemote {
|
|||
*/
|
||||
@JvmStatic
|
||||
fun getObject(emojiRequest: EmojiRequest): Response {
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url(emojiRequest.url)
|
||||
.build()
|
||||
|
||||
return okHttpClient.newCall(request).execute()
|
||||
return S3.getObject(emojiRequest.uri)
|
||||
}
|
||||
}
|
||||
|
||||
interface EmojiRequest {
|
||||
val url: String
|
||||
val uri: String
|
||||
}
|
||||
|
||||
class EmojiJsonRequest(version: Int) : EmojiRequest {
|
||||
override val url: String = "$BASE_STATIC_BUCKET_URL/$version/emoji_data.json"
|
||||
override val uri: String = "$BASE_STATIC_BUCKET_URI/$version/emoji_data.json"
|
||||
}
|
||||
|
||||
class EmojiImageRequest(
|
||||
|
@ -91,7 +50,7 @@ class EmojiImageRequest(
|
|||
name: String,
|
||||
format: String
|
||||
) : EmojiRequest {
|
||||
override val url: String = "$BASE_STATIC_BUCKET_URL/$version/$density/$name.$format"
|
||||
override val uri: String = "$BASE_STATIC_BUCKET_URI/$version/$density/$name.$format"
|
||||
}
|
||||
|
||||
class EmojiFileRequest(
|
||||
|
@ -99,5 +58,5 @@ class EmojiFileRequest(
|
|||
density: String,
|
||||
name: String,
|
||||
) : EmojiRequest {
|
||||
override val url: String = "$BASE_STATIC_BUCKET_URL/$version/$density/$name"
|
||||
override val uri: String = "$BASE_STATIC_BUCKET_URI/$version/$density/$name"
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ object Fonts {
|
|||
|
||||
private val TAG = Log.tag(Fonts::class.java)
|
||||
|
||||
private const val VERSION_URL = "https://updates.signal.org/dynamic/story-fonts/version.txt"
|
||||
private const val BASE_STATIC_BUCKET_URL = "https://updates.signal.org/static/story-fonts"
|
||||
private const val VERSION_URI = "${S3.DYNAMIC_PATH}/story-fonts/version.txt"
|
||||
private const val BASE_STATIC_BUCKET_URI = "${S3.STATIC_PATH}/story-fonts"
|
||||
private const val MANIFEST = "manifest.json"
|
||||
|
||||
private val taskCache = Collections.synchronizedMap(mutableMapOf<FontDownloadKey, ListenableFutureTask<Typeface>>())
|
||||
|
@ -201,7 +201,7 @@ object Fonts {
|
|||
*/
|
||||
@WorkerThread
|
||||
fun downloadLatestVersionLong(): Long {
|
||||
return S3.getLong(VERSION_URL)
|
||||
return S3.getLong(VERSION_URI)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,7 +211,7 @@ object Fonts {
|
|||
fun downloadAndVerifyLatestManifest(context: Context, version: FontVersion, manifestPath: String): Boolean {
|
||||
return S3.verifyAndWriteToDisk(
|
||||
context,
|
||||
"$BASE_STATIC_BUCKET_URL/${version.id}/$MANIFEST",
|
||||
"$BASE_STATIC_BUCKET_URI/${version.id}/$MANIFEST",
|
||||
File(getDirectory(context), manifestPath)
|
||||
)
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ object Fonts {
|
|||
|
||||
val script: FontManifest.FontScript = resolveFontScriptFromScriptName(supportedScript, fontManifest) ?: return null
|
||||
val path = getScriptPath(font, script) ?: return null
|
||||
val networkPath = "$BASE_STATIC_BUCKET_URL/${fontVersion.id}/$path"
|
||||
val networkPath = "$BASE_STATIC_BUCKET_URI/${fontVersion.id}/$path"
|
||||
val localUUID = UUID.randomUUID().toString()
|
||||
val localPath = "${fontVersion.path}/" + localUUID
|
||||
|
||||
|
|
|
@ -11,21 +11,9 @@ import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
|||
|
||||
import org.thoughtcrime.securesms.badges.models.Badge;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceTrustStore;
|
||||
import org.whispersystems.signalservice.api.push.TrustStore;
|
||||
import org.whispersystems.signalservice.api.util.Tls12SocketFactory;
|
||||
import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
|
@ -50,23 +38,7 @@ public class BadgeLoader implements ModelLoader<Badge, InputStream> {
|
|||
}
|
||||
|
||||
public static Factory createFactory() {
|
||||
try {
|
||||
OkHttpClient baseClient = ApplicationDependencies.getOkHttpClient();
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
TrustStore trustStore = new SignalServiceTrustStore(ApplicationDependencies.getApplication());
|
||||
TrustManager[] trustManagers = BlacklistingTrustManager.createFor(trustStore);
|
||||
|
||||
sslContext.init(null, trustManagers, null);
|
||||
|
||||
OkHttpClient client = baseClient.newBuilder()
|
||||
.sslSocketFactory(new Tls12SocketFactory(sslContext.getSocketFactory()), (X509TrustManager) trustManagers[0])
|
||||
.connectionSpecs(Util.immutableList(ConnectionSpec.RESTRICTED_TLS))
|
||||
.build();
|
||||
|
||||
return new Factory(client);
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
return new Factory(ApplicationDependencies.getSignalOkHttpClient());
|
||||
}
|
||||
|
||||
public static class Factory implements ModelLoaderFactory<Badge, InputStream> {
|
||||
|
|
|
@ -9,25 +9,15 @@ import com.bumptech.glide.load.model.GlideUrl
|
|||
import com.bumptech.glide.load.model.ModelLoader
|
||||
import com.bumptech.glide.load.model.ModelLoaderFactory
|
||||
import com.bumptech.glide.load.model.MultiModelLoaderFactory
|
||||
import okhttp3.ConnectionSpec
|
||||
import okhttp3.OkHttpClient
|
||||
import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialPresentation
|
||||
import org.thoughtcrime.securesms.badges.Badges
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.push.SignalServiceTrustStore
|
||||
import org.whispersystems.signalservice.api.push.TrustStore
|
||||
import org.whispersystems.signalservice.api.util.Tls12SocketFactory
|
||||
import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager
|
||||
import org.whispersystems.signalservice.internal.util.Util
|
||||
import java.io.InputStream
|
||||
import java.lang.Exception
|
||||
import java.security.KeyManagementException
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.util.Locale
|
||||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
/**
|
||||
* Glide Model allowing the direct loading of a GiftBadge.
|
||||
|
@ -102,25 +92,7 @@ data class GiftBadgeModel(val giftBadge: GiftBadge) : Key {
|
|||
companion object {
|
||||
@JvmStatic
|
||||
fun createFactory(): Factory {
|
||||
return try {
|
||||
val baseClient = ApplicationDependencies.getOkHttpClient()
|
||||
val sslContext = SSLContext.getInstance("TLS")
|
||||
val trustStore: TrustStore = SignalServiceTrustStore(ApplicationDependencies.getApplication())
|
||||
val trustManagers = BlacklistingTrustManager.createFor(trustStore)
|
||||
|
||||
sslContext.init(null, trustManagers, null)
|
||||
|
||||
val client = baseClient.newBuilder()
|
||||
.sslSocketFactory(Tls12SocketFactory(sslContext.socketFactory), trustManagers[0] as X509TrustManager)
|
||||
.connectionSpecs(Util.immutableList(ConnectionSpec.RESTRICTED_TLS))
|
||||
.build()
|
||||
|
||||
Factory(client)
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
throw AssertionError(e)
|
||||
} catch (e: KeyManagementException) {
|
||||
throw AssertionError(e)
|
||||
}
|
||||
return Factory(ApplicationDependencies.getSignalOkHttpClient())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.signal.core.util.Hex;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.protocol.InvalidMessageException;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
|
@ -23,10 +24,10 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
|||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.notifications.v2.NotificationThread;
|
||||
import org.thoughtcrime.securesms.releasechannel.ReleaseChannel;
|
||||
import org.thoughtcrime.securesms.s3.S3;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.signal.core.util.Hex;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
|
@ -43,7 +44,6 @@ import java.util.Objects;
|
|||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okio.Okio;
|
||||
|
@ -242,12 +242,7 @@ public final class AttachmentDownloadJob extends BaseJob {
|
|||
final Attachment attachment)
|
||||
throws IOException
|
||||
{
|
||||
Request request = new Request.Builder()
|
||||
.get()
|
||||
.url(Objects.requireNonNull(attachment.getFileName()))
|
||||
.build();
|
||||
|
||||
try (Response response = ApplicationDependencies.getOkHttpClient().newCall(request).execute()) {
|
||||
try (Response response = S3.getObject(Objects.requireNonNull(attachment.getFileName()))) {
|
||||
ResponseBody body = response.body();
|
||||
if (body != null) {
|
||||
SignalDatabase.attachments().insertAttachmentsForPlaceholder(messageId, attachmentId, Okio.buffer(body.source()).inputStream());
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.jobmanager.Job;
|
|||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.EmojiValues;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.s3.S3;
|
||||
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil;
|
||||
|
@ -24,11 +25,6 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* Downloads a new emoji search index based on our current version and language, if needed.
|
||||
*/
|
||||
|
@ -89,9 +85,7 @@ public final class EmojiSearchIndexDownloadJob extends BaseJob {
|
|||
|
||||
@Override
|
||||
protected void onRun() throws Exception {
|
||||
OkHttpClient client = ApplicationDependencies.getOkHttpClient();
|
||||
|
||||
Manifest manifest = downloadManifest(client);
|
||||
Manifest manifest = downloadManifest();
|
||||
|
||||
Locale locale = DynamicLanguageContextWrapper.getUsersSelectedLocale(context);
|
||||
String remoteLanguage = findMatchingLanguage(locale, manifest.getLanguages());
|
||||
|
@ -106,7 +100,7 @@ public final class EmojiSearchIndexDownloadJob extends BaseJob {
|
|||
|
||||
Log.i(TAG, "Need to get a new search index. Downloading version: " + manifest.getVersion() + ", language: " + remoteLanguage);
|
||||
|
||||
List<EmojiSearchData> searchIndex = downloadSearchIndex(client, manifest.getVersion(), remoteLanguage);
|
||||
List<EmojiSearchData> searchIndex = downloadSearchIndex(manifest.getVersion(), remoteLanguage);
|
||||
|
||||
SignalDatabase.emojiSearch().setSearchIndex(searchIndex);
|
||||
SignalStore.emojiValues().onSearchIndexUpdated(manifest.getVersion(), remoteLanguage);
|
||||
|
@ -125,33 +119,14 @@ public final class EmojiSearchIndexDownloadJob extends BaseJob {
|
|||
|
||||
}
|
||||
|
||||
private static @NonNull Manifest downloadManifest(@NonNull OkHttpClient client) throws IOException {
|
||||
String url = "https://updates.signal.org/dynamic/android/emoji/search/manifest.json";
|
||||
String body = downloadFile(client, url);
|
||||
|
||||
return JsonUtil.fromJson(body, Manifest.class);
|
||||
private static @NonNull Manifest downloadManifest() throws IOException {
|
||||
String manifest = S3.getString(S3.DYNAMIC_PATH + "/android/emoji/search/manifest.json");
|
||||
return JsonUtil.fromJson(manifest, Manifest.class);
|
||||
}
|
||||
|
||||
private static @NonNull List<EmojiSearchData> downloadSearchIndex(@NonNull OkHttpClient client, int version, @NonNull String language) throws IOException {
|
||||
String url = "https://updates.signal.org/static/android/emoji/search/" + version + "/" + language + ".json";
|
||||
String body = downloadFile(client, url);
|
||||
|
||||
return Arrays.asList(JsonUtil.fromJson(body, EmojiSearchData[].class));
|
||||
}
|
||||
|
||||
private static @NonNull String downloadFile(@NonNull OkHttpClient client, @NonNull String url) throws IOException {
|
||||
Call call = client.newCall(new Request.Builder().url(url).build());
|
||||
Response response = call.execute();
|
||||
|
||||
if (response.code() != 200) {
|
||||
throw new NonSuccessfulResponseCodeException(response.code());
|
||||
}
|
||||
|
||||
if (response.body() == null) {
|
||||
throw new NonSuccessfulResponseCodeException(404, "Missing body!");
|
||||
}
|
||||
|
||||
return response.body().string();
|
||||
private static @NonNull List<EmojiSearchData> downloadSearchIndex(int version, @NonNull String language) throws IOException {
|
||||
String data = S3.getString(S3.STATIC_PATH + "/android/emoji/search/" + version + "/" + language + ".json");
|
||||
return Arrays.asList(JsonUtil.fromJson(data, EmojiSearchData[].class));
|
||||
}
|
||||
|
||||
private static @NonNull String findMatchingLanguage(@NonNull Locale locale, List<String> languages) {
|
||||
|
|
|
@ -40,8 +40,8 @@ class RetrieveRemoteAnnouncementsJob private constructor(private val force: Bool
|
|||
|
||||
companion object {
|
||||
const val KEY = "RetrieveReleaseChannelJob"
|
||||
private const val MANIFEST = "https://updates.signal.org/dynamic/release-notes/release-notes.json"
|
||||
private const val BASE_RELEASE_NOTE = "https://updates.signal.org/static/release-notes"
|
||||
private const val MANIFEST = "${S3.DYNAMIC_PATH}/release-notes/release-notes.json"
|
||||
private const val BASE_RELEASE_NOTE = "${S3.STATIC_PATH}/release-notes"
|
||||
private const val KEY_FORCE = "force"
|
||||
|
||||
private val TAG = Log.tag(RetrieveRemoteAnnouncementsJob::class.java)
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.signal.core.util.logging.Log
|
|||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.util.EncryptedStreamUtils
|
||||
import org.thoughtcrime.securesms.util.JsonUtils
|
||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException
|
||||
import org.whispersystems.signalservice.internal.ServiceResponse
|
||||
import org.whispersystems.signalservice.internal.websocket.DefaultErrorMapper
|
||||
import org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper
|
||||
|
@ -30,7 +31,31 @@ import java.util.regex.Pattern
|
|||
object S3 {
|
||||
private val TAG = Log.tag(S3::class.java)
|
||||
|
||||
private val okHttpClient = ApplicationDependencies.getOkHttpClient()
|
||||
private val okHttpClient = ApplicationDependencies.getSignalOkHttpClient()
|
||||
|
||||
private const val S3_BASE = "https://updates2.signal.org"
|
||||
const val DYNAMIC_PATH = "/dynamic"
|
||||
const val STATIC_PATH = "/static"
|
||||
|
||||
/**
|
||||
* Fetches the content at the given endpoint and attempts to return it as a string.
|
||||
*
|
||||
* @param endpoint The endpoint at which to get the long
|
||||
* @return the string value of the body
|
||||
* @throws IOException if the call fails or the response body cannot be parsed
|
||||
*/
|
||||
@WorkerThread
|
||||
@JvmStatic
|
||||
@Throws(IOException::class)
|
||||
fun getString(endpoint: String): String {
|
||||
getObject(endpoint).use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
throw NonSuccessfulResponseCodeException(response.code())
|
||||
}
|
||||
|
||||
return response.body()?.string()?.trim() ?: throw IOException()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the content at the given endpoint and attempts to convert it into a long.
|
||||
|
@ -40,23 +65,14 @@ object S3 {
|
|||
* @throws IOException if the call fails or the response body cannot be parsed as a long
|
||||
*/
|
||||
@WorkerThread
|
||||
@Throws(IOException::class)
|
||||
fun getLong(endpoint: String): Long {
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url(endpoint)
|
||||
.build()
|
||||
|
||||
try {
|
||||
okHttpClient.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException()
|
||||
}
|
||||
|
||||
return response.body()?.bytes()?.let { String(it).trim().toLongOrNull() } ?: throw IOException()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Failed to retreive long value from S3")
|
||||
throw e
|
||||
val result = getString(endpoint).toLongOrNull()
|
||||
return if (result == null) {
|
||||
Log.w(TAG, "Failed to retrieve long value from S3")
|
||||
throw IOException("Unable to parse")
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,10 +80,12 @@ object S3 {
|
|||
* Retrieves an S3 object from the given endpoint.
|
||||
*/
|
||||
@WorkerThread
|
||||
@JvmStatic
|
||||
@Throws(IOException::class)
|
||||
fun getObject(endpoint: String): Response {
|
||||
val request = Request.Builder()
|
||||
.get()
|
||||
.url(endpoint)
|
||||
.url("$S3_BASE$endpoint")
|
||||
.build()
|
||||
|
||||
return okHttpClient.newCall(request).execute()
|
||||
|
@ -178,7 +196,7 @@ object S3 {
|
|||
fun getObjectMD5(endpoint: String): ByteArray? {
|
||||
val request = Request.Builder()
|
||||
.head()
|
||||
.url(endpoint)
|
||||
.url("$S3_BASE$endpoint")
|
||||
.build()
|
||||
|
||||
try {
|
||||
|
|
|
@ -34,6 +34,7 @@ class SpinnerApplicationContext : ApplicationContext() {
|
|||
ThreadPolicy.Builder()
|
||||
.detectDiskReads()
|
||||
.detectDiskWrites()
|
||||
.detectNetwork()
|
||||
.penaltyLog()
|
||||
.build()
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue