mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-02-13 01:20:07 +00:00
Detect when WebView is broken and return null poToken
Some old Android devices have a broken WebView implementation, that can't execute the poToken code. This is now detected and the getWebClientPoToken return null instead of throwing an error in such a case, to allow the extractor to try to extract the video data even without a poToken.
This commit is contained in:
parent
3fc487310b
commit
21df24abfd
@ -1,3 +1,13 @@
|
|||||||
package org.schabi.newpipe.util.potoken
|
package org.schabi.newpipe.util.potoken
|
||||||
|
|
||||||
class PoTokenException(message: String) : Exception(message)
|
class PoTokenException(message: String) : Exception(message)
|
||||||
|
|
||||||
|
// to be thrown if the WebView provided by the system is broken
|
||||||
|
class BadWebViewException(message: String) : Exception(message)
|
||||||
|
|
||||||
|
fun buildExceptionForJsError(error: String): Exception {
|
||||||
|
return if (error.contains("SyntaxError"))
|
||||||
|
BadWebViewException(error)
|
||||||
|
else
|
||||||
|
PoTokenException(error)
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ import org.schabi.newpipe.util.DeviceUtils
|
|||||||
object PoTokenProviderImpl : PoTokenProvider {
|
object PoTokenProviderImpl : PoTokenProvider {
|
||||||
val TAG = PoTokenProviderImpl::class.simpleName
|
val TAG = PoTokenProviderImpl::class.simpleName
|
||||||
private val webViewSupported by lazy { DeviceUtils.supportsWebView() }
|
private val webViewSupported by lazy { DeviceUtils.supportsWebView() }
|
||||||
|
private var webViewBadImpl = false // whether the system has a bad WebView implementation
|
||||||
|
|
||||||
private object WebPoTokenGenLock
|
private object WebPoTokenGenLock
|
||||||
private var webPoTokenVisitorData: String? = null
|
private var webPoTokenVisitorData: String? = null
|
||||||
@ -22,11 +23,24 @@ object PoTokenProviderImpl : PoTokenProvider {
|
|||||||
private var webPoTokenGenerator: PoTokenGenerator? = null
|
private var webPoTokenGenerator: PoTokenGenerator? = null
|
||||||
|
|
||||||
override fun getWebClientPoToken(videoId: String): PoTokenResult? {
|
override fun getWebClientPoToken(videoId: String): PoTokenResult? {
|
||||||
if (!webViewSupported) {
|
if (!webViewSupported || webViewBadImpl) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return getWebClientPoToken(videoId = videoId, forceRecreate = false)
|
try {
|
||||||
|
return getWebClientPoToken(videoId = videoId, forceRecreate = false)
|
||||||
|
} catch (e: RuntimeException) {
|
||||||
|
// RxJava's Single wraps exceptions into RuntimeErrors, so we need to unwrap them here
|
||||||
|
when (val cause = e.cause) {
|
||||||
|
is BadWebViewException -> {
|
||||||
|
Log.e(TAG, "Could not obtain poToken because WebView is broken", e)
|
||||||
|
webViewBadImpl = true
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
null -> throw e
|
||||||
|
else -> throw cause // includes PoTokenException
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,9 @@ import android.os.Build
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.webkit.ConsoleMessage
|
||||||
import android.webkit.JavascriptInterface
|
import android.webkit.JavascriptInterface
|
||||||
|
import android.webkit.WebChromeClient
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
@ -40,6 +42,24 @@ class PoTokenWebView private constructor(
|
|||||||
|
|
||||||
// so that we can run async functions and get back the result
|
// so that we can run async functions and get back the result
|
||||||
webView.addJavascriptInterface(this, JS_INTERFACE)
|
webView.addJavascriptInterface(this, JS_INTERFACE)
|
||||||
|
|
||||||
|
webView.webChromeClient = object : WebChromeClient() {
|
||||||
|
override fun onConsoleMessage(m: ConsoleMessage): Boolean {
|
||||||
|
if (m.message().contains("Uncaught")) {
|
||||||
|
// There should not be any uncaught errors while executing the code, because
|
||||||
|
// everything that can fail is guarded by try-catch. Therefore, this likely
|
||||||
|
// indicates that there was a syntax error in the code, i.e. the WebView only
|
||||||
|
// supports a really old version of JS.
|
||||||
|
|
||||||
|
val fmt = "\"${m.message()}\", source: ${m.sourceId()} (${m.lineNumber()})"
|
||||||
|
Log.e(TAG, "This WebView implementation is broken: $fmt")
|
||||||
|
|
||||||
|
// This can only happen during initialization, where there is no try-catch
|
||||||
|
onInitializationErrorCloseAndCancel(BadWebViewException(fmt))
|
||||||
|
}
|
||||||
|
return super.onConsoleMessage(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,7 +137,7 @@ class PoTokenWebView private constructor(
|
|||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Log.e(TAG, "Initialization error from JavaScript: $error")
|
Log.e(TAG, "Initialization error from JavaScript: $error")
|
||||||
}
|
}
|
||||||
onInitializationErrorCloseAndCancel(PoTokenException(error))
|
onInitializationErrorCloseAndCancel(buildExceptionForJsError(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -223,7 +243,7 @@ class PoTokenWebView private constructor(
|
|||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Log.e(TAG, "obtainPoToken error from JavaScript: $error")
|
Log.e(TAG, "obtainPoToken error from JavaScript: $error")
|
||||||
}
|
}
|
||||||
popPoTokenEmitter(identifier)?.onError(PoTokenException(error))
|
popPoTokenEmitter(identifier)?.onError(buildExceptionForJsError(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user