From c183fd8b22ec9f079c3558f85cf2031934f0f24e Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Wed, 11 Feb 2026 14:09:36 +0530 Subject: [PATCH 1/9] feat: pluginContext --- .prettierrc | 1 + package-lock.json | 17 +++ package.json | 4 +- src/lib/loadPlugin.js | 101 ++++++++------- src/plugins/pluginContext/package.json | 17 +++ src/plugins/pluginContext/plugin.xml | 22 ++++ .../pluginContext/src/android/Tee.java | 122 ++++++++++++++++++ .../pluginContext/www/PluginContext.js | 57 ++++++++ 8 files changed, 290 insertions(+), 51 deletions(-) create mode 100644 .prettierrc create mode 100644 src/plugins/pluginContext/package.json create mode 100644 src/plugins/pluginContext/plugin.xml create mode 100644 src/plugins/pluginContext/src/android/Tee.java create mode 100644 src/plugins/pluginContext/www/PluginContext.js diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/.prettierrc @@ -0,0 +1 @@ +{} diff --git a/package-lock.json b/package-lock.json index a1f07947e..2a6cfe0bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,6 +58,7 @@ "com.foxdebug.acode.rk.customtabs": "file:src/plugins/custom-tabs", "com.foxdebug.acode.rk.exec.proot": "file:src/plugins/proot", "com.foxdebug.acode.rk.exec.terminal": "file:src/plugins/terminal", + "com.foxdebug.acode.rk.plugin.plugincontext": "file:src/plugins/pluginContext", "cordova-android": "^14.0.1", "cordova-clipboard": "^1.3.0", "cordova-plugin-advanced-http": "^3.3.1", @@ -4010,6 +4011,10 @@ "resolved": "src/plugins/terminal", "link": true }, + "node_modules/com.foxdebug.acode.rk.plugin.plugincontext": { + "resolved": "src/plugins/pluginContext", + "link": true + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -8789,12 +8794,24 @@ "dev": true, "license": "Apache-2.0" }, + "src/plugins/gatekeeper": { + "name": "com.foxdebug.acode.rk.plugin.gatekeeper", + "version": "1.0.0", + "extraneous": true, + "license": "MIT" + }, "src/plugins/iap": { "name": "cordova-plugin-iap", "version": "1.0.0", "dev": true, "license": "ISC" }, + "src/plugins/pluginContext": { + "name": "com.foxdebug.acode.rk.plugin.plugincontext", + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, "src/plugins/proot": { "name": "com.foxdebug.acode.rk.exec.proot", "version": "1.0.0", diff --git a/package.json b/package.json index 1475f227d..af9dccbd3 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "com.foxdebug.acode.rk.exec.proot": {}, "com.foxdebug.acode.rk.exec.terminal": {}, "com.foxdebug.acode.rk.customtabs": {}, - "com.foxdebug.acode.rk.auth": {} + "com.foxdebug.acode.rk.auth": {}, + "com.foxdebug.acode.rk.plugin.plugincontext": {} }, "platforms": [ "android" @@ -69,6 +70,7 @@ "com.foxdebug.acode.rk.customtabs": "file:src/plugins/custom-tabs", "com.foxdebug.acode.rk.exec.proot": "file:src/plugins/proot", "com.foxdebug.acode.rk.exec.terminal": "file:src/plugins/terminal", + "com.foxdebug.acode.rk.plugin.plugincontext": "file:src/plugins/pluginContext", "cordova-android": "^14.0.1", "cordova-clipboard": "^1.3.0", "cordova-plugin-advanced-http": "^3.3.1", diff --git a/src/lib/loadPlugin.js b/src/lib/loadPlugin.js index 4078f29c9..d2639f16f 100644 --- a/src/lib/loadPlugin.js +++ b/src/lib/loadPlugin.js @@ -5,65 +5,66 @@ import Url from "utils/Url"; import actionStack from "./actionStack"; export default async function loadPlugin(pluginId, justInstalled = false) { - const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); - const cacheFile = Url.join(CACHE_STORAGE, pluginId); + const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); + const cacheFile = Url.join(CACHE_STORAGE, pluginId); - const pluginJson = await fsOperation( - Url.join(PLUGIN_DIR, pluginId, "plugin.json"), - ).readFile("json"); + const pluginJson = await fsOperation( + Url.join(PLUGIN_DIR, pluginId, "plugin.json"), + ).readFile("json"); - let mainUrl; - if ( - await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() - ) { - mainUrl = Url.join(baseUrl, pluginJson.main); - } else { - mainUrl = Url.join(baseUrl, "main.js"); - } + let mainUrl; + if ( + await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() + ) { + mainUrl = Url.join(baseUrl, pluginJson.main); + } else { + mainUrl = Url.join(baseUrl, "main.js"); + } - return new Promise((resolve, reject) => { - const $script = ; + return new Promise((resolve, reject) => { + const $script = ; - $script.onerror = (error) => { - reject( - new Error( - `Failed to load script for plugin ${pluginId}: ${error.message || error}`, - ), - ); - }; + $script.onerror = (error) => { + reject( + new Error( + `Failed to load script for plugin ${pluginId}: ${error.message || error}`, + ), + ); + }; - $script.onload = async () => { - const $page = Page("Plugin"); - $page.show = () => { - actionStack.push({ - id: pluginId, - action: $page.hide, - }); + $script.onload = async () => { + const $page = Page("Plugin"); + $page.show = () => { + actionStack.push({ + id: pluginId, + action: $page.hide, + }); - app.append($page); - }; + app.append($page); + }; - $page.onhide = function () { - actionStack.remove(pluginId); - }; + $page.onhide = function () { + actionStack.remove(pluginId); + }; - try { - if (!(await fsOperation(cacheFile).exists())) { - await fsOperation(CACHE_STORAGE).createFile(pluginId); - } + try { + if (!(await fsOperation(cacheFile).exists())) { + await fsOperation(CACHE_STORAGE).createFile(pluginId); + } - await acode.initPlugin(pluginId, baseUrl, $page, { - cacheFileUrl: await helpers.toInternalUri(cacheFile), - cacheFile: fsOperation(cacheFile), - firstInit: justInstalled, - }); + await acode.initPlugin(pluginId, baseUrl, $page, { + cacheFileUrl: await helpers.toInternalUri(cacheFile), + cacheFile: fsOperation(cacheFile), + firstInit: justInstalled, + ctx: await PluginContext.generate(pluginId, pluginJson), + }); - resolve(); - } catch (error) { - reject(error); - } - }; + resolve(); + } catch (error) { + reject(error); + } + }; - document.head.append($script); - }); + document.head.append($script); + }); } diff --git a/src/plugins/pluginContext/package.json b/src/plugins/pluginContext/package.json new file mode 100644 index 000000000..301d27b99 --- /dev/null +++ b/src/plugins/pluginContext/package.json @@ -0,0 +1,17 @@ +{ + "name": "com.foxdebug.acode.rk.plugin.plugincontext", + "version": "1.0.0", + "description": "PluginContext", + "cordova": { + "id": "com.foxdebug.acode.rk.plugin.plugincontext", + "platforms": [ + "android" + ] + }, + "keywords": [ + "ecosystem:cordova", + "cordova-android" + ], + "author": "@RohitKushvaha01", + "license": "MIT" +} diff --git a/src/plugins/pluginContext/plugin.xml b/src/plugins/pluginContext/plugin.xml new file mode 100644 index 000000000..dcc049664 --- /dev/null +++ b/src/plugins/pluginContext/plugin.xml @@ -0,0 +1,22 @@ + + + Gatekeeper + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/plugins/pluginContext/src/android/Tee.java b/src/plugins/pluginContext/src/android/Tee.java new file mode 100644 index 000000000..074c9d08b --- /dev/null +++ b/src/plugins/pluginContext/src/android/Tee.java @@ -0,0 +1,122 @@ +package com.foxdebug.acode.rk.plugin; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.UUID; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.HashSet; + +public class Tee extends CordovaPlugin { + + private static final Map tokenStore = new HashMap<>(); + private static final HashSet disclosed = new HashSet<>(); + private static final Map> permissionStore = new HashMap<>(); + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callback) + throws JSONException { + + if ("requestToken".equals(action)) { + String pluginId = args.getString(0); + String pluginJson = args.getString(1); + handleTokenRequest(pluginId, pluginJson, callback); + return true; + } + + if ("grantedPermission".equals(action)) { + String token = args.getString(0); + String permission = args.getString(1); + + if (!permissionStore.containsKey(token)) { + callback.error("INVALID_TOKEN"); + return true; + } + + boolean granted = grantedPermission(token, permission); + callback.success(granted ? 1 : 0); + return true; + } + + if ("listAllPermissions".equals(action)) { + String token = args.getString(0); + + if (!permissionStore.containsKey(token)) { + callback.error("INVALID_TOKEN"); + return true; + } + + List permissions = listAllPermissions(token); + JSONArray result = new JSONArray(permissions); + + callback.success(result); + return true; + } + + return false; + } + + private boolean grantedPermission(String token, String permission) { + List permissions = permissionStore.get(token); + return permissions != null && permissions.contains(permission); + } + + private List listAllPermissions(String token) { + List permissions = permissionStore.get(token); + + if (permissions == null) { + return new ArrayList<>(); + } + + return new ArrayList<>(permissions); // return copy (safe) + } + + + private synchronized void handleTokenRequest( + String pluginId, + String pluginJson, + CallbackContext callback + ) { + + if (disclosed.contains(pluginId)) { + callback.error("TOKEN_ALREADY_ISSUED"); + return; + } + + String token = tokenStore.get(pluginId); + + if (token == null) { + token = UUID.randomUUID().toString(); + tokenStore.put(pluginId, token); + } + + try { + JSONObject json = new JSONObject(pluginJson); + JSONArray permissions = json.optJSONArray("permissions"); + + List permissionList = new ArrayList<>(); + + if (permissions != null) { + for (int i = 0; i < permissions.length(); i++) { + permissionList.add(permissions.getString(i)); + } + } + + // Bind permissions to token + permissionStore.put(token, permissionList); + + } catch (JSONException e) { + callback.error("INVALID_PLUGIN_JSON"); + return; + } + + disclosed.add(pluginId); + callback.success(token); + } +} diff --git a/src/plugins/pluginContext/www/PluginContext.js b/src/plugins/pluginContext/www/PluginContext.js new file mode 100644 index 000000000..4ce65e7c0 --- /dev/null +++ b/src/plugins/pluginContext/www/PluginContext.js @@ -0,0 +1,57 @@ +var exec = require("cordova/exec"); + +const PluginContext = (function () { + const _state = new WeakMap(); + + class _PluginContext { + time = Date.now(); + constructor(pluginId, uuid) { + _state.set(this, { pluginId, uuid }); + Object.freeze(this); + } + grantedPermission(permission) { + const state = _state.get(this); + return new Promise((resolve, reject) => { + exec(resolve, reject, "Tee", "grantedPermission", [ + state.uuid, + permission, + ]); + }); + } + + listAllPermissions() { + const state = _state.get(this); + return new Promise((resolve, reject) => { + exec(resolve, reject, "Tee", "listAllPermissions", [state.uuid]); + }); + } + } + + //Object.freeze(this); + + return { + generate: async function (pluginId, pluginJson) { + try { + function requestToken(pluginId) { + return new Promise((resolve, reject) => { + exec(resolve, reject, "Tee", "requestToken", [ + pluginId, + pluginJson, + ]); + }); + } + + const uuid = await requestToken(pluginId); + return new _PluginContext(pluginId, uuid); + } catch (err) { + console.error( + `PluginContext generation failed for pluginId ${pluginId}:`, + err, + ); + return null; + } + }, + }; +})(); + +module.exports = PluginContext; From 86e8103a6cbc9783774f86b216f4430f0a621224 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Wed, 11 Feb 2026 14:15:14 +0530 Subject: [PATCH 2/9] format --- src/lib/loadPlugin.js | 102 +++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/lib/loadPlugin.js b/src/lib/loadPlugin.js index d2639f16f..e6e0b37bd 100644 --- a/src/lib/loadPlugin.js +++ b/src/lib/loadPlugin.js @@ -5,66 +5,66 @@ import Url from "utils/Url"; import actionStack from "./actionStack"; export default async function loadPlugin(pluginId, justInstalled = false) { - const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); - const cacheFile = Url.join(CACHE_STORAGE, pluginId); + const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); + const cacheFile = Url.join(CACHE_STORAGE, pluginId); - const pluginJson = await fsOperation( - Url.join(PLUGIN_DIR, pluginId, "plugin.json"), - ).readFile("json"); + const pluginJson = await fsOperation( + Url.join(PLUGIN_DIR, pluginId, "plugin.json"), + ).readFile("json"); - let mainUrl; - if ( - await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() - ) { - mainUrl = Url.join(baseUrl, pluginJson.main); - } else { - mainUrl = Url.join(baseUrl, "main.js"); - } + let mainUrl; + if ( + await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() + ) { + mainUrl = Url.join(baseUrl, pluginJson.main); + } else { + mainUrl = Url.join(baseUrl, "main.js"); + } - return new Promise((resolve, reject) => { - const $script = ; + return new Promise((resolve, reject) => { + const $script = ; - $script.onerror = (error) => { - reject( - new Error( - `Failed to load script for plugin ${pluginId}: ${error.message || error}`, - ), - ); - }; + $script.onerror = (error) => { + reject( + new Error( + `Failed to load script for plugin ${pluginId}: ${error.message || error}`, + ), + ); + }; - $script.onload = async () => { - const $page = Page("Plugin"); - $page.show = () => { - actionStack.push({ - id: pluginId, - action: $page.hide, - }); + $script.onload = async () => { + const $page = Page("Plugin"); + $page.show = () => { + actionStack.push({ + id: pluginId, + action: $page.hide, + }); - app.append($page); - }; + app.append($page); + }; - $page.onhide = function () { - actionStack.remove(pluginId); - }; + $page.onhide = function () { + actionStack.remove(pluginId); + }; - try { - if (!(await fsOperation(cacheFile).exists())) { - await fsOperation(CACHE_STORAGE).createFile(pluginId); - } + try { + if (!(await fsOperation(cacheFile).exists())) { + await fsOperation(CACHE_STORAGE).createFile(pluginId); + } - await acode.initPlugin(pluginId, baseUrl, $page, { - cacheFileUrl: await helpers.toInternalUri(cacheFile), - cacheFile: fsOperation(cacheFile), - firstInit: justInstalled, - ctx: await PluginContext.generate(pluginId, pluginJson), - }); + await acode.initPlugin(pluginId, baseUrl, $page, { + cacheFileUrl: await helpers.toInternalUri(cacheFile), + cacheFile: fsOperation(cacheFile), + firstInit: justInstalled, + ctx: await PluginContext.generate(pluginId, pluginJson), + }); - resolve(); - } catch (error) { - reject(error); - } - }; + resolve(); + } catch (error) { + reject(error); + } + }; - document.head.append($script); - }); + document.head.append($script); + }); } From 7b724e54cae3daecdaa40e6322662304794c896a Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Wed, 11 Feb 2026 21:14:01 +0530 Subject: [PATCH 3/9] fix: issues --- package.json | 1 - src/lib/loadPlugin.js | 105 +++++++++--------- .../pluginContext/www/PluginContext.js | 3 +- 3 files changed, 55 insertions(+), 54 deletions(-) diff --git a/package.json b/package.json index af9dccbd3..0e152fc54 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "com.foxdebug.acode.rk.exec.proot": {}, "com.foxdebug.acode.rk.exec.terminal": {}, "com.foxdebug.acode.rk.customtabs": {}, - "com.foxdebug.acode.rk.auth": {}, "com.foxdebug.acode.rk.plugin.plugincontext": {} }, "platforms": [ diff --git a/src/lib/loadPlugin.js b/src/lib/loadPlugin.js index e6e0b37bd..c96be38d2 100644 --- a/src/lib/loadPlugin.js +++ b/src/lib/loadPlugin.js @@ -5,66 +5,69 @@ import Url from "utils/Url"; import actionStack from "./actionStack"; export default async function loadPlugin(pluginId, justInstalled = false) { - const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); - const cacheFile = Url.join(CACHE_STORAGE, pluginId); + const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); + const cacheFile = Url.join(CACHE_STORAGE, pluginId); - const pluginJson = await fsOperation( - Url.join(PLUGIN_DIR, pluginId, "plugin.json"), - ).readFile("json"); + const pluginJson = await fsOperation( + Url.join(PLUGIN_DIR, pluginId, "plugin.json"), + ).readFile("json"); - let mainUrl; - if ( - await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() - ) { - mainUrl = Url.join(baseUrl, pluginJson.main); - } else { - mainUrl = Url.join(baseUrl, "main.js"); - } + let mainUrl; + if ( + await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() + ) { + mainUrl = Url.join(baseUrl, pluginJson.main); + } else { + mainUrl = Url.join(baseUrl, "main.js"); + } - return new Promise((resolve, reject) => { - const $script = ; + return new Promise((resolve, reject) => { + const $script = ; - $script.onerror = (error) => { - reject( - new Error( - `Failed to load script for plugin ${pluginId}: ${error.message || error}`, - ), - ); - }; + $script.onerror = (error) => { + reject( + new Error( + `Failed to load script for plugin ${pluginId}: ${error.message || error}`, + ), + ); + }; - $script.onload = async () => { - const $page = Page("Plugin"); - $page.show = () => { - actionStack.push({ - id: pluginId, - action: $page.hide, - }); + $script.onload = async () => { + const $page = Page("Plugin"); + $page.show = () => { + actionStack.push({ + id: pluginId, + action: $page.hide, + }); - app.append($page); - }; + app.append($page); + }; - $page.onhide = function () { - actionStack.remove(pluginId); - }; + $page.onhide = function () { + actionStack.remove(pluginId); + }; - try { - if (!(await fsOperation(cacheFile).exists())) { - await fsOperation(CACHE_STORAGE).createFile(pluginId); - } + try { + if (!(await fsOperation(cacheFile).exists())) { + await fsOperation(CACHE_STORAGE).createFile(pluginId); + } - await acode.initPlugin(pluginId, baseUrl, $page, { - cacheFileUrl: await helpers.toInternalUri(cacheFile), - cacheFile: fsOperation(cacheFile), - firstInit: justInstalled, - ctx: await PluginContext.generate(pluginId, pluginJson), - }); + await acode.initPlugin(pluginId, baseUrl, $page, { + cacheFileUrl: await helpers.toInternalUri(cacheFile), + cacheFile: fsOperation(cacheFile), + firstInit: justInstalled, + ctx: await PluginContext.generate( + pluginId, + JSON.stringify(pluginJson), + ), + }); - resolve(); - } catch (error) { - reject(error); - } - }; + resolve(); + } catch (error) { + reject(error); + } + }; - document.head.append($script); - }); + document.head.append($script); + }); } diff --git a/src/plugins/pluginContext/www/PluginContext.js b/src/plugins/pluginContext/www/PluginContext.js index 4ce65e7c0..11dea64e3 100644 --- a/src/plugins/pluginContext/www/PluginContext.js +++ b/src/plugins/pluginContext/www/PluginContext.js @@ -44,9 +44,8 @@ const PluginContext = (function () { const uuid = await requestToken(pluginId); return new _PluginContext(pluginId, uuid); } catch (err) { - console.error( + console.warn( `PluginContext generation failed for pluginId ${pluginId}:`, - err, ); return null; } From 82d32718df063b9a5e97955207be571477fcd989 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Fri, 13 Feb 2026 14:59:54 +0530 Subject: [PATCH 4/9] feat --- src/lib/loadPlugin.js | 108 +++++++++--------- .../pluginContext/src/android/Tee.java | 24 +++- .../pluginContext/www/PluginContext.js | 35 +++--- 3 files changed, 95 insertions(+), 72 deletions(-) diff --git a/src/lib/loadPlugin.js b/src/lib/loadPlugin.js index c96be38d2..bad8e81eb 100644 --- a/src/lib/loadPlugin.js +++ b/src/lib/loadPlugin.js @@ -5,69 +5,69 @@ import Url from "utils/Url"; import actionStack from "./actionStack"; export default async function loadPlugin(pluginId, justInstalled = false) { - const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); - const cacheFile = Url.join(CACHE_STORAGE, pluginId); + const baseUrl = await helpers.toInternalUri(Url.join(PLUGIN_DIR, pluginId)); + const cacheFile = Url.join(CACHE_STORAGE, pluginId); - const pluginJson = await fsOperation( - Url.join(PLUGIN_DIR, pluginId, "plugin.json"), - ).readFile("json"); + const pluginJson = await fsOperation( + Url.join(PLUGIN_DIR, pluginId, "plugin.json"), + ).readFile("json"); - let mainUrl; - if ( - await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() - ) { - mainUrl = Url.join(baseUrl, pluginJson.main); - } else { - mainUrl = Url.join(baseUrl, "main.js"); - } + let mainUrl; + if ( + await fsOperation(Url.join(PLUGIN_DIR, pluginId, pluginJson.main)).exists() + ) { + mainUrl = Url.join(baseUrl, pluginJson.main); + } else { + mainUrl = Url.join(baseUrl, "main.js"); + } - return new Promise((resolve, reject) => { - const $script = ; + return new Promise((resolve, reject) => { + const $script = ; - $script.onerror = (error) => { - reject( - new Error( - `Failed to load script for plugin ${pluginId}: ${error.message || error}`, - ), - ); - }; + $script.onerror = (error) => { + reject( + new Error( + `Failed to load script for plugin ${pluginId}: ${error.message || error}`, + ), + ); + }; - $script.onload = async () => { - const $page = Page("Plugin"); - $page.show = () => { - actionStack.push({ - id: pluginId, - action: $page.hide, - }); + $script.onload = async () => { + const $page = Page("Plugin"); + $page.show = () => { + actionStack.push({ + id: pluginId, + action: $page.hide, + }); - app.append($page); - }; + app.append($page); + }; - $page.onhide = function () { - actionStack.remove(pluginId); - }; + $page.onhide = function () { + actionStack.remove(pluginId); + }; - try { - if (!(await fsOperation(cacheFile).exists())) { - await fsOperation(CACHE_STORAGE).createFile(pluginId); - } + try { + if (!(await fsOperation(cacheFile).exists())) { + await fsOperation(CACHE_STORAGE).createFile(pluginId); + } - await acode.initPlugin(pluginId, baseUrl, $page, { - cacheFileUrl: await helpers.toInternalUri(cacheFile), - cacheFile: fsOperation(cacheFile), - firstInit: justInstalled, - ctx: await PluginContext.generate( - pluginId, - JSON.stringify(pluginJson), - ), - }); + await acode.initPlugin(pluginId, baseUrl, $page, { + cacheFileUrl: await helpers.toInternalUri(cacheFile), + cacheFile: fsOperation(cacheFile), + firstInit: justInstalled, + ctx: await PluginContext.generate( + pluginId, + JSON.stringify(pluginJson), + ), + }); - resolve(); - } catch (error) { - reject(error); - } - }; + resolve(); + } catch (error) { + reject(error); + } + }; - document.head.append($script); - }); + document.head.append($script); + }); } diff --git a/src/plugins/pluginContext/src/android/Tee.java b/src/plugins/pluginContext/src/android/Tee.java index 074c9d08b..c78f3e426 100644 --- a/src/plugins/pluginContext/src/android/Tee.java +++ b/src/plugins/pluginContext/src/android/Tee.java @@ -15,9 +15,14 @@ public class Tee extends CordovaPlugin { - private static final Map tokenStore = new HashMap<>(); - private static final HashSet disclosed = new HashSet<>(); - private static final Map> permissionStore = new HashMap<>(); + // pluginId : token + private /*static*/ final Map tokenStore = new HashMap<>(); + + //assined tokens + private /*static*/ final HashSet disclosed = new HashSet<>(); + + // token : list of permissions + private /*static*/ final Map> permissionStore = new HashMap<>(); @Override public boolean execute(String action, JSONArray args, CallbackContext callback) @@ -62,12 +67,20 @@ public boolean execute(String action, JSONArray args, CallbackContext callback) return false; } - private boolean grantedPermission(String token, String permission) { + //============================================================ + //do not change function signatures + public boolean isTokenValid(String token, String pluginId) { + String storedToken = tokenStore.get(pluginId); + return storedToken != null && token.equals(storedToken); + } + + + public boolean grantedPermission(String token, String permission) { List permissions = permissionStore.get(token); return permissions != null && permissions.contains(permission); } - private List listAllPermissions(String token) { + public List listAllPermissions(String token) { List permissions = permissionStore.get(token); if (permissions == null) { @@ -76,6 +89,7 @@ private List listAllPermissions(String token) { return new ArrayList<>(permissions); // return copy (safe) } + //============================================================ private synchronized void handleTokenRequest( diff --git a/src/plugins/pluginContext/www/PluginContext.js b/src/plugins/pluginContext/www/PluginContext.js index 11dea64e3..4f916e7a8 100644 --- a/src/plugins/pluginContext/www/PluginContext.js +++ b/src/plugins/pluginContext/www/PluginContext.js @@ -1,34 +1,45 @@ var exec = require("cordova/exec"); const PluginContext = (function () { - const _state = new WeakMap(); - + //============================= class _PluginContext { - time = Date.now(); - constructor(pluginId, uuid) { - _state.set(this, { pluginId, uuid }); + constructor(uuid) { + this.created_at = Date.now(); + this.uuid = uuid; Object.freeze(this); } + + toString() { + return this.uuid; + } + + [Symbol.toPrimitive](hint) { + if (hint === "number") { + return NaN; // prevent numeric coercion + } + return this.uuid; + } + grantedPermission(permission) { - const state = _state.get(this); return new Promise((resolve, reject) => { exec(resolve, reject, "Tee", "grantedPermission", [ - state.uuid, + this.uuid, permission, ]); }); } listAllPermissions() { - const state = _state.get(this); return new Promise((resolve, reject) => { - exec(resolve, reject, "Tee", "listAllPermissions", [state.uuid]); + exec(resolve, reject, "Tee", "listAllPermissions", [this.uuid]); }); } } //Object.freeze(this); + //=============================== + return { generate: async function (pluginId, pluginJson) { try { @@ -42,11 +53,9 @@ const PluginContext = (function () { } const uuid = await requestToken(pluginId); - return new _PluginContext(pluginId, uuid); + return new _PluginContext(uuid); } catch (err) { - console.warn( - `PluginContext generation failed for pluginId ${pluginId}:`, - ); + console.warn(`PluginContext creation failed for pluginId ${pluginId}:`); return null; } }, From b2f13e42c5a5d9a5ed9549d1de909753ae005b21 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Sun, 15 Feb 2026 15:07:41 +0530 Subject: [PATCH 5/9] fix: name --- package.json | 3 ++- src/plugins/pluginContext/plugin.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0e152fc54..850aed7af 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "com.foxdebug.acode.rk.exec.proot": {}, "com.foxdebug.acode.rk.exec.terminal": {}, "com.foxdebug.acode.rk.customtabs": {}, - "com.foxdebug.acode.rk.plugin.plugincontext": {} + "com.foxdebug.acode.rk.plugin.plugincontext": {}, + "com.foxdebug.acode.rk.auth": {} }, "platforms": [ "android" diff --git a/src/plugins/pluginContext/plugin.xml b/src/plugins/pluginContext/plugin.xml index dcc049664..2e7dd6ed5 100644 --- a/src/plugins/pluginContext/plugin.xml +++ b/src/plugins/pluginContext/plugin.xml @@ -1,6 +1,6 @@ - Gatekeeper + PluginContext From e0076eab4af789b088896ecdd2db9525a77ee437 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Sun, 15 Feb 2026 15:11:37 +0530 Subject: [PATCH 6/9] fix: pacvkage-lock.json --- package-lock.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2a6cfe0bd..97f3075b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8794,12 +8794,6 @@ "dev": true, "license": "Apache-2.0" }, - "src/plugins/gatekeeper": { - "name": "com.foxdebug.acode.rk.plugin.gatekeeper", - "version": "1.0.0", - "extraneous": true, - "license": "MIT" - }, "src/plugins/iap": { "name": "cordova-plugin-iap", "version": "1.0.0", From b4992a43f7762a1493a9a38669929d811b998fd6 Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Sun, 15 Feb 2026 17:39:42 +0530 Subject: [PATCH 7/9] Update src/plugins/pluginContext/src/android/Tee.java Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/plugins/pluginContext/src/android/Tee.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/pluginContext/src/android/Tee.java b/src/plugins/pluginContext/src/android/Tee.java index c78f3e426..3f1d2eac3 100644 --- a/src/plugins/pluginContext/src/android/Tee.java +++ b/src/plugins/pluginContext/src/android/Tee.java @@ -18,7 +18,7 @@ public class Tee extends CordovaPlugin { // pluginId : token private /*static*/ final Map tokenStore = new HashMap<>(); - //assined tokens + //assigned tokens private /*static*/ final HashSet disclosed = new HashSet<>(); // token : list of permissions From 88c40ffd619668f78c8abecccd9bccfecf6c016a Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 16 Feb 2026 09:18:13 +0530 Subject: [PATCH 8/9] Update src/plugins/pluginContext/www/PluginContext.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/plugins/pluginContext/www/PluginContext.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/pluginContext/www/PluginContext.js b/src/plugins/pluginContext/www/PluginContext.js index 4f916e7a8..380dfbb9b 100644 --- a/src/plugins/pluginContext/www/PluginContext.js +++ b/src/plugins/pluginContext/www/PluginContext.js @@ -55,7 +55,7 @@ const PluginContext = (function () { const uuid = await requestToken(pluginId); return new _PluginContext(uuid); } catch (err) { - console.warn(`PluginContext creation failed for pluginId ${pluginId}:`); + console.warn(`PluginContext creation failed for pluginId ${pluginId}:`, err); return null; } }, From 104d5e8cf2055fdef5ecf7aefc138d142d0ad732 Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 16 Feb 2026 09:19:05 +0530 Subject: [PATCH 9/9] Update src/plugins/pluginContext/src/android/Tee.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/plugins/pluginContext/src/android/Tee.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/pluginContext/src/android/Tee.java b/src/plugins/pluginContext/src/android/Tee.java index 3f1d2eac3..be6b75f4b 100644 --- a/src/plugins/pluginContext/src/android/Tee.java +++ b/src/plugins/pluginContext/src/android/Tee.java @@ -12,17 +12,19 @@ import java.util.Map; import java.util.HashMap; import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; public class Tee extends CordovaPlugin { // pluginId : token - private /*static*/ final Map tokenStore = new HashMap<>(); + private /*static*/ final Map tokenStore = new ConcurrentHashMap<>(); //assigned tokens - private /*static*/ final HashSet disclosed = new HashSet<>(); + private /*static*/ final Set disclosed = ConcurrentHashMap.newKeySet(); // token : list of permissions - private /*static*/ final Map> permissionStore = new HashMap<>(); + private /*static*/ final Map> permissionStore = new ConcurrentHashMap<>(); @Override public boolean execute(String action, JSONArray args, CallbackContext callback)