aboutsummaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt58
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt16
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt7
-rw-r--r--app/src/schemas/com.pitchedapps.frost.db.FrostPrivateDatabase/2.json201
5 files changed, 281 insertions, 5 deletions
diff --git a/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt
new file mode 100644
index 00000000..6ba6e0b6
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/pitchedapps/frost/db/CookieMigrationTest.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 Allan Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.pitchedapps.frost.db
+
+import androidx.room.Room
+import androidx.room.testing.MigrationTestHelper
+import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import kotlin.test.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class CookieMigrationTest {
+
+ private val TEST_DB = "cookie_migration_test"
+
+ private val ALL_MIGRATIONS = arrayOf(COOKIES_MIGRATION_1_2)
+
+ val helper: MigrationTestHelper = MigrationTestHelper(
+ InstrumentationRegistry.getInstrumentation(),
+ FrostPrivateDatabase::class.java.canonicalName,
+ FrameworkSQLiteOpenHelperFactory()
+ )
+
+ @Test
+ fun migrateAll() {
+ // Create earliest version of the database.
+ helper.createDatabase(TEST_DB, 1).apply {
+ close()
+ }
+
+ // Open latest version of the database. Room will validate the schema
+ // once all migrations execute.
+ Room.databaseBuilder(
+ InstrumentationRegistry.getInstrumentation().targetContext,
+ FrostPrivateDatabase::class.java,
+ TEST_DB
+ ).addMigrations(*ALL_MIGRATIONS).build().apply {
+ openHelper.writableDatabase
+ close()
+ }
+ }
+}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt
index 388edfe6..163d151b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/db/CookiesDb.kt
@@ -23,6 +23,8 @@ import androidx.room.Entity
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
import com.pitchedapps.frost.prefs.Prefs
import kotlinx.android.parcel.Parcelize
@@ -37,7 +39,8 @@ data class CookieEntity(
@ColumnInfo(name = "cookie_id")
val id: Long,
val name: String?,
- val cookie: String?
+ val cookie: String?,
+ val cookieMessenger: String? = null // Version 2
) : Parcelable {
override fun toString(): String = "CookieEntity(${hashCode()})"
@@ -61,6 +64,9 @@ interface CookieDao {
@Query("DELETE FROM cookies WHERE cookie_id = :id")
fun _deleteById(id: Long)
+
+ @Query("UPDATE cookies SET cookieMessenger = :cookie WHERE cookie_id = :id")
+ fun _updateMessengerCookie(id: Long, cookie: String?)
}
suspend fun CookieDao.selectAll() = dao { _selectAll() }
@@ -69,3 +75,11 @@ suspend fun CookieDao.save(cookie: CookieEntity) = dao { _save(cookie) }
suspend fun CookieDao.save(cookies: List<CookieEntity>) = dao { _save(cookies) }
suspend fun CookieDao.deleteById(id: Long) = dao { _deleteById(id) }
suspend fun CookieDao.currentCookie(prefs: Prefs) = selectById(prefs.userId)
+suspend fun CookieDao.updateMessengerCookie(id: Long, cookie: String?) =
+ dao { _updateMessengerCookie(id, cookie) }
+
+val COOKIES_MIGRATION_1_2 = object : Migration(1, 2) {
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL("ALTER TABLE cookies ADD COLUMN cookieMessenger TEXT")
+ }
+}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt
index 21a2f1dc..bd0b4ee0 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/db/Database.kt
@@ -31,7 +31,7 @@ interface FrostPrivateDao {
@Database(
entities = [CookieEntity::class, NotificationEntity::class, CacheEntity::class],
- version = 1,
+ version = 2,
exportSchema = true
)
abstract class FrostPrivateDatabase : RoomDatabase(), FrostPrivateDao {
@@ -84,7 +84,7 @@ class FrostDatabase(
val privateDb = Room.databaseBuilder(
context, FrostPrivateDatabase::class.java,
FrostPrivateDatabase.DATABASE_NAME
- ).frostBuild()
+ ).addMigrations(COOKIES_MIGRATION_1_2).frostBuild()
val publicDb = Room.databaseBuilder(
context, FrostPublicDatabase::class.java,
FrostPublicDatabase.DATABASE_NAME
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
index efaa03ab..db40495b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbCookie.kt
@@ -24,6 +24,7 @@ import com.pitchedapps.frost.db.CookieEntity
import com.pitchedapps.frost.db.deleteById
import com.pitchedapps.frost.db.save
import com.pitchedapps.frost.db.selectById
+import com.pitchedapps.frost.db.updateMessengerCookie
import com.pitchedapps.frost.prefs.Prefs
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.cookies
@@ -115,14 +116,16 @@ class FbCookie(private val prefs: Prefs, private val cookieDao: CookieDao) {
L.d { "Switching User; null cookie" }
return
}
+ val currentId = prefs.userId
withContext(Dispatchers.IO + NonCancellable) {
L.d { "Switching User" }
- // TODO save old messenger cookie
+ // Save current messenger cookie state.
+ cookieDao.updateMessengerCookie(currentId, messengerCookie)
prefs.userId = cookie.id
CookieManager.getInstance().apply {
removeAllCookies()
suspendSetWebCookie(FB_COOKIE_DOMAIN, cookie.cookie)
- // TODO set messenger cookie
+ suspendSetWebCookie(MESSENGER_COOKIE_DOMAIN, cookie.cookieMessenger)
flush()
}
}
diff --git a/app/src/schemas/com.pitchedapps.frost.db.FrostPrivateDatabase/2.json b/app/src/schemas/com.pitchedapps.frost.db.FrostPrivateDatabase/2.json
new file mode 100644
index 00000000..066f4478
--- /dev/null
+++ b/app/src/schemas/com.pitchedapps.frost.db.FrostPrivateDatabase/2.json
@@ -0,0 +1,201 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 2,
+ "identityHash": "c7625cc0226e291f14c14f528a11e739",
+ "entities": [
+ {
+ "tableName": "cookies",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cookie_id` INTEGER NOT NULL, `name` TEXT, `cookie` TEXT, `cookieMessenger` TEXT, PRIMARY KEY(`cookie_id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "cookie_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "cookie",
+ "columnName": "cookie",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "cookieMessenger",
+ "columnName": "cookieMessenger",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "cookie_id"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "notifications",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`notif_id` INTEGER NOT NULL, `userId` INTEGER NOT NULL, `href` TEXT NOT NULL, `title` TEXT, `text` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `profileUrl` TEXT, `type` TEXT NOT NULL, `unread` INTEGER NOT NULL, PRIMARY KEY(`notif_id`, `userId`), FOREIGN KEY(`userId`) REFERENCES `cookies`(`cookie_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "notif_id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "userId",
+ "columnName": "userId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "href",
+ "columnName": "href",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "text",
+ "columnName": "text",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "profileUrl",
+ "columnName": "profileUrl",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "unread",
+ "columnName": "unread",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "notif_id",
+ "userId"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [
+ {
+ "name": "index_notifications_notif_id",
+ "unique": false,
+ "columnNames": [
+ "notif_id"
+ ],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_notifications_notif_id` ON `${TABLE_NAME}` (`notif_id`)"
+ },
+ {
+ "name": "index_notifications_userId",
+ "unique": false,
+ "columnNames": [
+ "userId"
+ ],
+ "createSql": "CREATE INDEX IF NOT EXISTS `index_notifications_userId` ON `${TABLE_NAME}` (`userId`)"
+ }
+ ],
+ "foreignKeys": [
+ {
+ "table": "cookies",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "userId"
+ ],
+ "referencedColumns": [
+ "cookie_id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "frost_cache",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `type` TEXT NOT NULL, `lastUpdated` INTEGER NOT NULL, `contents` TEXT NOT NULL, PRIMARY KEY(`id`, `type`), FOREIGN KEY(`id`) REFERENCES `cookies`(`cookie_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "type",
+ "columnName": "type",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lastUpdated",
+ "columnName": "lastUpdated",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "contents",
+ "columnName": "contents",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "columnNames": [
+ "id",
+ "type"
+ ],
+ "autoGenerate": false
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "cookies",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "id"
+ ],
+ "referencedColumns": [
+ "cookie_id"
+ ]
+ }
+ ]
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c7625cc0226e291f14c14f528a11e739')"
+ ]
+ }
+} \ No newline at end of file