@metamask/snaps-controllers 3.6.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -1
- package/dist/cjs/cronjob/CronjobController.js +2 -2
- package/dist/cjs/cronjob/CronjobController.js.map +1 -1
- package/dist/cjs/services/ProxyPostMessageStream.js +3 -10
- package/dist/cjs/services/ProxyPostMessageStream.js.map +1 -1
- package/dist/cjs/services/node/NodeProcessExecutionService.js +13 -1
- package/dist/cjs/services/node/NodeProcessExecutionService.js.map +1 -1
- package/dist/cjs/services/node/NodeThreadExecutionService.js +14 -1
- package/dist/cjs/services/node/NodeThreadExecutionService.js.map +1 -1
- package/dist/cjs/services/offscreen/OffscreenExecutionService.js +36 -99
- package/dist/cjs/services/offscreen/OffscreenExecutionService.js.map +1 -1
- package/dist/cjs/services/proxy/ProxyExecutionService.js +110 -0
- package/dist/cjs/services/proxy/ProxyExecutionService.js.map +1 -0
- package/dist/cjs/snaps/SnapController.js +206 -96
- package/dist/cjs/snaps/SnapController.js.map +1 -1
- package/dist/cjs/snaps/endowments/enum.js +1 -0
- package/dist/cjs/snaps/endowments/enum.js.map +1 -1
- package/dist/cjs/snaps/endowments/index.js +12 -4
- package/dist/cjs/snaps/endowments/index.js.map +1 -1
- package/dist/cjs/snaps/endowments/signature-insight.js +106 -0
- package/dist/cjs/snaps/endowments/signature-insight.js.map +1 -0
- package/dist/cjs/utils.js +32 -0
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/cronjob/CronjobController.js +2 -2
- package/dist/esm/cronjob/CronjobController.js.map +1 -1
- package/dist/esm/services/ProxyPostMessageStream.js +3 -10
- package/dist/esm/services/ProxyPostMessageStream.js.map +1 -1
- package/dist/esm/services/node/NodeProcessExecutionService.js +13 -1
- package/dist/esm/services/node/NodeProcessExecutionService.js.map +1 -1
- package/dist/esm/services/node/NodeThreadExecutionService.js +14 -1
- package/dist/esm/services/node/NodeThreadExecutionService.js.map +1 -1
- package/dist/esm/services/offscreen/OffscreenExecutionService.js +36 -99
- package/dist/esm/services/offscreen/OffscreenExecutionService.js.map +1 -1
- package/dist/esm/services/proxy/ProxyExecutionService.js +100 -0
- package/dist/esm/services/proxy/ProxyExecutionService.js.map +1 -0
- package/dist/esm/snaps/SnapController.js +208 -98
- package/dist/esm/snaps/SnapController.js.map +1 -1
- package/dist/esm/snaps/endowments/enum.js +1 -0
- package/dist/esm/snaps/endowments/enum.js.map +1 -1
- package/dist/esm/snaps/endowments/index.js +10 -4
- package/dist/esm/snaps/endowments/index.js.map +1 -1
- package/dist/esm/snaps/endowments/signature-insight.js +99 -0
- package/dist/esm/snaps/endowments/signature-insight.js.map +1 -0
- package/dist/esm/utils.js +37 -0
- package/dist/esm/utils.js.map +1 -1
- package/dist/types/cronjob/CronjobController.d.ts +2 -2
- package/dist/types/services/ProxyPostMessageStream.d.ts +1 -2
- package/dist/types/services/offscreen/OffscreenExecutionService.d.ts +5 -22
- package/dist/types/services/proxy/ProxyExecutionService.d.ts +39 -0
- package/dist/types/snaps/SnapController.d.ts +33 -20
- package/dist/types/snaps/endowments/enum.d.ts +1 -0
- package/dist/types/snaps/endowments/index.d.ts +12 -0
- package/dist/types/snaps/endowments/signature-insight.d.ts +39 -0
- package/dist/types/utils.d.ts +99 -0
- package/package.json +10 -10
|
@@ -151,7 +151,7 @@ var _closeAllConnections = /*#__PURE__*/ new WeakMap(), _dynamicPermissions = /*
|
|
|
151
151
|
_initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
152
152
|
* Constructor helper for registering the controller's messaging system
|
|
153
153
|
* actions.
|
|
154
|
-
*/ _registerMessageHandlers = /*#__PURE__*/ new WeakSet(), _pollForLastRequestStatus = /*#__PURE__*/ new WeakSet(), _blockSnap = /*#__PURE__*/ new WeakSet(), /**
|
|
154
|
+
*/ _registerMessageHandlers = /*#__PURE__*/ new WeakSet(), _handlePreinstalledSnaps = /*#__PURE__*/ new WeakSet(), _pollForLastRequestStatus = /*#__PURE__*/ new WeakSet(), _blockSnap = /*#__PURE__*/ new WeakSet(), /**
|
|
155
155
|
* Unblocks a snap so that it can be enabled and started again. Emits
|
|
156
156
|
* {@link SnapUnblocked}. Does nothing if the snap is not installed or already
|
|
157
157
|
* unblocked.
|
|
@@ -168,7 +168,7 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
168
168
|
*
|
|
169
169
|
* @param snapId - The id of the snap to transition.
|
|
170
170
|
* @param event - The event enum to use to transition.
|
|
171
|
-
*/ _transition = /*#__PURE__*/ new WeakSet(), _terminateSnap = /*#__PURE__*/ new WeakSet(), /**
|
|
171
|
+
*/ _transition = /*#__PURE__*/ new WeakSet(), _terminateSnap = /*#__PURE__*/ new WeakSet(), _handleInitialConnections = /*#__PURE__*/ new WeakSet(), _addSnapToSubject = /*#__PURE__*/ new WeakSet(), /**
|
|
172
172
|
* Removes a snap's permission (caveat) from all subjects.
|
|
173
173
|
*
|
|
174
174
|
* @param snapId - The id of the Snap.
|
|
@@ -189,7 +189,7 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
189
189
|
*
|
|
190
190
|
* @param args - The add snap args.
|
|
191
191
|
* @returns The resulting snap object.
|
|
192
|
-
*/ _set = /*#__PURE__*/ new WeakSet(),
|
|
192
|
+
*/ _set = /*#__PURE__*/ new WeakSet(), _validateSnapPermissions = /*#__PURE__*/ new WeakSet(), /**
|
|
193
193
|
* Gets the RPC message handler for the given snap.
|
|
194
194
|
*
|
|
195
195
|
* @param snapId - The id of the Snap whose message handler to get.
|
|
@@ -207,6 +207,16 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
207
207
|
* @throws {@link Error}. If the snap exists before creation or if creation fails.
|
|
208
208
|
* @returns A `RollbackSnapshot`.
|
|
209
209
|
*/ _createRollbackSnapshot = /*#__PURE__*/ new WeakSet(), _rollbackSnap = /*#__PURE__*/ new WeakSet(), _rollbackSnaps = /*#__PURE__*/ new WeakSet(), _getRuntime = /*#__PURE__*/ new WeakSet(), _getRuntimeExpect = /*#__PURE__*/ new WeakSet(), _setupRuntime = /*#__PURE__*/ new WeakSet(), _calculatePermissionsChange = /*#__PURE__*/ new WeakSet(), /**
|
|
210
|
+
* Updates the permissions for a snap following an install, update or rollback.
|
|
211
|
+
*
|
|
212
|
+
* Grants newly requested permissions and revokes unused/revoked permissions.
|
|
213
|
+
*
|
|
214
|
+
* @param args - An options bag.
|
|
215
|
+
* @param args.snapId - The snap ID.
|
|
216
|
+
* @param args.newPermissions - New permissions to be granted.
|
|
217
|
+
* @param args.unusedPermissions - Unused permissions to be revoked.
|
|
218
|
+
* @param args.requestData - Optional request data from an approval.
|
|
219
|
+
*/ _updatePermissions = /*#__PURE__*/ new WeakSet(), /**
|
|
210
220
|
* Checks if a snap will pass version validation checks
|
|
211
221
|
* with the new version range that is requested. The first
|
|
212
222
|
* check that is done is to check if the existing snap version
|
|
@@ -492,6 +502,10 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
492
502
|
if (!Array.isArray(snapIds)) {
|
|
493
503
|
throw new Error('Expected array of snap ids.');
|
|
494
504
|
}
|
|
505
|
+
snapIds.forEach((snapId)=>{
|
|
506
|
+
const snap = this.getExpect(snapId);
|
|
507
|
+
(0, _utils.assert)(snap.removable !== false, `${snapId} is not removable.`);
|
|
508
|
+
});
|
|
495
509
|
await Promise.all(snapIds.map(async (snapId)=>{
|
|
496
510
|
const snap = this.getExpect(snapId);
|
|
497
511
|
const truncated = this.getTruncatedExpect(snapId);
|
|
@@ -506,7 +520,6 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
506
520
|
delete state.snaps[snapId];
|
|
507
521
|
delete state.snapStates[snapId];
|
|
508
522
|
});
|
|
509
|
-
this.messagingSystem.publish(`SnapController:snapRemoved`, truncated);
|
|
510
523
|
// If the snap has been fully installed before, also emit snapUninstalled.
|
|
511
524
|
if (snap.status !== _snapsutils.SnapStatus.Installing) {
|
|
512
525
|
this.messagingSystem.publish(`SnapController:snapUninstalled`, truncated);
|
|
@@ -686,6 +699,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
686
699
|
snapId,
|
|
687
700
|
type: SNAP_APPROVAL_INSTALL
|
|
688
701
|
});
|
|
702
|
+
this.messagingSystem.publish('SnapController:snapInstallStarted', snapId, origin, false);
|
|
689
703
|
// Existing snaps must be stopped before overwriting
|
|
690
704
|
if (existingSnap && this.isRunning(snapId)) {
|
|
691
705
|
await this.stopSnap(snapId, _snapsutils.SnapStatusEvents.Stop);
|
|
@@ -719,11 +733,13 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
719
733
|
return truncated;
|
|
720
734
|
} catch (error) {
|
|
721
735
|
(0, _snapsutils.logError)(`Error when adding ${snapId}.`, error);
|
|
736
|
+
const errorString = error instanceof Error ? error.message : error.toString();
|
|
722
737
|
_class_private_method_get(this, _updateApproval, updateApproval).call(this, pendingApproval.id, {
|
|
723
738
|
loading: false,
|
|
724
739
|
type: SNAP_APPROVAL_INSTALL,
|
|
725
|
-
error:
|
|
740
|
+
error: errorString
|
|
726
741
|
});
|
|
742
|
+
this.messagingSystem.publish('SnapController:snapInstallFailed', snapId, origin, false, errorString);
|
|
727
743
|
throw error;
|
|
728
744
|
}
|
|
729
745
|
}
|
|
@@ -755,9 +771,11 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
755
771
|
type: SNAP_APPROVAL_UPDATE
|
|
756
772
|
});
|
|
757
773
|
try {
|
|
774
|
+
this.messagingSystem.publish('SnapController:snapInstallStarted', snapId, origin, true);
|
|
758
775
|
const snap = this.getExpect(snapId);
|
|
759
|
-
const
|
|
760
|
-
const
|
|
776
|
+
const oldManifest = snap.manifest;
|
|
777
|
+
const newSnap = await (0, _utils1.fetchSnap)(snapId, location);
|
|
778
|
+
const { sourceCode: sourceCodeFile, manifest: manifestFile } = newSnap;
|
|
761
779
|
const manifest = manifestFile.result;
|
|
762
780
|
const newVersion = manifest.version;
|
|
763
781
|
if (!(0, _utils.gtVersion)(newVersion, snap.version)) {
|
|
@@ -794,28 +812,22 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
794
812
|
_class_private_method_get(this, _set, set).call(this, {
|
|
795
813
|
origin,
|
|
796
814
|
id: snapId,
|
|
797
|
-
files: newSnap
|
|
815
|
+
files: newSnap,
|
|
798
816
|
isUpdate: true
|
|
799
817
|
});
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
}
|
|
806
|
-
if (
|
|
807
|
-
this.
|
|
808
|
-
approvedPermissions: approvedNewPermissions,
|
|
809
|
-
subject: {
|
|
810
|
-
origin: snapId
|
|
811
|
-
},
|
|
812
|
-
requestData
|
|
813
|
-
});
|
|
818
|
+
_class_private_method_get(this, _updatePermissions, updatePermissions).call(this, {
|
|
819
|
+
snapId,
|
|
820
|
+
unusedPermissions,
|
|
821
|
+
newPermissions: approvedNewPermissions,
|
|
822
|
+
requestData
|
|
823
|
+
});
|
|
824
|
+
if (manifest.initialConnections) {
|
|
825
|
+
_class_private_method_get(this, _handleInitialConnections, handleInitialConnections).call(this, snapId, oldManifest.initialConnections ?? null, manifest.initialConnections);
|
|
814
826
|
}
|
|
815
827
|
const rollbackSnapshot = _class_private_method_get(this, _getRollbackSnapshot, getRollbackSnapshot).call(this, snapId);
|
|
816
828
|
if (rollbackSnapshot !== undefined) {
|
|
817
829
|
rollbackSnapshot.permissions.revoked = unusedPermissions;
|
|
818
|
-
rollbackSnapshot.permissions.granted =
|
|
830
|
+
rollbackSnapshot.permissions.granted = approvedNewPermissions;
|
|
819
831
|
rollbackSnapshot.permissions.requestData = requestData;
|
|
820
832
|
}
|
|
821
833
|
const sourceCode = sourceCodeFile.toString();
|
|
@@ -839,11 +851,13 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
839
851
|
return truncatedSnap;
|
|
840
852
|
} catch (error) {
|
|
841
853
|
(0, _snapsutils.logError)(`Error when updating ${snapId},`, error);
|
|
854
|
+
const errorString = error instanceof Error ? error.message : error.toString();
|
|
842
855
|
_class_private_method_get(this, _updateApproval, updateApproval).call(this, pendingApproval.id, {
|
|
843
856
|
loading: false,
|
|
844
|
-
error:
|
|
857
|
+
error: errorString,
|
|
845
858
|
type: SNAP_APPROVAL_UPDATE
|
|
846
859
|
});
|
|
860
|
+
this.messagingSystem.publish('SnapController:snapInstallFailed', snapId, origin, true, errorString);
|
|
847
861
|
throw error;
|
|
848
862
|
}
|
|
849
863
|
}
|
|
@@ -878,14 +892,13 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
878
892
|
permissions: processedPermissions
|
|
879
893
|
});
|
|
880
894
|
const { permissions: approvedPermissions, ...requestData } = await pendingApproval.promise;
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
});
|
|
895
|
+
_class_private_method_get(this, _updatePermissions, updatePermissions).call(this, {
|
|
896
|
+
snapId,
|
|
897
|
+
newPermissions: approvedPermissions,
|
|
898
|
+
requestData
|
|
899
|
+
});
|
|
900
|
+
if (snap.manifest.initialConnections) {
|
|
901
|
+
_class_private_method_get(this, _handleInitialConnections, handleInitialConnections).call(this, snapId, null, snap.manifest.initialConnections);
|
|
889
902
|
}
|
|
890
903
|
} finally{
|
|
891
904
|
const runtime = _class_private_method_get(this, _getRuntimeExpect, getRuntimeExpect).call(this, snapId);
|
|
@@ -947,7 +960,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
947
960
|
}
|
|
948
961
|
constructor({ closeAllConnections, messenger, state, dynamicPermissions = [
|
|
949
962
|
'eth_accounts'
|
|
950
|
-
], environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = (0, _utils.inMilliseconds)(5, _utils.Duration.Second), maxIdleTime = (0, _utils.inMilliseconds)(30, _utils.Duration.Second), maxRequestTime = (0, _utils.inMilliseconds)(60, _utils.Duration.Second), fetchFunction = globalThis.fetch.bind(globalThis), featureFlags = {}, detectSnapLocation: detectSnapLocationFunction = _location.detectSnapLocation }){
|
|
963
|
+
], environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = (0, _utils.inMilliseconds)(5, _utils.Duration.Second), maxIdleTime = (0, _utils.inMilliseconds)(30, _utils.Duration.Second), maxRequestTime = (0, _utils.inMilliseconds)(60, _utils.Duration.Second), fetchFunction = globalThis.fetch.bind(globalThis), featureFlags = {}, detectSnapLocation: detectSnapLocationFunction = _location.detectSnapLocation, preinstalledSnaps }){
|
|
951
964
|
super({
|
|
952
965
|
messenger,
|
|
953
966
|
metadata: {
|
|
@@ -985,6 +998,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
985
998
|
});
|
|
986
999
|
_class_private_method_init(this, _initializeStateMachine);
|
|
987
1000
|
_class_private_method_init(this, _registerMessageHandlers);
|
|
1001
|
+
_class_private_method_init(this, _handlePreinstalledSnaps);
|
|
988
1002
|
_class_private_method_init(this, _pollForLastRequestStatus);
|
|
989
1003
|
/**
|
|
990
1004
|
* Blocks an installed snap and prevents it from being started again. Emits
|
|
@@ -1002,6 +1016,8 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1002
1016
|
*
|
|
1003
1017
|
* @param snapId - The snap to terminate.
|
|
1004
1018
|
*/ _class_private_method_init(this, _terminateSnap);
|
|
1019
|
+
_class_private_method_init(this, _handleInitialConnections);
|
|
1020
|
+
_class_private_method_init(this, _addSnapToSubject);
|
|
1005
1021
|
_class_private_method_init(this, _removeSnapFromSubjects);
|
|
1006
1022
|
_class_private_method_init(this, _revokeAllSnapPermissions);
|
|
1007
1023
|
_class_private_method_init(this, _createApproval);
|
|
@@ -1029,13 +1045,6 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1029
1045
|
* @returns An array of the names of the endowments.
|
|
1030
1046
|
*/ _class_private_method_init(this, _getEndowments);
|
|
1031
1047
|
_class_private_method_init(this, _set);
|
|
1032
|
-
/**
|
|
1033
|
-
* Fetches the manifest and source code of a snap.
|
|
1034
|
-
*
|
|
1035
|
-
* @param snapId - The id of the Snap.
|
|
1036
|
-
* @param location - Source from which snap will be fetched.
|
|
1037
|
-
* @returns A tuple of the Snap manifest object and the Snap source code.
|
|
1038
|
-
*/ _class_private_method_init(this, _fetchSnap);
|
|
1039
1048
|
_class_private_method_init(this, _validateSnapPermissions);
|
|
1040
1049
|
_class_private_method_init(this, _getRpcRequestHandler);
|
|
1041
1050
|
_class_private_method_init(this, _triggerPhishingListUpdate);
|
|
@@ -1080,6 +1089,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1080
1089
|
_class_private_method_init(this, _getRuntimeExpect);
|
|
1081
1090
|
_class_private_method_init(this, _setupRuntime);
|
|
1082
1091
|
_class_private_method_init(this, _calculatePermissionsChange);
|
|
1092
|
+
_class_private_method_init(this, _updatePermissions);
|
|
1083
1093
|
_class_private_method_init(this, _isValidUpdate);
|
|
1084
1094
|
/**
|
|
1085
1095
|
* Call a lifecycle hook on a snap, if the snap has the
|
|
@@ -1176,7 +1186,10 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1176
1186
|
});
|
|
1177
1187
|
_class_private_method_get(this, _initializeStateMachine, initializeStateMachine).call(this);
|
|
1178
1188
|
_class_private_method_get(this, _registerMessageHandlers, registerMessageHandlers).call(this);
|
|
1179
|
-
|
|
1189
|
+
if (preinstalledSnaps) {
|
|
1190
|
+
_class_private_method_get(this, _handlePreinstalledSnaps, handlePreinstalledSnaps).call(this, preinstalledSnaps);
|
|
1191
|
+
}
|
|
1192
|
+
Object.values(this.state?.snaps ?? {}).forEach((snap)=>_class_private_method_get(this, _setupRuntime, setupRuntime).call(this, snap.id));
|
|
1180
1193
|
}
|
|
1181
1194
|
}
|
|
1182
1195
|
function initializeStateMachine() {
|
|
@@ -1253,6 +1266,63 @@ function registerMessageHandlers() {
|
|
|
1253
1266
|
this.messagingSystem.registerActionHandler(`${controllerName}:revokeDynamicPermissions`, (...args)=>this.revokeDynamicSnapPermissions(...args));
|
|
1254
1267
|
this.messagingSystem.registerActionHandler(`${controllerName}:getFile`, async (...args)=>this.getSnapFile(...args));
|
|
1255
1268
|
}
|
|
1269
|
+
function handlePreinstalledSnaps(preinstalledSnaps) {
|
|
1270
|
+
for (const { snapId, manifest, files, removable } of preinstalledSnaps){
|
|
1271
|
+
const existingSnap = this.get(snapId);
|
|
1272
|
+
const isAlreadyInstalled = existingSnap !== undefined;
|
|
1273
|
+
const isUpdate = isAlreadyInstalled && (0, _utils.gtVersion)(manifest.version, existingSnap.version);
|
|
1274
|
+
// Disallow downgrades and overwriting non preinstalled snaps
|
|
1275
|
+
if (isAlreadyInstalled && (!isUpdate || existingSnap.preinstalled !== true)) {
|
|
1276
|
+
continue;
|
|
1277
|
+
}
|
|
1278
|
+
const manifestFile = new _snapsutils.VirtualFile({
|
|
1279
|
+
path: _snapsutils.NpmSnapFileNames.Manifest,
|
|
1280
|
+
value: JSON.stringify(manifest),
|
|
1281
|
+
result: manifest
|
|
1282
|
+
});
|
|
1283
|
+
const virtualFiles = files.map(({ path, value })=>new _snapsutils.VirtualFile({
|
|
1284
|
+
value,
|
|
1285
|
+
path
|
|
1286
|
+
}));
|
|
1287
|
+
const { filePath, iconPath } = manifest.source.location.npm;
|
|
1288
|
+
const sourceCode = virtualFiles.find((file)=>file.path === filePath);
|
|
1289
|
+
const svgIcon = iconPath ? virtualFiles.find((file)=>file.path === iconPath) : undefined;
|
|
1290
|
+
(0, _utils.assert)(sourceCode, 'Source code not provided for preinstalled snap.');
|
|
1291
|
+
(0, _utils.assert)(!iconPath || iconPath && svgIcon, 'Icon not provided for preinstalled snap.');
|
|
1292
|
+
(0, _utils.assert)(manifest.source.files === undefined, 'Auxiliary files are not currently supported for preinstalled snaps.');
|
|
1293
|
+
const localizationFiles = manifest.source.locales?.map((path)=>virtualFiles.find((file)=>file.path === path)) ?? [];
|
|
1294
|
+
const validatedLocalizationFiles = (0, _snapsutils.getValidatedLocalizationFiles)(localizationFiles.filter(Boolean));
|
|
1295
|
+
(0, _utils.assert)(localizationFiles.length === validatedLocalizationFiles.length, 'Missing localization files for preinstalled snap.');
|
|
1296
|
+
const filesObject = {
|
|
1297
|
+
manifest: manifestFile,
|
|
1298
|
+
sourceCode,
|
|
1299
|
+
svgIcon,
|
|
1300
|
+
auxiliaryFiles: [],
|
|
1301
|
+
localizationFiles: validatedLocalizationFiles
|
|
1302
|
+
};
|
|
1303
|
+
// Add snap to the SnapController state
|
|
1304
|
+
_class_private_method_get(this, _set, set).call(this, {
|
|
1305
|
+
id: snapId,
|
|
1306
|
+
origin: 'metamask',
|
|
1307
|
+
files: filesObject,
|
|
1308
|
+
removable,
|
|
1309
|
+
preinstalled: true
|
|
1310
|
+
});
|
|
1311
|
+
// Setup permissions
|
|
1312
|
+
const processedPermissions = (0, _permissions.processSnapPermissions)(manifest.initialPermissions);
|
|
1313
|
+
_class_private_method_get(this, _validateSnapPermissions, validateSnapPermissions).call(this, processedPermissions);
|
|
1314
|
+
const { newPermissions, unusedPermissions } = _class_private_method_get(this, _calculatePermissionsChange, calculatePermissionsChange).call(this, snapId, processedPermissions);
|
|
1315
|
+
_class_private_method_get(this, _updatePermissions, updatePermissions).call(this, {
|
|
1316
|
+
snapId,
|
|
1317
|
+
newPermissions,
|
|
1318
|
+
unusedPermissions
|
|
1319
|
+
});
|
|
1320
|
+
// Set status
|
|
1321
|
+
this.update((state)=>{
|
|
1322
|
+
state.snaps[snapId].status = _snapsutils.SnapStatus.Stopped;
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1256
1326
|
function pollForLastRequestStatus() {
|
|
1257
1327
|
_class_private_field_set(this, _timeoutForLastRequestStatus, setTimeout(()=>{
|
|
1258
1328
|
_class_private_method_get(this, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax).call(this).catch((error)=>{
|
|
@@ -1315,6 +1385,52 @@ async function terminateSnap(snapId) {
|
|
|
1315
1385
|
await this.messagingSystem.call('ExecutionService:terminateSnap', snapId);
|
|
1316
1386
|
this.messagingSystem.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
|
|
1317
1387
|
}
|
|
1388
|
+
function handleInitialConnections(snapId, previousInitialConnections, initialConnections) {
|
|
1389
|
+
if (previousInitialConnections) {
|
|
1390
|
+
const revokedInitialConnections = (0, _utils1.setDiff)(previousInitialConnections, initialConnections);
|
|
1391
|
+
for (const origin of Object.keys(revokedInitialConnections)){
|
|
1392
|
+
this.removeSnapFromSubject(origin, snapId);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
for (const origin of Object.keys(initialConnections)){
|
|
1396
|
+
_class_private_method_get(this, _addSnapToSubject, addSnapToSubject).call(this, origin, snapId);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
function addSnapToSubject(origin, snapId) {
|
|
1400
|
+
const subjectPermissions = this.messagingSystem.call('PermissionController:getPermissions', origin);
|
|
1401
|
+
const existingCaveat = subjectPermissions?.[_snapsrpcmethods.WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat)=>caveat.type === _snapsutils.SnapCaveatType.SnapIds);
|
|
1402
|
+
const subjectHasSnap = Boolean((existingCaveat?.value)?.[snapId]);
|
|
1403
|
+
// If the subject is already connected to the snap, this is a no-op.
|
|
1404
|
+
if (subjectHasSnap) {
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
// If an existing caveat exists, we add the snap to that.
|
|
1408
|
+
if (existingCaveat) {
|
|
1409
|
+
this.messagingSystem.call('PermissionController:updateCaveat', origin, _snapsrpcmethods.WALLET_SNAP_PERMISSION_KEY, _snapsutils.SnapCaveatType.SnapIds, {
|
|
1410
|
+
...existingCaveat,
|
|
1411
|
+
[snapId]: {}
|
|
1412
|
+
});
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1415
|
+
const approvedPermissions = {
|
|
1416
|
+
[_snapsrpcmethods.WALLET_SNAP_PERMISSION_KEY]: {
|
|
1417
|
+
caveats: [
|
|
1418
|
+
{
|
|
1419
|
+
type: _snapsutils.SnapCaveatType.SnapIds,
|
|
1420
|
+
value: {
|
|
1421
|
+
[snapId]: {}
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
]
|
|
1425
|
+
}
|
|
1426
|
+
};
|
|
1427
|
+
this.messagingSystem.call('PermissionController:grantPermissions', {
|
|
1428
|
+
approvedPermissions,
|
|
1429
|
+
subject: {
|
|
1430
|
+
origin
|
|
1431
|
+
}
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1318
1434
|
function removeSnapFromSubjects(snapId) {
|
|
1319
1435
|
const subjects = this.messagingSystem.call('PermissionController:getSubjectNames');
|
|
1320
1436
|
for (const subject of subjects){
|
|
@@ -1372,8 +1488,8 @@ async function add(args) {
|
|
|
1372
1488
|
// If fetching and setting the snap succeeds, this property will be set
|
|
1373
1489
|
// to null in the authorize() method.
|
|
1374
1490
|
runtime.installPromise = (async ()=>{
|
|
1375
|
-
const fetchedSnap = await
|
|
1376
|
-
const manifest = fetchedSnap.
|
|
1491
|
+
const fetchedSnap = await (0, _utils1.fetchSnap)(snapId, location);
|
|
1492
|
+
const manifest = fetchedSnap.manifest.result;
|
|
1377
1493
|
if (!(0, _utils.satisfiesVersionRange)(manifest.version, versionRange)) {
|
|
1378
1494
|
throw new Error(`Version mismatch. Manifest for "${snapId}" specifies version "${manifest.version}" which doesn't satisfy requested version range "${versionRange}".`);
|
|
1379
1495
|
}
|
|
@@ -1383,7 +1499,7 @@ async function add(args) {
|
|
|
1383
1499
|
});
|
|
1384
1500
|
return _class_private_method_get(this, _set, set).call(this, {
|
|
1385
1501
|
...args,
|
|
1386
|
-
|
|
1502
|
+
files: fetchedSnap,
|
|
1387
1503
|
id: snapId
|
|
1388
1504
|
});
|
|
1389
1505
|
})();
|
|
@@ -1446,10 +1562,10 @@ async function getEndowments(snapId) {
|
|
|
1446
1562
|
return dedupedEndowments;
|
|
1447
1563
|
}
|
|
1448
1564
|
function set(args) {
|
|
1449
|
-
const { id: snapId, origin, files, isUpdate = false } = args;
|
|
1565
|
+
const { id: snapId, origin, files, isUpdate = false, removable, preinstalled } = args;
|
|
1450
1566
|
const { manifest, sourceCode: sourceCodeFile, svgIcon, auxiliaryFiles: rawAuxiliaryFiles, localizationFiles } = files;
|
|
1451
1567
|
(0, _snapsutils.assertIsSnapManifest)(manifest.result);
|
|
1452
|
-
const { version } = manifest.result;
|
|
1568
|
+
const { version, proposedName } = manifest.result;
|
|
1453
1569
|
const sourceCode = sourceCodeFile.toString();
|
|
1454
1570
|
(0, _utils.assert)(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
|
|
1455
1571
|
const auxiliaryFiles = rawAuxiliaryFiles.map((file)=>{
|
|
@@ -1477,6 +1593,8 @@ function set(args) {
|
|
|
1477
1593
|
// previous state.
|
|
1478
1594
|
blocked: false,
|
|
1479
1595
|
enabled: true,
|
|
1596
|
+
removable,
|
|
1597
|
+
preinstalled,
|
|
1480
1598
|
id: snapId,
|
|
1481
1599
|
initialPermissions: manifest.result.initialPermissions,
|
|
1482
1600
|
manifest: manifest.result,
|
|
@@ -1501,42 +1619,18 @@ function set(args) {
|
|
|
1501
1619
|
rollbackSnapshot.statePatches = inversePatches;
|
|
1502
1620
|
}
|
|
1503
1621
|
}
|
|
1504
|
-
this.messagingSystem.
|
|
1622
|
+
this.messagingSystem.call('SubjectMetadataController:addSubjectMetadata', {
|
|
1623
|
+
subjectType: _permissioncontroller.SubjectType.Snap,
|
|
1624
|
+
name: proposedName,
|
|
1625
|
+
origin: snap.id,
|
|
1626
|
+
version,
|
|
1627
|
+
svgIcon: svgIcon?.toString() ?? null
|
|
1628
|
+
});
|
|
1505
1629
|
return {
|
|
1506
1630
|
...snap,
|
|
1507
1631
|
sourceCode
|
|
1508
1632
|
};
|
|
1509
1633
|
}
|
|
1510
|
-
async function fetchSnap(snapId, location) {
|
|
1511
|
-
try {
|
|
1512
|
-
const manifest = await location.manifest();
|
|
1513
|
-
const sourceCode = await location.fetch(manifest.result.source.location.npm.filePath);
|
|
1514
|
-
const { iconPath } = manifest.result.source.location.npm;
|
|
1515
|
-
const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;
|
|
1516
|
-
const auxiliaryFiles = await (0, _utils1.getSnapFiles)(location, manifest.result.source.files);
|
|
1517
|
-
await Promise.all(auxiliaryFiles.map(async (file)=>{
|
|
1518
|
-
// This should still be safe
|
|
1519
|
-
// eslint-disable-next-line require-atomic-updates
|
|
1520
|
-
file.data.base64 = await (0, _snapsutils.encodeBase64)(file);
|
|
1521
|
-
}));
|
|
1522
|
-
const localizationFiles = await (0, _utils1.getSnapFiles)(location, manifest.result.source.locales);
|
|
1523
|
-
const validatedLocalizationFiles = (0, _snapsutils.getValidatedLocalizationFiles)(localizationFiles);
|
|
1524
|
-
const files = {
|
|
1525
|
-
manifest,
|
|
1526
|
-
sourceCode,
|
|
1527
|
-
svgIcon,
|
|
1528
|
-
auxiliaryFiles,
|
|
1529
|
-
localizationFiles: validatedLocalizationFiles
|
|
1530
|
-
};
|
|
1531
|
-
await (0, _snapsutils.validateFetchedSnap)(files);
|
|
1532
|
-
return {
|
|
1533
|
-
files,
|
|
1534
|
-
location
|
|
1535
|
-
};
|
|
1536
|
-
} catch (error) {
|
|
1537
|
-
throw new Error(`Failed to fetch snap "${snapId}": ${(0, _snapssdk.getErrorMessage)(error)}.`);
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
1634
|
function validateSnapPermissions(processedPermissions) {
|
|
1541
1635
|
const permissionKeys = Object.keys(processedPermissions);
|
|
1542
1636
|
const handlerPermissions = Array.from(new Set(Object.values(_endowments.handlerEndowments)));
|
|
@@ -1629,6 +1723,17 @@ async function assertSnapRpcRequestResult(handlerType, result) {
|
|
|
1629
1723
|
(0, _snapsutils.validateComponentLinks)(result.content, _class_private_method_get(this, _checkPhishingList, checkPhishingList).bind(this));
|
|
1630
1724
|
break;
|
|
1631
1725
|
}
|
|
1726
|
+
case _snapsutils.HandlerType.OnSignature:
|
|
1727
|
+
{
|
|
1728
|
+
(0, _utils.assertStruct)(result, _snapsutils.OnSignatureResponseStruct);
|
|
1729
|
+
// Null is an allowed return value here
|
|
1730
|
+
if (result === null) {
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
await _class_private_method_get(this, _triggerPhishingListUpdate, triggerPhishingListUpdate).call(this);
|
|
1734
|
+
(0, _snapsutils.validateComponentLinks)(result.content, _class_private_method_get(this, _checkPhishingList, checkPhishingList).bind(this));
|
|
1735
|
+
break;
|
|
1736
|
+
}
|
|
1632
1737
|
case _snapsutils.HandlerType.OnHomePage:
|
|
1633
1738
|
(0, _utils.assertStruct)(result, _snapsutils.OnHomePageResponseStruct);
|
|
1634
1739
|
await _class_private_method_get(this, _triggerPhishingListUpdate, triggerPhishingListUpdate).call(this);
|
|
@@ -1667,11 +1772,7 @@ function createRollbackSnapshot(snapId) {
|
|
|
1667
1772
|
(0, _utils.assert)(_class_private_field_get(this, _rollbackSnapshots).get(snapId) === undefined, new Error(`Snap "${snapId}" rollback snapshot already exists.`));
|
|
1668
1773
|
_class_private_field_get(this, _rollbackSnapshots).set(snapId, {
|
|
1669
1774
|
statePatches: [],
|
|
1670
|
-
permissions: {
|
|
1671
|
-
revoked: null,
|
|
1672
|
-
granted: [],
|
|
1673
|
-
requestData: null
|
|
1674
|
-
},
|
|
1775
|
+
permissions: {},
|
|
1675
1776
|
newVersion: ''
|
|
1676
1777
|
});
|
|
1677
1778
|
const newRollbackSnapshot = _class_private_field_get(this, _rollbackSnapshots).get(snapId);
|
|
@@ -1699,20 +1800,12 @@ async function rollbackSnap(snapId) {
|
|
|
1699
1800
|
state.snaps[snapId].status = _snapsutils.SnapStatus.Stopped;
|
|
1700
1801
|
});
|
|
1701
1802
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
requestData: permissions.requestData
|
|
1709
|
-
});
|
|
1710
|
-
}
|
|
1711
|
-
if (permissions.granted?.length) {
|
|
1712
|
-
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
1713
|
-
[snapId]: permissions.granted
|
|
1714
|
-
});
|
|
1715
|
-
}
|
|
1803
|
+
_class_private_method_get(this, _updatePermissions, updatePermissions).call(this, {
|
|
1804
|
+
snapId,
|
|
1805
|
+
unusedPermissions: permissions.granted,
|
|
1806
|
+
newPermissions: permissions.revoked,
|
|
1807
|
+
requestData: permissions.requestData
|
|
1808
|
+
});
|
|
1716
1809
|
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
1717
1810
|
this.messagingSystem.publish('SnapController:snapRolledback', truncatedSnap, rollbackSnapshot.newVersion);
|
|
1718
1811
|
_class_private_field_get(this, _rollbackSnapshots).delete(snapId);
|
|
@@ -1768,6 +1861,23 @@ function calculatePermissionsChange(snapId, desiredPermissionsSet) {
|
|
|
1768
1861
|
approvedPermissions
|
|
1769
1862
|
};
|
|
1770
1863
|
}
|
|
1864
|
+
function updatePermissions({ snapId, unusedPermissions = {}, newPermissions = {}, requestData }) {
|
|
1865
|
+
const unusedPermissionsKeys = Object.keys(unusedPermissions);
|
|
1866
|
+
if ((0, _utils.isNonEmptyArray)(unusedPermissionsKeys)) {
|
|
1867
|
+
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
1868
|
+
[snapId]: unusedPermissionsKeys
|
|
1869
|
+
});
|
|
1870
|
+
}
|
|
1871
|
+
if ((0, _utils.isNonEmptyArray)(Object.keys(newPermissions))) {
|
|
1872
|
+
this.messagingSystem.call('PermissionController:grantPermissions', {
|
|
1873
|
+
approvedPermissions: newPermissions,
|
|
1874
|
+
subject: {
|
|
1875
|
+
origin: snapId
|
|
1876
|
+
},
|
|
1877
|
+
requestData
|
|
1878
|
+
});
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1771
1881
|
function isValidUpdate(snapId, newVersionRange) {
|
|
1772
1882
|
const existingSnap = this.getExpect(snapId);
|
|
1773
1883
|
if ((0, _utils.satisfiesVersionRange)(existingSnap.version, newVersionRange)) {
|