From 0685382083c1f590b71ad9f0cceff888612ad1f5 Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 23 Jan 2021 15:57:59 -0500 Subject: [PATCH] Extract user agent string from WebView --- .../network/CloudflareInterceptor.kt | 3 +- .../tachiyomi/network/UserAgentInterceptor.kt | 4 +- .../tachiyomi/source/online/HttpSource.kt | 7 +-- .../tachiyomi/util/system/WebViewUtil.kt | 43 +++++++++++++------ 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt index de143801b..83481a89c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt @@ -9,7 +9,6 @@ import android.webkit.WebSettings import android.webkit.WebView import android.widget.Toast import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.WebViewClientCompat import eu.kanade.tachiyomi.util.system.WebViewUtil @@ -99,7 +98,7 @@ class CloudflareInterceptor(private val context: Context) : Interceptor { // Avoid sending empty User-Agent, Chromium WebView will reset to default if empty webview.settings.userAgentString = request.header("User-Agent") - ?: HttpSource.DEFAULT_USERAGENT + ?: WebViewUtil.DEFAULT_USER_AGENT webview.webViewClient = object : WebViewClientCompat() { override fun onPageFinished(view: WebView, url: String) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/UserAgentInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/network/UserAgentInterceptor.kt index a5aa3e4f5..8d9e43a10 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/UserAgentInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/UserAgentInterceptor.kt @@ -1,6 +1,6 @@ package eu.kanade.tachiyomi.network -import eu.kanade.tachiyomi.source.online.HttpSource +import eu.kanade.tachiyomi.util.system.WebViewUtil import okhttp3.Interceptor import okhttp3.Response @@ -12,7 +12,7 @@ class UserAgentInterceptor : Interceptor { val newRequest = originalRequest .newBuilder() .removeHeader("User-Agent") - .addHeader("User-Agent", HttpSource.DEFAULT_USERAGENT) + .addHeader("User-Agent", WebViewUtil.DEFAULT_USER_AGENT) .build() chain.proceed(newRequest) } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt index 23b15ff47..0824fff2c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt @@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.util.system.WebViewUtil import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request @@ -74,7 +75,7 @@ abstract class HttpSource : CatalogueSource { * Headers builder for requests. Implementations can override this method for custom headers. */ protected open fun headersBuilder() = Headers.Builder().apply { - add("User-Agent", DEFAULT_USERAGENT) + add("User-Agent", WebViewUtil.DEFAULT_USER_AGENT) } /** @@ -369,8 +370,4 @@ abstract class HttpSource : CatalogueSource { * Returns the list of filters for the source. */ override fun getFilterList() = FilterList() - - companion object { - const val DEFAULT_USERAGENT = "Mozilla/5.0 (Windows NT 6.3; WOW64)" - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt index a89f639ca..7f10186ce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewUtil.kt @@ -1,26 +1,39 @@ package eu.kanade.tachiyomi.util.system +import android.annotation.SuppressLint import android.content.Context import android.content.pm.PackageManager import android.webkit.CookieManager import android.webkit.WebSettings import android.webkit.WebView +import eu.kanade.tachiyomi.util.lang.launchUI +import timber.log.Timber object WebViewUtil { val WEBVIEW_UA_VERSION_REGEX by lazy { Regex(""".*Chrome/(\d+)\..*""") } + var DEFAULT_USER_AGENT: String = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + private set + const val REQUESTED_WITH = "com.android.browser" - const val MINIMUM_WEBVIEW_VERSION = 86 + const val MINIMUM_WEBVIEW_VERSION = 87 fun supportsWebView(context: Context): Boolean { try { // May throw android.webkit.WebViewFactory$MissingWebViewPackageException if WebView // is not installed CookieManager.getInstance() + + launchUI { + DEFAULT_USER_AGENT = WebView(context) + .getDefaultUserAgentString() + .replace("; wv", "") + } } catch (e: Exception) { + Timber.e(e) return false } @@ -29,9 +42,10 @@ object WebViewUtil { } fun WebView.isOutdated(): Boolean { - return getWebViewMajorVersion(this) < WebViewUtil.MINIMUM_WEBVIEW_VERSION + return getWebViewMajorVersion() < WebViewUtil.MINIMUM_WEBVIEW_VERSION } +@SuppressLint("SetJavaScriptEnabled") fun WebView.setDefaultSettings() { with(settings) { javaScriptEnabled = true @@ -44,22 +58,25 @@ fun WebView.setDefaultSettings() { } } -// Based on https://stackoverflow.com/a/29218966 -private fun getWebViewMajorVersion(webview: WebView): Int { - val originalUA: String = webview.settings.userAgentString - - // Next call to getUserAgentString() will get us the default - webview.settings.userAgentString = null - - val uaRegexMatch = WebViewUtil.WEBVIEW_UA_VERSION_REGEX.matchEntire(webview.settings.userAgentString) - val webViewVersion: Int = if (uaRegexMatch != null && uaRegexMatch.groupValues.size > 1) { +private fun WebView.getWebViewMajorVersion(): Int { + val uaRegexMatch = WebViewUtil.WEBVIEW_UA_VERSION_REGEX.matchEntire(getDefaultUserAgentString()) + return if (uaRegexMatch != null && uaRegexMatch.groupValues.size > 1) { uaRegexMatch.groupValues[1].toInt() } else { 0 } +} + +// Based on https://stackoverflow.com/a/29218966 +private fun WebView.getDefaultUserAgentString(): String { + val originalUA: String = settings.userAgentString + + // Next call to getUserAgentString() will get us the default + settings.userAgentString = null + val defaultUserAgentString = settings.userAgentString // Revert to original UA string - webview.settings.userAgentString = originalUA + settings.userAgentString = originalUA - return webViewVersion + return defaultUserAgentString }