From 98107e40bc855d994d004e66aa132f5579fad394 Mon Sep 17 00:00:00 2001 From: tarsin Date: Thu, 2 Mar 2023 15:34:42 +0800 Subject: [PATCH] Refactor cookies database --- .../hippo/ehviewer/client/EhCookieStore.kt | 5 +- .../ehviewer/ui/login/CookieSignInScreen.kt | 2 +- .../java/com/hippo/network/CookieDatabase.kt | 158 ++++++++---------- 3 files changed, 74 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt b/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt index 06d8d2307..85dd47b28 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhCookieStore.kt @@ -18,6 +18,7 @@ package com.hippo.ehviewer.client import com.hippo.ehviewer.EhApplication import com.hippo.network.CookieDatabase import com.hippo.network.CookieSet +import eu.kanade.tachiyomi.util.lang.launchIO import io.ktor.client.plugins.cookies.CookiesStorage import io.ktor.http.Url import okhttp3.Cookie @@ -179,7 +180,9 @@ object EhCookieStore : CookieJar, CookiesStorage { @Synchronized fun clear() { map.clear() - db.clear() + launchIO { + db.clear() + } } override suspend fun addCookie(requestUrl: Url, cookie: io.ktor.http.Cookie) {} diff --git a/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt b/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt index 6c6f9e2e7..16486286d 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt @@ -114,10 +114,10 @@ fun CookieSignInScene() { ipbPassHashErrorState = false } focusManager.clearFocus() - storeCookie(ipbMemberId, ipbPassHash, igneous) isProgressIndicatorVisible = true signInJob = coroutineScope.launchIO { runCatching { + storeCookie(ipbMemberId, ipbPassHash, igneous) EhEngine.getProfile() }.onSuccess { withNonCancellableContext { diff --git a/app/src/main/java/com/hippo/network/CookieDatabase.kt b/app/src/main/java/com/hippo/network/CookieDatabase.kt index 06802701d..984638cb9 100644 --- a/app/src/main/java/com/hippo/network/CookieDatabase.kt +++ b/app/src/main/java/com/hippo/network/CookieDatabase.kt @@ -29,41 +29,80 @@ import androidx.room.RoomDatabase import androidx.room.Update import okhttp3.Cookie as OkHttpCookie +@Entity(tableName = "OK_HTTP_3_COOKIE") +class Cookie( + @ColumnInfo(name = "NAME") + var name: String, + @ColumnInfo(name = "VALUE") + var value: String, + @ColumnInfo(name = "EXPIRES_AT") + var expiresAt: Long, + @ColumnInfo(name = "DOMAIN") + var domain: String, + @ColumnInfo(name = "PATH") + var path: String, + @ColumnInfo(name = "SECURE") + var secure: Boolean, + @ColumnInfo(name = "HTTP_ONLY") + var httpOnly: Boolean, + @ColumnInfo(name = "PERSISTENT") + var persistent: Boolean, + @ColumnInfo(name = "HOST_ONLY") + var hostOnly: Boolean, + @PrimaryKey + @ColumnInfo(name = "_id") + var id: Long? +) + +@Dao +interface CookiesDao { + @Query("SELECT * FROM OK_HTTP_3_COOKIE") + fun list(): List + + @Delete + fun delete(cookie: Cookie) + + @Insert + fun insert(cookie: Cookie): Long + + @Update + fun update(cookie: Cookie) +} + +@Database(entities = [Cookie::class], version = 1, exportSchema = false) +abstract class CookiesDatabase : RoomDatabase() { + abstract fun cookiesDao(): CookiesDao +} + internal class CookieDatabase(context: Context, name: String) { private val cookieIdMap: MutableMap = HashMap() - private val db = - Room.databaseBuilder(context, CookiesDatabase::class.java, name).allowMainThreadQueries() - .build() + private val db = Room.databaseBuilder(context, CookiesDatabase::class.java, name).build() - val allCookies: MutableMap - get() { - val now = System.currentTimeMillis() - val map: MutableMap = HashMap() - val toRemove: MutableList = ArrayList() - db.cookiesDao().list().forEach { - if (!it.persistent || it.expiresAt <= now) { - toRemove.add(it.id!!) - } else { - val okhttpCookie = it.toOkHttp3Cookie() - cookieIdMap[okhttpCookie] = it.id!! - - // Put cookie to set - val set = map[it.domain] ?: CookieSet().apply { map[it.domain] = this } - set.add(okhttpCookie) - } + val allCookies by lazy { + val now = System.currentTimeMillis() + val map: MutableMap = HashMap() + val toRemove: MutableList = ArrayList() + db.cookiesDao().list().forEach { + if (!it.persistent || it.expiresAt <= now) { + toRemove.add(it.id!!) + } else { + val okhttpCookie = it.toOkHttp3Cookie() + cookieIdMap[okhttpCookie] = it.id!! + val set = map[it.domain] ?: CookieSet().apply { map[it.domain] = this } + set.add(okhttpCookie) } - if (toRemove.isNotEmpty()) { - val statement = - db.compileStatement("DELETE FROM $TABLE_COOKIE WHERE $COLUMN_ID = ?;") - db.runInTransaction { - toRemove.forEach { - statement.bindLong(1, it) - statement.executeUpdateDelete() - } - } - } - return map } + if (toRemove.isNotEmpty()) { + val statement = db.compileStatement("DELETE FROM OK_HTTP_3_COOKIE WHERE _id = ?;") + db.runInTransaction { + toRemove.forEach { + statement.bindLong(1, it) + statement.executeUpdateDelete() + } + } + } + map + } fun add(cookie: OkHttpCookie) { db.cookiesDao().insert(cookie.toCookie()).apply { cookieIdMap[cookie] = this } @@ -88,31 +127,6 @@ internal class CookieDatabase(context: Context, name: String) { } } -@Entity(tableName = TABLE_COOKIE) -data class Cookie( - @ColumnInfo(name = COLUMN_NAME) - var name: String, - @ColumnInfo(name = COLUMN_VALUE) - var value: String, - @ColumnInfo(name = COLUMN_EXPIRES_AT) - var expiresAt: Long, - @ColumnInfo(name = COLUMN_DOMAIN) - var domain: String, - @ColumnInfo(name = COLUMN_PATH) - var path: String, - @ColumnInfo(name = COLUMN_SECURE) - var secure: Boolean, - @ColumnInfo(name = COLUMN_HTTP_ONLY) - var httpOnly: Boolean, - @ColumnInfo(name = COLUMN_PERSISTENT) - var persistent: Boolean, - @ColumnInfo(name = COLUMN_HOST_ONLY) - var hostOnly: Boolean, - @PrimaryKey - @ColumnInfo(name = COLUMN_ID) - var id: Long? -) - fun Cookie.toOkHttp3Cookie(): OkHttpCookie { return OkHttpCookie.Builder().apply { name(name) @@ -130,37 +144,3 @@ private fun OkHttpCookie.toCookie(id: Long? = null): Cookie { name, value, expiresAt, domain, path, secure, httpOnly, persistent, hostOnly, id ) } - -@Dao -interface CookiesDao { - @Query("SELECT * FROM $TABLE_COOKIE") - fun list(): List - - @Delete - fun delete(cookie: Cookie) - - @Insert - fun insert(cookie: Cookie): Long - - @Update - fun update(cookie: Cookie) -} - -@Database(entities = [Cookie::class], version = DB_VERSION, exportSchema = false) -abstract class CookiesDatabase : RoomDatabase() { - abstract fun cookiesDao(): CookiesDao -} - -private const val VERSION_1 = 1 -private const val TABLE_COOKIE = "OK_HTTP_3_COOKIE" -private const val COLUMN_ID = "_id" -private const val COLUMN_NAME = "NAME" -private const val COLUMN_VALUE = "VALUE" -private const val COLUMN_EXPIRES_AT = "EXPIRES_AT" -private const val COLUMN_DOMAIN = "DOMAIN" -private const val COLUMN_PATH = "PATH" -private const val COLUMN_SECURE = "SECURE" -private const val COLUMN_HTTP_ONLY = "HTTP_ONLY" -private const val COLUMN_PERSISTENT = "PERSISTENT" -private const val COLUMN_HOST_ONLY = "HOST_ONLY" -private const val DB_VERSION = VERSION_1