mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-28 12:30:12 +02:00
feat(composer_hooks): armv7 support
This commit is contained in:
parent
2bb055f464
commit
33dc0c7510
@ -772,7 +772,7 @@
|
||||
"properties": {
|
||||
"composer_hooks": {
|
||||
"name": "Composer Hooks",
|
||||
"description": "Injects code into the Composer cross-platform UI framework (arm64 only)",
|
||||
"description": "Injects code into the Composer cross-platform UI framework",
|
||||
"properties": {
|
||||
"bypass_camera_roll_limit": {
|
||||
"name": "Bypass Camera Roll Limit",
|
||||
@ -780,7 +780,7 @@
|
||||
},
|
||||
"composer_console": {
|
||||
"name": "Composer Console",
|
||||
"description": "Allows you to execute JavaScript code in Composer"
|
||||
"description": "Allows you to execute JavaScript code in Composer (arm64 only)"
|
||||
},
|
||||
"composer_logs": {
|
||||
"name": "Composer Logs",
|
||||
|
@ -1,9 +1,3 @@
|
||||
const callExport = require('composer_core/src/DeviceBridge')[EXPORTED_FUNCTION_NAME];
|
||||
|
||||
if (!callExport) {
|
||||
return "No export function found";
|
||||
}
|
||||
|
||||
const config = callExport("getConfig");
|
||||
|
||||
if (config.composerLogs) {
|
||||
|
@ -186,21 +186,16 @@ class ComposerHooks: Feature("ComposerHooks", loadParams = FeatureLoadParams.ACT
|
||||
return
|
||||
}
|
||||
|
||||
val hookResult = context.native.composerEval("""
|
||||
(() => { try { const EXPORTED_FUNCTION_NAME = "$exportedFunctionName"; $loaderScript
|
||||
context.native.setComposerLoader("""
|
||||
(() => { const callExport = require('composer_core/src/DeviceBridge')["$exportedFunctionName"]; try { $loaderScript
|
||||
} catch (e) {
|
||||
return e.toString() + "\n" + e.stack;
|
||||
try {
|
||||
callExport("log", "error", e.toString() + "\n" + e.stack);
|
||||
} catch (t) {}
|
||||
}
|
||||
return "success";
|
||||
})()
|
||||
})();
|
||||
""".trimIndent().trim())
|
||||
|
||||
if (hookResult != "success") {
|
||||
context.shortToast(("Composer loader failed : $hookResult").also {
|
||||
context.log.error(it)
|
||||
})
|
||||
}
|
||||
|
||||
if (config.composerConsole.get()) {
|
||||
injectConsole()
|
||||
}
|
||||
@ -221,16 +216,6 @@ class ComposerHooks: Feature("ComposerHooks", loadParams = FeatureLoadParams.ACT
|
||||
}
|
||||
}
|
||||
|
||||
var composerThreadTask: (() -> Unit)? = null
|
||||
|
||||
findClass("com.snap.composer.callable.ComposerFunctionNative").hook("nativePerform", HookStage.BEFORE) {
|
||||
composerThreadTask?.invoke()
|
||||
composerThreadTask = null
|
||||
}
|
||||
|
||||
context.coroutineScope.launch {
|
||||
context.native.waitForComposer()
|
||||
composerThreadTask = ::loadHooks
|
||||
}
|
||||
loadHooks()
|
||||
}
|
||||
}
|
@ -93,20 +93,32 @@ namespace ComposerHook {
|
||||
|
||||
static uintptr_t global_instance;
|
||||
static JSContext *global_ctx;
|
||||
static std::string* composer_loader;
|
||||
|
||||
HOOK_DEF(JSValue, js_eval, uintptr_t instance, JSContext *ctx, uintptr_t this_obj, uint8_t *input, uintptr_t input_len, const char *filename, unsigned int flags, unsigned int scope_idx) {
|
||||
HOOK_DEF(JSValue, js_eval, uintptr_t instance, JSContext *ctx, uintptr_t this_obj, char *input, uintptr_t input_len, const char *filename, unsigned int flags, unsigned int scope_idx) {
|
||||
if (global_instance == 0 || global_ctx == nullptr) {
|
||||
global_instance = instance;
|
||||
global_ctx = ctx;
|
||||
}
|
||||
LOGD("Injecting composer loader");
|
||||
|
||||
composer_loader->resize(composer_loader->size() + input_len);
|
||||
memcpy((void*) (composer_loader->c_str() + composer_loader->size() - input_len), input, input_len);
|
||||
|
||||
input = (char*) composer_loader->c_str();
|
||||
input_len = composer_loader->size();
|
||||
} else {
|
||||
if (composer_loader != nullptr) {
|
||||
delete composer_loader;
|
||||
composer_loader = nullptr;
|
||||
}
|
||||
}
|
||||
return js_eval_original(instance, ctx, this_obj, input, input_len, filename, flags, scope_idx);
|
||||
}
|
||||
|
||||
void waitForComposer(JNIEnv *, jobject) {
|
||||
while (global_instance == 0 || global_ctx == nullptr) {
|
||||
usleep(10000);
|
||||
}
|
||||
void setComposerLoader(JNIEnv *env, jobject, jstring code) {
|
||||
auto code_str = env->GetStringUTFChars(code, nullptr);
|
||||
composer_loader = new std::string(code_str, env->GetStringUTFLength(code));
|
||||
env->ReleaseStringUTFChars(code, code_str);
|
||||
}
|
||||
|
||||
jstring composerEval(JNIEnv *env, jobject, jstring script) {
|
||||
@ -117,7 +129,7 @@ namespace ComposerHook {
|
||||
|
||||
auto script_str = env->GetStringUTFChars(script, nullptr);
|
||||
auto length = env->GetStringUTFLength(script);
|
||||
auto jsvalue = js_eval_original(global_instance, global_ctx, (uintptr_t) &global_ctx->global_obj, (uint8_t *) script_str, length, "<input>", 0, 0);
|
||||
auto jsvalue = js_eval_original(global_instance, global_ctx, (uintptr_t) &global_ctx->global_obj, (char *) script_str, length, "<eval>", 0, 0);
|
||||
env->ReleaseStringUTFChars(script, script_str);
|
||||
|
||||
if (jsvalue.tag == JS_TAG_STRING) {
|
||||
@ -157,12 +169,11 @@ namespace ComposerHook {
|
||||
}
|
||||
|
||||
void init() {
|
||||
if (!ARM64) return;
|
||||
auto js_eval_ptr = util::find_signature(
|
||||
common::client_module.base,
|
||||
common::client_module.size,
|
||||
"00 E4 00 6F 29 00 80 52 76 00 04 8B",
|
||||
-0x28
|
||||
ARM64 ? "00 E4 00 6F 29 00 80 52 76 00 04 8B" : "A1 B0 07 92 81 46",
|
||||
ARM64 ? -0x28 : -0x7
|
||||
);
|
||||
if (js_eval_ptr == 0) {
|
||||
LOGE("js_eval_ptr signature not found");
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <string>
|
||||
#include <dobby.h>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
#include "logger.h"
|
||||
#include "common.h"
|
||||
@ -33,21 +32,13 @@ bool JNICALL init(JNIEnv *env, jobject clazz) {
|
||||
|
||||
util::remap_sections(BUILD_PACKAGE);
|
||||
|
||||
auto threads = std::vector<std::thread>();
|
||||
|
||||
#define RUN(body) \
|
||||
threads.push_back(std::thread([&] { body; }))
|
||||
|
||||
RUN(UnaryCallHook::init(env));
|
||||
RUN(AssetHook::init(env));
|
||||
RUN(FstatHook::init());
|
||||
RUN(SqliteMutexHook::init());
|
||||
RUN(DuplexHook::init(env));
|
||||
UnaryCallHook::init(env);
|
||||
AssetHook::init(env);
|
||||
FstatHook::init();
|
||||
SqliteMutexHook::init();
|
||||
DuplexHook::init(env);
|
||||
if (common::native_config->composer_hooks) {
|
||||
RUN(ComposerHook::init());
|
||||
}
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
ComposerHook::init();
|
||||
}
|
||||
|
||||
LOGD("Native initialized");
|
||||
@ -94,7 +85,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *_) {
|
||||
methods.push_back({"init", "()Z", (void *)init});
|
||||
methods.push_back({"loadConfig", "(L" BUILD_NAMESPACE "/NativeConfig;)V", (void *)load_config});
|
||||
methods.push_back({"lockDatabase", "(Ljava/lang/String;Ljava/lang/Runnable;)V", (void *)lock_database});
|
||||
methods.push_back({"waitForComposer", "()V", (void *) ComposerHook::waitForComposer});
|
||||
methods.push_back({"setComposerLoader", "(Ljava/lang/String;)V", (void *) ComposerHook::setComposerLoader});
|
||||
methods.push_back({"composerEval", "(Ljava/lang/String;)Ljava/lang/String;",(void *) ComposerHook::composerEval});
|
||||
|
||||
env->RegisterNatives(env->FindClass(std::string(BUILD_NAMESPACE "/NativeLib").c_str()), methods.data(), methods.size());
|
||||
|
@ -2,6 +2,7 @@ package me.rhunk.snapenhance.nativelib
|
||||
|
||||
import android.util.Log
|
||||
|
||||
@Suppress("KotlinJniMissingFunction")
|
||||
class NativeLib {
|
||||
var nativeUnaryCallCallback: (NativeRequestData) -> Unit = {}
|
||||
var nativeShouldLoadAsset: (String) -> Boolean = { true }
|
||||
@ -62,6 +63,6 @@ class NativeLib {
|
||||
private external fun init(): Boolean
|
||||
private external fun loadConfig(config: NativeConfig)
|
||||
private external fun lockDatabase(name: String, callback: Runnable)
|
||||
external fun waitForComposer()
|
||||
external fun setComposerLoader(code: String)
|
||||
external fun composerEval(code: String): String?
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user