mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-31 06:43:56 +01:00 
			
		
		
		
	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:
		
							parent
							
								
									ab9e57f5be
								
							
						
					
					
						commit
						8db0b54929
					
				
					 57 changed files with 422 additions and 518 deletions
				
			
		|  | @ -1,77 +0,0 @@ | |||
| package fr.free.nrw.commons; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import fr.free.nrw.commons.auth.SessionManager; | ||||
| import fr.free.nrw.commons.kvstore.JsonKvStore; | ||||
| import okhttp3.OkHttpClient; | ||||
| import org.wikipedia.AppAdapter; | ||||
| import org.wikipedia.dataclient.SharedPreferenceCookieManager; | ||||
| import org.wikipedia.json.GsonMarshaller; | ||||
| import org.wikipedia.json.GsonUnmarshaller; | ||||
| 
 | ||||
| public class CommonsAppAdapter extends AppAdapter { | ||||
|     private final int DEFAULT_THUMB_SIZE = 640; | ||||
|     private final String COOKIE_STORE_NAME = "cookie_store"; | ||||
| 
 | ||||
|     private final SessionManager sessionManager; | ||||
|     private final JsonKvStore preferences; | ||||
| 
 | ||||
|     CommonsAppAdapter(@NonNull SessionManager sessionManager, @NonNull JsonKvStore preferences) { | ||||
|         this.sessionManager = sessionManager; | ||||
|         this.preferences = preferences; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getMediaWikiBaseUrl() { | ||||
|         return BuildConfig.COMMONS_URL; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getRestbaseUriFormat() { | ||||
|         return BuildConfig.COMMONS_URL; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public OkHttpClient getOkHttpClient() { | ||||
|         return OkHttpConnectionFactory.getClient(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public int getDesiredLeadImageDp() { | ||||
|         return DEFAULT_THUMB_SIZE; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isLoggedIn() { | ||||
|         return sessionManager.isUserLoggedIn(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getUserName() { | ||||
|         return sessionManager.getUserName(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getPassword() { | ||||
|         return sessionManager.getPassword(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public SharedPreferenceCookieManager getCookies() { | ||||
|         if (!preferences.contains(COOKIE_STORE_NAME)) { | ||||
|             return null; | ||||
|         } | ||||
|         return GsonUnmarshaller.unmarshal(SharedPreferenceCookieManager.class, | ||||
|                 preferences.getString(COOKIE_STORE_NAME, null)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void setCookies(@NonNull SharedPreferenceCookieManager cookies) { | ||||
|         preferences.putString(COOKIE_STORE_NAME, GsonMarshaller.marshal(cookies)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean logErrorsInsteadOfCrashing() { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | @ -41,6 +41,7 @@ import fr.free.nrw.commons.media.CustomOkHttpNetworkFetcher; | |||
| import fr.free.nrw.commons.settings.Prefs; | ||||
| import fr.free.nrw.commons.upload.FileUtils; | ||||
| import fr.free.nrw.commons.utils.ConfigUtils; | ||||
| import fr.free.nrw.commons.wikidata.cookies.CommonsCookieJar; | ||||
| import io.reactivex.Completable; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.internal.functions.Functions; | ||||
|  | @ -58,7 +59,6 @@ import org.acra.annotation.AcraCore; | |||
| import org.acra.annotation.AcraDialog; | ||||
| import org.acra.annotation.AcraMailSender; | ||||
| import org.acra.data.StringFormat; | ||||
| import org.wikipedia.AppAdapter; | ||||
| import org.wikipedia.language.AppLanguageLookUpTable; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
|  | @ -94,6 +94,9 @@ public class CommonsApplication extends MultiDexApplication { | |||
|     @Named("default_preferences") | ||||
|     JsonKvStore defaultPrefs; | ||||
| 
 | ||||
|     @Inject | ||||
|     CommonsCookieJar cookieJar; | ||||
| 
 | ||||
|     @Inject | ||||
|     CustomOkHttpNetworkFetcher customOkHttpNetworkFetcher; | ||||
| 
 | ||||
|  | @ -161,8 +164,6 @@ public class CommonsApplication extends MultiDexApplication { | |||
|             .getCommonsApplicationComponent() | ||||
|             .inject(this); | ||||
| 
 | ||||
|         AppAdapter.set(new CommonsAppAdapter(sessionManager, defaultPrefs)); | ||||
| 
 | ||||
|         initTimber(); | ||||
| 
 | ||||
|         if (!defaultPrefs.getBoolean("has_user_manually_removed_location")) { | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| package fr.free.nrw.commons; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import fr.free.nrw.commons.wikidata.cookies.CommonsCookieJar; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | @ -15,28 +15,27 @@ import okhttp3.Response; | |||
| import okhttp3.ResponseBody; | ||||
| import okhttp3.logging.HttpLoggingInterceptor; | ||||
| import okhttp3.logging.HttpLoggingInterceptor.Level; | ||||
| import org.wikipedia.dataclient.SharedPreferenceCookieManager; | ||||
| import org.wikipedia.dataclient.okhttp.HttpStatusException; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| public final class OkHttpConnectionFactory { | ||||
|     private static final String CACHE_DIR_NAME = "okhttp-cache"; | ||||
|     private static final long NET_CACHE_SIZE = 64 * 1024 * 1024; | ||||
|     @NonNull private static final Cache NET_CACHE = new Cache(new File(CommonsApplication.getInstance().getCacheDir(), | ||||
|             CACHE_DIR_NAME), NET_CACHE_SIZE); | ||||
| 
 | ||||
|     @NonNull | ||||
|     private static final OkHttpClient CLIENT = createClient(); | ||||
|     public static OkHttpClient CLIENT; | ||||
| 
 | ||||
|     @NonNull public static OkHttpClient getClient() { | ||||
|     @NonNull public static OkHttpClient getClient(final CommonsCookieJar cookieJar) { | ||||
|         if (CLIENT == null) { | ||||
|             CLIENT = createClient(cookieJar); | ||||
|         } | ||||
|         return CLIENT; | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private static OkHttpClient createClient() { | ||||
|     private static OkHttpClient createClient(final CommonsCookieJar cookieJar) { | ||||
|         return new OkHttpClient.Builder() | ||||
|                 .cookieJar(SharedPreferenceCookieManager.getInstance()) | ||||
|                 .cache(NET_CACHE) | ||||
|                 .cookieJar(cookieJar) | ||||
|                 .cache(new Cache(new File(CommonsApplication.getInstance().getCacheDir(), CACHE_DIR_NAME), NET_CACHE_SIZE)) | ||||
|                 .connectTimeout(120, TimeUnit.SECONDS) | ||||
|                 .writeTimeout(120, TimeUnit.SECONDS) | ||||
|                 .readTimeout(120, TimeUnit.SECONDS) | ||||
|  |  | |||
|  | @ -2,8 +2,6 @@ package fr.free.nrw.commons.auth.csrf | |||
| 
 | ||||
| import androidx.annotation.VisibleForTesting | ||||
| import fr.free.nrw.commons.auth.SessionManager | ||||
| import org.wikipedia.AppAdapter | ||||
| import org.wikipedia.dataclient.SharedPreferenceCookieManager | ||||
| import org.wikipedia.dataclient.mwapi.MwQueryResponse | ||||
| import fr.free.nrw.commons.auth.login.LoginClient | ||||
| import fr.free.nrw.commons.auth.login.LoginCallback | ||||
|  | @ -19,7 +17,8 @@ import java.util.concurrent.Executors.newSingleThreadExecutor | |||
| class CsrfTokenClient( | ||||
|     private val sessionManager: SessionManager, | ||||
|     private val csrfTokenInterface: CsrfTokenInterface, | ||||
|     private val loginClient: LoginClient | ||||
|     private val loginClient: LoginClient, | ||||
|     private val logoutClient: LogoutClient | ||||
| ) { | ||||
|     private var retries = 0 | ||||
|     private var csrfTokenCall: Call<MwQueryResponse?>? = null | ||||
|  | @ -27,8 +26,8 @@ class CsrfTokenClient( | |||
|     @Throws(Throwable::class) | ||||
|     fun getTokenBlocking(): String { | ||||
|         var token = "" | ||||
|         val userName = AppAdapter.get().getUserName() | ||||
|         val password = AppAdapter.get().getPassword() | ||||
|         val userName = sessionManager.userName ?: "" | ||||
|         val password = sessionManager.password ?: "" | ||||
| 
 | ||||
|         for (retry in 0 until MAX_RETRIES_OF_LOGIN_BLOCKING) { | ||||
|             try { | ||||
|  | @ -47,7 +46,7 @@ class CsrfTokenClient( | |||
|                 } | ||||
| 
 | ||||
|                 token = response.body()!!.query()!!.csrfToken()!! | ||||
|                 if (AppAdapter.get().isLoggedIn() && token == ANON_TOKEN) { | ||||
|                 if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) { | ||||
|                     throw RuntimeException("App believes we're logged in, but got anonymous token.") | ||||
|                 } | ||||
|                 break | ||||
|  | @ -66,7 +65,7 @@ class CsrfTokenClient( | |||
|     fun request(service: CsrfTokenInterface, cb: Callback): Call<MwQueryResponse?> = | ||||
|         requestToken(service, object : Callback { | ||||
|             override fun success(token: String?) { | ||||
|                 if (AppAdapter.get().isLoggedIn() && token == ANON_TOKEN) { | ||||
|                 if (sessionManager.isUserLoggedIn && token == ANON_TOKEN) { | ||||
|                     retryWithLogin(cb) { | ||||
|                         RuntimeException("App believes we're logged in, but got anonymous token.") | ||||
|                     } | ||||
|  | @ -102,11 +101,11 @@ class CsrfTokenClient( | |||
|     } | ||||
| 
 | ||||
|     private fun retryWithLogin(callback: Callback, caught: () -> Throwable?) { | ||||
|         val userName = AppAdapter.get().getUserName() | ||||
|         val password = AppAdapter.get().getPassword() | ||||
|         val userName = sessionManager.userName | ||||
|         val password = sessionManager.password | ||||
|         if (retries < MAX_RETRIES && !userName.isNullOrEmpty() && !password.isNullOrEmpty()) { | ||||
|             retries++ | ||||
|             SharedPreferenceCookieManager.getInstance().clearAllCookies() | ||||
|             logoutClient.logout() | ||||
|             login(userName, password, callback) { | ||||
|                 Timber.i("retrying...") | ||||
|                 cancel() | ||||
|  |  | |||
|  | @ -0,0 +1,8 @@ | |||
| package fr.free.nrw.commons.auth.csrf | ||||
| 
 | ||||
| import fr.free.nrw.commons.wikidata.cookies.CommonsCookieStorage | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class LogoutClient @Inject constructor(private val store: CommonsCookieStorage) { | ||||
|     fun logout() = store.clear() | ||||
| } | ||||
|  | @ -257,8 +257,8 @@ public class CommonsApplicationModule { | |||
| 
 | ||||
|     @Named("username") | ||||
|     @Provides | ||||
|     public String provideLoggedInUsername() { | ||||
|         return Objects.toString(AppAdapter.get().getUserName(), ""); | ||||
|     public String provideLoggedInUsername(SessionManager sessionManager) { | ||||
|         return Objects.toString(sessionManager.getUserName(), ""); | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|  |  | |||
|  | @ -12,7 +12,10 @@ import fr.free.nrw.commons.actions.PageEditClient; | |||
| import fr.free.nrw.commons.actions.PageEditInterface; | ||||
| import fr.free.nrw.commons.actions.ThanksInterface; | ||||
| import fr.free.nrw.commons.auth.SessionManager; | ||||
| import fr.free.nrw.commons.auth.csrf.CsrfTokenClient; | ||||
| import fr.free.nrw.commons.auth.csrf.CsrfTokenInterface; | ||||
| import fr.free.nrw.commons.auth.csrf.LogoutClient; | ||||
| import fr.free.nrw.commons.auth.login.LoginClient; | ||||
| import fr.free.nrw.commons.auth.login.LoginInterface; | ||||
| import fr.free.nrw.commons.category.CategoryInterface; | ||||
| import fr.free.nrw.commons.explore.depictions.DepictsClient; | ||||
|  | @ -30,6 +33,8 @@ import fr.free.nrw.commons.upload.WikiBaseInterface; | |||
| import fr.free.nrw.commons.upload.depicts.DepictsInterface; | ||||
| import fr.free.nrw.commons.wikidata.CommonsServiceFactory; | ||||
| import fr.free.nrw.commons.wikidata.WikidataInterface; | ||||
| import fr.free.nrw.commons.wikidata.cookies.CommonsCookieJar; | ||||
| import fr.free.nrw.commons.wikidata.cookies.CommonsCookieStorage; | ||||
| import java.io.File; | ||||
| import java.util.Locale; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | @ -40,11 +45,8 @@ import okhttp3.HttpUrl; | |||
| import okhttp3.OkHttpClient; | ||||
| import okhttp3.logging.HttpLoggingInterceptor; | ||||
| import okhttp3.logging.HttpLoggingInterceptor.Level; | ||||
| import fr.free.nrw.commons.auth.csrf.CsrfTokenClient; | ||||
| import org.wikipedia.AppAdapter; | ||||
| import org.wikipedia.dataclient.WikiSite; | ||||
| import org.wikipedia.json.GsonUtil; | ||||
| import fr.free.nrw.commons.auth.login.LoginClient; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| @Module | ||||
|  | @ -78,8 +80,8 @@ public class NetworkingModule { | |||
| 
 | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     public CommonsServiceFactory serviceFactory() { | ||||
|         return new CommonsServiceFactory(AppAdapter.get().getOkHttpClient()); | ||||
|     public CommonsServiceFactory serviceFactory(CommonsCookieJar cookieJar) { | ||||
|         return new CommonsServiceFactory(OkHttpConnectionFactory.getClient(cookieJar)); | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|  | @ -107,12 +109,27 @@ public class NetworkingModule { | |||
|             gson); | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     public CommonsCookieStorage provideCookieStorage( | ||||
|         @Named("default_preferences") JsonKvStore preferences) { | ||||
|         CommonsCookieStorage cookieStorage = new CommonsCookieStorage(preferences); | ||||
|         cookieStorage.load(); | ||||
|         return cookieStorage; | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     public CommonsCookieJar provideCookieJar(CommonsCookieStorage storage) { | ||||
|         return new CommonsCookieJar(storage); | ||||
|     } | ||||
| 
 | ||||
|     @Named(NAMED_COMMONS_CSRF) | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     public CsrfTokenClient provideCommonsCsrfTokenClient(SessionManager sessionManager, | ||||
|         CsrfTokenInterface tokenInterface, LoginClient loginClient) { | ||||
|         return new CsrfTokenClient(sessionManager, tokenInterface, loginClient); | ||||
|         CsrfTokenInterface tokenInterface, LoginClient loginClient, LogoutClient logoutClient) { | ||||
|         return new CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient); | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|  |  | |||
|  | @ -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() } | ||||
| } | ||||
|  | @ -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 | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Paul Hawke
						Paul Hawke