|
package de.aoksystems.ma.abp.smp.common |
|
|
|
import android.content.Context |
|
import android.support.annotation.VisibleForTesting |
|
import de.aoksystems.ma.abp.common.util.InstanceFactory |
|
import de.aoksystems.ma.abp.common.util.TimeProvider |
|
import de.aoksystems.ma.abp.common.util.callbacks.AppCodeResetCallbackRegistry |
|
import io.reactivex.Completable |
|
import okhttp3.Cookie |
|
import okhttp3.CookieJar |
|
import okhttp3.HttpUrl |
|
|
|
internal class PersistentCookieJar(context: Context, private val timeProvider: TimeProvider) : CookieJar { |
|
|
|
private val sharedPreferences by lazy { |
|
context.getSharedPreferences(PREF_FILE_KEY, Context.MODE_PRIVATE) |
|
} |
|
|
|
private var cookieStore: Map<String, Cookie> = mapOf() |
|
|
|
private fun clearCookies() { |
|
cookieStore = emptyMap() |
|
sharedPreferences.edit().clear().apply() |
|
} |
|
|
|
private fun parseCookie(url: String, cookie: String): Cookie { |
|
val parsedUrl = requireNotNull(HttpUrl.parse(url)) { "could not parse URL $url" } |
|
return requireNotNull(Cookie.parse(parsedUrl, cookie)) { "could not parse Cookie $cookie" } |
|
} |
|
|
|
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) { |
|
cookies.forEach { newCookie -> |
|
cookieStore = cookieStore.plus(newCookie.key() to newCookie) |
|
} |
|
persistCookies() |
|
} |
|
|
|
override fun loadForRequest(url: HttpUrl): List<Cookie> { |
|
cookieStore = if (cookieStore.isEmpty()) restoreCookies() else cookieStore |
|
val size = cookieStore.size |
|
if (size == 0) return emptyList() |
|
cookieStore = cookieStore.filter { timeProvider.getCurrentTime() < it.value.expiresAt() } |
|
if (size != cookieStore.size) persistCookies() |
|
return cookieStore.map { it.value }.filter { it.matches(url) } |
|
} |
|
|
|
private fun restoreCookies(): Map<String, Cookie> { |
|
val result = mutableMapOf<String, Cookie>() |
|
sharedPreferences.all.entries.forEach { entry -> |
|
result[entry.key] = parseCookie(entry.key, entry.value.toString()) |
|
} |
|
return result |
|
} |
|
|
|
private fun persistCookies() { |
|
val editor = sharedPreferences.edit() |
|
cookieStore.forEach { entry -> |
|
if (entry.value.persistent()) editor.putString(entry.key, entry.value.toString()) |
|
} |
|
editor.apply() |
|
} |
|
|
|
internal fun hasCookie(name: String): Boolean = cookieStore.any { it.value.name() == name } |
|
|
|
private fun Cookie.key(): String = (if (secure()) "https" else "http") + "://${domain()}${path()}#${name()}" |
|
|
|
companion object { |
|
@VisibleForTesting |
|
internal const val PREF_FILE_KEY = "my-pref-file" |
|
} |
|
} |
Hacked together, untested, beware!