Improve background WebView usage

devel
Koitharu 7 months ago
parent 43d3a2cc6a
commit f8687bb697
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.network.webview
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import kotlinx.coroutines.CancellableContinuation
import kotlin.coroutines.Continuation import kotlin.coroutines.Continuation
import kotlin.coroutines.resume import kotlin.coroutines.resume
@ -14,7 +15,9 @@ open class ContinuationResumeWebViewClient(
} }
protected fun resumeContinuation(view: WebView?) { protected fun resumeContinuation(view: WebView?) {
view?.webViewClient = WebViewClient() // reset to default if (continuation !is CancellableContinuation || continuation.isActive) {
continuation.resume(Unit) view?.webViewClient = WebViewClient() // reset to default
continuation.resume(Unit)
}
} }
} }

@ -3,9 +3,10 @@ package org.koitharu.kotatsu.core.network.webview
import android.content.Context import android.content.Context
import android.webkit.WebSettings import android.webkit.WebSettings
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.annotation.MainThread
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
@ -25,7 +26,6 @@ import java.lang.ref.WeakReference
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider import javax.inject.Provider
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
@ -47,16 +47,20 @@ class WebViewExecutor @Inject constructor(
suspend fun evaluateJs(baseUrl: String?, script: String): String? = mutex.withLock { suspend fun evaluateJs(baseUrl: String?, script: String): String? = mutex.withLock {
withContext(Dispatchers.Main.immediate) { withContext(Dispatchers.Main.immediate) {
val webView = obtainWebView() val webView = obtainWebView()
if (!baseUrl.isNullOrEmpty()) { try {
suspendCoroutine { cont -> if (!baseUrl.isNullOrEmpty()) {
webView.webViewClient = ContinuationResumeWebViewClient(cont) suspendCoroutine { cont ->
webView.loadDataWithBaseURL(baseUrl, " ", "text/html", null, null) webView.webViewClient = ContinuationResumeWebViewClient(cont)
webView.loadDataWithBaseURL(baseUrl, " ", "text/html", null, null)
}
} }
} suspendCoroutine { cont ->
suspendCoroutine { cont -> webView.evaluateJavascript(script) { result ->
webView.evaluateJavascript(script) { result -> cont.resume(result?.takeUnless { it == "null" })
cont.resume(result?.takeUnless { it == "null" }) }
} }
} finally {
webView.reset()
} }
} }
} }
@ -69,23 +73,18 @@ class WebViewExecutor @Inject constructor(
exception.source.getUserAgent()?.let { exception.source.getUserAgent()?.let {
webView.settings.userAgentString = it webView.settings.userAgentString = it
} }
coroutineScope { withTimeout(timeout) {
withTimeout(timeout) { suspendCancellableCoroutine { cont ->
suspendCancellableCoroutine { cont -> webView.webViewClient = CaptchaContinuationClient(
webView.webViewClient = CaptchaContinuationClient( cookieJar = cookieJar,
cookieJar = cookieJar, targetUrl = exception.url,
targetUrl = exception.url, continuation = cont,
continuation = cont, )
) webView.loadUrl(exception.url)
cont.invokeOnCancellation {
webView.stopLoadingAsync()
}
webView.loadUrl(exception.url)
}
} }
} }
} finally { } finally {
webView.settings.userAgentString = defaultUserAgent webView.reset()
} }
} }
}.onFailure { e -> }.onFailure { e ->
@ -117,9 +116,12 @@ class WebViewExecutor @Inject constructor(
return repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT) return repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT)
} }
private fun WebView.stopLoadingAsync() { @MainThread
Dispatchers.Main.dispatch(EmptyCoroutineContext) { private fun WebView.reset() {
stopLoading() stopLoading()
} webViewClient = WebViewClient()
settings.userAgentString = defaultUserAgent
loadDataWithBaseURL(null, " ", "text/html", null, null)
clearHistory()
} }
} }

Loading…
Cancel
Save