mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-08-25 03:36:46 +00:00
Cleanup, fixes, clearCookies support on httpClients
This commit is contained in:
parent
b3f9de3b83
commit
ff531b5e77
9 changed files with 99 additions and 141 deletions
|
@ -56,6 +56,7 @@ class DevJSClient : JSClient {
|
||||||
|
|
||||||
override fun getCopy(privateCopy: Boolean, noSaveState: Boolean): JSClient {
|
override fun getCopy(privateCopy: Boolean, noSaveState: Boolean): JSClient {
|
||||||
val client = DevJSClient(_context, descriptor, _script, if(!privateCopy) _auth else null, _captcha, if (noSaveState) null else saveState(), devID);
|
val client = DevJSClient(_context, descriptor, _script, if(!privateCopy) _auth else null, _captcha, if (noSaveState) null else saveState(), devID);
|
||||||
|
client.setReloadData(getReloadData(true));
|
||||||
if (noSaveState)
|
if (noSaveState)
|
||||||
client.initialize()
|
client.initialize()
|
||||||
return client
|
return client
|
||||||
|
|
|
@ -84,6 +84,8 @@ open class JSClient : IPlatformClient {
|
||||||
private var _channelCapabilities: ResultCapabilities? = null;
|
private var _channelCapabilities: ResultCapabilities? = null;
|
||||||
private var _peekChannelTypes: List<String>? = null;
|
private var _peekChannelTypes: List<String>? = null;
|
||||||
|
|
||||||
|
private var _usedReloadData: String? = null;
|
||||||
|
|
||||||
protected val _script: String;
|
protected val _script: String;
|
||||||
|
|
||||||
private var _initialized: Boolean = false;
|
private var _initialized: Boolean = false;
|
||||||
|
@ -198,6 +200,7 @@ open class JSClient : IPlatformClient {
|
||||||
|
|
||||||
open fun getCopy(withoutCredentials: Boolean = false, noSaveState: Boolean = false): JSClient {
|
open fun getCopy(withoutCredentials: Boolean = false, noSaveState: Boolean = false): JSClient {
|
||||||
val client = JSClient(_context, descriptor, if (noSaveState) null else saveState(), _script, withoutCredentials);
|
val client = JSClient(_context, descriptor, if (noSaveState) null else saveState(), _script, withoutCredentials);
|
||||||
|
client.setReloadData(getReloadData(true));
|
||||||
if (noSaveState)
|
if (noSaveState)
|
||||||
client.initialize()
|
client.initialize()
|
||||||
return client
|
return client
|
||||||
|
@ -215,19 +218,29 @@ open class JSClient : IPlatformClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setReloadData(data: String?) {
|
fun setReloadData(data: String?) {
|
||||||
declareOnEnable.put("__reloadData", data ?: "");
|
if(data == null) {
|
||||||
|
if(declareOnEnable.containsKey("__reloadData"))
|
||||||
|
declareOnEnable.remove("__reloadData");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
declareOnEnable.put("__reloadData", data ?: "");
|
||||||
|
}
|
||||||
|
fun getReloadData(orLast: Boolean): String? {
|
||||||
|
if(declareOnEnable.containsKey("__reloadData"))
|
||||||
|
return declareOnEnable["__reloadData"];
|
||||||
|
else if(orLast)
|
||||||
|
return _usedReloadData;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
if (_initialized) return
|
if (_initialized) return
|
||||||
|
|
||||||
Logger.i(TAG, "Plugin [${config.name}] initializing");
|
|
||||||
plugin.start();
|
plugin.start();
|
||||||
Logger.i(TAG, "Plugin [${config.name}] started");
|
|
||||||
plugin.execute("plugin.config = ${Json.encodeToString(config)}");
|
plugin.execute("plugin.config = ${Json.encodeToString(config)}");
|
||||||
plugin.execute("plugin.settings = parseSettings(${Json.encodeToString(descriptor.getSettingsWithDefaults())})");
|
plugin.execute("plugin.settings = parseSettings(${Json.encodeToString(descriptor.getSettingsWithDefaults())})");
|
||||||
|
|
||||||
Logger.i(TAG, "Plugin [${config.name}] configs set");
|
|
||||||
|
|
||||||
descriptor.appSettings.loadDefaults(descriptor.config);
|
descriptor.appSettings.loadDefaults(descriptor.config);
|
||||||
|
|
||||||
|
@ -255,7 +268,6 @@ open class JSClient : IPlatformClient {
|
||||||
hasGetChannelPlaylists = plugin.executeBoolean("!!source.getChannelPlaylists") ?: false,
|
hasGetChannelPlaylists = plugin.executeBoolean("!!source.getChannelPlaylists") ?: false,
|
||||||
hasGetContentRecommendations = plugin.executeBoolean("!!source.getContentRecommendations") ?: false
|
hasGetContentRecommendations = plugin.executeBoolean("!!source.getContentRecommendations") ?: false
|
||||||
);
|
);
|
||||||
Logger.i(TAG, "Plugin [${config.name}] capabilities retrieved");
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (capabilities.hasGetChannelTemplateByClaimMap)
|
if (capabilities.hasGetChannelTemplateByClaimMap)
|
||||||
|
@ -277,8 +289,11 @@ open class JSClient : IPlatformClient {
|
||||||
}
|
}
|
||||||
plugin.execute("source.enable(${Json.encodeToString(config)}, parseSettings(${Json.encodeToString(descriptor.getSettingsWithDefaults())}), ${Json.encodeToString(_injectedSaveState)})");
|
plugin.execute("source.enable(${Json.encodeToString(config)}, parseSettings(${Json.encodeToString(descriptor.getSettingsWithDefaults())}), ${Json.encodeToString(_injectedSaveState)})");
|
||||||
|
|
||||||
if(declareOnEnable.containsKey("__reloadData"))
|
if(declareOnEnable.containsKey("__reloadData")) {
|
||||||
|
Logger.i(TAG, "Plugin [${config.name}] enabled with reload data: ${declareOnEnable["__reloadData"]}");
|
||||||
|
_usedReloadData = declareOnEnable["__reloadData"];
|
||||||
declareOnEnable.remove("__reloadData");
|
declareOnEnable.remove("__reloadData");
|
||||||
|
}
|
||||||
_enabled = true;
|
_enabled = true;
|
||||||
}
|
}
|
||||||
@JSDocs(1, "source.saveState()", "Provide a string that is passed to enable for quicker startup of multiple instances")
|
@JSDocs(1, "source.saveState()", "Provide a string that is passed to enable for quicker startup of multiple instances")
|
||||||
|
|
|
@ -67,9 +67,28 @@ class JSHttpClient : ManagedHttpClient {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resetAuthCookies() {
|
||||||
|
_currentCookieMap.clear();
|
||||||
|
if(!_auth?.cookieMap.isNullOrEmpty()) {
|
||||||
|
for(domainCookies in _auth!!.cookieMap!!)
|
||||||
|
_currentCookieMap.put(domainCookies.key, HashMap(domainCookies.value));
|
||||||
|
}
|
||||||
|
if(!_captcha?.cookieMap.isNullOrEmpty()) {
|
||||||
|
for(domainCookies in _captcha!!.cookieMap!!) {
|
||||||
|
if(_currentCookieMap.containsKey(domainCookies.key))
|
||||||
|
_currentCookieMap[domainCookies.key]?.putAll(domainCookies.value);
|
||||||
|
else
|
||||||
|
_currentCookieMap.put(domainCookies.key, HashMap(domainCookies.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun clearOtherCookies() {
|
||||||
|
_otherCookieMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
override fun clone(): ManagedHttpClient {
|
override fun clone(): ManagedHttpClient {
|
||||||
val newClient = JSHttpClient(_jsClient, _auth);
|
val newClient = JSHttpClient(_jsClient, _auth);
|
||||||
//newClient._currentCookieMap = HashMap(_currentCookieMap.toList().associate { Pair(it.first, HashMap(it.second)) })
|
newClient._currentCookieMap = HashMap(_currentCookieMap.toList().associate { Pair(it.first, HashMap(it.second)) })
|
||||||
return newClient;
|
return newClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class JSRequestModifier: IRequestModifier {
|
||||||
private val _plugin: JSClient;
|
private val _plugin: JSClient;
|
||||||
private val _config: IV8PluginConfig;
|
private val _config: IV8PluginConfig;
|
||||||
private var _modifier: V8ValueObject;
|
private var _modifier: V8ValueObject;
|
||||||
override var allowByteSkip: Boolean;
|
override var allowByteSkip: Boolean = false;
|
||||||
|
|
||||||
constructor(plugin: JSClient, modifier: V8ValueObject) {
|
constructor(plugin: JSClient, modifier: V8ValueObject) {
|
||||||
this._plugin = plugin;
|
this._plugin = plugin;
|
||||||
|
@ -24,10 +24,13 @@ class JSRequestModifier: IRequestModifier {
|
||||||
this._config = plugin.config;
|
this._config = plugin.config;
|
||||||
val config = plugin.config;
|
val config = plugin.config;
|
||||||
|
|
||||||
allowByteSkip = modifier.getOrNull(config, "allowByteSkip", "JSRequestModifier") ?: true;
|
plugin.busy {
|
||||||
|
allowByteSkip = modifier.getOrNull(config, "allowByteSkip", "JSRequestModifier") ?: true;
|
||||||
|
|
||||||
|
if(!modifier.has("modifyRequest"))
|
||||||
|
throw ScriptImplementationException(config, "RequestModifier is missing modifyRequest", null);
|
||||||
|
}
|
||||||
|
|
||||||
if(!modifier.has("modifyRequest"))
|
|
||||||
throw ScriptImplementationException(config, "RequestModifier is missing modifyRequest", null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun modifyRequest(url: String, headers: Map<String, String>): IRequest {
|
override fun modifyRequest(url: String, headers: Map<String, String>): IRequest {
|
||||||
|
@ -35,13 +38,15 @@ class JSRequestModifier: IRequestModifier {
|
||||||
return Request(url, headers);
|
return Request(url, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSRequestModifier", "builder.modifyRequest()") {
|
return _plugin.busy {
|
||||||
_modifier.invoke("modifyRequest", url, headers);
|
val result = V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSRequestModifier", "builder.modifyRequest()") {
|
||||||
} as V8ValueObject;
|
_modifier.invoke("modifyRequest", url, headers);
|
||||||
|
} as V8ValueObject;
|
||||||
|
|
||||||
val req = JSRequest(_plugin, result, url, headers);
|
val req = JSRequest(_plugin, result, url, headers);
|
||||||
result.close();
|
result.close();
|
||||||
return req;
|
return@busy req;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -62,9 +62,11 @@ abstract class JSSource {
|
||||||
if (!hasRequestModifier || _obj.isClosed)
|
if (!hasRequestModifier || _obj.isClosed)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
val result = V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSVideoUrlSource", "obj.getRequestModifier()") {
|
val result = _plugin.isBusyWith("getRequestModifier") {
|
||||||
_obj.invoke("getRequestModifier", arrayOf<Any>());
|
V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSVideoUrlSource", "obj.getRequestModifier()") {
|
||||||
};
|
_obj.invoke("getRequestModifier", arrayOf<Any>());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (result !is V8ValueObject)
|
if (result !is V8ValueObject)
|
||||||
return null;
|
return null;
|
||||||
|
@ -76,13 +78,12 @@ abstract class JSSource {
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Logger.v("JSSource", "Request executor for [${type}] requesting");
|
Logger.v("JSSource", "Request executor for [${type}] requesting");
|
||||||
val result = V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSSource", "obj.getRequestExecutor()") {
|
val result =_plugin.isBusyWith("getRequestExecutor") {
|
||||||
_plugin.isBusyWith("getRequestExecutor") {
|
V8Plugin.catchScriptErrors<Any>(_config, "[${_config.name}] JSSource", "obj.getRequestExecutor()") {
|
||||||
_plugin.getUnderlyingPlugin().busy {
|
_obj.invoke("getRequestExecutor", arrayOf<Any>());
|
||||||
_obj.invoke("getRequestExecutor", arrayOf<Any>());
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
Logger.v("JSSource", "Request executor for [${type}] received");
|
Logger.v("JSSource", "Request executor for [${type}] received");
|
||||||
|
|
||||||
if (result !is V8ValueObject)
|
if (result !is V8ValueObject)
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
package com.futo.platformplayer.engine
|
package com.futo.platformplayer.engine
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.caoccao.javet.entities.JavetEntityError
|
|
||||||
import com.caoccao.javet.exceptions.JavetCompilationException
|
import com.caoccao.javet.exceptions.JavetCompilationException
|
||||||
import com.caoccao.javet.exceptions.JavetException
|
import com.caoccao.javet.exceptions.JavetException
|
||||||
import com.caoccao.javet.exceptions.JavetExecutionException
|
import com.caoccao.javet.exceptions.JavetExecutionException
|
||||||
import com.caoccao.javet.interfaces.IJavetEntityError
|
import com.caoccao.javet.interfaces.IJavetEntityError
|
||||||
import com.caoccao.javet.interop.V8Host
|
import com.caoccao.javet.interop.V8Host
|
||||||
import com.caoccao.javet.interop.V8Runtime
|
import com.caoccao.javet.interop.V8Runtime
|
||||||
import com.caoccao.javet.interop.options.V8Flags
|
|
||||||
import com.caoccao.javet.interop.options.V8RuntimeOptions
|
|
||||||
import com.caoccao.javet.values.V8Value
|
import com.caoccao.javet.values.V8Value
|
||||||
import com.caoccao.javet.values.primitive.V8ValueBoolean
|
import com.caoccao.javet.values.primitive.V8ValueBoolean
|
||||||
import com.caoccao.javet.values.primitive.V8ValueInteger
|
import com.caoccao.javet.values.primitive.V8ValueInteger
|
||||||
|
@ -17,7 +14,6 @@ import com.caoccao.javet.values.primitive.V8ValueString
|
||||||
import com.caoccao.javet.values.reference.V8ValueObject
|
import com.caoccao.javet.values.reference.V8ValueObject
|
||||||
import com.futo.platformplayer.api.http.ManagedHttpClient
|
import com.futo.platformplayer.api.http.ManagedHttpClient
|
||||||
import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient
|
import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient
|
||||||
import com.futo.platformplayer.assume
|
|
||||||
import com.futo.platformplayer.constructs.Event1
|
import com.futo.platformplayer.constructs.Event1
|
||||||
import com.futo.platformplayer.engine.exceptions.NoInternetException
|
import com.futo.platformplayer.engine.exceptions.NoInternetException
|
||||||
import com.futo.platformplayer.engine.exceptions.PluginEngineStoppedException
|
import com.futo.platformplayer.engine.exceptions.PluginEngineStoppedException
|
||||||
|
@ -44,7 +40,6 @@ import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.states.StateAssets
|
import com.futo.platformplayer.states.StateAssets
|
||||||
import com.futo.platformplayer.warnIfMainThread
|
import com.futo.platformplayer.warnIfMainThread
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.Semaphore
|
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
|
@ -58,7 +53,7 @@ class V8Plugin {
|
||||||
val httpClientAuth: ManagedHttpClient get() = _clientAuth;
|
val httpClientAuth: ManagedHttpClient get() = _clientAuth;
|
||||||
val httpClientOthers: Map<String, JSHttpClient> get() = _clientOthers;
|
val httpClientOthers: Map<String, JSHttpClient> get() = _clientOthers;
|
||||||
|
|
||||||
var startId: Int = 0;
|
var runtimeId: Int = 0;
|
||||||
|
|
||||||
fun registerHttpClient(client: JSHttpClient) {
|
fun registerHttpClient(client: JSHttpClient) {
|
||||||
synchronized(_clientOthers) {
|
synchronized(_clientOthers) {
|
||||||
|
@ -76,11 +71,8 @@ class V8Plugin {
|
||||||
var isStopped = true;
|
var isStopped = true;
|
||||||
val onStopped = Event1<V8Plugin>();
|
val onStopped = Event1<V8Plugin>();
|
||||||
|
|
||||||
//TODO: Implement a more universal isBusy system for plugins + JSClient + pooling? TBD if propagation would be beneficial
|
private val _busyLock = ReentrantLock()
|
||||||
//private val _busyCounterLock = Object();
|
val isBusy get() = _busyLock.isLocked;
|
||||||
//private var _busyCounter = 0;
|
|
||||||
private val _busyLock = ReentrantLock()//Semaphore(1);
|
|
||||||
val isBusy get() = _busyLock.isLocked;//synchronized(_busyCounterLock) { _busyCounter > 0 };
|
|
||||||
|
|
||||||
var allowDevSubmit: Boolean = false
|
var allowDevSubmit: Boolean = false
|
||||||
private set(value) {
|
private set(value) {
|
||||||
|
@ -150,24 +142,19 @@ class V8Plugin {
|
||||||
synchronized(_runtimeLock) {
|
synchronized(_runtimeLock) {
|
||||||
if (_runtime != null)
|
if (_runtime != null)
|
||||||
return;
|
return;
|
||||||
startId + 1;
|
runtimeId = runtimeId + 1;
|
||||||
//V8RuntimeOptions.V8_FLAGS.setUseStrict(true);
|
//V8RuntimeOptions.V8_FLAGS.setUseStrict(true);
|
||||||
val host = V8Host.getV8Instance();
|
val host = V8Host.getV8Instance();
|
||||||
val options = host.jsRuntimeType.getRuntimeOptions();
|
val options = host.jsRuntimeType.getRuntimeOptions();
|
||||||
|
|
||||||
Logger.i(TAG, "Plugin [${config.name}] start: Creating runtime")
|
|
||||||
|
|
||||||
_runtime = host.createV8Runtime(options);
|
_runtime = host.createV8Runtime(options);
|
||||||
if (!host.isIsolateCreated)
|
if (!host.isIsolateCreated)
|
||||||
throw IllegalStateException("Isolate not created");
|
throw IllegalStateException("Isolate not created");
|
||||||
|
|
||||||
Logger.i(TAG, "Plugin [${config.name}] start: Created runtime")
|
|
||||||
|
|
||||||
//Setup bridge
|
//Setup bridge
|
||||||
_runtime?.let {
|
_runtime?.let {
|
||||||
it.converter = V8Converter();
|
it.converter = V8Converter();
|
||||||
|
|
||||||
Logger.i(TAG, "Plugin [${config.name}] start: Loading packages")
|
|
||||||
for (pack in _depsPackages) {
|
for (pack in _depsPackages) {
|
||||||
if (pack.variableName != null)
|
if (pack.variableName != null)
|
||||||
it.createV8ValueObject().use { v8valueObject ->
|
it.createV8ValueObject().use { v8valueObject ->
|
||||||
|
@ -180,8 +167,6 @@ class V8Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.i(TAG, "Plugin [${config.name}] start: Loading deps")
|
|
||||||
|
|
||||||
//Load deps
|
//Load deps
|
||||||
for (dep in _deps)
|
for (dep in _deps)
|
||||||
catchScriptErrors("Dep[${dep.key}]") {
|
catchScriptErrors("Dep[${dep.key}]") {
|
||||||
|
@ -192,13 +177,11 @@ class V8Plugin {
|
||||||
if (config.allowEval)
|
if (config.allowEval)
|
||||||
it.allowEval(true);
|
it.allowEval(true);
|
||||||
|
|
||||||
Logger.i(TAG, "Plugin [${config.name}] start: Loading script")
|
|
||||||
//Load plugin
|
//Load plugin
|
||||||
catchScriptErrors("Plugin[${config.name}]") {
|
catchScriptErrors("Plugin[${config.name}]") {
|
||||||
it.getExecutor(script).executeVoid()
|
it.getExecutor(script).executeVoid()
|
||||||
};
|
};
|
||||||
isStopped = false;
|
isStopped = false;
|
||||||
Logger.i(TAG, "Plugin [${config.name}] start: Script loaded")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,7 +193,7 @@ class V8Plugin {
|
||||||
if(isStopped)
|
if(isStopped)
|
||||||
return@busy;
|
return@busy;
|
||||||
isStopped = true;
|
isStopped = true;
|
||||||
startId = -1;
|
runtimeId = runtimeId + 1;
|
||||||
|
|
||||||
//Cleanup http
|
//Cleanup http
|
||||||
for(pack in _depsPackages) {
|
for(pack in _depsPackages) {
|
||||||
|
@ -260,79 +243,11 @@ class V8Plugin {
|
||||||
runtime.getExecutor(js).execute()
|
runtime.getExecutor(js).execute()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
synchronized(_busyCounterLock) {
|
|
||||||
_busyCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
val runtime = _runtime ?: throw IllegalStateException("JSPlugin not started yet");
|
|
||||||
try {
|
|
||||||
return catchScriptErrors("Plugin[${config.name}]", js) {
|
|
||||||
runtime.getExecutor(js).execute()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
synchronized(_busyCounterLock) {
|
|
||||||
//Free busy *after* afterBusy calls are done to prevent calls on dead runtimes
|
|
||||||
try {
|
|
||||||
afterBusy.emit(_busyCounter - 1);
|
|
||||||
}
|
|
||||||
catch(ex: Throwable) {
|
|
||||||
Logger.e(TAG, "Unhandled V8Plugin.afterBusy", ex);
|
|
||||||
}
|
|
||||||
_busyCounter--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
fun executeBoolean(js: String) : Boolean? = busy { catchScriptErrors("Plugin[${config.name}]") { executeTyped<V8ValueBoolean>(js).value } }
|
fun executeBoolean(js: String) : Boolean? = busy { catchScriptErrors("Plugin[${config.name}]") { executeTyped<V8ValueBoolean>(js).value } }
|
||||||
fun executeString(js: String) : String? = busy { catchScriptErrors("Plugin[${config.name}]") { executeTyped<V8ValueString>(js).value } }
|
fun executeString(js: String) : String? = busy { catchScriptErrors("Plugin[${config.name}]") { executeTyped<V8ValueString>(js).value } }
|
||||||
fun executeInteger(js: String) : Int? = busy { catchScriptErrors("Plugin[${config.name}]") { executeTyped<V8ValueInteger>(js).value } }
|
fun executeInteger(js: String) : Int? = busy { catchScriptErrors("Plugin[${config.name}]") { executeTyped<V8ValueInteger>(js).value } }
|
||||||
|
|
||||||
/*
|
|
||||||
fun <T> whenNotBusyBlocking(handler: (V8Plugin)->T): T {
|
|
||||||
while(true) {
|
|
||||||
synchronized(_busyCounterLock) {
|
|
||||||
if(_busyCounter == 0)
|
|
||||||
{
|
|
||||||
return handler(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Thread.sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
fun whenNotBusy(handler: (V8Plugin)->Unit) {
|
|
||||||
synchronized(_busyCounterLock) {
|
|
||||||
if(_busyCounter == 0)
|
|
||||||
handler(this);
|
|
||||||
else {
|
|
||||||
val tag = Object();
|
|
||||||
afterBusy.subscribe(tag) {
|
|
||||||
if(it == 0) {
|
|
||||||
Logger.w(TAG, "V8Plugin afterBusy handled");
|
|
||||||
afterBusy.remove(tag);
|
|
||||||
|
|
||||||
var failed = false;
|
|
||||||
synchronized(_busyCounterLock) {
|
|
||||||
if(_busyCounter > 0) {
|
|
||||||
failed = true;
|
|
||||||
return@synchronized
|
|
||||||
}
|
|
||||||
handler(this);
|
|
||||||
}
|
|
||||||
if(failed)
|
|
||||||
busy {
|
|
||||||
handler(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private fun getPackage(packageName: String, allowNull: Boolean = false): V8Package? {
|
private fun getPackage(packageName: String, allowNull: Boolean = false): V8Package? {
|
||||||
//TODO: Auto get all package types?
|
//TODO: Auto get all package types?
|
||||||
return when(packageName) {
|
return when(packageName) {
|
||||||
|
@ -397,15 +312,12 @@ class V8Plugin {
|
||||||
val obj = executeEx.scriptingError?.context as IJavetEntityError
|
val obj = executeEx.scriptingError?.context as IJavetEntityError
|
||||||
if(obj.context.containsKey("plugin_type") == true) {
|
if(obj.context.containsKey("plugin_type") == true) {
|
||||||
val pluginType = obj.context["plugin_type"].toString();
|
val pluginType = obj.context["plugin_type"].toString();
|
||||||
//val pluginType = obj.get<V8ValueString>("plugin_type").toString();
|
|
||||||
|
|
||||||
//Captcha
|
//Captcha
|
||||||
if (pluginType == "CaptchaRequiredException") {
|
if (pluginType == "CaptchaRequiredException") {
|
||||||
throw ScriptCaptchaRequiredException(config,
|
throw ScriptCaptchaRequiredException(config,
|
||||||
obj.context["url"]?.toString(),
|
obj.context["url"]?.toString(),
|
||||||
obj.context["body"]?.toString(),
|
obj.context["body"]?.toString(),
|
||||||
//obj.get<V8ValueString>("url")?.toString(),
|
|
||||||
//obj.get<V8ValueString>("body")?.toString(),
|
|
||||||
executeEx, executeEx.scriptingError?.stack, codeStripped);
|
executeEx, executeEx.scriptingError?.stack, codeStripped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,8 +326,6 @@ class V8Plugin {
|
||||||
throw ScriptReloadRequiredException(config,
|
throw ScriptReloadRequiredException(config,
|
||||||
obj.context["msg"]?.toString(),
|
obj.context["msg"]?.toString(),
|
||||||
obj.context["reloadData"]?.toString(),
|
obj.context["reloadData"]?.toString(),
|
||||||
//obj.get<V8ValueString>("message")?.toString(),
|
|
||||||
//obj.get<V8ValueString>("reloadData")?.toString(),
|
|
||||||
executeEx, executeEx.scriptingError?.stack, codeStripped);
|
executeEx, executeEx.scriptingError?.stack, codeStripped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,9 +391,4 @@ class V8Plugin {
|
||||||
return StateAssets.readAsset(context, path) ?: throw java.lang.IllegalStateException("script ${path} not found");
|
return StateAssets.readAsset(context, path) ?: throw java.lang.IllegalStateException("script ${path} not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Methods available for scripts (bridge object)
|
|
||||||
*/
|
|
||||||
}
|
}
|
|
@ -82,7 +82,8 @@ class PackageBridge : V8Package {
|
||||||
@V8Property
|
@V8Property
|
||||||
fun supportedFeatures(): Array<String> {
|
fun supportedFeatures(): Array<String> {
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
"ReloadRequiredException"
|
"ReloadRequiredException",
|
||||||
|
"HttpBatchClient"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,14 +131,10 @@ class PackageBridge : V8Package {
|
||||||
timeoutMap.remove(id);
|
timeoutMap.remove(id);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Logger.v(TAG, "Timeout started [${id}]");
|
|
||||||
_plugin.busy {
|
_plugin.busy {
|
||||||
Logger.v(TAG, "Timeout call started [${id}]");
|
|
||||||
if(!_plugin.isStopped)
|
if(!_plugin.isStopped)
|
||||||
funcClone.callVoid(null, arrayOf<Any>());
|
funcClone.callVoid(null, arrayOf<Any>());
|
||||||
Logger.v(TAG, "Timeout call ended [${id}]");
|
|
||||||
}
|
}
|
||||||
Logger.v(TAG, "Timeout resolved [${id}]");
|
|
||||||
}
|
}
|
||||||
catch(ex: Throwable) {
|
catch(ex: Throwable) {
|
||||||
Logger.e(TAG, "Failed timeout callback", ex);
|
Logger.e(TAG, "Failed timeout callback", ex);
|
||||||
|
@ -173,7 +170,7 @@ class PackageBridge : V8Package {
|
||||||
Logger.i(TAG, "Plugin toast [${_config.name}]: ${str}");
|
Logger.i(TAG, "Plugin toast [${_config.name}]: ${str}");
|
||||||
StateApp.instance.scopeOrNull?.launch(Dispatchers.Main) {
|
StateApp.instance.scopeOrNull?.launch(Dispatchers.Main) {
|
||||||
try {
|
try {
|
||||||
UIDialogs.toast(str);
|
UIDialogs.appToast(str);
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Logger.e(TAG, "Failed to show toast.", e);
|
Logger.e(TAG, "Failed to show toast.", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,6 +347,17 @@ class PackageHttp: V8Package {
|
||||||
_clientId = if(_client is JSHttpClient) _client.clientId else null;
|
_clientId = if(_client is JSHttpClient) _client.clientId else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@V8Function
|
||||||
|
fun resetAuthCookies(){
|
||||||
|
if(_client is JSHttpClient)
|
||||||
|
_client.resetAuthCookies();
|
||||||
|
}
|
||||||
|
@V8Function
|
||||||
|
fun clearOtherCookies(){
|
||||||
|
if(_client is JSHttpClient)
|
||||||
|
_client.clearOtherCookies();
|
||||||
|
}
|
||||||
|
|
||||||
@V8Function
|
@V8Function
|
||||||
fun setDefaultHeaders(defaultHeaders: Map<String, String>) {
|
fun setDefaultHeaders(defaultHeaders: Map<String, String>) {
|
||||||
for(pair in defaultHeaders)
|
for(pair in defaultHeaders)
|
||||||
|
|
|
@ -567,7 +567,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
findViewTreeLifecycleOwner()?.lifecycle?.coroutineScope?.launch(Dispatchers.IO) {
|
findViewTreeLifecycleOwner()?.lifecycle?.coroutineScope?.launch(Dispatchers.IO) {
|
||||||
var startId = -1;
|
var startId = -1;
|
||||||
try {
|
try {
|
||||||
startId = videoSource?.getUnderlyingPlugin()?.getUnderlyingPlugin()?.startId ?: -1;
|
startId = videoSource?.getUnderlyingPlugin()?.getUnderlyingPlugin()?.runtimeId ?: -1;
|
||||||
val generated = videoSource.generate();
|
val generated = videoSource.generate();
|
||||||
if (generated != null) {
|
if (generated != null) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
@ -597,7 +597,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
val plugin = videoSource.getUnderlyingPlugin();
|
val plugin = videoSource.getUnderlyingPlugin();
|
||||||
if(plugin == null)
|
if(plugin == null)
|
||||||
return@launch;
|
return@launch;
|
||||||
if(startId != -1 && plugin.getUnderlyingPlugin()?.startId != startId)
|
if(startId != -1 && plugin.getUnderlyingPlugin()?.runtimeId != startId)
|
||||||
return@launch;
|
return@launch;
|
||||||
StatePlatform.instance.handleReloadRequired(reloadRequired, {
|
StatePlatform.instance.handleReloadRequired(reloadRequired, {
|
||||||
onReloadRequired.emit();
|
onReloadRequired.emit();
|
||||||
|
@ -689,17 +689,17 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
private fun swapAudioSourceDashRaw(audioSource: JSDashManifestRawAudioSource, play: Boolean, resume: Boolean): Boolean {
|
private fun swapAudioSourceDashRaw(audioSource: JSDashManifestRawAudioSource, play: Boolean, resume: Boolean): Boolean {
|
||||||
Logger.i(TAG, "Loading AudioSource [DashRaw]");
|
Logger.i(TAG, "Loading AudioSource [DashRaw]");
|
||||||
val dataSource = if(audioSource is JSSource && (audioSource.requiresCustomDatasource))
|
|
||||||
audioSource.getHttpDataSourceFactory()
|
|
||||||
else
|
|
||||||
DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT);
|
|
||||||
if(audioSource.hasGenerate) {
|
if(audioSource.hasGenerate) {
|
||||||
findViewTreeLifecycleOwner()?.lifecycle?.coroutineScope?.launch(Dispatchers.IO) {
|
findViewTreeLifecycleOwner()?.lifecycle?.coroutineScope?.launch(Dispatchers.IO) {
|
||||||
var startId = -1;
|
var startId = -1;
|
||||||
try {
|
try {
|
||||||
startId = audioSource.getUnderlyingPlugin()?.getUnderlyingPlugin()?.startId ?: -1;
|
startId = audioSource.getUnderlyingPlugin()?.getUnderlyingPlugin()?.runtimeId ?: -1;
|
||||||
val generated = audioSource.generate();
|
val generated = audioSource.generate();
|
||||||
if(generated != null) {
|
if(generated != null) {
|
||||||
|
val dataSource = if(audioSource is JSSource && (audioSource.requiresCustomDatasource))
|
||||||
|
audioSource.getHttpDataSourceFactory()
|
||||||
|
else
|
||||||
|
DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT);
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
_lastVideoMediaSource = DashMediaSource.Factory(dataSource)
|
_lastVideoMediaSource = DashMediaSource.Factory(dataSource)
|
||||||
.createMediaSource(DashManifestParser().parse(Uri.parse(audioSource.url),
|
.createMediaSource(DashManifestParser().parse(Uri.parse(audioSource.url),
|
||||||
|
@ -713,7 +713,7 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
val plugin = audioSource.getUnderlyingPlugin();
|
val plugin = audioSource.getUnderlyingPlugin();
|
||||||
if(plugin == null)
|
if(plugin == null)
|
||||||
return@launch;
|
return@launch;
|
||||||
if(startId != -1 && plugin.getUnderlyingPlugin()?.startId != startId)
|
if(startId != -1 && plugin.getUnderlyingPlugin()?.runtimeId != startId)
|
||||||
return@launch;
|
return@launch;
|
||||||
StatePlatform.instance.reEnableClient(plugin.id, {
|
StatePlatform.instance.reEnableClient(plugin.id, {
|
||||||
onReloadRequired.emit();
|
onReloadRequired.emit();
|
||||||
|
@ -726,6 +726,10 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
val dataSource = if(audioSource is JSSource && (audioSource.requiresCustomDatasource))
|
||||||
|
audioSource.getHttpDataSourceFactory()
|
||||||
|
else
|
||||||
|
DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT);
|
||||||
_lastVideoMediaSource = DashMediaSource.Factory(dataSource)
|
_lastVideoMediaSource = DashMediaSource.Factory(dataSource)
|
||||||
.createMediaSource(
|
.createMediaSource(
|
||||||
DashManifestParser().parse(
|
DashManifestParser().parse(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue