Extract user agent string from WebView

This commit is contained in:
arkon 2021-01-23 15:57:59 -05:00
parent 04a993c997
commit 0685382083
4 changed files with 35 additions and 22 deletions

View file

@ -9,7 +9,6 @@ import android.webkit.WebSettings
import android.webkit.WebView import android.webkit.WebView
import android.widget.Toast import android.widget.Toast
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.system.WebViewClientCompat import eu.kanade.tachiyomi.util.system.WebViewClientCompat
import eu.kanade.tachiyomi.util.system.WebViewUtil 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 // Avoid sending empty User-Agent, Chromium WebView will reset to default if empty
webview.settings.userAgentString = request.header("User-Agent") webview.settings.userAgentString = request.header("User-Agent")
?: HttpSource.DEFAULT_USERAGENT ?: WebViewUtil.DEFAULT_USER_AGENT
webview.webViewClient = object : WebViewClientCompat() { webview.webViewClient = object : WebViewClientCompat() {
override fun onPageFinished(view: WebView, url: String) { override fun onPageFinished(view: WebView, url: String) {

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.network package eu.kanade.tachiyomi.network
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.util.system.WebViewUtil
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Response import okhttp3.Response
@ -12,7 +12,7 @@ class UserAgentInterceptor : Interceptor {
val newRequest = originalRequest val newRequest = originalRequest
.newBuilder() .newBuilder()
.removeHeader("User-Agent") .removeHeader("User-Agent")
.addHeader("User-Agent", HttpSource.DEFAULT_USERAGENT) .addHeader("User-Agent", WebViewUtil.DEFAULT_USER_AGENT)
.build() .build()
chain.proceed(newRequest) chain.proceed(newRequest)
} else { } else {

View file

@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.system.WebViewUtil
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -74,7 +75,7 @@ abstract class HttpSource : CatalogueSource {
* Headers builder for requests. Implementations can override this method for custom headers. * Headers builder for requests. Implementations can override this method for custom headers.
*/ */
protected open fun headersBuilder() = Headers.Builder().apply { 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. * Returns the list of filters for the source.
*/ */
override fun getFilterList() = FilterList() override fun getFilterList() = FilterList()
companion object {
const val DEFAULT_USERAGENT = "Mozilla/5.0 (Windows NT 6.3; WOW64)"
}
} }

View file

@ -1,26 +1,39 @@
package eu.kanade.tachiyomi.util.system package eu.kanade.tachiyomi.util.system
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.webkit.CookieManager import android.webkit.CookieManager
import android.webkit.WebSettings import android.webkit.WebSettings
import android.webkit.WebView import android.webkit.WebView
import eu.kanade.tachiyomi.util.lang.launchUI
import timber.log.Timber
object WebViewUtil { object WebViewUtil {
val WEBVIEW_UA_VERSION_REGEX by lazy { val WEBVIEW_UA_VERSION_REGEX by lazy {
Regex(""".*Chrome/(\d+)\..*""") 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 REQUESTED_WITH = "com.android.browser"
const val MINIMUM_WEBVIEW_VERSION = 86 const val MINIMUM_WEBVIEW_VERSION = 87
fun supportsWebView(context: Context): Boolean { fun supportsWebView(context: Context): Boolean {
try { try {
// May throw android.webkit.WebViewFactory$MissingWebViewPackageException if WebView // May throw android.webkit.WebViewFactory$MissingWebViewPackageException if WebView
// is not installed // is not installed
CookieManager.getInstance() CookieManager.getInstance()
launchUI {
DEFAULT_USER_AGENT = WebView(context)
.getDefaultUserAgentString()
.replace("; wv", "")
}
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e)
return false return false
} }
@ -29,9 +42,10 @@ object WebViewUtil {
} }
fun WebView.isOutdated(): Boolean { fun WebView.isOutdated(): Boolean {
return getWebViewMajorVersion(this) < WebViewUtil.MINIMUM_WEBVIEW_VERSION return getWebViewMajorVersion() < WebViewUtil.MINIMUM_WEBVIEW_VERSION
} }
@SuppressLint("SetJavaScriptEnabled")
fun WebView.setDefaultSettings() { fun WebView.setDefaultSettings() {
with(settings) { with(settings) {
javaScriptEnabled = true javaScriptEnabled = true
@ -44,22 +58,25 @@ fun WebView.setDefaultSettings() {
} }
} }
// Based on https://stackoverflow.com/a/29218966 private fun WebView.getWebViewMajorVersion(): Int {
private fun getWebViewMajorVersion(webview: WebView): Int { val uaRegexMatch = WebViewUtil.WEBVIEW_UA_VERSION_REGEX.matchEntire(getDefaultUserAgentString())
val originalUA: String = webview.settings.userAgentString return if (uaRegexMatch != null && uaRegexMatch.groupValues.size > 1) {
// 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) {
uaRegexMatch.groupValues[1].toInt() uaRegexMatch.groupValues[1].toInt()
} else { } else {
0 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 // Revert to original UA string
webview.settings.userAgentString = originalUA settings.userAgentString = originalUA
return webViewVersion return defaultUserAgentString
} }