@metamask/snaps-controllers 4.0.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 +12 -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 +198 -93
- 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/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 +200 -95
- 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/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 +31 -3
- 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 +8 -8
|
@@ -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);
|
|
@@ -685,6 +699,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
685
699
|
snapId,
|
|
686
700
|
type: SNAP_APPROVAL_INSTALL
|
|
687
701
|
});
|
|
702
|
+
this.messagingSystem.publish('SnapController:snapInstallStarted', snapId, origin, false);
|
|
688
703
|
// Existing snaps must be stopped before overwriting
|
|
689
704
|
if (existingSnap && this.isRunning(snapId)) {
|
|
690
705
|
await this.stopSnap(snapId, _snapsutils.SnapStatusEvents.Stop);
|
|
@@ -718,11 +733,13 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
718
733
|
return truncated;
|
|
719
734
|
} catch (error) {
|
|
720
735
|
(0, _snapsutils.logError)(`Error when adding ${snapId}.`, error);
|
|
736
|
+
const errorString = error instanceof Error ? error.message : error.toString();
|
|
721
737
|
_class_private_method_get(this, _updateApproval, updateApproval).call(this, pendingApproval.id, {
|
|
722
738
|
loading: false,
|
|
723
739
|
type: SNAP_APPROVAL_INSTALL,
|
|
724
|
-
error:
|
|
740
|
+
error: errorString
|
|
725
741
|
});
|
|
742
|
+
this.messagingSystem.publish('SnapController:snapInstallFailed', snapId, origin, false, errorString);
|
|
726
743
|
throw error;
|
|
727
744
|
}
|
|
728
745
|
}
|
|
@@ -754,9 +771,11 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
754
771
|
type: SNAP_APPROVAL_UPDATE
|
|
755
772
|
});
|
|
756
773
|
try {
|
|
774
|
+
this.messagingSystem.publish('SnapController:snapInstallStarted', snapId, origin, true);
|
|
757
775
|
const snap = this.getExpect(snapId);
|
|
758
|
-
const
|
|
759
|
-
const
|
|
776
|
+
const oldManifest = snap.manifest;
|
|
777
|
+
const newSnap = await (0, _utils1.fetchSnap)(snapId, location);
|
|
778
|
+
const { sourceCode: sourceCodeFile, manifest: manifestFile } = newSnap;
|
|
760
779
|
const manifest = manifestFile.result;
|
|
761
780
|
const newVersion = manifest.version;
|
|
762
781
|
if (!(0, _utils.gtVersion)(newVersion, snap.version)) {
|
|
@@ -793,28 +812,22 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
793
812
|
_class_private_method_get(this, _set, set).call(this, {
|
|
794
813
|
origin,
|
|
795
814
|
id: snapId,
|
|
796
|
-
files: newSnap
|
|
815
|
+
files: newSnap,
|
|
797
816
|
isUpdate: true
|
|
798
817
|
});
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
}
|
|
805
|
-
if (
|
|
806
|
-
this.
|
|
807
|
-
approvedPermissions: approvedNewPermissions,
|
|
808
|
-
subject: {
|
|
809
|
-
origin: snapId
|
|
810
|
-
},
|
|
811
|
-
requestData
|
|
812
|
-
});
|
|
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);
|
|
813
826
|
}
|
|
814
827
|
const rollbackSnapshot = _class_private_method_get(this, _getRollbackSnapshot, getRollbackSnapshot).call(this, snapId);
|
|
815
828
|
if (rollbackSnapshot !== undefined) {
|
|
816
829
|
rollbackSnapshot.permissions.revoked = unusedPermissions;
|
|
817
|
-
rollbackSnapshot.permissions.granted =
|
|
830
|
+
rollbackSnapshot.permissions.granted = approvedNewPermissions;
|
|
818
831
|
rollbackSnapshot.permissions.requestData = requestData;
|
|
819
832
|
}
|
|
820
833
|
const sourceCode = sourceCodeFile.toString();
|
|
@@ -838,11 +851,13 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
838
851
|
return truncatedSnap;
|
|
839
852
|
} catch (error) {
|
|
840
853
|
(0, _snapsutils.logError)(`Error when updating ${snapId},`, error);
|
|
854
|
+
const errorString = error instanceof Error ? error.message : error.toString();
|
|
841
855
|
_class_private_method_get(this, _updateApproval, updateApproval).call(this, pendingApproval.id, {
|
|
842
856
|
loading: false,
|
|
843
|
-
error:
|
|
857
|
+
error: errorString,
|
|
844
858
|
type: SNAP_APPROVAL_UPDATE
|
|
845
859
|
});
|
|
860
|
+
this.messagingSystem.publish('SnapController:snapInstallFailed', snapId, origin, true, errorString);
|
|
846
861
|
throw error;
|
|
847
862
|
}
|
|
848
863
|
}
|
|
@@ -877,14 +892,13 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
877
892
|
permissions: processedPermissions
|
|
878
893
|
});
|
|
879
894
|
const { permissions: approvedPermissions, ...requestData } = await pendingApproval.promise;
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
});
|
|
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);
|
|
888
902
|
}
|
|
889
903
|
} finally{
|
|
890
904
|
const runtime = _class_private_method_get(this, _getRuntimeExpect, getRuntimeExpect).call(this, snapId);
|
|
@@ -946,7 +960,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
946
960
|
}
|
|
947
961
|
constructor({ closeAllConnections, messenger, state, dynamicPermissions = [
|
|
948
962
|
'eth_accounts'
|
|
949
|
-
], 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 }){
|
|
950
964
|
super({
|
|
951
965
|
messenger,
|
|
952
966
|
metadata: {
|
|
@@ -984,6 +998,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
984
998
|
});
|
|
985
999
|
_class_private_method_init(this, _initializeStateMachine);
|
|
986
1000
|
_class_private_method_init(this, _registerMessageHandlers);
|
|
1001
|
+
_class_private_method_init(this, _handlePreinstalledSnaps);
|
|
987
1002
|
_class_private_method_init(this, _pollForLastRequestStatus);
|
|
988
1003
|
/**
|
|
989
1004
|
* Blocks an installed snap and prevents it from being started again. Emits
|
|
@@ -1001,6 +1016,8 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1001
1016
|
*
|
|
1002
1017
|
* @param snapId - The snap to terminate.
|
|
1003
1018
|
*/ _class_private_method_init(this, _terminateSnap);
|
|
1019
|
+
_class_private_method_init(this, _handleInitialConnections);
|
|
1020
|
+
_class_private_method_init(this, _addSnapToSubject);
|
|
1004
1021
|
_class_private_method_init(this, _removeSnapFromSubjects);
|
|
1005
1022
|
_class_private_method_init(this, _revokeAllSnapPermissions);
|
|
1006
1023
|
_class_private_method_init(this, _createApproval);
|
|
@@ -1028,13 +1045,6 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1028
1045
|
* @returns An array of the names of the endowments.
|
|
1029
1046
|
*/ _class_private_method_init(this, _getEndowments);
|
|
1030
1047
|
_class_private_method_init(this, _set);
|
|
1031
|
-
/**
|
|
1032
|
-
* Fetches the manifest and source code of a snap.
|
|
1033
|
-
*
|
|
1034
|
-
* @param snapId - The id of the Snap.
|
|
1035
|
-
* @param location - Source from which snap will be fetched.
|
|
1036
|
-
* @returns A tuple of the Snap manifest object and the Snap source code.
|
|
1037
|
-
*/ _class_private_method_init(this, _fetchSnap);
|
|
1038
1048
|
_class_private_method_init(this, _validateSnapPermissions);
|
|
1039
1049
|
_class_private_method_init(this, _getRpcRequestHandler);
|
|
1040
1050
|
_class_private_method_init(this, _triggerPhishingListUpdate);
|
|
@@ -1079,6 +1089,7 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1079
1089
|
_class_private_method_init(this, _getRuntimeExpect);
|
|
1080
1090
|
_class_private_method_init(this, _setupRuntime);
|
|
1081
1091
|
_class_private_method_init(this, _calculatePermissionsChange);
|
|
1092
|
+
_class_private_method_init(this, _updatePermissions);
|
|
1082
1093
|
_class_private_method_init(this, _isValidUpdate);
|
|
1083
1094
|
/**
|
|
1084
1095
|
* Call a lifecycle hook on a snap, if the snap has the
|
|
@@ -1175,7 +1186,10 @@ class SnapController extends _basecontroller.BaseController {
|
|
|
1175
1186
|
});
|
|
1176
1187
|
_class_private_method_get(this, _initializeStateMachine, initializeStateMachine).call(this);
|
|
1177
1188
|
_class_private_method_get(this, _registerMessageHandlers, registerMessageHandlers).call(this);
|
|
1178
|
-
|
|
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));
|
|
1179
1193
|
}
|
|
1180
1194
|
}
|
|
1181
1195
|
function initializeStateMachine() {
|
|
@@ -1252,6 +1266,63 @@ function registerMessageHandlers() {
|
|
|
1252
1266
|
this.messagingSystem.registerActionHandler(`${controllerName}:revokeDynamicPermissions`, (...args)=>this.revokeDynamicSnapPermissions(...args));
|
|
1253
1267
|
this.messagingSystem.registerActionHandler(`${controllerName}:getFile`, async (...args)=>this.getSnapFile(...args));
|
|
1254
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
|
+
}
|
|
1255
1326
|
function pollForLastRequestStatus() {
|
|
1256
1327
|
_class_private_field_set(this, _timeoutForLastRequestStatus, setTimeout(()=>{
|
|
1257
1328
|
_class_private_method_get(this, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax).call(this).catch((error)=>{
|
|
@@ -1314,6 +1385,52 @@ async function terminateSnap(snapId) {
|
|
|
1314
1385
|
await this.messagingSystem.call('ExecutionService:terminateSnap', snapId);
|
|
1315
1386
|
this.messagingSystem.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
|
|
1316
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
|
+
}
|
|
1317
1434
|
function removeSnapFromSubjects(snapId) {
|
|
1318
1435
|
const subjects = this.messagingSystem.call('PermissionController:getSubjectNames');
|
|
1319
1436
|
for (const subject of subjects){
|
|
@@ -1371,8 +1488,8 @@ async function add(args) {
|
|
|
1371
1488
|
// If fetching and setting the snap succeeds, this property will be set
|
|
1372
1489
|
// to null in the authorize() method.
|
|
1373
1490
|
runtime.installPromise = (async ()=>{
|
|
1374
|
-
const fetchedSnap = await
|
|
1375
|
-
const manifest = fetchedSnap.
|
|
1491
|
+
const fetchedSnap = await (0, _utils1.fetchSnap)(snapId, location);
|
|
1492
|
+
const manifest = fetchedSnap.manifest.result;
|
|
1376
1493
|
if (!(0, _utils.satisfiesVersionRange)(manifest.version, versionRange)) {
|
|
1377
1494
|
throw new Error(`Version mismatch. Manifest for "${snapId}" specifies version "${manifest.version}" which doesn't satisfy requested version range "${versionRange}".`);
|
|
1378
1495
|
}
|
|
@@ -1382,7 +1499,7 @@ async function add(args) {
|
|
|
1382
1499
|
});
|
|
1383
1500
|
return _class_private_method_get(this, _set, set).call(this, {
|
|
1384
1501
|
...args,
|
|
1385
|
-
|
|
1502
|
+
files: fetchedSnap,
|
|
1386
1503
|
id: snapId
|
|
1387
1504
|
});
|
|
1388
1505
|
})();
|
|
@@ -1445,7 +1562,7 @@ async function getEndowments(snapId) {
|
|
|
1445
1562
|
return dedupedEndowments;
|
|
1446
1563
|
}
|
|
1447
1564
|
function set(args) {
|
|
1448
|
-
const { id: snapId, origin, files, isUpdate = false } = args;
|
|
1565
|
+
const { id: snapId, origin, files, isUpdate = false, removable, preinstalled } = args;
|
|
1449
1566
|
const { manifest, sourceCode: sourceCodeFile, svgIcon, auxiliaryFiles: rawAuxiliaryFiles, localizationFiles } = files;
|
|
1450
1567
|
(0, _snapsutils.assertIsSnapManifest)(manifest.result);
|
|
1451
1568
|
const { version, proposedName } = manifest.result;
|
|
@@ -1476,6 +1593,8 @@ function set(args) {
|
|
|
1476
1593
|
// previous state.
|
|
1477
1594
|
blocked: false,
|
|
1478
1595
|
enabled: true,
|
|
1596
|
+
removable,
|
|
1597
|
+
preinstalled,
|
|
1479
1598
|
id: snapId,
|
|
1480
1599
|
initialPermissions: manifest.result.initialPermissions,
|
|
1481
1600
|
manifest: manifest.result,
|
|
@@ -1512,36 +1631,6 @@ function set(args) {
|
|
|
1512
1631
|
sourceCode
|
|
1513
1632
|
};
|
|
1514
1633
|
}
|
|
1515
|
-
async function fetchSnap(snapId, location) {
|
|
1516
|
-
try {
|
|
1517
|
-
const manifest = await location.manifest();
|
|
1518
|
-
const sourceCode = await location.fetch(manifest.result.source.location.npm.filePath);
|
|
1519
|
-
const { iconPath } = manifest.result.source.location.npm;
|
|
1520
|
-
const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;
|
|
1521
|
-
const auxiliaryFiles = await (0, _utils1.getSnapFiles)(location, manifest.result.source.files);
|
|
1522
|
-
await Promise.all(auxiliaryFiles.map(async (file)=>{
|
|
1523
|
-
// This should still be safe
|
|
1524
|
-
// eslint-disable-next-line require-atomic-updates
|
|
1525
|
-
file.data.base64 = await (0, _snapsutils.encodeBase64)(file);
|
|
1526
|
-
}));
|
|
1527
|
-
const localizationFiles = await (0, _utils1.getSnapFiles)(location, manifest.result.source.locales);
|
|
1528
|
-
const validatedLocalizationFiles = (0, _snapsutils.getValidatedLocalizationFiles)(localizationFiles);
|
|
1529
|
-
const files = {
|
|
1530
|
-
manifest,
|
|
1531
|
-
sourceCode,
|
|
1532
|
-
svgIcon,
|
|
1533
|
-
auxiliaryFiles,
|
|
1534
|
-
localizationFiles: validatedLocalizationFiles
|
|
1535
|
-
};
|
|
1536
|
-
await (0, _snapsutils.validateFetchedSnap)(files);
|
|
1537
|
-
return {
|
|
1538
|
-
files,
|
|
1539
|
-
location
|
|
1540
|
-
};
|
|
1541
|
-
} catch (error) {
|
|
1542
|
-
throw new Error(`Failed to fetch snap "${snapId}": ${(0, _snapssdk.getErrorMessage)(error)}.`);
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
1634
|
function validateSnapPermissions(processedPermissions) {
|
|
1546
1635
|
const permissionKeys = Object.keys(processedPermissions);
|
|
1547
1636
|
const handlerPermissions = Array.from(new Set(Object.values(_endowments.handlerEndowments)));
|
|
@@ -1634,6 +1723,17 @@ async function assertSnapRpcRequestResult(handlerType, result) {
|
|
|
1634
1723
|
(0, _snapsutils.validateComponentLinks)(result.content, _class_private_method_get(this, _checkPhishingList, checkPhishingList).bind(this));
|
|
1635
1724
|
break;
|
|
1636
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
|
+
}
|
|
1637
1737
|
case _snapsutils.HandlerType.OnHomePage:
|
|
1638
1738
|
(0, _utils.assertStruct)(result, _snapsutils.OnHomePageResponseStruct);
|
|
1639
1739
|
await _class_private_method_get(this, _triggerPhishingListUpdate, triggerPhishingListUpdate).call(this);
|
|
@@ -1672,11 +1772,7 @@ function createRollbackSnapshot(snapId) {
|
|
|
1672
1772
|
(0, _utils.assert)(_class_private_field_get(this, _rollbackSnapshots).get(snapId) === undefined, new Error(`Snap "${snapId}" rollback snapshot already exists.`));
|
|
1673
1773
|
_class_private_field_get(this, _rollbackSnapshots).set(snapId, {
|
|
1674
1774
|
statePatches: [],
|
|
1675
|
-
permissions: {
|
|
1676
|
-
revoked: null,
|
|
1677
|
-
granted: [],
|
|
1678
|
-
requestData: null
|
|
1679
|
-
},
|
|
1775
|
+
permissions: {},
|
|
1680
1776
|
newVersion: ''
|
|
1681
1777
|
});
|
|
1682
1778
|
const newRollbackSnapshot = _class_private_field_get(this, _rollbackSnapshots).get(snapId);
|
|
@@ -1704,20 +1800,12 @@ async function rollbackSnap(snapId) {
|
|
|
1704
1800
|
state.snaps[snapId].status = _snapsutils.SnapStatus.Stopped;
|
|
1705
1801
|
});
|
|
1706
1802
|
}
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
requestData: permissions.requestData
|
|
1714
|
-
});
|
|
1715
|
-
}
|
|
1716
|
-
if (permissions.granted?.length) {
|
|
1717
|
-
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
1718
|
-
[snapId]: permissions.granted
|
|
1719
|
-
});
|
|
1720
|
-
}
|
|
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
|
+
});
|
|
1721
1809
|
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
1722
1810
|
this.messagingSystem.publish('SnapController:snapRolledback', truncatedSnap, rollbackSnapshot.newVersion);
|
|
1723
1811
|
_class_private_field_get(this, _rollbackSnapshots).delete(snapId);
|
|
@@ -1773,6 +1861,23 @@ function calculatePermissionsChange(snapId, desiredPermissionsSet) {
|
|
|
1773
1861
|
approvedPermissions
|
|
1774
1862
|
};
|
|
1775
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
|
+
}
|
|
1776
1881
|
function isValidUpdate(snapId, newVersionRange) {
|
|
1777
1882
|
const existingSnap = this.getExpect(snapId);
|
|
1778
1883
|
if ((0, _utils.satisfiesVersionRange)(existingSnap.version, newVersionRange)) {
|