Remove dependency injection from interceptors

Includes side effects:
- No longer need to restart app for user agent string change to take effect

Also fix the default UA summary going blank when resetting sometimes

Co-Authored-By: arkon <4098258+arkon@users.noreply.github.com>
This commit is contained in:
Jays2Kings 2023-10-25 13:33:33 -07:00
parent 6359cd8207
commit 77e3ad1c99
7 changed files with 40 additions and 30 deletions

View file

@ -22,15 +22,17 @@ class NetworkHelper(val context: Context) {
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(::defaultUserAgent) }
private val cloudflareInterceptor by lazy {
CloudflareInterceptor(context, cookieJar, ::defaultUserAgent)
}
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)
@ -68,9 +70,8 @@ class NetworkHelper(val context: Context) {
.build()
}
val defaultUserAgent by lazy {
preferences.defaultUserAgent().get().replace("\n", " ").trim()
}
val defaultUserAgent
get() = preferences.defaultUserAgent().get().replace("\n", " ").trim()
companion object {
const val DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0"

View file

@ -6,7 +6,7 @@ import android.webkit.WebView
import android.widget.Toast
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.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,26 +15,31 @@ 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
}
override fun intercept(chain: Interceptor.Chain, request: Request, response: Response): Response {
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 +75,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,12 +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()
@ -15,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.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.launchUI
@ -16,14 +15,15 @@ import okhttp3.Headers
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
import timber.log.Timber
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 +85,8 @@ 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
Timber.d("User agent: ${defaultUserAgentProvider()}")
settings.userAgentString = request.header("User-Agent") ?: defaultUserAgentProvider()
}
}
}

View file

@ -219,7 +219,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
?.distinct() ?: emptyList()
val cleared = urls.sumOf {
network.cookieManager.remove(it.toHttpUrl())
network.cookieJar.remove(it.toHttpUrl())
}
Timber.d("Cleared $cleared cookies for: ${urls.joinToString()}")

View file

@ -272,7 +272,7 @@ class SettingsAdvancedController : SettingsController() {
titleRes = R.string.clear_cookies
onClick {
network.cookieManager.removeAll()
network.cookieJar.removeAll()
activity?.toast(R.string.cookies_cleared)
}
}
@ -321,7 +321,6 @@ class SettingsAdvancedController : SettingsController() {
context.toast(R.string.error_user_agent_string_invalid)
return@onChange false
}
activity?.toast(R.string.requires_app_restart)
true
}
}

View file

@ -24,6 +24,11 @@ class EditTextResetPreference @JvmOverloads constructor(
defValue = defaultValue as? String ?: defValue
}
override fun setDefaultValue(defaultValue: Any?) {
super.setDefaultValue(defaultValue)
defValue = defaultValue as? String ?: defValue
}
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
sharedPreferences?.getString(key, defValue)
}