Skip to content

Commit df79e64

Browse files
RohitKushvaha01greptile-apps[bot]Copilot
authored
PluginContext (#1867)
* feat: pluginContext * format * fix: issues * feat * fix: name * fix: pacvkage-lock.json * Update src/plugins/pluginContext/src/android/Tee.java Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update src/plugins/pluginContext/www/PluginContext.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update src/plugins/pluginContext/src/android/Tee.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent c77b117 commit df79e64

File tree

8 files changed

+260
-0
lines changed

8 files changed

+260
-0
lines changed

.prettierrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"com.foxdebug.acode.rk.exec.proot": {},
4141
"com.foxdebug.acode.rk.exec.terminal": {},
4242
"com.foxdebug.acode.rk.customtabs": {},
43+
"com.foxdebug.acode.rk.plugin.plugincontext": {},
4344
"com.foxdebug.acode.rk.auth": {}
4445
},
4546
"platforms": [
@@ -69,6 +70,7 @@
6970
"com.foxdebug.acode.rk.customtabs": "file:src/plugins/custom-tabs",
7071
"com.foxdebug.acode.rk.exec.proot": "file:src/plugins/proot",
7172
"com.foxdebug.acode.rk.exec.terminal": "file:src/plugins/terminal",
73+
"com.foxdebug.acode.rk.plugin.plugincontext": "file:src/plugins/pluginContext",
7274
"cordova-android": "^14.0.1",
7375
"cordova-clipboard": "^1.3.0",
7476
"cordova-plugin-advanced-http": "^3.3.1",

src/lib/loadPlugin.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ export default async function loadPlugin(pluginId, justInstalled = false) {
5656
cacheFileUrl: await helpers.toInternalUri(cacheFile),
5757
cacheFile: fsOperation(cacheFile),
5858
firstInit: justInstalled,
59+
ctx: await PluginContext.generate(
60+
pluginId,
61+
JSON.stringify(pluginJson),
62+
),
5963
});
6064

6165
resolve();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "com.foxdebug.acode.rk.plugin.plugincontext",
3+
"version": "1.0.0",
4+
"description": "PluginContext",
5+
"cordova": {
6+
"id": "com.foxdebug.acode.rk.plugin.plugincontext",
7+
"platforms": [
8+
"android"
9+
]
10+
},
11+
"keywords": [
12+
"ecosystem:cordova",
13+
"cordova-android"
14+
],
15+
"author": "@RohitKushvaha01",
16+
"license": "MIT"
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="com.foxdebug.acode.rk.plugin.plugincontext" version="1.0.0">
3+
<name>PluginContext</name>
4+
5+
6+
<js-module name="PluginContext" src="www/PluginContext.js">
7+
<clobbers target="window.PluginContext" />
8+
</js-module>
9+
10+
11+
<platform name="android">
12+
<config-file parent="/*" target="res/xml/config.xml">
13+
<feature name="Tee">
14+
<param name="android-package" value="com.foxdebug.acode.rk.plugin.Tee" />
15+
</feature>
16+
</config-file>
17+
18+
<source-file src="src/android/Tee.java" target-dir="src/com/foxdebug/acode/rk/plugin" />
19+
20+
21+
</platform>
22+
</plugin>
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package com.foxdebug.acode.rk.plugin;
2+
3+
import org.apache.cordova.CallbackContext;
4+
import org.apache.cordova.CordovaPlugin;
5+
import org.json.JSONArray;
6+
import org.json.JSONException;
7+
import org.json.JSONObject;
8+
9+
import java.util.UUID;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.HashMap;
14+
import java.util.HashSet;
15+
import java.util.Set;
16+
import java.util.concurrent.ConcurrentHashMap;
17+
18+
public class Tee extends CordovaPlugin {
19+
20+
// pluginId : token
21+
private /*static*/ final Map<String, String> tokenStore = new ConcurrentHashMap<>();
22+
23+
//assigned tokens
24+
private /*static*/ final Set<String> disclosed = ConcurrentHashMap.newKeySet();
25+
26+
// token : list of permissions
27+
private /*static*/ final Map<String, List<String>> permissionStore = new ConcurrentHashMap<>();
28+
29+
@Override
30+
public boolean execute(String action, JSONArray args, CallbackContext callback)
31+
throws JSONException {
32+
33+
if ("requestToken".equals(action)) {
34+
String pluginId = args.getString(0);
35+
String pluginJson = args.getString(1);
36+
handleTokenRequest(pluginId, pluginJson, callback);
37+
return true;
38+
}
39+
40+
if ("grantedPermission".equals(action)) {
41+
String token = args.getString(0);
42+
String permission = args.getString(1);
43+
44+
if (!permissionStore.containsKey(token)) {
45+
callback.error("INVALID_TOKEN");
46+
return true;
47+
}
48+
49+
boolean granted = grantedPermission(token, permission);
50+
callback.success(granted ? 1 : 0);
51+
return true;
52+
}
53+
54+
if ("listAllPermissions".equals(action)) {
55+
String token = args.getString(0);
56+
57+
if (!permissionStore.containsKey(token)) {
58+
callback.error("INVALID_TOKEN");
59+
return true;
60+
}
61+
62+
List<String> permissions = listAllPermissions(token);
63+
JSONArray result = new JSONArray(permissions);
64+
65+
callback.success(result);
66+
return true;
67+
}
68+
69+
return false;
70+
}
71+
72+
//============================================================
73+
//do not change function signatures
74+
public boolean isTokenValid(String token, String pluginId) {
75+
String storedToken = tokenStore.get(pluginId);
76+
return storedToken != null && token.equals(storedToken);
77+
}
78+
79+
80+
public boolean grantedPermission(String token, String permission) {
81+
List<String> permissions = permissionStore.get(token);
82+
return permissions != null && permissions.contains(permission);
83+
}
84+
85+
public List<String> listAllPermissions(String token) {
86+
List<String> permissions = permissionStore.get(token);
87+
88+
if (permissions == null) {
89+
return new ArrayList<>();
90+
}
91+
92+
return new ArrayList<>(permissions); // return copy (safe)
93+
}
94+
//============================================================
95+
96+
97+
private synchronized void handleTokenRequest(
98+
String pluginId,
99+
String pluginJson,
100+
CallbackContext callback
101+
) {
102+
103+
if (disclosed.contains(pluginId)) {
104+
callback.error("TOKEN_ALREADY_ISSUED");
105+
return;
106+
}
107+
108+
String token = tokenStore.get(pluginId);
109+
110+
if (token == null) {
111+
token = UUID.randomUUID().toString();
112+
tokenStore.put(pluginId, token);
113+
}
114+
115+
try {
116+
JSONObject json = new JSONObject(pluginJson);
117+
JSONArray permissions = json.optJSONArray("permissions");
118+
119+
List<String> permissionList = new ArrayList<>();
120+
121+
if (permissions != null) {
122+
for (int i = 0; i < permissions.length(); i++) {
123+
permissionList.add(permissions.getString(i));
124+
}
125+
}
126+
127+
// Bind permissions to token
128+
permissionStore.put(token, permissionList);
129+
130+
} catch (JSONException e) {
131+
callback.error("INVALID_PLUGIN_JSON");
132+
return;
133+
}
134+
135+
disclosed.add(pluginId);
136+
callback.success(token);
137+
}
138+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
var exec = require("cordova/exec");
2+
3+
const PluginContext = (function () {
4+
//=============================
5+
class _PluginContext {
6+
constructor(uuid) {
7+
this.created_at = Date.now();
8+
this.uuid = uuid;
9+
Object.freeze(this);
10+
}
11+
12+
toString() {
13+
return this.uuid;
14+
}
15+
16+
[Symbol.toPrimitive](hint) {
17+
if (hint === "number") {
18+
return NaN; // prevent numeric coercion
19+
}
20+
return this.uuid;
21+
}
22+
23+
grantedPermission(permission) {
24+
return new Promise((resolve, reject) => {
25+
exec(resolve, reject, "Tee", "grantedPermission", [
26+
this.uuid,
27+
permission,
28+
]);
29+
});
30+
}
31+
32+
listAllPermissions() {
33+
return new Promise((resolve, reject) => {
34+
exec(resolve, reject, "Tee", "listAllPermissions", [this.uuid]);
35+
});
36+
}
37+
}
38+
39+
//Object.freeze(this);
40+
41+
//===============================
42+
43+
return {
44+
generate: async function (pluginId, pluginJson) {
45+
try {
46+
function requestToken(pluginId) {
47+
return new Promise((resolve, reject) => {
48+
exec(resolve, reject, "Tee", "requestToken", [
49+
pluginId,
50+
pluginJson,
51+
]);
52+
});
53+
}
54+
55+
const uuid = await requestToken(pluginId);
56+
return new _PluginContext(uuid);
57+
} catch (err) {
58+
console.warn(`PluginContext creation failed for pluginId ${pluginId}:`, err);
59+
return null;
60+
}
61+
},
62+
};
63+
})();
64+
65+
module.exports = PluginContext;

0 commit comments

Comments
 (0)