Primer paso de la investigacion. Se aportan el .apk, las carpetas con el apk extraido y el apk descompilado. El archivo API_DOCUMENTATION.md es un archivo donde se anotaran los descubrimientos del funcionamiento de la API, y los .py son scripts para probar la funcionalidad de la API con los métodos que vayamos encontrando. Finalmente, los archivos .js son scripts de Frida para extraer informacion de la APP durante la ejecucion.
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
package com.google.firebase.remoteconfig.internal;
|
||||
|
||||
import android.util.Log;
|
||||
import com.google.android.gms.tasks.Continuation;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.android.gms.tasks.Tasks;
|
||||
import com.google.firebase.remoteconfig.ConfigUpdate;
|
||||
import com.google.firebase.remoteconfig.ConfigUpdateListener;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigClientException;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigException;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException;
|
||||
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/* loaded from: classes3.dex */
|
||||
public class ConfigAutoFetch {
|
||||
private static final int MAXIMUM_FETCH_ATTEMPTS = 3;
|
||||
private static final String REALTIME_DISABLED_KEY = "featureDisabled";
|
||||
private static final String TEMPLATE_VERSION_KEY = "latestTemplateVersionNumber";
|
||||
private final ConfigCacheClient activatedCache;
|
||||
private final ConfigFetchHandler configFetchHandler;
|
||||
private final Set<ConfigUpdateListener> eventListeners;
|
||||
private final HttpURLConnection httpURLConnection;
|
||||
private final Random random = new Random();
|
||||
private final ConfigUpdateListener retryCallback;
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
public ConfigAutoFetch(HttpURLConnection httpURLConnection, ConfigFetchHandler configFetchHandler, ConfigCacheClient configCacheClient, Set<ConfigUpdateListener> set, ConfigUpdateListener configUpdateListener, ScheduledExecutorService scheduledExecutorService) {
|
||||
this.httpURLConnection = httpURLConnection;
|
||||
this.configFetchHandler = configFetchHandler;
|
||||
this.activatedCache = configCacheClient;
|
||||
this.eventListeners = set;
|
||||
this.retryCallback = configUpdateListener;
|
||||
this.scheduledExecutorService = scheduledExecutorService;
|
||||
}
|
||||
|
||||
private void autoFetch(final int i, final long j4) {
|
||||
if (i == 0) {
|
||||
propagateErrors(new FirebaseRemoteConfigServerException("Unable to fetch the latest version of the template.", FirebaseRemoteConfigException.Code.CONFIG_UPDATE_NOT_FETCHED));
|
||||
} else {
|
||||
this.scheduledExecutorService.schedule(new Runnable() { // from class: com.google.firebase.remoteconfig.internal.ConfigAutoFetch.1
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
ConfigAutoFetch.this.fetchLatestConfig(i, j4);
|
||||
}
|
||||
}, this.random.nextInt(4), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void executeAllListenerCallbacks(ConfigUpdate configUpdate) {
|
||||
Iterator<ConfigUpdateListener> it = this.eventListeners.iterator();
|
||||
while (it.hasNext()) {
|
||||
it.next().onUpdate(configUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
private static Boolean fetchResponseIsUpToDate(ConfigFetchHandler.FetchResponse fetchResponse, long j4) {
|
||||
if (fetchResponse.getFetchedConfigs() != null) {
|
||||
return Boolean.valueOf(fetchResponse.getFetchedConfigs().getTemplateVersionNumber() >= j4);
|
||||
}
|
||||
return Boolean.valueOf(fetchResponse.getStatus() == 1);
|
||||
}
|
||||
|
||||
/* JADX WARN: Code restructure failed: missing block: B:11:0x0030, code lost:
|
||||
|
||||
r5 = new org.json.JSONObject(r4);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:12:0x0039, code lost:
|
||||
|
||||
if (r5.has(com.google.firebase.remoteconfig.internal.ConfigAutoFetch.REALTIME_DISABLED_KEY) == false) goto L38;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:14:0x003f, code lost:
|
||||
|
||||
if (r5.getBoolean(com.google.firebase.remoteconfig.internal.ConfigAutoFetch.REALTIME_DISABLED_KEY) == false) goto L39;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:16:0x0041, code lost:
|
||||
|
||||
r9.retryCallback.onError(new com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException("The server is temporarily unavailable. Try again in a few minutes.", com.google.firebase.remoteconfig.FirebaseRemoteConfigException.Code.CONFIG_UPDATE_UNAVAILABLE));
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:24:0x0056, code lost:
|
||||
|
||||
if (isEventListenersEmpty() == false) goto L21;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:26:0x005d, code lost:
|
||||
|
||||
if (r5.has(com.google.firebase.remoteconfig.internal.ConfigAutoFetch.TEMPLATE_VERSION_KEY) == false) goto L41;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:28:0x005f, code lost:
|
||||
|
||||
r6 = r9.configFetchHandler.getTemplateVersionNumber();
|
||||
r4 = r5.getLong(com.google.firebase.remoteconfig.internal.ConfigAutoFetch.TEMPLATE_VERSION_KEY);
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:29:0x006b, code lost:
|
||||
|
||||
if (r4 <= r6) goto L42;
|
||||
*/
|
||||
/* JADX WARN: Code restructure failed: missing block: B:31:0x006d, code lost:
|
||||
|
||||
autoFetch(3, r4);
|
||||
*/
|
||||
/*
|
||||
Code decompiled incorrectly, please refer to instructions dump.
|
||||
To view partially-correct add '--show-bad-code' argument
|
||||
*/
|
||||
private void handleNotifications(java.io.InputStream r10) throws java.io.IOException {
|
||||
/*
|
||||
r9 = this;
|
||||
java.lang.String r0 = "latestTemplateVersionNumber"
|
||||
java.lang.String r1 = "featureDisabled"
|
||||
java.io.BufferedReader r2 = new java.io.BufferedReader
|
||||
java.io.InputStreamReader r3 = new java.io.InputStreamReader
|
||||
java.lang.String r4 = "utf-8"
|
||||
r3.<init>(r10, r4)
|
||||
r2.<init>(r3)
|
||||
java.lang.String r3 = ""
|
||||
L12:
|
||||
r4 = r3
|
||||
L13:
|
||||
java.lang.String r5 = r2.readLine()
|
||||
if (r5 == 0) goto L8a
|
||||
java.lang.String r4 = C.w.n(r4, r5)
|
||||
java.lang.String r6 = "}"
|
||||
boolean r5 = r5.contains(r6)
|
||||
if (r5 == 0) goto L13
|
||||
java.lang.String r4 = r9.parseAndValidateConfigUpdateMessage(r4)
|
||||
boolean r5 = r4.isEmpty()
|
||||
if (r5 == 0) goto L30
|
||||
goto L13
|
||||
L30:
|
||||
org.json.JSONObject r5 = new org.json.JSONObject // Catch: org.json.JSONException -> L50
|
||||
r5.<init>(r4) // Catch: org.json.JSONException -> L50
|
||||
boolean r4 = r5.has(r1) // Catch: org.json.JSONException -> L50
|
||||
if (r4 == 0) goto L52
|
||||
boolean r4 = r5.getBoolean(r1) // Catch: org.json.JSONException -> L50
|
||||
if (r4 == 0) goto L52
|
||||
com.google.firebase.remoteconfig.ConfigUpdateListener r4 = r9.retryCallback // Catch: org.json.JSONException -> L50
|
||||
com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException r5 = new com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException // Catch: org.json.JSONException -> L50
|
||||
java.lang.String r6 = "The server is temporarily unavailable. Try again in a few minutes."
|
||||
com.google.firebase.remoteconfig.FirebaseRemoteConfigException$Code r7 = com.google.firebase.remoteconfig.FirebaseRemoteConfigException.Code.CONFIG_UPDATE_UNAVAILABLE // Catch: org.json.JSONException -> L50
|
||||
r5.<init>(r6, r7) // Catch: org.json.JSONException -> L50
|
||||
r4.onError(r5) // Catch: org.json.JSONException -> L50
|
||||
goto L8a
|
||||
L50:
|
||||
r4 = move-exception
|
||||
goto L72
|
||||
L52:
|
||||
boolean r4 = r9.isEventListenersEmpty() // Catch: org.json.JSONException -> L50
|
||||
if (r4 == 0) goto L59
|
||||
goto L8a
|
||||
L59:
|
||||
boolean r4 = r5.has(r0) // Catch: org.json.JSONException -> L50
|
||||
if (r4 == 0) goto L12
|
||||
com.google.firebase.remoteconfig.internal.ConfigFetchHandler r4 = r9.configFetchHandler // Catch: org.json.JSONException -> L50
|
||||
long r6 = r4.getTemplateVersionNumber() // Catch: org.json.JSONException -> L50
|
||||
long r4 = r5.getLong(r0) // Catch: org.json.JSONException -> L50
|
||||
int r6 = (r4 > r6 ? 1 : (r4 == r6 ? 0 : -1))
|
||||
if (r6 <= 0) goto L12
|
||||
r6 = 3
|
||||
r9.autoFetch(r6, r4) // Catch: org.json.JSONException -> L50
|
||||
goto L12
|
||||
L72:
|
||||
com.google.firebase.remoteconfig.FirebaseRemoteConfigClientException r5 = new com.google.firebase.remoteconfig.FirebaseRemoteConfigClientException
|
||||
java.lang.Throwable r6 = r4.getCause()
|
||||
com.google.firebase.remoteconfig.FirebaseRemoteConfigException$Code r7 = com.google.firebase.remoteconfig.FirebaseRemoteConfigException.Code.CONFIG_UPDATE_MESSAGE_INVALID
|
||||
java.lang.String r8 = "Unable to parse config update message."
|
||||
r5.<init>(r8, r6, r7)
|
||||
r9.propagateErrors(r5)
|
||||
java.lang.String r5 = "FirebaseRemoteConfig"
|
||||
java.lang.String r6 = "Unable to parse latest config update message."
|
||||
android.util.Log.e(r5, r6, r4)
|
||||
goto L12
|
||||
L8a:
|
||||
r2.close()
|
||||
r10.close()
|
||||
return
|
||||
*/
|
||||
throw new UnsupportedOperationException("Method not decompiled: com.google.firebase.remoteconfig.internal.ConfigAutoFetch.handleNotifications(java.io.InputStream):void");
|
||||
}
|
||||
|
||||
private synchronized boolean isEventListenersEmpty() {
|
||||
return this.eventListeners.isEmpty();
|
||||
}
|
||||
|
||||
/* JADX INFO: Access modifiers changed from: private */
|
||||
public /* synthetic */ Task lambda$fetchLatestConfig$0(Task task, Task task2, long j4, int i, Task task3) throws Exception {
|
||||
if (!task.isSuccessful()) {
|
||||
return Tasks.forException(new FirebaseRemoteConfigClientException("Failed to auto-fetch config update.", task.getException()));
|
||||
}
|
||||
if (!task2.isSuccessful()) {
|
||||
return Tasks.forException(new FirebaseRemoteConfigClientException("Failed to get activated config for auto-fetch", task2.getException()));
|
||||
}
|
||||
ConfigFetchHandler.FetchResponse fetchResponse = (ConfigFetchHandler.FetchResponse) task.getResult();
|
||||
ConfigContainer configContainer = (ConfigContainer) task2.getResult();
|
||||
if (!fetchResponseIsUpToDate(fetchResponse, j4).booleanValue()) {
|
||||
Log.d(FirebaseRemoteConfig.TAG, "Fetched template version is the same as SDK's current version. Retrying fetch.");
|
||||
autoFetch(i, j4);
|
||||
return Tasks.forResult(null);
|
||||
}
|
||||
if (fetchResponse.getFetchedConfigs() == null) {
|
||||
Log.d(FirebaseRemoteConfig.TAG, "The fetch succeeded, but the backend had no updates.");
|
||||
return Tasks.forResult(null);
|
||||
}
|
||||
if (configContainer == null) {
|
||||
configContainer = ConfigContainer.newBuilder().build();
|
||||
}
|
||||
Set<String> changedParams = configContainer.getChangedParams(fetchResponse.getFetchedConfigs());
|
||||
if (changedParams.isEmpty()) {
|
||||
Log.d(FirebaseRemoteConfig.TAG, "Config was fetched, but no params changed.");
|
||||
return Tasks.forResult(null);
|
||||
}
|
||||
executeAllListenerCallbacks(ConfigUpdate.create(changedParams));
|
||||
return Tasks.forResult(null);
|
||||
}
|
||||
|
||||
private String parseAndValidateConfigUpdateMessage(String str) {
|
||||
int indexOf = str.indexOf(123);
|
||||
int lastIndexOf = str.lastIndexOf(125);
|
||||
return (indexOf < 0 || lastIndexOf < 0 || indexOf >= lastIndexOf) ? "" : str.substring(indexOf, lastIndexOf + 1);
|
||||
}
|
||||
|
||||
private synchronized void propagateErrors(FirebaseRemoteConfigException firebaseRemoteConfigException) {
|
||||
Iterator<ConfigUpdateListener> it = this.eventListeners.iterator();
|
||||
while (it.hasNext()) {
|
||||
it.next().onError(firebaseRemoteConfigException);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Task<Void> fetchLatestConfig(int i, final long j4) {
|
||||
final int i4 = i - 1;
|
||||
try {
|
||||
try {
|
||||
final Task<ConfigFetchHandler.FetchResponse> fetchNowWithTypeAndAttemptNumber = this.configFetchHandler.fetchNowWithTypeAndAttemptNumber(ConfigFetchHandler.FetchType.REALTIME, 3 - i4);
|
||||
final Task<ConfigContainer> task = this.activatedCache.get();
|
||||
return Tasks.whenAllComplete((Task<?>[]) new Task[]{fetchNowWithTypeAndAttemptNumber, task}).continueWithTask(this.scheduledExecutorService, new Continuation() { // from class: com.google.firebase.remoteconfig.internal.a
|
||||
@Override // com.google.android.gms.tasks.Continuation
|
||||
public final Object then(Task task2) {
|
||||
Task lambda$fetchLatestConfig$0;
|
||||
lambda$fetchLatestConfig$0 = ConfigAutoFetch.this.lambda$fetchLatestConfig$0(fetchNowWithTypeAndAttemptNumber, task, j4, i4, task2);
|
||||
return lambda$fetchLatestConfig$0;
|
||||
}
|
||||
});
|
||||
} catch (Throwable th) {
|
||||
th = th;
|
||||
throw th;
|
||||
}
|
||||
} catch (Throwable th2) {
|
||||
th = th2;
|
||||
throw th;
|
||||
}
|
||||
}
|
||||
|
||||
public void listenForNotifications() {
|
||||
HttpURLConnection httpURLConnection = this.httpURLConnection;
|
||||
if (httpURLConnection == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
InputStream inputStream = httpURLConnection.getInputStream();
|
||||
handleNotifications(inputStream);
|
||||
inputStream.close();
|
||||
} catch (IOException e4) {
|
||||
Log.d(FirebaseRemoteConfig.TAG, "Stream was cancelled due to an exception. Retrying the connection...", e4);
|
||||
} finally {
|
||||
this.httpURLConnection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user