375 lines
18 KiB
Java
375 lines
18 KiB
Java
|
package com.google.firebase.installations.remote;
|
||
|
|
||
|
import android.content.Context;
|
||
|
import android.content.pm.PackageManager;
|
||
|
import android.net.TrafficStats;
|
||
|
import android.text.TextUtils;
|
||
|
import android.util.JsonReader;
|
||
|
import com.google.android.gms.common.internal.Preconditions;
|
||
|
import com.google.android.gms.common.util.AndroidUtilsLight;
|
||
|
import com.google.android.gms.common.util.Hex;
|
||
|
import com.google.common.net.HttpHeaders;
|
||
|
import com.google.firebase.crashlytics.internal.common.AbstractSpiCall;
|
||
|
import com.google.firebase.heartbeatinfo.HeartBeatInfo;
|
||
|
import com.google.firebase.inject.Provider;
|
||
|
import com.google.firebase.installations.FirebaseInstallationsException;
|
||
|
import com.google.firebase.installations.remote.InstallationResponse;
|
||
|
import com.google.firebase.installations.remote.TokenResult;
|
||
|
import com.google.firebase.platforminfo.UserAgentPublisher;
|
||
|
import com.huawei.hms.android.HwBuildEx;
|
||
|
import io.grpc.internal.GrpcUtil;
|
||
|
import java.io.BufferedReader;
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStream;
|
||
|
import java.io.InputStreamReader;
|
||
|
import java.io.OutputStream;
|
||
|
import java.net.HttpURLConnection;
|
||
|
import java.net.MalformedURLException;
|
||
|
import java.net.URL;
|
||
|
import java.net.URLConnection;
|
||
|
import java.nio.charset.Charset;
|
||
|
import java.util.regex.Pattern;
|
||
|
import java.util.zip.GZIPOutputStream;
|
||
|
import org.json.JSONException;
|
||
|
import org.json.JSONObject;
|
||
|
|
||
|
/* loaded from: classes2.dex */
|
||
|
public class FirebaseInstallationServiceClient {
|
||
|
private static final Pattern EXPIRATION_TIMESTAMP_PATTERN = Pattern.compile("[0-9]+s");
|
||
|
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||
|
private final Context context;
|
||
|
private final Provider<HeartBeatInfo> heartbeatInfo;
|
||
|
private final RequestLimiter requestLimiter = new RequestLimiter();
|
||
|
private final Provider<UserAgentPublisher> userAgentPublisher;
|
||
|
|
||
|
private static boolean isSuccessfulResponseCode(int i) {
|
||
|
return i >= 200 && i < 300;
|
||
|
}
|
||
|
|
||
|
private static void logBadConfigError() {
|
||
|
}
|
||
|
|
||
|
public FirebaseInstallationServiceClient(Context context, Provider<UserAgentPublisher> provider, Provider<HeartBeatInfo> provider2) {
|
||
|
this.context = context;
|
||
|
this.userAgentPublisher = provider;
|
||
|
this.heartbeatInfo = provider2;
|
||
|
}
|
||
|
|
||
|
public InstallationResponse createFirebaseInstallation(String str, String str2, String str3, String str4, String str5) throws FirebaseInstallationsException {
|
||
|
int responseCode;
|
||
|
InstallationResponse readCreateResponse;
|
||
|
if (!this.requestLimiter.isRequestAllowed()) {
|
||
|
throw new FirebaseInstallationsException("Firebase Installations Service is unavailable. Please try again later.", FirebaseInstallationsException.Status.UNAVAILABLE);
|
||
|
}
|
||
|
URL fullyQualifiedRequestUri = getFullyQualifiedRequestUri(String.format("projects/%s/installations", str3));
|
||
|
for (int i = 0; i <= 1; i++) {
|
||
|
TrafficStats.setThreadStatsTag(32769);
|
||
|
HttpURLConnection openHttpURLConnection = openHttpURLConnection(fullyQualifiedRequestUri, str);
|
||
|
try {
|
||
|
try {
|
||
|
openHttpURLConnection.setRequestMethod(GrpcUtil.HTTP_METHOD);
|
||
|
openHttpURLConnection.setDoOutput(true);
|
||
|
if (str5 != null) {
|
||
|
openHttpURLConnection.addRequestProperty("x-goog-fis-android-iid-migration-auth", str5);
|
||
|
}
|
||
|
writeFIDCreateRequestBodyToOutputStream(openHttpURLConnection, str2, str4);
|
||
|
responseCode = openHttpURLConnection.getResponseCode();
|
||
|
this.requestLimiter.setNextRequestTime(responseCode);
|
||
|
} catch (IOException | AssertionError unused) {
|
||
|
}
|
||
|
if (isSuccessfulResponseCode(responseCode)) {
|
||
|
readCreateResponse = readCreateResponse(openHttpURLConnection);
|
||
|
} else {
|
||
|
logFisCommunicationError(openHttpURLConnection, str4, str, str3);
|
||
|
if (responseCode == 429) {
|
||
|
throw new FirebaseInstallationsException("Firebase servers have received too many requests from this client in a short period of time. Please try again later.", FirebaseInstallationsException.Status.TOO_MANY_REQUESTS);
|
||
|
}
|
||
|
if (responseCode < 500 || responseCode >= 600) {
|
||
|
logBadConfigError();
|
||
|
readCreateResponse = InstallationResponse.builder().setResponseCode(InstallationResponse.ResponseCode.BAD_CONFIG).build();
|
||
|
} else {
|
||
|
openHttpURLConnection.disconnect();
|
||
|
TrafficStats.clearThreadStatsTag();
|
||
|
}
|
||
|
}
|
||
|
return readCreateResponse;
|
||
|
} finally {
|
||
|
openHttpURLConnection.disconnect();
|
||
|
TrafficStats.clearThreadStatsTag();
|
||
|
}
|
||
|
}
|
||
|
throw new FirebaseInstallationsException("Firebase Installations Service is unavailable. Please try again later.", FirebaseInstallationsException.Status.UNAVAILABLE);
|
||
|
}
|
||
|
|
||
|
private void writeFIDCreateRequestBodyToOutputStream(HttpURLConnection httpURLConnection, String str, String str2) throws IOException {
|
||
|
writeRequestBodyToOutputStream(httpURLConnection, getJsonBytes(buildCreateFirebaseInstallationRequestBody(str, str2)));
|
||
|
}
|
||
|
|
||
|
private static byte[] getJsonBytes(JSONObject jSONObject) throws IOException {
|
||
|
return jSONObject.toString().getBytes("UTF-8");
|
||
|
}
|
||
|
|
||
|
private static void writeRequestBodyToOutputStream(URLConnection uRLConnection, byte[] bArr) throws IOException {
|
||
|
OutputStream outputStream = uRLConnection.getOutputStream();
|
||
|
if (outputStream == null) {
|
||
|
throw new IOException("Cannot send request to FIS servers. No OutputStream available.");
|
||
|
}
|
||
|
GZIPOutputStream gZIPOutputStream = new GZIPOutputStream(outputStream);
|
||
|
try {
|
||
|
gZIPOutputStream.write(bArr);
|
||
|
} finally {
|
||
|
try {
|
||
|
gZIPOutputStream.close();
|
||
|
outputStream.close();
|
||
|
} catch (IOException unused) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static JSONObject buildCreateFirebaseInstallationRequestBody(String str, String str2) {
|
||
|
try {
|
||
|
JSONObject jSONObject = new JSONObject();
|
||
|
jSONObject.put("fid", str);
|
||
|
jSONObject.put("appId", str2);
|
||
|
jSONObject.put("authVersion", "FIS_v2");
|
||
|
jSONObject.put("sdkVersion", "a:17.0.0");
|
||
|
return jSONObject;
|
||
|
} catch (JSONException e) {
|
||
|
throw new IllegalStateException(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void writeGenerateAuthTokenRequestBodyToOutputStream(HttpURLConnection httpURLConnection) throws IOException {
|
||
|
writeRequestBodyToOutputStream(httpURLConnection, getJsonBytes(buildGenerateAuthTokenRequestBody()));
|
||
|
}
|
||
|
|
||
|
private static JSONObject buildGenerateAuthTokenRequestBody() {
|
||
|
try {
|
||
|
JSONObject jSONObject = new JSONObject();
|
||
|
jSONObject.put("sdkVersion", "a:17.0.0");
|
||
|
JSONObject jSONObject2 = new JSONObject();
|
||
|
jSONObject2.put("installation", jSONObject);
|
||
|
return jSONObject2;
|
||
|
} catch (JSONException e) {
|
||
|
throw new IllegalStateException(e);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private URL getFullyQualifiedRequestUri(String str) throws FirebaseInstallationsException {
|
||
|
try {
|
||
|
return new URL(String.format("https://%s/%s/%s", "firebaseinstallations.googleapis.com", "v1", str));
|
||
|
} catch (MalformedURLException e) {
|
||
|
throw new FirebaseInstallationsException(e.getMessage(), FirebaseInstallationsException.Status.UNAVAILABLE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public TokenResult generateAuthToken(String str, String str2, String str3, String str4) throws FirebaseInstallationsException {
|
||
|
int responseCode;
|
||
|
TokenResult readGenerateAuthTokenResponse;
|
||
|
if (!this.requestLimiter.isRequestAllowed()) {
|
||
|
throw new FirebaseInstallationsException("Firebase Installations Service is unavailable. Please try again later.", FirebaseInstallationsException.Status.UNAVAILABLE);
|
||
|
}
|
||
|
URL fullyQualifiedRequestUri = getFullyQualifiedRequestUri(String.format("projects/%s/installations/%s/authTokens:generate", str3, str2));
|
||
|
for (int i = 0; i <= 1; i++) {
|
||
|
TrafficStats.setThreadStatsTag(32771);
|
||
|
HttpURLConnection openHttpURLConnection = openHttpURLConnection(fullyQualifiedRequestUri, str);
|
||
|
try {
|
||
|
openHttpURLConnection.setRequestMethod(GrpcUtil.HTTP_METHOD);
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
sb.append("FIS_v2 ");
|
||
|
sb.append(str4);
|
||
|
openHttpURLConnection.addRequestProperty(HttpHeaders.AUTHORIZATION, sb.toString());
|
||
|
openHttpURLConnection.setDoOutput(true);
|
||
|
writeGenerateAuthTokenRequestBodyToOutputStream(openHttpURLConnection);
|
||
|
responseCode = openHttpURLConnection.getResponseCode();
|
||
|
this.requestLimiter.setNextRequestTime(responseCode);
|
||
|
} catch (IOException | AssertionError unused) {
|
||
|
} catch (Throwable th) {
|
||
|
openHttpURLConnection.disconnect();
|
||
|
TrafficStats.clearThreadStatsTag();
|
||
|
throw th;
|
||
|
}
|
||
|
if (isSuccessfulResponseCode(responseCode)) {
|
||
|
readGenerateAuthTokenResponse = readGenerateAuthTokenResponse(openHttpURLConnection);
|
||
|
} else {
|
||
|
logFisCommunicationError(openHttpURLConnection, null, str, str3);
|
||
|
if (responseCode == 401 || responseCode == 404) {
|
||
|
readGenerateAuthTokenResponse = TokenResult.builder().setResponseCode(TokenResult.ResponseCode.AUTH_ERROR).build();
|
||
|
} else {
|
||
|
if (responseCode == 429) {
|
||
|
throw new FirebaseInstallationsException("Firebase servers have received too many requests from this client in a short period of time. Please try again later.", FirebaseInstallationsException.Status.TOO_MANY_REQUESTS);
|
||
|
}
|
||
|
if (responseCode < 500 || responseCode >= 600) {
|
||
|
logBadConfigError();
|
||
|
readGenerateAuthTokenResponse = TokenResult.builder().setResponseCode(TokenResult.ResponseCode.BAD_CONFIG).build();
|
||
|
} else {
|
||
|
openHttpURLConnection.disconnect();
|
||
|
TrafficStats.clearThreadStatsTag();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
openHttpURLConnection.disconnect();
|
||
|
TrafficStats.clearThreadStatsTag();
|
||
|
return readGenerateAuthTokenResponse;
|
||
|
}
|
||
|
throw new FirebaseInstallationsException("Firebase Installations Service is unavailable. Please try again later.", FirebaseInstallationsException.Status.UNAVAILABLE);
|
||
|
}
|
||
|
|
||
|
private HttpURLConnection openHttpURLConnection(URL url, String str) throws FirebaseInstallationsException {
|
||
|
HeartBeatInfo.HeartBeat heartBeatCode;
|
||
|
try {
|
||
|
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
|
||
|
httpURLConnection.setConnectTimeout(HwBuildEx.VersionCodes.CUR_DEVELOPMENT);
|
||
|
httpURLConnection.setUseCaches(false);
|
||
|
httpURLConnection.setReadTimeout(HwBuildEx.VersionCodes.CUR_DEVELOPMENT);
|
||
|
httpURLConnection.addRequestProperty(HttpHeaders.CONTENT_TYPE, AbstractSpiCall.ACCEPT_JSON_VALUE);
|
||
|
httpURLConnection.addRequestProperty("Accept", AbstractSpiCall.ACCEPT_JSON_VALUE);
|
||
|
httpURLConnection.addRequestProperty(HttpHeaders.CONTENT_ENCODING, "gzip");
|
||
|
httpURLConnection.addRequestProperty(HttpHeaders.CACHE_CONTROL, "no-cache");
|
||
|
httpURLConnection.addRequestProperty("X-Android-Package", this.context.getPackageName());
|
||
|
if (this.heartbeatInfo.get() != null && this.userAgentPublisher.get() != null && (heartBeatCode = this.heartbeatInfo.get().getHeartBeatCode("fire-installations-id")) != HeartBeatInfo.HeartBeat.NONE) {
|
||
|
httpURLConnection.addRequestProperty("x-firebase-client", this.userAgentPublisher.get().getUserAgent());
|
||
|
httpURLConnection.addRequestProperty("x-firebase-client-log-type", Integer.toString(heartBeatCode.getCode()));
|
||
|
}
|
||
|
httpURLConnection.addRequestProperty("X-Android-Cert", getFingerprintHashForPackage());
|
||
|
httpURLConnection.addRequestProperty("x-goog-api-key", str);
|
||
|
return httpURLConnection;
|
||
|
} catch (IOException unused) {
|
||
|
throw new FirebaseInstallationsException("Firebase Installations Service is unavailable. Please try again later.", FirebaseInstallationsException.Status.UNAVAILABLE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private InstallationResponse readCreateResponse(HttpURLConnection httpURLConnection) throws AssertionError, IOException {
|
||
|
InputStream inputStream = httpURLConnection.getInputStream();
|
||
|
JsonReader jsonReader = new JsonReader(new InputStreamReader(inputStream, UTF_8));
|
||
|
TokenResult.Builder builder = TokenResult.builder();
|
||
|
InstallationResponse.Builder builder2 = InstallationResponse.builder();
|
||
|
jsonReader.beginObject();
|
||
|
while (jsonReader.hasNext()) {
|
||
|
String nextName = jsonReader.nextName();
|
||
|
if (nextName.equals("name")) {
|
||
|
builder2.setUri(jsonReader.nextString());
|
||
|
} else if (nextName.equals("fid")) {
|
||
|
builder2.setFid(jsonReader.nextString());
|
||
|
} else if (nextName.equals("refreshToken")) {
|
||
|
builder2.setRefreshToken(jsonReader.nextString());
|
||
|
} else if (nextName.equals("authToken")) {
|
||
|
jsonReader.beginObject();
|
||
|
while (jsonReader.hasNext()) {
|
||
|
String nextName2 = jsonReader.nextName();
|
||
|
if (nextName2.equals("token")) {
|
||
|
builder.setToken(jsonReader.nextString());
|
||
|
} else if (nextName2.equals("expiresIn")) {
|
||
|
builder.setTokenExpirationTimestamp(parseTokenExpirationTimestamp(jsonReader.nextString()));
|
||
|
} else {
|
||
|
jsonReader.skipValue();
|
||
|
}
|
||
|
}
|
||
|
builder2.setAuthToken(builder.build());
|
||
|
jsonReader.endObject();
|
||
|
} else {
|
||
|
jsonReader.skipValue();
|
||
|
}
|
||
|
}
|
||
|
jsonReader.endObject();
|
||
|
jsonReader.close();
|
||
|
inputStream.close();
|
||
|
return builder2.setResponseCode(InstallationResponse.ResponseCode.OK).build();
|
||
|
}
|
||
|
|
||
|
private TokenResult readGenerateAuthTokenResponse(HttpURLConnection httpURLConnection) throws AssertionError, IOException {
|
||
|
InputStream inputStream = httpURLConnection.getInputStream();
|
||
|
JsonReader jsonReader = new JsonReader(new InputStreamReader(inputStream, UTF_8));
|
||
|
TokenResult.Builder builder = TokenResult.builder();
|
||
|
jsonReader.beginObject();
|
||
|
while (jsonReader.hasNext()) {
|
||
|
String nextName = jsonReader.nextName();
|
||
|
if (nextName.equals("token")) {
|
||
|
builder.setToken(jsonReader.nextString());
|
||
|
} else if (nextName.equals("expiresIn")) {
|
||
|
builder.setTokenExpirationTimestamp(parseTokenExpirationTimestamp(jsonReader.nextString()));
|
||
|
} else {
|
||
|
jsonReader.skipValue();
|
||
|
}
|
||
|
}
|
||
|
jsonReader.endObject();
|
||
|
jsonReader.close();
|
||
|
inputStream.close();
|
||
|
return builder.setResponseCode(TokenResult.ResponseCode.OK).build();
|
||
|
}
|
||
|
|
||
|
private String getFingerprintHashForPackage() {
|
||
|
try {
|
||
|
Context context = this.context;
|
||
|
byte[] packageCertificateHashBytes = AndroidUtilsLight.getPackageCertificateHashBytes(context, context.getPackageName());
|
||
|
if (packageCertificateHashBytes == null) {
|
||
|
return null;
|
||
|
}
|
||
|
return Hex.bytesToStringUppercase(packageCertificateHashBytes, false);
|
||
|
} catch (PackageManager.NameNotFoundException unused) {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static long parseTokenExpirationTimestamp(String str) {
|
||
|
Preconditions.checkArgument(EXPIRATION_TIMESTAMP_PATTERN.matcher(str).matches(), "Invalid Expiration Timestamp.");
|
||
|
if (str == null || str.length() == 0) {
|
||
|
return 0L;
|
||
|
}
|
||
|
return Long.parseLong(str.substring(0, str.length() - 1));
|
||
|
}
|
||
|
|
||
|
private static void logFisCommunicationError(HttpURLConnection httpURLConnection, String str, String str2, String str3) {
|
||
|
if (TextUtils.isEmpty(readErrorResponse(httpURLConnection))) {
|
||
|
return;
|
||
|
}
|
||
|
availableFirebaseOptions(str, str2, str3);
|
||
|
}
|
||
|
|
||
|
private static String availableFirebaseOptions(String str, String str2, String str3) {
|
||
|
Object[] objArr = new Object[3];
|
||
|
objArr[0] = str2;
|
||
|
objArr[1] = str3;
|
||
|
objArr[2] = TextUtils.isEmpty(str) ? "" : ", ".concat(String.valueOf(str));
|
||
|
return String.format("Firebase options used while communicating with Firebase server APIs: %s, %s%s", objArr);
|
||
|
}
|
||
|
|
||
|
private static String readErrorResponse(HttpURLConnection httpURLConnection) {
|
||
|
InputStream errorStream = httpURLConnection.getErrorStream();
|
||
|
if (errorStream == null) {
|
||
|
return null;
|
||
|
}
|
||
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(errorStream, UTF_8));
|
||
|
try {
|
||
|
try {
|
||
|
StringBuilder sb = new StringBuilder();
|
||
|
while (true) {
|
||
|
String readLine = bufferedReader.readLine();
|
||
|
if (readLine == null) {
|
||
|
break;
|
||
|
}
|
||
|
sb.append(readLine);
|
||
|
sb.append('\n');
|
||
|
}
|
||
|
String format = String.format("Error when communicating with the Firebase Installations server API. HTTP response: [%d %s: %s]", Integer.valueOf(httpURLConnection.getResponseCode()), httpURLConnection.getResponseMessage(), sb);
|
||
|
try {
|
||
|
bufferedReader.close();
|
||
|
} catch (IOException unused) {
|
||
|
}
|
||
|
return format;
|
||
|
} catch (IOException unused2) {
|
||
|
return null;
|
||
|
}
|
||
|
} catch (IOException unused3) {
|
||
|
bufferedReader.close();
|
||
|
return null;
|
||
|
} catch (Throwable th) {
|
||
|
try {
|
||
|
bufferedReader.close();
|
||
|
} catch (IOException unused4) {
|
||
|
}
|
||
|
throw th;
|
||
|
}
|
||
|
}
|
||
|
}
|