Skip to content

Commit 6730f17

Browse files
committed
Merge branch 'develop' into 'master'
Develop See merge request papers/airgap/airgap-vault!431
2 parents 35f35e6 + f665565 commit 6730f17

File tree

78 files changed

+3151
-468
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+3151
-468
lines changed

android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/FileExplorer.kt

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ interface StaticSourcesExplorer {
1414
fun readIsolatedModulesScript(): ByteArray
1515
}
1616

17-
interface DynamicSourcesExplorer<in M : JSModule> {
17+
interface DynamicSourcesExplorer {
18+
fun removeModules(identifiers: List<String>)
19+
fun removeAllModules()
20+
}
21+
22+
interface SourcesExplorer<in M : JSModule> {
1823
fun listModules(): List<String>
1924

2025
fun readModuleSources(module: M): Sequence<ByteArray>
@@ -55,6 +60,14 @@ class FileExplorer private constructor(
5560
}
5661
}
5762

63+
fun removeInstalledModules(identifiers: List<String>) {
64+
filesExplorer.removeModules(identifiers)
65+
}
66+
67+
fun removeAllInstalledModules() {
68+
filesExplorer.removeAllModules()
69+
}
70+
5871
fun readModuleSources(module: JSModule): Sequence<ByteArray> =
5972
when (module) {
6073
is JSModule.Asset -> assetsExplorer.readModuleSources(module)
@@ -70,7 +83,7 @@ class FileExplorer private constructor(
7083
}
7184

7285
private fun <T : JSModule> loadModules(
73-
explorer: DynamicSourcesExplorer<T>,
86+
explorer: SourcesExplorer<T>,
7487
constructor: (identifier: String, namespace: String?, preferredEnvironment: JSEnvironment.Type, paths: List<String>) -> T,
7588
): List<T> = explorer.listModules().map { module ->
7689
val manifest = JSObject(explorer.readModuleManifest(module).decodeToString())
@@ -96,7 +109,7 @@ class FileExplorer private constructor(
96109
}
97110
}
98111

99-
private class AssetsExplorer(private val context: Context) : StaticSourcesExplorer, DynamicSourcesExplorer<JSModule.Asset> {
112+
private class AssetsExplorer(private val context: Context) : StaticSourcesExplorer, SourcesExplorer<JSModule.Asset> {
100113
override fun readJavaScriptEngineUtils(): ByteArray = context.assets.readBytes(JAVA_SCRIPT_ENGINE_UTILS)
101114
override fun readIsolatedModulesScript(): ByteArray = context.assets.readBytes(SCRIPT)
102115

@@ -117,10 +130,20 @@ private class AssetsExplorer(private val context: Context) : StaticSourcesExplor
117130
}
118131
}
119132

120-
private class FilesExplorer(private val context: Context) : DynamicSourcesExplorer<JSModule.Installed> {
133+
private class FilesExplorer(private val context: Context) : DynamicSourcesExplorer, SourcesExplorer<JSModule.Installed> {
121134
private val modulesDir: File
122135
get() = File(context.filesDir, MODULES_DIR)
123136

137+
override fun removeModules(identifiers: List<String>) {
138+
identifiers.forEach {
139+
File(modulesDir, it).deleteRecursively()
140+
}
141+
}
142+
143+
override fun removeAllModules() {
144+
modulesDir.deleteRecursively()
145+
}
146+
124147
override fun listModules(): List<String> = modulesDir.list()?.toList() ?: emptyList()
125148

126149
override fun readModuleSources(module: JSModule.Installed): Sequence<ByteArray> =

android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/IsolatedModules.kt

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class IsolatedModules : Plugin() {
1818
private val fileExplorer: FileExplorer by lazy { FileExplorer(context) }
1919

2020
@PluginMethod
21-
fun previewModule(call: PluginCall) {
21+
fun previewDynamicModule(call: PluginCall) {
2222
call.executeCatching {
2323
assertReceived(Param.PATH, Param.DIRECTORY)
2424

@@ -44,7 +44,7 @@ class IsolatedModules : Plugin() {
4444
}
4545

4646
@PluginMethod
47-
fun registerModule(call: PluginCall) {
47+
fun registerDynamicModule(call: PluginCall) {
4848
call.executeCatching {
4949
assertReceived(Param.IDENTIFIER, Param.PROTOCOL_IDENTIFIERS)
5050

@@ -60,7 +60,26 @@ class IsolatedModules : Plugin() {
6060
}
6161

6262
@PluginMethod
63-
fun loadModules(call: PluginCall) {
63+
fun removeDynamicModules(call: PluginCall) {
64+
activity.lifecycleScope.launch {
65+
call.executeCatching {
66+
val jsEvaluator = jsEvaluator.await()
67+
68+
identifiers?.let {
69+
fileExplorer.removeInstalledModules(it)
70+
jsEvaluator.deregisterModules(it)
71+
} ?: run {
72+
fileExplorer.removeAllInstalledModules()
73+
jsEvaluator.deregisterAllModules()
74+
}
75+
76+
resolve()
77+
}
78+
}
79+
}
80+
81+
@PluginMethod
82+
fun loadAllModules(call: PluginCall) {
6483
activity.lifecycleScope.launch {
6584
call.executeCatching {
6685
val modules = fileExplorer.loadAssetModules() + fileExplorer.loadInstalledModules()
@@ -117,6 +136,9 @@ class IsolatedModules : Plugin() {
117136
private val PluginCall.identifier: String
118137
get() = getString(Param.IDENTIFIER)!!
119138

139+
private val PluginCall.identifiers: List<String>?
140+
get() = getArray(Param.PROTOCOL_IDENTIFIERS, null)?.toList()
141+
120142
private val PluginCall.protocolIdentifiers: List<String>
121143
get() = getArray(Param.PROTOCOL_IDENTIFIERS).toList()
122144

@@ -145,6 +167,7 @@ class IsolatedModules : Plugin() {
145167
const val PATH = "path"
146168
const val DIRECTORY = "directory"
147169
const val IDENTIFIER = "identifier"
170+
const val IDENTIFIERS = "identifiers"
148171
const val PROTOCOL_IDENTIFIERS = "protocolIdentifiers"
149172
const val PROTOCOL_TYPE = "protocolType"
150173
const val TARGET = "target"

android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/JSEvaluator.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ class JSEvaluator constructor(
2222
module.registerFor(protocolIdentifiers)
2323
}
2424

25+
fun deregisterModules(identifiers: List<String>) {
26+
identifiers.forEach { modules.remove(it) }
27+
}
28+
29+
fun deregisterAllModules() {
30+
modules.clear()
31+
}
32+
2533
suspend fun evaluatePreviewModule(module: JSModule): JSObject =
2634
module.environment.run(module, JSModuleAction.Load(null)).also {
2735
module.appendType(it)

ios/App/App/IsolatedModules/FileExplorer.swift

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ struct FileExplorer {
5555
})
5656
}
5757

58+
func removeModules(_ identifiers: [String]) throws {
59+
try documentExplorer.removeModules(identifiers)
60+
}
61+
62+
func removeAllModules() throws {
63+
try documentExplorer.removeAllModules()
64+
}
65+
5866
func readModuleSources(_ module: JSModule) throws -> [Data] {
5967
switch module {
6068
case .asset(let asset):
@@ -77,7 +85,7 @@ struct FileExplorer {
7785
}
7886
}
7987

80-
private func loadModules<T: JSModuleProtocol, E: DynamicSourcesExplorer>(
88+
private func loadModules<T: JSModuleProtocol, E: SourcesExplorer>(
8189
using explorer: E,
8290
creatingModuleWith moduleInit: (_ identifier: String, _ namespace: String?, _ preferredEnvironment: JSEnvironmentKind, _ sources: [String]) -> T
8391
) throws -> [T] where E.T == T {
@@ -107,7 +115,7 @@ struct FileExplorer {
107115

108116
// MARK: AssetsExplorer
109117

110-
private struct AssetsExplorer: DynamicSourcesExplorer {
118+
private struct AssetsExplorer: SourcesExplorer {
111119
typealias T = JSModule.Asset
112120

113121
static let assetsURL: URL = Bundle.main.url(forResource: "public", withExtension: nil)!.appendingPathComponent("assets")
@@ -149,23 +157,49 @@ private struct AssetsExplorer: DynamicSourcesExplorer {
149157

150158
// MARK: DocumentExplorer
151159

152-
private struct DocumentExplorer: DynamicSourcesExplorer {
160+
private struct DocumentExplorer: SourcesExplorer, DynamicSourcesExplorer {
153161
typealias T = JSModule.Instsalled
154162

155163
private static let modulesDir: String = "protocol_modules"
156164

157165
private let fileManager: FileManager
158166

167+
private var documentsURL: URL? { fileManager.urls(for: .documentDirectory, in: .userDomainMask).first }
168+
private var modulesDirURL: URL? { documentsURL?.appendingPathComponent(Self.modulesDir) }
169+
159170
init(fileManager: FileManager) {
160171
self.fileManager = fileManager
161172
}
162173

174+
func removeModules(_ identifiers: [String]) throws {
175+
guard let modulesDirURL = modulesDirURL else {
176+
return
177+
}
178+
179+
var isDirectory: ObjCBool = true
180+
try identifiers.forEach {
181+
if fileManager.fileExists(atPath: modulesDirURL.path, isDirectory: &isDirectory) {
182+
try fileManager.removeItem(at: modulesDirURL.appendingPathComponent($0))
183+
}
184+
}
185+
}
186+
187+
func removeAllModules() throws {
188+
var isDirectory: ObjCBool = true
189+
guard let modulesDirURL = modulesDirURL, fileManager.fileExists(atPath: modulesDirURL.path, isDirectory: &isDirectory) else {
190+
return
191+
}
192+
193+
try fileManager.removeItem(at: modulesDirURL)
194+
}
195+
163196
func listModules() throws -> [String] {
164-
guard let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
197+
guard let modulesDirURL = modulesDirURL else {
165198
return []
166199
}
167200

168-
let modulesDirPath = url.appendingPathComponent(Self.modulesDir).path
201+
let modulesDirPath = modulesDirURL.path
202+
169203
guard fileManager.fileExists(atPath: modulesDirPath) else {
170204
return []
171205
}
@@ -194,9 +228,9 @@ private struct DocumentExplorer: DynamicSourcesExplorer {
194228
}
195229
}
196230

197-
// MARK: DynamicSourcesExplorer
231+
// MARK: SourcesExplorer
198232

199-
private protocol DynamicSourcesExplorer {
233+
private protocol SourcesExplorer {
200234
associatedtype T
201235

202236
func listModules() throws -> [String]
@@ -205,6 +239,11 @@ private protocol DynamicSourcesExplorer {
205239
func readModuleManifest(_ module: String) throws -> Data
206240
}
207241

242+
private protocol DynamicSourcesExplorer {
243+
func removeModules(_ identifiers: [String]) throws
244+
func removeAllModules() throws
245+
}
246+
208247
// MARK: Extensions
209248

210249
private extension FileExplorer {

ios/App/App/IsolatedModules/IsolatedModules.m

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010

1111
// disable true isolation until it's production ready
1212
//CAP_PLUGIN(IsolatedModules, "IsolatedModules",
13-
// CAP_PLUGIN_METHOD(previewModule, CAPPluginReturnPromise);
14-
// CAP_PLUGIN_METHOD(registerModule, CAPPluginReturnPromise);
15-
// CAP_PLUGIN_METHOD(loadModules, CAPPluginReturnPromise);
13+
// CAP_PLUGIN_METHOD(previewDynamicModule, CAPPluginReturnPromise);
14+
// CAP_PLUGIN_METHOD(registerDynamicModule, CAPPluginReturnPromise);
15+
// CAP_PLUGIN_METHOD(removeDynamicModules, CAPPluginReturnPromise);
16+
// CAP_PLUGIN_METHOD(loadAllModules, CAPPluginReturnPromise);
1617
// CAP_PLUGIN_METHOD(callMethod, CAPPluginReturnPromise);
1718
//)

ios/App/App/IsolatedModules/IsolatedModules.swift

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class IsolatedModules: CAPPlugin {
1414
private let fileExplorer: FileExplorer = .shared
1515
private lazy var jsEvaluator: JSEvaluator = .init(fileExplorer: fileExplorer)
1616

17-
@objc func previewModule(_ call: CAPPluginCall) {
17+
@objc func previewDynamicModule(_ call: CAPPluginCall) {
1818
call.assertReceived(forMethod: "previewModule", requiredParams: Param.PATH, Param.DIRECTORY)
1919

2020
do {
@@ -41,7 +41,7 @@ public class IsolatedModules: CAPPlugin {
4141
}
4242
}
4343

44-
@objc func registerModule(_ call: CAPPluginCall) {
44+
@objc func registerDynamicModule(_ call: CAPPluginCall) {
4545
call.assertReceived(forMethod: "registerModule", requiredParams: Param.IDENTIFIER, Param.PROTOCOL_IDENTIFIERS)
4646

4747
do {
@@ -64,7 +64,24 @@ public class IsolatedModules: CAPPlugin {
6464
}
6565
}
6666

67-
@objc func loadModules(_ call: CAPPluginCall) {
67+
@objc func removeDynamicModules(_ call: CAPPluginCall) {
68+
Task {
69+
do {
70+
if let identifiers = call.identifiers {
71+
try fileExplorer.removeModules(identifiers)
72+
await jsEvaluator.deregisterModules(identifiers)
73+
} else {
74+
try fileExplorer.removeAllModules()
75+
await jsEvaluator.deregisterAllModules()
76+
}
77+
call.resolve()
78+
} catch {
79+
call.reject("Error: \(error)")
80+
}
81+
}
82+
}
83+
84+
@objc func loadAllModules(_ call: CAPPluginCall) {
6885
Task {
6986
do {
7087
let protocolType = call.protocolType
@@ -152,6 +169,7 @@ public class IsolatedModules: CAPPlugin {
152169
static let PATH = "path"
153170
static let DIRECTORY = "directory"
154171
static let IDENTIFIER = "identifier"
172+
static let IDENTIFIERS = "identifiers"
155173
static let PROTOCOL_IDENTIFIERS = "protocolIdentifiers"
156174
static let PROTOCOL_TYPE = "protocolType"
157175
static let TARGET = "target"
@@ -176,6 +194,15 @@ private extension CAPPluginCall {
176194
}
177195

178196
var identifier: String? { return getString(IsolatedModules.Param.IDENTIFIER) }
197+
var identifiers: [String]? {
198+
return getArray(IsolatedModules.Param.IDENTIFIERS)?.compactMap {
199+
if let string = $0 as? String {
200+
return string
201+
} else {
202+
return nil
203+
}
204+
}
205+
}
179206
var protocolIdentifiers: [String]? {
180207
return getArray(IsolatedModules.Param.PROTOCOL_IDENTIFIERS)?.compactMap {
181208
if let string = $0 as? String {

ios/App/App/IsolatedModules/JS/JSEvaluator.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ class JSEvaluator {
2222
await modulesManager.registerModule(module, forProtocols: protocolIdentifiers)
2323
}
2424

25+
func deregisterModules(_ identifiers: [String]) async {
26+
await modulesManager.deregisterModules(identifiers)
27+
}
28+
29+
func deregisterAllModules() async {
30+
await modulesManager.deregisterAllModules()
31+
}
32+
2533
func evaluatePreviewModule(_ module: JSModule) async throws -> [String: Any] {
2634
return try await self.webViewEnv.run(.load(.init(protocolType: nil)), in: module)
2735
}
@@ -146,6 +154,14 @@ class JSEvaluator {
146154
modules[module.identifier] = module
147155
protocolIdentifiers.forEach { identifier in modules[identifier] = module }
148156
}
157+
158+
func deregisterModules(_ identifiers: [String]) {
159+
identifiers.forEach { modules.removeValue(forKey: $0) }
160+
}
161+
162+
func deregisterAllModules() {
163+
modules.removeAll()
164+
}
149165
}
150166

151167
enum Error: Swift.Error {

0 commit comments

Comments
 (0)