Remove the data-client app adapter implementation (#5499)

* logErrorsInsteadOfCrashing only ever returned false, so remove it and simplify logger

* Removed unused getMediaWikiBaseUrl()

* Removed getDesiredLeadImageDp() from commons app adapter, since it's unused

* Inlined the isLoggedIn() method of the app adapter

* Inline the app adapter username/password

* Removed the unused getRestbaseUriFormat() from the commons app adapter

* Remove references to the data-client SharedPreferenceCookieManager

* Manage our own OkHttpClient and remove the AppAdapter implementation
This commit is contained in:
Paul Hawke 2024-01-30 19:21:43 -06:00 committed by GitHub
parent ab9e57f5be
commit 8db0b54929
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 422 additions and 518 deletions

View file

@ -0,0 +1,98 @@
package fr.free.nrw.commons.wikidata.cookies
import okhttp3.Cookie
import okhttp3.CookieJar
import okhttp3.HttpUrl
class CommonsCookieJar(private val cookieStorage: CommonsCookieStorage) : CookieJar {
override fun loadForRequest(url: HttpUrl): List<Cookie> {
val cookieList = mutableListOf<Cookie>()
val domain: String = url.toUri().getAuthority()
cookieStorage.domains.forEach { domainSpec ->
if (domain.endsWith(domainSpec, true)) {
buildCookieList(cookieList, cookieStorage[domainSpec], null)
} else if (domainSpec.endsWith("commons.wikimedia.org")) {
// For sites outside the wikipedia.org domain, transfer the centralauth cookies
// from commons.wikimedia.org unconditionally.
buildCookieList(cookieList, cookieStorage[domainSpec], "centralauth_")
}
}
return cookieList
}
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
if (cookies.isEmpty()) {
return
}
var cookieJarModified = false
cookies.forEach { cookie ->
// Default to the URI's domain if cookie's domain is not explicitly set
val domainSpec = cookie.domainSpec(url)
if (!cookieStorage.contains(domainSpec)) {
cookieStorage[domainSpec] = mutableListOf()
}
val cookieList = cookieStorage[domainSpec]
if (cookie.expiredOrDeleted()) {
cookieJarModified = cookieList.removeAll { it.name == cookie.name }
} else {
val i = cookieList.iterator()
var exists = false
while (i.hasNext()) {
val c = i.next()
if (c == cookie) {
// an identical cookie already exists, so we don't need to update it.
exists = true
break
} else if (c.name == cookie.name) {
// it's a cookie with the same name, but different contents, so remove the
// current cookie, so that the new one will be added.
i.remove()
}
}
if (!exists) {
cookieList.add(cookie)
cookieJarModified = true
}
}
cookieStorage[domainSpec] = cookieList
}
if (cookieJarModified) {
cookieStorage.save()
}
}
private fun buildCookieList(
outList: MutableList<Cookie>, inList: MutableList<Cookie>, prefix: String?
) {
var cookieJarModified = false
val i = inList.iterator()
while (i.hasNext()) {
val cookie = i.next()
if (prefix != null && !cookie.name.startsWith(prefix)) {
continue
}
// But wait, is the cookie expired?
if (cookie.expiresAt < System.currentTimeMillis()) {
i.remove()
cookieJarModified = true
} else {
outList.add(cookie)
}
}
if (cookieJarModified) {
cookieStorage.save()
}
}
private fun Cookie.expiredOrDeleted(): Boolean =
expiresAt < System.currentTimeMillis() || "deleted" == value
private fun Cookie.domainSpec(url: HttpUrl): String =
domain.ifEmpty { url.toUri().getAuthority() }
}

View file

@ -0,0 +1,93 @@
package fr.free.nrw.commons.wikidata.cookies
import com.google.gson.GsonBuilder
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import fr.free.nrw.commons.kvstore.JsonKvStore
import okhttp3.Cookie
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import org.wikipedia.dataclient.WikiSite
private const val COOKIE_STORE = "cookie_store"
class CommonsCookieStorage(private val preferences: JsonKvStore? = null) {
private val gson = GsonBuilder().registerTypeAdapter(
CommonsCookieStorage::class.java,
CookieStorageTypeAdapter()
).create()
private val cookieMap: MutableMap<String, List<Cookie>> = mutableMapOf()
val domains : Set<String> get() = cookieMap.keys.toSet()
operator fun set(domainSpec: String, cookies: MutableList<Cookie>) =
cookieMap.put(domainSpec, cookies.toList())
operator fun get(domainSpec: String): MutableList<Cookie> =
cookieMap[domainSpec]?.toMutableList() ?: mutableListOf()
fun clear() {
cookieMap.clear()
save()
}
fun load() {
cookieMap.clear()
val json = preferences!!.getString(COOKIE_STORE, null)
if (!json.isNullOrEmpty()) {
val serializedData = gson.fromJson(json, CommonsCookieStorage::class.java)
cookieMap.putAll(serializedData.cookieMap)
}
}
fun save() =
preferences!!.putString(COOKIE_STORE, gson.toJson(this))
fun contains(domainSpec: String): Boolean =
cookieMap.containsKey(domainSpec)
companion object {
fun from(map: Map<String, List<Cookie>>) = CommonsCookieStorage().apply {
cookieMap.clear()
cookieMap.putAll(map)
}
}
}
private class CookieStorageTypeAdapter : TypeAdapter<CommonsCookieStorage>() {
override fun write(out: JsonWriter, value: CommonsCookieStorage) {
out.beginObject()
value.domains.forEach { domain ->
out.name(domain).beginArray()
value[domain].forEach { out.value(it.toString()) }
out.endArray()
}
out.endObject()
}
override fun read(input: JsonReader): CommonsCookieStorage {
val map = mutableMapOf<String, List<Cookie>>()
input.beginObject()
while (input.hasNext()) {
val key = input.nextName()
map[key] = input.readCookies((WikiSite.DEFAULT_SCHEME + "://" + key).toHttpUrlOrNull())
}
input.endObject()
return CommonsCookieStorage.from(map)
}
private fun JsonReader.readCookies(url: HttpUrl?): MutableList<Cookie> {
val list = mutableListOf<Cookie>()
beginArray()
while (hasNext()) {
val str = nextString()
url?.let {
val element: Cookie? = Cookie.parse(url, str)
element?.let { list += element }
}
}
endArray()
return list
}
}