Remove dependency injection from core module and data module from presentation-widget module

Includes side effects:
- No longer need to restart app for user agent string change to take effect
- parseAs extension function requires a Json instance in the calling context, which doesn't necessarily need to be the default one provided by Injekt
This commit is contained in:
arkon
2023-02-20 19:02:38 -05:00
parent 10d7349506
commit 93523ef50b
34 changed files with 576 additions and 433 deletions

View File

@@ -6,26 +6,30 @@ import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.util.concurrent.TimeUnit
class NetworkHelper(context: Context) {
private val preferences: NetworkPreferences by injectLazy()
class NetworkHelper(
context: Context,
private val preferences: NetworkPreferences,
) {
private val cacheDir = File(context.cacheDir, "network_cache")
private val cacheSize = 5L * 1024 * 1024 // 5 MiB
val cookieManager = AndroidCookieJar()
val cookieJar = AndroidCookieJar()
private val userAgentInterceptor by lazy { UserAgentInterceptor() }
private val cloudflareInterceptor by lazy { CloudflareInterceptor(context) }
private val userAgentInterceptor by lazy {
UserAgentInterceptor(::defaultUserAgentProvider)
}
private val cloudflareInterceptor by lazy {
CloudflareInterceptor(context, cookieJar, ::defaultUserAgentProvider)
}
private val baseClientBuilder: OkHttpClient.Builder
get() {
val builder = OkHttpClient.Builder()
.cookieJar(cookieManager)
.cookieJar(cookieJar)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.callTimeout(2, TimeUnit.MINUTES)
@@ -65,7 +69,5 @@ class NetworkHelper(context: Context) {
.build()
}
val defaultUserAgent by lazy {
preferences.defaultUserAgent().get().trim()
}
fun defaultUserAgentProvider() = preferences.defaultUserAgent().get().trim()
}

View File

@@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.network
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.okio.decodeFromBufferedSource
import kotlinx.serialization.serializer
@@ -16,8 +15,6 @@ import okhttp3.Response
import rx.Observable
import rx.Producer
import rx.Subscription
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.coroutines.resumeWithException
@@ -131,14 +128,18 @@ fun OkHttpClient.newCachelessCallWithProgress(request: Request, listener: Progre
return progressClient.newCall(request)
}
context(Json)
inline fun <reified T> Response.parseAs(): T {
return decodeFromJsonResponse(serializer(), this)
}
@OptIn(ExperimentalSerializationApi::class)
fun <T> decodeFromJsonResponse(deserializer: DeserializationStrategy<T>, response: Response): T {
context(Json)
fun <T> decodeFromJsonResponse(
deserializer: DeserializationStrategy<T>,
response: Response,
): T {
return response.body.source().use {
Injekt.get<Json>().decodeFromBufferedSource(deserializer, it)
decodeFromBufferedSource(deserializer, it)
}
}

View File

@@ -6,7 +6,7 @@ import android.webkit.WebView
import android.widget.Toast
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.core.R
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.AndroidCookieJar
import eu.kanade.tachiyomi.util.system.WebViewClientCompat
import eu.kanade.tachiyomi.util.system.isOutdated
import eu.kanade.tachiyomi.util.system.toast
@@ -15,16 +15,17 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
import java.io.IOException
import java.util.concurrent.CountDownLatch
class CloudflareInterceptor(private val context: Context) : WebViewInterceptor(context) {
class CloudflareInterceptor(
private val context: Context,
private val cookieManager: AndroidCookieJar,
defaultUserAgentProvider: () -> String,
) : WebViewInterceptor(context, defaultUserAgentProvider) {
private val executor = ContextCompat.getMainExecutor(context)
private val networkHelper: NetworkHelper by injectLazy()
override fun shouldIntercept(response: Response): Boolean {
// Check if Cloudflare anti-bot is on
return response.code in ERROR_CODES && response.header("Server") in SERVER_CHECK
@@ -33,8 +34,8 @@ class CloudflareInterceptor(private val context: Context) : WebViewInterceptor(c
override fun intercept(chain: Interceptor.Chain, request: Request, response: Response): Response {
try {
response.close()
networkHelper.cookieManager.remove(request.url, COOKIE_NAMES, 0)
val oldCookie = networkHelper.cookieManager.get(request.url)
cookieManager.remove(request.url, COOKIE_NAMES, 0)
val oldCookie = cookieManager.get(request.url)
.firstOrNull { it.name == "cf_clearance" }
resolveWithWebView(request, oldCookie)
@@ -70,7 +71,7 @@ class CloudflareInterceptor(private val context: Context) : WebViewInterceptor(c
webview?.webViewClient = object : WebViewClientCompat() {
override fun onPageFinished(view: WebView, url: String) {
fun isCloudFlareBypassed(): Boolean {
return networkHelper.cookieManager.get(origRequestUrl.toHttpUrl())
return cookieManager.get(origRequestUrl.toHttpUrl())
.firstOrNull { it.name == "cf_clearance" }
.let { it != null && it != oldCookie }
}

View File

@@ -1,13 +1,11 @@
package eu.kanade.tachiyomi.network.interceptor
import eu.kanade.tachiyomi.network.NetworkHelper
import okhttp3.Interceptor
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
class UserAgentInterceptor : Interceptor {
private val networkHelper: NetworkHelper by injectLazy()
class UserAgentInterceptor(
private val defaultUserAgentProvider: () -> String,
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
@@ -16,7 +14,7 @@ class UserAgentInterceptor : Interceptor {
val newRequest = originalRequest
.newBuilder()
.removeHeader("User-Agent")
.addHeader("User-Agent", networkHelper.defaultUserAgent)
.addHeader("User-Agent", defaultUserAgentProvider())
.build()
chain.proceed(newRequest)
} else {

View File

@@ -6,7 +6,6 @@ import android.webkit.WebSettings
import android.webkit.WebView
import android.widget.Toast
import eu.kanade.tachiyomi.core.R
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.WebViewUtil
import eu.kanade.tachiyomi.util.system.setDefaultSettings
@@ -16,14 +15,14 @@ import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import tachiyomi.core.util.lang.launchUI
import uy.kohesive.injekt.injectLazy
import java.util.Locale
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
abstract class WebViewInterceptor(private val context: Context) : Interceptor {
private val networkHelper: NetworkHelper by injectLazy()
abstract class WebViewInterceptor(
private val context: Context,
private val defaultUserAgentProvider: () -> String,
) : Interceptor {
/**
* When this is called, it initializes the WebView if it wasn't already. We use this to avoid
@@ -85,7 +84,7 @@ abstract class WebViewInterceptor(private val context: Context) : Interceptor {
return WebView(context).apply {
setDefaultSettings()
// Avoid sending empty User-Agent, Chromium WebView will reset to default if empty
settings.userAgentString = request.header("User-Agent") ?: networkHelper.defaultUserAgent
settings.userAgentString = request.header("User-Agent") ?: defaultUserAgentProvider()
}
}
}