Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,13 @@ The following libraries are available for the various Firebase products.

| Service or Product | Port of Android version |
|---------------------------------------------------------------------------------------------------|:------------------------|
| [Firebase Android BoM](https://maven.google.com/web/index.html?#com.google.firebase:firebase-bom) | `32.7.0` |
| [Firebase Android BoM](https://maven.google.com/web/index.html?#com.google.firebase:firebase-bom) | `34.18.0` |
| [Authentication](https://firebase.google.com/docs/auth) | N/A[^1] |
| [Cloud Firestore](https://firebase.google.com/docs/firestore) | `24.10.0` |
| [Realtime Database](https://firebase.google.com/docs/database) | `20.3.0` |
| [Cloud Functions](https://firebase.google.com/docs/functions) | `20.4.0` |
| ~[Remote Config](https://firebase.google.com/docs/remote-config)~ | `21.6.0`[^2] |
| ~[Installations](https://firebase.google.com/docs/projects/manage-installations)~ | `17.2.0`[^2] |
| [Cloud Firestore](https://firebase.google.com/docs/firestore) | `26.6.0` |
| [Realtime Database](https://firebase.google.com/docs/database) | `22.0.1` |
| [Cloud Functions](https://firebase.google.com/docs/functions) | `22.1.1` |
| ~[Remote Config](https://firebase.google.com/docs/remote-config)~ | `23.1.0`[^2] |
| ~[Installations](https://firebase.google.com/docs/projects/manage-installations)~ | `19.1.2`[^2] |

[^1]: Google has not open-sourced the Firebase Auth implementation for Android so a basic implementation using the Rest API is provided.
[^2]: Although the libraries are inlcuded they are currently not funtional
Expand Down
8 changes: 8 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,17 @@ dependencies {
implementation(libs.io.grpc.protobuf.lite)
implementation(libs.io.grpc.stub)
implementation(libs.androidx.collection)
// firebase-common 22 keeps its heartbeat store in a preferences DataStore (see com.google.firebase.datastorage.JavaDataStorage)
implementation(libs.androidx.datastore.core)
implementation(libs.androidx.datastore.preferences.core)
implementation(libs.io.grpc.okhttp)
implementation(libs.androidx.lifecycle.common)
implementation(libs.androidx.lifecycle.viewmodel)
// Plain-jar dependencies of the bumped libraries that the aar configuration resolves but does not ship: Functions
// 22 returns a Reactive Streams Publisher from HttpsCallableReference.stream(), Firestore 26 evaluates regex and
// like filters with re2j.
api(libs.reactive.streams)
implementation(libs.re2j)
}

tasks.named("publishToMavenLocal").configure {
Expand Down
9 changes: 7 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[versions]
androidx-datastore = "1.1.7"
androidx-lifecycle = "2.10.0-alpha01"
ben-manes-versions = "0.51.0"
google-firebase-bom = "32.7.0"
google-firebase-bom = "34.18.0"
Comment thread
nbransby marked this conversation as resolved.
io-grpc = "1.68.0"
jlleitschuh-ktlint = "12.1.1"
kotlin = "2.0.20"
Expand All @@ -12,6 +13,8 @@ publish = "0.34.0"

[libraries]
androidx-collection = { module = "androidx.collection:collection", version = "1.4.3" }
androidx-datastore-core = { module = "androidx.datastore:datastore-core", version.ref = "androidx-datastore" }
androidx-datastore-preferences-core = { module = "androidx.datastore:datastore-preferences-core", version.ref = "androidx-datastore" }
androidx-lifecycle-common = { module = "androidx.lifecycle:lifecycle-common", version.ref = "androidx-lifecycle" }
androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
google-firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "google-firebase-bom" }
Expand All @@ -32,7 +35,9 @@ kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinx-serialization" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "3.12.13" }
okhttp = { module = "com.squareup.okhttp3:okhttp", version = "4.12.0" }
re2j = { module = "com.google.re2j:re2j", version = "1.6" }
reactive-streams = { module = "org.reactivestreams:reactive-streams", version = "1.0.4" }
robolectric-android-all = { module = "org.robolectric:android-all", version = "14-robolectric-10818077" }
xerial-sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version = "3.46.1.0" }

Expand Down
3 changes: 3 additions & 0 deletions src/main/java/android/content/Context.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ open class Context {
val noBackupFilesDir: File
get() = File(System.getProperty("java.io.tmpdir"))

val filesDir: File
get() = FirebasePlatform.firebasePlatform.getFilesDir()

val classLoader: ClassLoader
get() = ClassLoader.getSystemClassLoader()

Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/google/firebase/FirebasePlatform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ abstract class FirebasePlatform {
abstract fun log(msg: String)

open fun getDatabasePath(name: String): File = File("${System.getProperty("java.io.tmpdir")}${File.separatorChar}$name")

/** The directory the Firebase SDKs keep their files in, such as the DataStore of the firebase-common heartbeat store. */
open fun getFilesDir(): File = File(System.getProperty("java.io.tmpdir"))
}
143 changes: 60 additions & 83 deletions src/main/java/com/google/firebase/auth/FirebaseAuth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.longOrNull
import okhttp3.Call
import okhttp3.Callback
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import java.io.IOException
import java.util.Base64
Expand Down Expand Up @@ -112,7 +113,7 @@ data class FirebaseUserImpl internal constructor(

override fun delete(): Task<Void> {
val source = TaskCompletionSource<Void>()
val body = RequestBody.create(FirebaseAuth.getInstance(app).json, JsonObject(mapOf("idToken" to JsonPrimitive(idToken))).toString())
val body = JsonObject(mapOf("idToken" to JsonPrimitive(idToken))).toString().toRequestBody(FirebaseAuth.getInstance(app).json)
val request =
Request
.Builder()
Expand Down Expand Up @@ -166,17 +167,14 @@ data class FirebaseUserImpl internal constructor(
): Task<Unit> {
val source = TaskCompletionSource<Unit>()
val body =
RequestBody.create(
FirebaseAuth.getInstance(app).json,
JsonObject(
mapOf(
"idToken" to JsonPrimitive(idToken),
"email" to JsonPrimitive(email),
"newEmail" to JsonPrimitive(newEmail),
"requestType" to JsonPrimitive(OobRequestType.VERIFY_AND_CHANGE_EMAIL.name)
)
).toString()
)
JsonObject(
mapOf(
"idToken" to JsonPrimitive(idToken),
"email" to JsonPrimitive(email),
"newEmail" to JsonPrimitive(newEmail),
"requestType" to JsonPrimitive(OobRequestType.VERIFY_AND_CHANGE_EMAIL.name)
)
).toString().toRequestBody(FirebaseAuth.getInstance(app).json)
val request =
Request
.Builder()
Expand Down Expand Up @@ -237,7 +235,7 @@ data class FirebaseUserImpl internal constructor(
class FirebaseAuth constructor(
val app: FirebaseApp
) : InternalAuthProvider {
internal val json = MediaType.parse("application/json; charset=utf-8")
internal val json = "application/json; charset=utf-8".toMediaType()
internal val client: OkHttpClient =
OkHttpClient
.Builder()
Expand Down Expand Up @@ -276,7 +274,7 @@ class FirebaseAuth constructor(
createAuthInvalidUserException("accounts", request, response)
)
} else {
if (response.body()?.use { it.string() }?.also { responseBody ->
if (response.body?.use { it.string() }?.also { responseBody ->
user = setResult(responseBody)
source.setResult(AuthResult { user })
} == null
Expand Down Expand Up @@ -352,7 +350,7 @@ class FirebaseAuth constructor(
fun signInAnonymously(): Task<AuthResult> {
val source = enqueueAuthPost(
url = "identitytoolkit.googleapis.com/v1/accounts:signUp",
body = RequestBody.create(json, JsonObject(mapOf("returnSecureToken" to JsonPrimitive(true))).toString()),
body = JsonObject(mapOf("returnSecureToken" to JsonPrimitive(true))).toString().toRequestBody(json),
setResult = { responseBody ->
FirebaseUserImpl(app, jsonParser.parseToJsonElement(responseBody).jsonObject, isAnonymous = true)
}
Expand All @@ -363,10 +361,7 @@ class FirebaseAuth constructor(
fun signInWithCustomToken(customToken: String): Task<AuthResult> {
val source = enqueueAuthPost(
url = "www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken",
body = RequestBody.create(
json,
JsonObject(mapOf("token" to JsonPrimitive(customToken), "returnSecureToken" to JsonPrimitive(true))).toString()
),
body = JsonObject(mapOf("token" to JsonPrimitive(customToken), "returnSecureToken" to JsonPrimitive(true))).toString().toRequestBody(json),
setResult = { responseBody ->
FirebaseUserImpl(app, jsonParser.parseToJsonElement(responseBody).jsonObject)
}
Expand All @@ -378,10 +373,7 @@ class FirebaseAuth constructor(
val source = TaskCompletionSource<AuthResult>()

val body =
RequestBody.create(
json,
JsonObject(mapOf("idToken" to JsonPrimitive(user?.idToken))).toString()
)
JsonObject(mapOf("idToken" to JsonPrimitive(user?.idToken))).toString().toRequestBody(json)
val request =
Request
.Builder()
Expand Down Expand Up @@ -411,7 +403,7 @@ class FirebaseAuth constructor(
val newBody =
jsonParser
.parseToJsonElement(
response.body()?.use { it.string() } ?: ""
response.body?.use { it.string() } ?: ""
).jsonObject

user = user?.copy(
Expand All @@ -436,16 +428,13 @@ class FirebaseAuth constructor(
enqueueAuthPost(
url = "www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser",
body =
RequestBody.create(
json,
JsonObject(
mapOf(
"email" to JsonPrimitive(email),
"password" to JsonPrimitive(password),
"returnSecureToken" to JsonPrimitive(true)
)
).toString()
),
JsonObject(
mapOf(
"email" to JsonPrimitive(email),
"password" to JsonPrimitive(password),
"returnSecureToken" to JsonPrimitive(true)
)
).toString().toRequestBody(json),
setResult = { responseBody ->
FirebaseUserImpl(
app = app,
Expand All @@ -464,16 +453,13 @@ class FirebaseAuth constructor(
enqueueAuthPost(
url = "www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword",
body =
RequestBody.create(
json,
JsonObject(
mapOf(
"email" to JsonPrimitive(email),
"password" to JsonPrimitive(password),
"returnSecureToken" to JsonPrimitive(true)
)
).toString()
),
JsonObject(
mapOf(
"email" to JsonPrimitive(email),
"password" to JsonPrimitive(password),
"returnSecureToken" to JsonPrimitive(true)
)
).toString().toRequestBody(json),
setResult = { responseBody ->
FirebaseUserImpl(app, jsonParser.parseToJsonElement(responseBody).jsonObject)
}
Expand All @@ -486,7 +472,7 @@ class FirebaseAuth constructor(
request: Request,
response: Response
): FirebaseAuthInvalidUserException {
val body = response.body()!!.use { it.string() }
val body = response.body!!.use { it.string() }
val jsonObject = jsonParser.parseToJsonElement(body).jsonObject

return FirebaseAuthInvalidUserException(
Expand All @@ -497,20 +483,20 @@ class FirebaseAuth constructor(
?.contentOrNull
?: "UNKNOWN_ERROR",
"$action API returned an error, " +
"with url [${request.method()}] ${request.url()} ${request.body()} -- " +
"response [${response.code()}] ${response.message()} $body"
"with url [${request.method}] ${request.url} ${request.body} -- " +
"response [${response.code}] ${response.message} $body"
)
}

fun signOut() {
// cancel token refresher
client
.dispatcher()
.dispatcher
.queuedCalls()
.find { it.request().tag() == REFRESH_TOKEN_TAG }
?.cancel() ?: {
client
.dispatcher()
.dispatcher
.runningCalls()
.find { it.request().tag() == REFRESH_TOKEN_TAG }
?.cancel()
Expand Down Expand Up @@ -548,15 +534,12 @@ class FirebaseAuth constructor(
private fun enqueueRefreshTokenCall(user: FirebaseUserImpl): TaskCompletionSource<FirebaseUserImpl> {
val source = TaskCompletionSource<FirebaseUserImpl>()
val body =
RequestBody.create(
json,
JsonObject(
mapOf(
"refresh_token" to JsonPrimitive(user.refreshToken),
"grant_type" to JsonPrimitive("refresh_token")
)
).toString()
)
JsonObject(
mapOf(
"refresh_token" to JsonPrimitive(user.refreshToken),
"grant_type" to JsonPrimitive("refresh_token")
)
).toString().toRequestBody(json)
val request =
Request
.Builder()
Expand All @@ -579,7 +562,7 @@ class FirebaseAuth constructor(
call: Call,
response: Response
) {
val responseBody = response.body()?.use { it.string() }
val responseBody = response.body?.use { it.string() }

if (!response.isSuccessful || responseBody == null) {
signOutAndThrowInvalidUserException(responseBody.orEmpty(), "token API returned an error: $body")
Expand Down Expand Up @@ -615,16 +598,13 @@ class FirebaseAuth constructor(
val source = TaskCompletionSource<Unit>()

val body =
RequestBody.create(
json,
JsonObject(
mapOf(
"idToken" to JsonPrimitive(user?.idToken),
"email" to JsonPrimitive(email),
"returnSecureToken" to JsonPrimitive(true)
)
).toString()
)
JsonObject(
mapOf(
"idToken" to JsonPrimitive(user?.idToken),
"email" to JsonPrimitive(email),
"returnSecureToken" to JsonPrimitive(true)
)
).toString().toRequestBody(json)
val request =
Request
.Builder()
Expand Down Expand Up @@ -659,7 +639,7 @@ class FirebaseAuth constructor(
val newBody =
jsonParser
.parseToJsonElement(
response.body()?.use { it.string() } ?: ""
response.body?.use { it.string() } ?: ""
).jsonObject

user?.let { prev ->
Expand Down Expand Up @@ -689,17 +669,14 @@ class FirebaseAuth constructor(
val source = TaskCompletionSource<Unit>()

val body =
RequestBody.create(
json,
JsonObject(
mapOf(
"idToken" to JsonPrimitive(user?.idToken),
"displayName" to JsonPrimitive(request.displayName),
"photoUrl" to JsonPrimitive(request.photoUrl),
"returnSecureToken" to JsonPrimitive(true)
)
).toString()
)
JsonObject(
mapOf(
"idToken" to JsonPrimitive(user?.idToken),
"displayName" to JsonPrimitive(request.displayName),
"photoUrl" to JsonPrimitive(request.photoUrl),
"returnSecureToken" to JsonPrimitive(true)
)
).toString().toRequestBody(json)
val req =
Request
.Builder()
Expand Down Expand Up @@ -734,7 +711,7 @@ class FirebaseAuth constructor(
val newBody =
jsonParser
.parseToJsonElement(
response.body()?.use { it.string() } ?: ""
response.body?.use { it.string() } ?: ""
).jsonObject

user?.let { prev ->
Expand Down
Loading
Loading