Horis 1 год назад
Родитель
Сommit
cd8b1e4f01

+ 40 - 2
app/src/main/java/io/legado/app/help/http/BackstageWebView.kt

@@ -2,6 +2,7 @@ package io.legado.app.help.http
 
 import android.annotation.SuppressLint
 import android.net.http.SslError
+import android.os.Build
 import android.os.Handler
 import android.os.Looper
 import android.util.AndroidRuntimeException
@@ -20,6 +21,9 @@ import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Runnable
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.withTimeout
+import okhttp3.Protocol
+import okhttp3.Request
+import okhttp3.Response
 import org.apache.commons.text.StringEscapeUtils
 import splitties.init.appCtx
 import java.lang.ref.WeakReference
@@ -143,7 +147,20 @@ class BackstageWebView(
 
     private inner class HtmlWebViewClient : WebViewClient() {
 
-        var runnable: EvalJsRunnable? = null
+        private var runnable: EvalJsRunnable? = null
+        private var isRedirect = false
+
+        override fun shouldOverrideUrlLoading(
+            view: WebView,
+            request: WebResourceRequest
+        ): Boolean {
+            isRedirect = isRedirect || if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                request.isRedirect
+            } else {
+                request.url.toString() != view.url
+            }
+            return super.shouldOverrideUrlLoading(view, request)
+        }
 
         override fun onPageFinished(view: WebView, url: String) {
             setCookie(url)
@@ -181,7 +198,7 @@ class BackstageWebView(
                     val content = StringEscapeUtils.unescapeJson(result)
                         .replace(quoteRegex, "")
                     try {
-                        val response = StrResponse(url, content)
+                        val response = buildStrResponse(content)
                         callback?.onResult(response)
                     } catch (e: Exception) {
                         callback?.onError(e)
@@ -201,6 +218,27 @@ class BackstageWebView(
                 retry++
                 mHandler.postDelayed(this@EvalJsRunnable, 1000)
             }
+
+            private fun buildStrResponse(content: String): StrResponse {
+                if (!isRedirect) {
+                    return StrResponse(url, content)
+                }
+                val originUrl = this@BackstageWebView.url ?: url
+                val originResponse = Response.Builder()
+                    .code(302)
+                    .request(Request.Builder().url(originUrl).build())
+                    .protocol(Protocol.HTTP_1_1)
+                    .message("Found")
+                    .build()
+                val response = Response.Builder()
+                    .code(200)
+                    .request(Request.Builder().url(url).build())
+                    .protocol(Protocol.HTTP_1_1)
+                    .message("OK")
+                    .priorResponse(originResponse)
+                    .build()
+                return StrResponse(response, content)
+            }
         }
 
     }

+ 12 - 3
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt

@@ -32,6 +32,8 @@ import kotlinx.coroutines.withTimeout
 import org.apache.commons.text.StringEscapeUtils
 import org.jsoup.nodes.Node
 import org.mozilla.javascript.NativeObject
+import org.mozilla.javascript.Scriptable
+import java.lang.ref.WeakReference
 import java.net.URL
 import java.util.Locale
 import java.util.regex.Pattern
@@ -70,6 +72,7 @@ class AnalyzeRule(
     private val stringRuleCache = hashMapOf<String, List<SourceRule>>()
     private val regexCache = hashMapOf<String, Regex?>()
     private val scriptCache = hashMapOf<String, CompiledScript>()
+    private var topScopeRef: WeakReference<Scriptable>? = null
 
     private var coroutineContext: CoroutineContext = EmptyCoroutineContext
 
@@ -758,9 +761,15 @@ class AnalyzeRule(
             bindings["nextChapterUrl"] = nextChapterUrl
             bindings["rssArticle"] = rssArticle
         }
-        val scope = RhinoScriptEngine.getRuntimeScope(bindings)
-        source?.getShareScope(coroutineContext)?.let {
-            scope.prototype = it
+        val topScope = source?.getShareScope(coroutineContext) ?: topScopeRef?.get()
+        val scope = if (topScope == null) {
+            RhinoScriptEngine.getRuntimeScope(bindings).apply {
+                topScopeRef = WeakReference(prototype)
+            }
+        } else {
+            bindings.apply {
+                prototype = topScope
+            }
         }
         val script = compileScriptCache(jsStr)
         return script.eval(scope, coroutineContext)